Horizontal vs. Vertical Project Structure

When creating new projects, especially when using new technologies or patterns, it's common to start with a very horizontal or layer-based folder structure:

An example of a layer-based folder structure, with folders for each layer in the project

As the project evolves artifacts are added to each folder. Over time, I find this structure becomes hard to work with:

  • When editing a view and needing to find the view model, there's a lot of scrolling involved
  • If I decide to split an area of functionality into a different assembly, it's not so easy to track down the files I need
  • I'm much more likely to need to edit all of the "change address" artifacts than I am to edit all of the "view model" artifacts in a single unit of work.

My preference is to structure projects vertically by feature, using a folder per feature:

An example of a feature-based folder structure, with folders for each feature in the project

A picture of me

Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy, an automated deployment tool.

Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.

05 May 2010

This has become my preference as well; for the very same reasons. :-)

05 May 2010

I really like this idea, it is so simple and makes so much sense. Could you show (or point to) some more examples of this approach by using more complex projects?

05 May 2010

That's a nice approach, but how do you deal with namespaces then? Do they resemble the folders structure? Or do you manually keep them "horizontal"?

06 May 2010

@arconaut, namespaces should always match folder names - I have no exceptions for that rule. So the namespaces are feature-oriented too.

08 May 2010

The only exception I do with this is for Silverlight projects when I've to create links. As a rule of thumb all files are shared (linked) except files on the Server or Silverlight folders. For example, ViewModels and Views will be in the same folder (for that particular feature), but the DataContracts, ServiceContracts and other shared files for that feature are in a different folder.

For View/ViewModels you could also nest them, similar to the way VS nests Views and Codebehind files.

09 May 2010

Awesome idea Paul.

The 'Areas' functionality in ASP.NET MVC uses a similar concept, but I like the idea of applying vertical layering to the whole project.

22 May 2010

Interesting approach.

Actually, it suggests that the way to list items in Solution Explorer should not be neccesarrily on the basis of file location, but perhaps could have its own sorting system implemented; where you could then add "tags" or "categories" to files (held in metadata in the .sln file). Then the tags could be rendered as a tree or some similar strategy.

I suppose this could be done with a vs add-in, if one was so inclined.

26 May 2010

Nice post. I absolutely agree with grouping files that are functionally cohesive. It just makes much more sense than organising them based on their type.

27 May 2010

Good to see this going public. I have been using that style for the last couple of years in my composite projects. Once you have more than a just a hand full of views/models it becomes a complete mess using the "old" way. I like to think of the "old" way as grouping by coincidence, as opposed to grouping by cohesion.

@Silky: I dont think there is any need to tag of categorise anything.

@Paul: I would go one step further an move the Services stuff out of the project and consume it via a shared interface. Allows for better integration and less coupling at coding time. Will throw up a (long over due) post about soon.

28 May 2010

@Lee: Pretty odd statement. Completely devoid of any logic.

16 Jun 2010

Is this done in the UI part of the project only, or does this reflect domain/data layer as well?

16 Jun 2010

Hi Robert,

The domain model generally isn't specific to a feature, but underpins a set of features, so I usually keep it together. Since repositories serve the aggregate roots of the domain, they also wouldn't be segmented by features. That said, I would try to split different contextual boundaries of the domain using namespaces.

Having a gateway class per feature, or at least command/query handlers or services per feature, which work over the domain, has worked well for me.