Skip to content

Developing Features not Layers

Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.

Learn more about Software Architecture & Design.
Join thousands of developers getting weekly updates to increase your understanding of software architecture and design concepts.


Developing and thinking about features not layers is something I’ve moved towards over the last several years. I’ve mentioned it in several blog posts and I don’t think I ever explicitly created a post about it.

CQRS

The real enabler has been CQRS.  For those unfamiliar with CQRS or if you think it’s complicated, let me share a quote from Greg Young:
CQRS is simply the creation of two objects where there was previously only one. The separation occurs based upon whether the methods are a command or a query (the same definition that is used by Meyer in Command and Query Separation, a command is any method that mutates state and a query is any method that returns a value).
That’s it.  It’s nothing more complicated than that. I think where the confusion lies is a lot of articles, blog posts, etc where the content describes much more than CQRS. CQRS is not event sourcing. CQRS is not domain driven design. CQRS does not mean multiple data stores. CQRS does not mean using a service bus. CQRS does mean having eventual consistency. CQRS is simply the creation of two objects where there was previously only one.

Features vs Layers

For me a feature in the technical sense is a command or a query.  It could also be a combination of a few put together. I often have commands and queries dictate on their own how they are layered inside. This means that an individual command decides how it may do data access.  It may not be a shared concern between another command. For comparison, here’s is how I visualize the difference.

Layered

Layered In the layered approach, we separate and organize our code by technical concerns.  Authentication, Business Logic Layer (BLL) and Data Access Layer (DAL) are all contained.  Once layer invokes the next.

CQRS

Features not Layers The difference in our CQRS approach is that our Commands and Queries contain the layers of technical concerns within them.  We don’t have layers spanning over the entire application. This has some pretty profound implications in terms of being able to make different decisions in smaller units. As well the biggest distinction is we can start thinking, developing and organize our code by business concerns rather than technical concern.

Organizing by Feature

If you want to see how this works in practice, I’ve blogged about writing your code this way.  Most of my sample code uses the MediatR library for handling things like Commands and Queries. I recommend checking out my Fat Controller CQRS Diet: Vertical Slices post which demonstrates how to do this in ASP.NET MVC Core.

Testing

One aspect that took longer to come around was testing in the same manner. Meaning, I start writing tests and thinking about them around my features rather than layers within a feature. My new few series of posts will be around testing features / vertical slices. I love hearing your comments, questions and recommendations as it usually leads me down to other blog posts.  Please post a comments or on Twitter.

9 thoughts on “Developing Features not Layers”

  1. I believe it was you who introduced me to this idea a while back; anyway, I’ve since been won over and had a chance to start a new project building and organizing like this, and it just works so well. A whole class of annoyances don’t exist anymore – scrolling through all the views/controllers/js files just to find the single one you want, anyone?

    1. Thanks! I do think a layered approach is fading away more and more. I think the shift has been to first focus on use cases/business capabilities/features rather primary focus on the technical concerns.

Leave a Reply

Your email address will not be published. Required fields are marked *