I have been coding for a while, but mostly scripts and simple applications. I’ve moved into a new role where it is all about developing Web Apps and using a proper MVC architecture, so I am desperately trying to learn about all that very quickly.
I hope this question is not too similar to “Best Practices for MVC Architecture” but as I am going through a few different tutorials, I noticed that some have multiple controllers for different things.
How many controllers does a single web app need?
I realize this would be difficult to answer without an example so I’ll provide one:
Application:
- User logs in.
- User can do one of three things:
a) Upload a file (stored in a mongodb database with meta data).
b) Search for a file.
c) Log out.
My question is a general one, but I gave the example to help out anyone trying to answer.
1
For your example I would create two controllers:
- Sessions Controller for Login and Logout (create and destroy session for REST like layout)
- Files Controller for everything on files (index=search and create=upload)
In general a RESTful approach where you think about everything as a resource that can be displayed, created, edited and destroyed gives you a good idea how to structure things. As you can see from my examples I don’t stick too close to every single verb in REST.
You would most likely need more controllers for further functionality. For example a Users Controller where users can create new accounts. And in addition to this you would need an admin interface where you can edit the resources with higher privileges. In such a case it is quite common to have nearly every controller duplicated.
A very very rough estimate to get an initial idea could be one controller for every table in your database that users can access. But this is really only a very crude measurement.
2
It really depends on the web app. In your example, one is probably sufficient. If you were to implement a full blown ecommerce app with shipping, tax, inventory management, tiered pricing, etc., then you just might want to have a couple more.
If your controller suffers from one or more code smells (especially Large Class or God Object) then you know you’re probably past the point where just one will do.
It really depends on your application needs and architecture of business modules.
A general rule of thumb, number of required controllers depend on a number of modules and sub-modules in the Web app.
As a complementary, it would be helpful to organize the controllers into Areas. The concept of Areas is build into the ASP.NET MVC framework and it simplifies the organization of controllers that serve one module.
There are a number of related discussions:
- MVC Architecture
- ASP.NET MVC controller actions design
- mvc Controller And View directories organization
- What does MVC class organization look like for multiple views and controllers?
2
I like Apple’s way of doing it.
Every view is controlled by only one view controller.
~View Controller Programming Guide for iOS
The idea is that you should be able to easily swap out Views. IMO, by only having 1 Controller
per View
it makes it easier to accomplish this. But I’m sure you could have a Controller with multiple Views and still design it so you can switch Views without changing program logic.
6
One example that I like is thinking of a thermostat. A thermostat is a great visual for viewing the MVC pattern.
On an older, analogue thermostat you can picture things like this:
View – The temperature reader, which displays the current temperature.
Controller – The dial, where you change the temperature
Model – The parts inside that are invoked by the controller that cause the temperature to change.
You should always abide by designs that allow loose coupling and limit models and their associated controllers to a single task, and you should use as many modules/controllers as you need. Depending on the size of your application, you may have far less views than you do models and controllers. This is to be expected with any large size application. Good Object-Oriented Programming is characterized by loose coupling, encapsulation, inheritance, and polymorphism. Not all languages support polymorphism to the same degree (function, method, operator overloading / overriding).
If you want to have a better understanding of employing the MVC architecture properly, consult the GoF “Design Patterns: Elements of Reusable … Software” which uses C++ and SmallTalk for example code. This book is not the alpha and omega, but it’s certainly a start!
Good luck!
I assume that your example will evolve into a complex system.
Application:
User logs in:
LoginController
Its sole responsibility is to handle logins, re-direct or notify user of the outcome.
Upload a file
UploadController
I assume here that you want to upload any type of file. If at later date you decide to upload MP3s and PDFs, then I’d have a base UploadController, MP3UploadController and PDFUploadController.
Search for a file.
SearchFileController
This would suffice for a basic requirement. You can have multiple search controllers at a later date depending on how complex the search logic becomes. The last thing you want to have is a single SearchController with 20 action methods performing different searches.
Log out.
– LogoutController
.
One might consider this to be an overkill, but I don’t think it is. I think it’s clean and nicely separated.
If I were to look at this project structure, I would instantly know what it does and how it’s structured. To take it a step further, I would put LoginController
and LogoutController
into separate area.
I’ve developed something like this before and it worked really well.
5
Most of your code would be happening in a business layer right? If that’s the case then all you are really doing in your controller is returning data to the view.
Not really sure if I’m a fan of separating the controllers into subtypes. Whilst you should maintain separation of concerns I think subtypes is going a little too far. Also you need to be careful in cases where heavy objects are initialized in the constructor or a controller. For example: in your example you would want a heavy object, used only for search/upload file to be released when the user is on the login page.
It’s better to have a controller per logic unit, for example AccountController (login, registration, logout), FileController (search, upload) and so on.
In general you may say that every MODEL has its own CONTROLLERs and dedicated VIEWs.
By saying general I mean that this is the best practice.
application Aspects (like user management) should be translated to application service and need to be called by the controller it self, or to wrap your controller (using attributes that make the controller functionality “visible” according to request user role, for instance).
Remember that all controllers should basically handle CRUD operations over model and use different views for different filters.
In my opinion one of the major advantages of MVC as pattern is that it deliver the best way to tie models and views.
About the example you added:
I would create 2 controller: one for the all user login operation (register, login, logout etc.) and the second for file operations (Upload and search).
note that the first should also be backed up with some Aspect related to the Login functionality and the second is ordinary controller
2