Organizing Code by Feature using Vertical Slices

I’ve written about organizing code by feature and vertical slices instead of technical concern quite a bit on this blog. However, it doesn’t seem to have caught on as much as I’ve hoped. I’m always seeing posts on Twitter about this concept where people finally catch on and make the discovery.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

Technical Concern

I’ve always found it interesting that layers or technical concerns ended up being seemingly the most important thing when organizing code. I’m curious how this came to be. My guess is there are many reasons, but I think project template/scaffolding are a culprit.

If you create a brand new ASP.NET Core MVC application, you’re going to get a folder for Models, Views, and Controllers. By default everything is organized by technical concern.

What I find interesting about this is you usually end up having Models, Views, and Controllers all be a 1:1:1. Meaning a ViewModel is likely only used in one View which is only used in one Controller Action. If this is the case, why benefit does having these files/classes live in a project structure based on technical concern?

What does your application do?

I care about capabilities. Features. I care about what an application does.

When I’m looking at a project structure and see a ManageController file, that gives me no insights into features or capabilities that bring to the system. Looking at this project structure below, of course, it’s an e-commerce site, but what are the rich set of features it provides?

Change

When I was creating systems in layers, my pain point was making simple changes to an existing feature or adding a new feature.

Having to edit multiple files across multiple projects seemed absurd and cumbersome.

Data is flowing throw layers. When a user invokes a request, data must flow through all the layers to ultimately hit a database. The same occurs when you need to present data to a user.

In some situations, you could be editing more than 6 files for a simple change.

  • DataAccess/ShoppingCartModel.cs
  • DataAccess/ShoppingCartRepository.cs
  • BusinessLogic/ShoppingCartServices.cs
  • Controllers/ShoppingCartController.cs
  • ViewModels/ShoppingCartViewModel.cs
  • Views/ShoppingCart/View.cshtml

Organize Code by Feature

Organizing Code by Feature

When you start organizing code by feature you get the benefit of not having to jump around a codebase. Things that related in behavior are placed together. From the screenshot above, if you need to make a change to how products are added to a Shopping Cart, guess which file you’d be changing?

Layers in Features

I’m not saying to throw out layers. Layers ultimately live inside the vertical slice of a feature.

The way I like to describe this is think of your system/service as a cake that has multiple layers. Each layer represents a technical concern. If you have a data access layer, it controls all of the data access within that service/system.

Instead of it being application wide, cut a slice out of that cake.

You still have layers. You still have technical responsibilities, but you’ve made those boundaries to within the vertical slice of a feature.

Dependencies

The biggest win when you start organizing by feature, is now your dependencies are within the vertical slice. This allows you to manage dependencies per vertical slice.

If you wanted to move from EF6 to EF Core, you could do this one vertical slice at a time. It does not mean you have to re-write an entire data access layer to migrate from one to the other.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

More

Defining Service Boundaries by Splitting Entities

Defining Service Boundaries is a really important part of building a loosely coupled system, yet can often be difficult. Here’s one way of realizing where service boundaries lie but looking at Entities and the properties and how they relate.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

Catalog

For the purpose of this example, I’m going to use an e-commerce, distribution domain. Don’t worry too much if you don’t know distribution. At a high level, you buy products from vendors, store them in your warehouse, then sell them to customers.

Here’s what my Loosely Coupled Monolith demo application has as a solution structure.

Defining Service

There are 4 boundaries defined. Catalog, Purchasing, Sales, and Shipping.

In the Catalog project, we have a ProductModel that represents a product in our system.

Dependency

Because we have this singular model of a product in our Catalog boundary, you can imagine the rest of the system will need access to it. In the Sales boundary, we have a feature to create an Order, which requires the Price of a product we’re purchasing.

For Sales to get the Product Price, we’ve exposed an interface & implementation to return product info.

Now here’s an example of using the IProductQuery.GetProduct() in our PurchaseProduct feature in our Sales boundary.

Splitting Entities

Now, this might not seem like all that bad that Sales has to take a dependency on Catalog. But we want our boundaries to be as autonomous as possible.

The primary reason I think the above example occurs is that the notion of an entity must live only in one place. I call this the “Entity as a Service”. Where a particular boundary owns an entity and provides an API to manage that entity.

In my example in this post, the Catalog boundary owns the Product entity.

What’s better served, in my opinion, is to have each boundary own the behavior and data around the concept of an entity.

Sale Price

The Price property/field on our ProductModel has no bearing on any other property on that model. Meaning, the price does not affect the name of the product. The same goes for Cost and Quantity. If any of those properties were to change, it has no bearing on what the Price is.

If they have no bearing to each other, why are they in the same model?

In this case, Price on a Product actually belongs to the Sales boundary, not the Catalog.

We can have the same concept of a Product live in multiple boundaries.

The above example is the ProductModel I’ve created for the Sales Boundary and added it to our Entity Framework SalesDbContext.

Now the PurchaseProduct feature does not need a dependency on Catalog anymore.

Cost

Since we no longer need the Price in our Catalog ProductModel, I’ve removed it.

Now the Cost property is the next easy target. The likely same applies that our Purchasing boundary would be the owner of the Cost. It’s going to be managing this value with the Vendor/Manufacturer, so it would make sense that it would own the Cost of a Product.

Quantity

Quantity here is referring to the Quantity on Hand of the product in the warehouse. The logical next step would that the Quantity on Hand would be managed by an Inventory or Warehouse boundary.

Warehouses with physical goods can some times do what is called an Inventory Adjustment. This can happen for various reasons such as people actually counting the products, finding damaged product, etc. This is a way to update the system to reflect the actual quantity on hand.

What if we had business rule that stated that you cannot purchase a product if there is no quantity on hand?

How would you model this? Would Sales have to have a dependency on the Inventory/Warehouse context so it could get the latest Quantity on Hand of a product?

In the situations I’ve been in, they use a business function called Available to Promise. This is a value that is calculated by the quantity on hand in the warehouse, what has been purchased from vendors but not yet received, and what has been ordered.

Defining Service

With using asynchronous messaging/events, the Sales context would keep track of a products ATP value and use that for the business rule around when an Product can be ordered.

Defining Service Boundaries

Defining service boundaries is difficult. Start out by looking at your Entities and splitting them up by sharing the same concept of a Entity across multiple boundaries.

An Entity does NOT need to reside in one single boundary. As shown in this example, the concept of a Product can reside in many different boundaries, and each concept owning the data/behavior it owns.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Links

Why use MediatR? 3 reasons why and 1 reason not

Why use MediatR? 3 reasons why and 1 reason not

The MediatR library by Jimmy Bogard has become increasingly popular over recent years, and deservedly so. By its own definition, it’s a simple, unambitious mediator implementation in .NET. Why are so many developers using it? Why should you use MediatR? Here are 3 reasons why you should at least consider using it and one reason why shouldn’t.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this one regarding MediatR.

What is MediatR?

For those unfamiliar with MediatR library or the mediator pattern:

In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program’s running behavior.

Reason #1: Decoupling

Most examples I’ve seen using MediatR are with ASP.NET Core, but that doesn’t mean that’s the only framework where it’s useful. The point is decoupling your application code from the top-level framework code. Whatever code is actually in charge of executing your code.

Here’s a example using ASP.NET Core MVC

The point is creating a request object that you pass to MediatR which in turn invokes the correct Handler for that request object.

The PlaceOrderHandler has no references to any types or APIs in ASP.NET Core.

Reason #2: Application Requests

The reason why decoupling from top-level framework code such as ASP.NET Core can be important is to ask yourself: Is the application I’m creating an application or a web application?

There’s a difference between a web application and just an application.

An application can have many different inputs. Not all incoming requests are going to be via HTTP. There may be various ways that interact with your application.

For example, you could have recurring jobs that need to perform specific actions at a given time during the day. Or you may also have work that gets triggered from specific messages you’re picking up from a Message Broker.

There are a number of ways that you may want to invoke behaviors in your system that don’t initiate from an HTTP request.

In my example above with ASP.NET Core, we’re ultimately converting an HTTP request into an Application Request. That Application request is entirely decoupled from any specific top level framework and could be invoke from anywhere.

Using MediatR to create application requests to cross an integration boundary.

Reason #3: Request Pipelines

Once you start thinking about application requests, you can go deeper into creating a pipeline for those requests.

If you’re familiar with ASP.NET Core middleware, the purpose is to define a pipeline for an HTTP request.

You can create the same concept using MediatR behaviors. There are a few different ways to create them but here’s an example of a that implements the IPipelineBehavior

When you call mediator.Send() this behavior is called first prior to your primary handler (PlaceOrderHandler). The RequestHandlerDelegate which is a delegate to call PlaceOrderHandler. This allows us to do primary work before calling it or possibly even short-circuiting and not calling it at all, say if we had some validation issues.

This means you could have any number of pre-processors that can be run prior to the primary handler, or post-processors that can be run after.

Why use MediatR

This is incredibly powerful and allows you to separate different concerns related to a given application request.

Why Not?

The reason you may not want to use MediatR is simply that everything is done in-process. Meaning that wherever process is calling mediator.Send() is also the same process that is executing the relevant Handler for that request.

Udi Dahan the founder of NServiceBus posed this question on Twitter with my response.

Why use MediatR

With everything in-process, this becomes really apparent with Events/Notifications (MediatR calls them Notifications).

A notification can have zero or multiple handlers. However the execution of all the notification handlers are done all in the same process.

Why use MediatR

In the example above, if you publish a notification to MediatR, and there are 3 handlers for that notification, it will execute all 3. But what happens if one of them fails and throws an exception?

That exception will bubble up back to where you published the message via MediatR. How do you want to handle this? Can you re-publish that message again and have the handlers that succeeded run again? What if one of them was sending an email?

You want event/notification handlers to be run in independently in isolation. This is where out-of-process messaging comes in.

In this case, you might want to look at NServiceBus, Brighter, MassTransit, Rebus.

More

If you want more details on how MediatR works, I’ve talked and written about this in my Fat Controller CQRS Diet where I use MediatR as an example on how to decouple your application code from top-level framework code.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.