33

I'm getting ready to take the bend out of asp and into an mvc framework, asp.net mvc or nancy. Wherever I go, I see folders for controllers/modules and folders for views. Is this just a pavlovian reflex of tidying things away by type, or is there some deeper wisdom operating? I have a little proof-of-concept project where I store together the files I'm likely to open together, a considerable comfort. Since these files are also likely to call each other, they can do so with shorter, less brittle, relative links. This pattern is challenged by mvc, because the folder path no longer automatically corresponds to the url path, and, in asp.net mvc, the project templates and routing enforce the views\ controllers\ schism.

This microsoft page introduces the concept of areas. It can be read as an admission of how unwieldy large apps become because of this artificial separation.

People will object "separation of concerns", but separation of concerns is already achieved by having separate source files. There's no concrete gain, it seems to me, from taking these source files that are tightly coupled, and sending them to opposite ends of the folder structure?

Is anyone else fighting this? Any tips?

  • 3
    You don't think it's logical to separate back-end code files from view files? If we're already taking the direction why not put the relevant CSS and JavaScript files in the same folder too? – Alternatex Feb 23 '16 at 10:09
  • 2
    If you get Resharper, then F12 on the call to View in the controller takes you to the view and the first option in the right click menu on the view takes you to the controller, and the whole problem with the lack of navigation goes away. – Pete Kirkham Feb 23 '16 at 10:16
  • 3
    @Alternatex I'm sorry but I don't see how a controller is "back-end". It's tightly coupled to it's view(s). The view's no good without a controller, the controller no use without the view. One day you'll want to delete them together. That for me is the best test of what belongs together in a folder?? Unless someone can show me a better way? – bbsimonbb Feb 23 '16 at 10:20
  • 2
    Views are presentation layer. Controllers are layer which contain services, which may contain objects from your domain, which contain your business logic, which therefore contain the back-end logic of your application. Views only consists of trivial conditionals and simple loops for iteration over collections, if your views contain something else, you are doing it wrong. As with the regular structure, you have separated the back-end and front-end, which to me is a better structure than the one you're suggesting. – Andy Feb 23 '16 at 10:58
  • 9
    So no shortage of folk to tell me that a controller is crockery so it goes in the crockery cupboard. Views are glasses so they go in the glass cupboard. I know that a controller is crockery, but I'm proposing it would be great to have a lunch cupboard and a dinner cupboard, since we're talking about stuff that only gets used at lunch or at dinner. – bbsimonbb Feb 23 '16 at 13:45
37

I'd like to say it's cargo cult programming, but there are technical reasons for this structure. Asp.Net MVC took a convention over configuration approach to nearly everything. By default, the Razor view engine searches the Views directory in order to resolve which view to return from the controller. There are however a few hacks to get a different project structure and Microsoft even provides an MVC feature called Areas to let us create a more sane project structure. You could also implement your own view engine in order to specify where to look for views.

Why do I say that it's cargo cult programming and that you're correct about this? Uncle Bob convinced me that the project's directory structure shouldn't tell me that it's an MVC application. It should tell me that it's a store front, or a time off request system, or whatever. The high level structure and architecture should tell us about what this thing is, not how it was implemented.

In short, I believe you're right about this, but any other directory structure would simply be fighting against the framework and trust me when I say that you don't want to try to make the Asp.Net MVC framework do something it wasn't designed to do. It's a pity that it's not more configurable really.


To quickly address architectural concerns, I do still believe that the business models (business, not view) and the DAL should live in a separate project/library that gets called from your MVC app.

It's just that the controller really is very tightly coupled with the view and likely to be modified together. We're all wise to remember the difference between coupling via dependency and logical coupling. Just because the code has had its dependencies decoupled doesn't make it less logically coupled.

  • 1
    The comprehensive way of controlling where razor looks for views is here. I might just persevere. – bbsimonbb Feb 24 '16 at 11:23
  • 3
    I watched uncle bob, at x1.25 as suggested. It leaves me thinking that if IT architects built buildings, we'd all be living on little groups of rafts tied together, floating around on some lake. Life would not necessarily be simpler. – bbsimonbb Feb 24 '16 at 11:32
  • 1
    It get's a little more complicated. To really co-locate controllers and views, you will want to resolve the view path at runtime, to include the controller namespace. Here's how to do it. – bbsimonbb Feb 25 '16 at 9:42
  • 1
    Also take a look at feature-oriented software development (fosd.net), for the academic counterpart to what Uncle Bob is describing. – ngm Jul 6 '16 at 10:18
  • 1
    Conway’s Law at work. I’m sure that works at your company @Flater. The standard MVC layout works at lots of companies, but I still prefer to group thing by semantics over syntax. The companies I’ve work for have been organized around products instead of roles/job functions. I believe this is the root of my preference here. – RubberDuck Aug 24 '18 at 8:09
8

Whatever the reason, this is poor practise. It is very anti-OO because packages or folders (whatever you want to call them), should have weak inter-dependencies. Classes (or files) inside them should have strong inter-dependencies.

By throwing all the views in one folder and all the controllers in another folder you are creating two packages with very very tight coupling. This goes against the principle of having weak inter package dependencies.

A view and a controller are two halves of a whole and should belong to each other. You wouldn't have one cupboard draw for left side socks, and another draw for right side socks.

6

To answer your 'Why everyone...?' question: Here are some potential reasons, although I'm not entirely sure which combination of them is a real cause, since it is actually a subjective question

  • To replicate the logical architecture (model, view, controller) with a matching folder and namespace structure

  • Out of convention & convenience to follow the ASP.net MVC project template

  • To group by namespace, since Controllers/ folder will lead to a .Controllers namespace

  • Might enable some scenarios in DI/IoC where controller classes are only queried/scanned from a namespace that contains/ends-with 'Controllers' (this could be wrong)

  • To allow for T4 templates to scan and scaffold models & controllers to generate views

You can always create and follow your own convention if it makes sense to your project, no one can/will stop you. But be mindful that if you work in a large project and/or large team, then the default convention that is known to everyone might be a better choice (not necessarily the right one, though!)

If your convention is easier to follow and does not hinder productivity, then by all means do it! and maybe even write about it a blog post or two to socialise it with the developer community and get feedback

2

One reason to keep views and controllers in separate directories is when you have front end and back end developers working on a project. You can prevent front end developers from accessing back end code (e.g. to assist with PCI compliance, restricting who has access to sensitive code).

Another reason is to make it easier to have "themes" and switch out all of the templates by making a minor change to the view path.

A third reason is to have a simple directory pattern when specifying views in the MVC framework. It is easier to specify the sub-directory and file rather than a big long path to each view.

The only "tight coupling" should be:

  1. Variables sent into the view by the controller.
  2. Form fields or actions in the view, sent back to the controller.

I use a generic controller and try to keep variable names in the view generic, so that many views can use the same controller, and many controllers can use the same view. For this reason I prefer to keep the views entirely separate. The model is where you can differentiate each "thing" in your application - they can be objects with a list of properties and methods to access/modify these properties.

For tightly coupled code, an approach that could work for you is keeping all files that are part of a package or "module" together in a namespaced directory. Then you can use a script to copy or "compile" your raw templates into the main "views" directory. For example:


    lib/my-namespace/my-package/
        -> controllers/
        -> models/
        -> views/
            -> theme/
               -> template-name1
    app/compiled_views/theme/
        -> url/path/template-name1

Unfortunately, if you want to change the structure of an existing theme, there is more weaving in and out of package directories to update the views.

Consider that views are just a way to format data, whether it is json, xml, csv, or html. This especially helps if you want your application to also work as an API. Try to decouple the view from the data, by using generic variable names, so you can use the same template for many controllers or models (or use includes to minimize the amount of code you need to maintain).

1

Not necessarily everyone does this. For example python's Django framework has the concept of an app, where sub-modules of your application live in their own directories with their own models and views and templates(views are what Django calls controllers essentially). I happen to prefer that way of doing things because that means that I can easily package an "app" and reuse it across projects just by including it in the apps list in my projects settings. It's also easier to find out where different parts are. If I look at the urls.py file and see something like url(r'^users/', include('my_site.users.urls')), I know that the module my_site.users contains all the code that handles users. I know to look at the modules my_site.users.views and my_site.users.models when I want to see how users are created and authenticated. I know that all my routes are defined in my_site.users.url.

Also if it's generic enough I can probably use that module in other sites just by changing the configuration or package it as a library and publish it as OSS.

1

Remember it's the Microsoft recommended way to keep the controllers and views in different folder, so many would follow recommended structure,

  1. One reason could be controllers always does not have one to one relationship with views, especially the partial views can be shared among controllers.
  2. Another reason could be when your project grows, you might want to pull controllers and unit tests out to another project(s), but it's pretty hard to do the same for views plus views/js/css belong together as they refer each other.

Having said that there are many posts about doing it your way, such as this.

  • "it's the Microsoft recommended way" ... Can you clarify what you mean by that? Is there an actual, authoritative MS article about this? Or, is that just the default project setup for an MVC app? And, if you're basing this on the latter, isn't it possible that the default MVC project setup is what it is because it's how "everyone" does it?? – svidgen Dec 21 '16 at 15:30
  • 1
    Based on the article msdn.microsoft.com/en-us/library/… it says "Controllers, which is the recommended" and so on for the views, etc.. – Low Flying Pelican Dec 27 '16 at 4:52
0

For the record

Why do I say that it's cargo cult programming and that you're correct about this? Uncle Bob convinced me that the project's directory structure shouldn't tell me that it's an MVC application. It should tell me that it's a store front, or a time off request system, or whatever. The high level structure and architecture should tell us about what this thing is, not how it was implemented.

Question: Who has access to the code?. Programmers. Do end-users care about the code?. No. And, what a programmer does, code. Or more specifically, classes based on types (controllers, service, model and so on). So it makes sense and it's easy to debug a code, if you are able to find a code based on the type of code, instead of in the behavior of the code. Plus, let's say a team project, one is in charge of the controller, another of the model, another of the dao and another of the view. It's easy to separate the project into parts. A good code is a code that is easy to debug, not a syntax sugar code. Uncle Bob is wrong again.

Trying to mimicking the behavior of the project (a store front) is cargo cult.

  • 2
    Whan I code I care the most about features, not types. When I see a feature not working as expected I know something's wrong in the code related to that feature while I don't necessarily know which type of code it is. – Goyo Aug 24 '18 at 7:17
  • 1
    “let’s say a team project, one is in charge of the controller, another the model, another the dao” Such a team will have a hard time shipping anything and when they do it will have cost far more in communication overhead and bugs. – RubberDuck Aug 24 '18 at 7:56
  • As established in a comment chain under the accepted answer, you've got a point but only in certain cases. When a company focuses on MVC projects that it sells to many varied clients, keeping an MVC structure makes sense for reusability. When a company focuses on a niche (e.g. webshops) and possibly uses many different technologies, it makes more sense to have a webshop-oriented structure. This is a practical application of Conway's Law. The code (and therefore also project structure) should follow the company's structure. – Flater Aug 24 '18 at 8:22
  • @RubberDuck: You can make an argument for added cost either way. You're right that when different people do different technical components, that you have increased business logic communication. However, if you have different people fully implement different features, then you may have increased costs in making sure everyone is on board (skilled + agreeing) with using the same technical approach. Either way, you need communication overhead to make sure people work together. – Flater Aug 24 '18 at 8:25
  • Yes and handoffs always cost more than having a single pair of devs implementing a feature end to end IME. – RubberDuck Aug 24 '18 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.