Almost a year ago I wrote an article about feature folders vs tech folders. I explained why you should favor feature folders vs tech folders. While I see this style of architecture more and more, I also see that developers use tech folders inside feature folders. In this article, I am going to describe alternatives to this type of structure.
So how do sub-tech folders look like? Developers structure their MVC application into feature folders but one level below that starts adding different folders specific to MVC - ViewModels, Controllers, Models, Views. Also, there might be other technical folders like - Services, Interfaces, Implementations, Repositories etc. At the end, feature folder will look like this:
Now a feature folder looks like a small MVC application. This looks better than before with huge MVC application where everything goes into these tech folders but still, tech folders hide your application purpose.
There are several issues with this approach. As I mentioned, it hides the purpose of your application and with feature folders - specific feature's main components. See Quicksilver's Cart feature - the structure looks like in the typical MVC application and it is impossible to say what are the main components of this feature.
Another issue is that it hides smaller features. It is really easy to add multiple features into one feature folder. Yes, those now are grouped and easier to find but those still mixes different features. Same Quicksilver's Cart feature hides Wishlist.
Sub-tech folders also make closely related code be separated. For example, I've seen where interfaces are explicitly put into a different folder than implementations - Interfaces and Implementations. This makes harder to reason about the code. Another example can be found in the Quicksilver - view model factories are separated from view models which those factories are creating.
Then comes the issue with any other type of code. How one will call the tech folder where the class doesn't fit in the existing tech folders? Maybe call it Others or Classes? It sounds weird. So developers tend to not extract separate classes even if it would lead to a better design but keep all the logic in controllers, views, models etc. Then we see huge controllers which are hard to maintain.
Another option - do not use any sub-folders and place everything in the root of the feature folder. This is a most common approach dealing with feature folders. You can find examples of that in the Scott Sauber's blog, Jimmy Bogard's talk and more.
While it works and works fine, in the Episerver projects it might get quite messy as the pages might have quite complex views with lots of partial views. Also, front-end code for these views will get into the feature folder and make it messier.
The sub-feature folder is the concept of splitting your feature into smaller ones. You might have checkout feature which could be split into shipment, billing, order confirmation etc. sub-features. So creating a separate folder for each of these sub-features makes it much easier to reason about the code.
It might look like this:
There are some disadvantages. It is hard to configure MVC to pick up views from the sub-feature folders. Also, it still keeps all the front-end stuff together with the back-end.
So if tech sub-folders are not good, without sub-folders it might get messy, and feature sub-folders have their own issues, what is the solution? It depends. It depends on your project - how complex it is, how complex your views are etc.
You can mix different concepts together. Find what matches your needs. I will give you few hints.
Tech and feature sub-folder mix
The reason why tech sub-folders are bad is because developers tend to create those too granular. It is enough to separate just bigger concepts. For example, create a separate folder for views if you have a lot of them or create a separate folder for models. But do not split it more granularly.
With feature sub-folders, do not be afraid to mix in some tech folders if it becomes too messy. Add a separate folder for views, models etc. in the feature sub-folder.
With bigger and really complex applications which have a lot of business logic, it is wise to separate those into layers according to Domain Driven Design. There is a good book - Implementing Domain-Driven Design which describes this approach well.
Basically, separate your domain, application, UI, data access etc. logic within the feature. It might be separated within feature folder or split into separate assemblies.
When separating these concepts in the feature folder, it might look like this:
There are different ways how you can structure your code but the main goal is to keep it easy to work with. You can achieve it different ways but keep in mind that the "feature" is a main concept.