Feature Oriented project structure

When setting up a project in whichever framework or language you choose one of the most important and longest lasting decisions will be how you structure your project. Recently I've set up projects by feature rather than a more traditionally adopted structure.

Common project structure

A common project structure, for example a Xamarin app targeting iOS and Android and using a repository pattern would look something like the following:

  MyFunkyApp.sln
    MyFunkyApp.iOS.csproj
    
    MyFunkyApp.Droid.csproj
    
    MyFunkyApp.Core.csproj
      Providers/
        Interfaces/
          IEmailProvider.cs
        EmailProvider.cs
        
      Repositories/
        Interfaces/
          ICustomerRepository.cs
          IOrderRepository.cs
          
        CustomerRespository.cs
        OrderRepository.cs
        
    MyFunkyApp.Domain.csproj
      Customer.cs
      Order.cs
      LineItem.cs
      Attachment.cs
      
    MyFunkyApp.UnitTests.csproj
      Core/
        Providers/
          EmailProviderTests.cs
          
      Domain/
        CustomerTests.cs

Now let's compare this to a feature orientated project structure.

Feature Oriented project structure

  MyFunkyApp.sln
    MyFunkyApp.iOS.csproj
    
    MyFunkyApp.Droid.csproj

    MyFunkyApp.Features.csproj
      Email/
        EmailProvider.cs
        Attachment.cs
        EmailProviderTests.cs
        IEmailProvider.cs
        
      Orders/          
        Customer.cs
        CustomerRespository.cs
        ICustomerRepository.cs
        IOrderRepository.cs
        LineItem.cs        
        Order.cs        
        OrderRepository.cs        

The output projects (in my case the iOS and Android apps) stay the same but classes are grouped by their function or feature rather than their type.

Why?

So let's cut to the chase, why am I advocating this project structure?

  • No more searching for that darn class! - the efficiency and concentration advantage of not having to search for a class file but having it right there next to the class file you're working on helps maintain my concentration and work more efficiently.
  • Clearer context and inter-dependence - by grouping classes by features you can more easily see what makes up each feature in your code and how those classes depend on each other
  • Eaier to see what's covered by tests - by having your test files there alongside the classes they're covering you can clearly see what's covered by your tests (hopefully everything!) and what's missing, still to be added.

Why not?

Though I believe there are some clear advantages to using a feature oriented project structure there are some disadvantages and pitfalls to watch out for:

  • Are you comfortable shipping unit tests in production code? Though there are workarounds (hello #if DEBUG) it's something to be aware of.
  • Will your domain classes be shipped separately? The obvious advantage of using separate csprojs and producing separate DLLs is to produce multiple outputs from a project that can be used elsewhere within the organisation, for example in a frontend app and then a separately built admin site for fulfilling MyFunkyApp's orders.
  • By extension of including a lot of your files in the same project and therefore the same DLL you're negating the use of the internal access modifier.

In conclusion

For most projects a simpler feature oriented approach seems like it makes sense, I'll continue to experiment with it and push the boundaries of the type of project it works for and the type of project it's less successful on. Check back to see how I get on!