Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,125 | Comments: 45,493

filter by tags archive

Limit your abstractionsYou only get six to a dozen in the entire app

time to read 4 min | 630 words

Let us take a look at another part of the DDD sample application. This time, the booking service.


One thing that is really glaring at me is that we have a mix of both commands and queries in this interface. Also, just consider the name. It is a Booking service, but it doesn’t actually seem to have an actual meaning in the application itself. There is no entity named Booking, and except for the BookNewCargo, there is no mention of booking anywhere in the application.

You know what, maybe there is logic in the RequestPossibleRoutesForCargo that is actually meaningful beyond a simple query. Such as charging the customer for the calculation, or reserving space on the route that we selected, etc.

At any rate, I don’t like this service at all. In fact, any time that you have something that is called XyzService, you ought to suspect it.  Let me take this one step further. I don’t like that it is an interface, and I don’t like how it is composed. I don’t see it as an independent thing. Going further than that, I don’t really see a reason why we would need an interface here. You might have noticed what the title of this series is. I want to limit abstraction, and IBookingService is an abstraction, one that I don’t see any value in.

In most applications, I like to have a very small number of abstractions. Usually in the order of half a dozen to a dozen (top!). I usually think about them like this:

  1. Controllers
  3. Entities
  4. Commands
  5. Tasks
  6. Events
  7. Queries

Sometimes you have a few more, but those are the major ones. Controllers,Views and Entities are fairly obvious, I would imagine. But what about the rest?

Command is a package “thing” that happen immediately. Tasks are very like commands, except that they don’t have an explicit execution date and Events allow you to build smarts into the system. We have already seen how I handle events, in the previous posts in this series. And Queries should be fairly obvious as well.

Let us tackle Commands now, and then explain why they are bad later on.

When I said that I don’t want abstractions, I meant that I don’t want an interface and an implementation, and some way to connect the two, etc. I don’t really see a lot of value in that for the common case.

Let us break it apart into commands, which would give us this:

public class AssignCargoToRoute : Command
  public Itinerary Itinerary { get;set; }
  TrackingId TrackingId { get;set; }

  public override void Execute()

public class BookNewCargo : Command
  public UnLocode Origin {get;set;}
  public UnLocode Destination { get;set; }
  public DateTime ArrivalDeadline {get;set;}

  public TrackingId Result {get;set;}
  public override void Execute()

I am very fond in having a base class for those types of things. The base class provide me with the infrastructure support for the command in question.

In my next post, I’ll go over why I don’t like this approach, and discuss other ways to structure things so it is more suitable for an actual application.

More posts in "Limit your abstractions" series:

  1. (22 Feb 2012) And how do you handle testing?
  2. (21 Feb 2012) The key is in the infrastructure…
  3. (20 Feb 2012) Refactoring toward reduced abstractions
  4. (16 Feb 2012) So what is the whole big deal about?
  5. (15 Feb 2012) All cookies looks the same to the cookie cutter
  6. (14 Feb 2012) Commands vs. Tasks, did you forget the workflow?
  7. (13 Feb 2012) You only get six to a dozen in the entire app
  8. (10 Feb 2012) Application Events–event processing and RX
  9. (09 Feb 2012) Application Events–Proposed Solution #2–Cohesion
  10. (07 Feb 2012) Application Events–Proposed Solution #1
  11. (06 Feb 2012) Application Events–what about change?
  12. (03 Feb 2012) Application Events–the wrong way
  13. (02 Feb 2012) Analyzing a DDD application


Omer Katz

"In most applications, I like to have a very small number of abstractions. Usually in the order of half a dozen to a dozen (top!). I usually thing about them like this:" You meant think and not thing.

Omer Mor

You're absolutely right. IBookingService is a terrible interface. It should have been called IBookingManager ! :-)

Khalid Abuhakmeh

Would you qualify any use of an interface as an abstraction that goes against your six to twelve count?

For example, if I use IDocumentSession or IQueryable instead of the concrete implementation in my code, did I just use one up? Or is it more about creating wrapper classes for encapsulating logic?


Nice one. I think this post will be a game changer for a lot of people.

Ayende Rahien

Khalid, No, those aren't your own things, they belong to the infrastructure.

Dan Vanderboom

I agree with the general premise. Having a small number of the right kind of abstractions is important for maintaining the coherence of code organization.

Events provide endpoints for reactive code to attach Tasks or Commands as responses.

You refer to SL/WPF-style Commands, but what do you mean by Tasks? TPL Tasks?

Commands packaged as separate classes are often too granular, but delegate commands are possible as well. I also occasionally invoke remote commands on a server in the same way I invoke queries.

What drives me nuts is the inconsistency of seeing XyzService alongside AbcManager, etc.

Chris Wright

It's a tad ambiguous whether you mean to say "I don't like this approach that I just outlined with the Command base class and various implementations; and I'll discuss why in my next post", or "I don't like the approach that the sample application took; and I'll discuss in further detail why I dislike this approach in my next post".


I second Chris Wright. Can you please clarify Oren!


Given a standard ASP.NET MVC website would you consider Custom ActionFilters, ActionResults, HtmlHelpers, ModelBinders, Validators, Route Constraints etc in your list of abstractions or are they just infrastructure? If they are just infrastructure how are they different from most the things you listed?

Ayende Rahien

Betty, No, they are all infrastructure. If you have many of them, that indicates a problem with either bad infrastructure or wrong headed use of it.

Daniel Lang

Oren, I totally agree with except for the testing thing. I often find myself introducing abstractions and interfaces just for testing purposes, so that I can stub and mock them out in my tests.

What does that mean? Do I structure my code the wrong way? I'm absolutely sure that I don't generally test too much, so I guess I probably test the wrong things or have my code layed out wrong.

Ayende Rahien

Daniel, Yes, you are doing it wrong :-) You don't need all of that for testing, I am actually going to touch testing specifically in a later post

Andrey Shchekin

How would you actually create commands though (in a system that uses dependency injection)?

Ayende Rahien

Andrey, I wouldn't :-) I am discussing this in detail in a future post.


I presume you are happy to allow additional abstractions for strategies identified within the system?

Ayende Rahien

hammerip , I am not sure that I am following the question


Sorry, badly worded. I mean if you need to use strategy pattern, e.g. ICargoRouteCalculator

Comment preview

Comments have been closed on this topic.


  1. RavenDB 3.5 whirl wind tour: I'll have the 3+1 goodies to go, please - 2 days from now
  2. The design of RavenDB 4.0: Voron has a one track mind - 3 days from now
  3. RavenDB 3.5 whirl wind tour: Digging deep into the internals - 4 days from now
  4. The design of RavenDB 4.0: Separation of indexes and documents - 5 days from now
  5. RavenDB 3.5 whirl wind tour: Deeper insights to indexing - 6 days from now

And 10 more posts are pending...

There are posts all the way to May 30, 2016


  1. The design of RavenDB 4.0 (14):
    05 May 2016 - Physically segregating collections
  2. RavenDB 3.5 whirl wind tour (14):
    04 May 2016 - I’ll find who is taking my I/O bandwidth and they SHALL pay
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats