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.

image

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
  2. Views
  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