ASP.NET MVC and EPiServer CMS Visual Studio templates by default split the code into Models, Views, Controllers folders and it leads most of the developers to use this style of code structuring. I'll call this approach as Tech folders. But there are other ways available.
ASP.NET MVC provides Areas support which can be used to organize your code by features. EPiServer code also can be organized using Areas. Valdis Iljuconoks has two articles about it - Full support for Asp.Net Mvc areas in EPiServer 7.5 and Asp.Net Mvc Areas in EPiServer - Part 2.
Another approach is Feature folders. There are quite a lot of articles which describes it:
- Feature Folders In ASP.NET MVC
- Introducing the ASP.NET MVC “Feature Folders” Project Structure
- Grouping by feature in ASP.Net MVC
- The Obvious Architecture
- A View Engine for ASP.NET MVC Feature-Based Organized
- Structure your code by feature
- A Feature-Oriented Directory Structure For C# Projects
Also, EPiServer's Commerce starter site - Quicksilver uses Feature folders.
Both Areas and Feature folders separate the code by features, so I will refer to both as Feature folders.
Further, I am going to show analysis of dependencies between components in both approaches. I created two EPiServer Alloy Tech sites where the first one is left untouched, but the second one is refactored into Feature folders.
Dependency Structure Matrix
Rows and columns are components which can be assemblies, namespaces or types. Each component lives in column and row with the same index. Blue cells represent dependency when the component in the column is using the component in the row. Green cells represent opposite dependency. Black cells represent dependency cycle.
Read more about Dependency Structure Matrix on NDepend page.
First let's look at a higher level - dependencies between namespaces.
Below is a Feature folders' namespace dependency matrix.
From the Features namespace (inner square) it is easy to see that there are not many dependencies between different features. Only Articles and PageLists, Start and Contacts and Start and Common.Blocks have one-way dependencies which mean that namespaces within Features namespace have low coupling.
It is also visible that Business, Base, Layout, and Media are used by all features. There are few cyclic dependencies (in black). One is the shared layout and IPageViewModel used in Alloy Tech. I wrote about it before. And second is template render which defines custom views for some models.
Now lets look at Tech folders.
While dependency matrix seems simpler, it shows heavy coupling between namespaces. From this view, it is possible to see that Controllers and Business are heavily dependent on Models. It is impossible to see which application's feature is dependent on other feature. But you can see that Models has Layered code structuring. Unfortunately Controllers and Business namespaces are not. Also, Tech folders have cyclic dependencies for same reasons as Feature folders have.
Let's look at Feature folders' dependency matrix first.
Also, here it is easy to see that features within Features namespace are quite independent - most of the dependencies are within namespace itself. You can spot those dependencies as squares on the diagonal. This matches code structure pattern - High Cohesion - Low Coupling. As we know our applications should tend to have high cohesion and low coupling.
Unfortunately, Tech folders do not have such pattern.
From this matrix, you can see that dependencies for a particular feature are spread over different namespaces. This matrix also shows that Tech folders are quite badly layered. In the layered structure most of the blue cells should be in the lower left triangle but green ones in the upper-right triangle. Feature folders have better-layered structuring.
From this Feature folder and Tech folder comparison, it is quite easy to understand the benefits of Feature folders and why Tech folders should be used only for demos or application prototypes. Feature folders provide lower coupling same time grouping related code together. The only disadvantage using Feature folders is that frameworks do not "understand" those by default - you might need to configure those for your needs.