Organize by Feature

Organize by FeatureThis post is about how I organize by feature.  Features being my commands and queries.

If you have not familiar with CQRS, it may be worth a look at some of my other posts to get some Context.

 Layers

What I found interesting was as I moved from thinking about layers to thinking about features and vertical slices, I didn’t immediately organize my code that way.  I would still organize my code by what it represented (eg layer).

My project structure would look something like this:

By Layer

In the example above, for a Web Api type endpoint for returning data regarding a customer, there are 3 files I would have open:

  • Controllers/CustomerController.cs
  • Queries/GetCustomer.cs
  • ViewModels/CustomerViewModel.cs

For commands, the list is slightly reduced to:

  • Controllers/CustomersController.cs
  • Commands/ChangeCustomerPricingLevelc.s

Why?

I was so used to organizing code by layer, but there was no real reason to.  Simply out of habit.

One reason was also the ASP.NET Routing convention.  I always used routes by naming convention rather than by using the Route attribute. I’m not a particular fan of Attributes, but that’s another discussion.

Luckily in NancyFX you define your routes a bit different in the Constructor of your Module (similar to Controller).

Organize by Feature

There is nothing stopping us from taking all relevant classes associated to a command or query and adding them to all one file.  This provides a really easy way to view all the relevant code where you would need to make change.

By organizing by feature, our structure could now look like:

byfeature

Single File

For our ChangeCustomerPricing level command, we can now have the our Module (Controller), Command, Handler all within the same file for easy access and modification.

My convention has been to add them all to the same namspace.  The namespace being the name of the feature.

Our CustomerModel.cs and all other models that may cut across multiple queries or commands will still be organized by Folder.

If we end up adding additional functionality to a command or query, say Validation or Authorization, we can do so in the appropriate feature file.

Tests

One complaint I still have is not being able to have Tests in a very accessible way since they are in a separate test project.  Resharpers “Show Covering Tests”is an easier way to navigate but I’m still looking for something more.

Comments

I’d love to hear how you organize by feature or any other insights.  Please share in the comments below or on twitter.


Related Posts

14 thoughts to “Organize by Feature”

    1. Why isn’t it being used more? Good question!

      From my own experiences, I was so used to the unfortunate state of “Layer All The Things” that I was accustomed to organizing my code that way. And as mentioned, although I started coding with less layers, I still organized that way out of habit, without any reason.

    2. I love this approach. Where I worked we actually designed an entire
      API with a single Web API controller that would simply dispatch the
      requests through the MediatR pipeline using the Json-Rpc 2.0 format.
      Worked amazingly at getting rid of boilerplate. The angular 1.0
      application simply called the endpoint with QueryProducts, GetProduct,
      SaveProduct, etc. We had a T4 that would go through the solution and
      automatically create a javascript file with a function for each
      Command/Query it found based on interfaces. We ended up creating each
      Command as a separate file in the project with the Handler and Response
      types as nested classes. The team absolutely loved the architecture. One
      class in, one class out, everything together.

      // GetProduct.cs (not real code)
      public class GetProduct : IRequest
      {
      public int Id { get; set; }

      public class Product
      {
      public int Id { get; set; }
      public string Name { get; set; }
      };

      internal class Handler : IRequestHandler
      {
      private DbContext _db;

      public Handler(DbContext db)
      {
      _db = db;
      }

      public Product Handle(GetProduct cmd)
      {
      var product = _db.Database.SqlQuery(“SELECT * FROM Product WHERE Id={0}”, cmd.Id).Single();
      return Mapper.Map(product, new Product());
      }
      };
      };

      1. Thanks for the reply. I generally create an endpoint for each command/query because almost all the time, the URI contains information I need to further populate the command/query.

        Eg, /api/customers/123/orders/456

        This would likely map to say GetCustomerOrder query which I would create in the endpoint passing URI params into the query constructor.

        1. Here’s an example of how you pass parameters to a single /jsonrpc endpoint using JSON-RPC 2.0:

          {
          “method”: “GetProduct”,
          “params”: { “Id”: 1 }
          }

          {
          “method”: “QueryProducts”,
          “params”: { “InStock”:true, “Category”:”Shoes” }
          }

          I hope that example makes more sense of how a single endpoint could work.
          http://www.jsonrpc.org/specification

          Since we are mapping the json to command classes I took a little liberty with the spec so it accepts a json object, instead of an array as would map to a method’s parameters, but the rest is the same (and I guess we could’ve used an array of a single item).

          What we generated on the javascript side looked something like this:

          function ($scope, jsonrpcService) {
          jsonrpcService.GetProduct({Id:1}).then(x => $scope.products = x);
          }

        1. I really wish we had used TypeScript on that project, but there were some javascript purists on the team that didn’t want to go that route at the time for various reasons I don’t remember and I didn’t push it (I should have but we were under a tight deadline and nobody knew TypeScript 🙂 Our generator ultimately just created a jsonrpcService for Angular that had a method for each request and returned a promise with the results. TypeScript would have been awesome to have code completion on the model passed to each method and refactoring support, etc.

          I’ve also used MediatR with MVC similar to what you demonstrate in the article on a few smaller projects and loved how clean the controllers were! Here’s a little demo I showed to our local user group last year:
          https://raw.githubusercontent.com/Command-R/CommanderDemo/master/CommanderDemo.Web/Services/HomeController.cs

          1. Nice, I like the Send().

            I’ve been thinking auto generating the return query models in TypeScript as it would just save time to what our frontend guys have to make anyways. They already generate a TypeScript class/interface that is generally identical to what is returned from the API. This would just save the trouble. I’m just not sure what dangers lie ahead that I’m unaware of.

          2. Yeah, I think the unknown was probably one of the reasons we didn’t try TypeScript at the time, though I ultimately regretted it once we started refactoring stuff. If you decide to go that route, be sure to blog about it and let us know what you find 😉

Leave a Reply

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