Saturday, May 31, 2008

Domain Services in Domain Driven Design (DDD)

This post is part of a series I am writing on Domain Driven Design (DDD).

"A SERVICE is an operation offered as an interface that stands alone in the model, without encapsulating state, as ENTITIES and VALUE OBJECTS do." [Evans 2003]

The above defines what a Domain Service is. Any behaviour, operation or activity that cannot logically fit into an Object is a good candidate for being exposed as a service. However the important thing to note here is that the Service being exposed should represent a domain concept. This ensures you don't get carried away and create tons of services with very less entities and vo's.


Rules to be followed by Domain Services

A domain service has to abide by only 2 cardinal principles

  1. It has to be stateless
  2. It should have some meaning in domain e.g. AccountTransferService, AdjustOrderService etc

Identifying Domain Services


I carve out a service in any one of the following conditions
  1. The concept behind an entity/vo does not lend itself to the activity being modelled. If by adding the activity concerned the meaning of the entity/vo is diluted, the activity is better off exposed as a service. In other words, if there is no obvious owner expose behaviour as a service.

  2. When the activity being modelled spans across different entities/vo's that are not part of same aggregate, expose a domain service that co-ordinates the activity across the many objects involved.

    For e.g. when adjusting or modifying an existing order, the order, payment and delivery entities have to be updated. I find it more easier and intuitive to model this as a service rather than have all logic in Order.adjust method. To access and modify Delivery/Payment entities, Order entity may have to do a deep object graph traversal. The order entity may not always be qualified to handle this traversal. The OrderAdjustService however, would use a repository to look up all concerned entities and co-ordinate the adjust method among them. This ensures all domain logic of how adjusts happen is still contained within the entities and the service just acts as an orchestrator.

    In fact I like to have an Order.adjust method that the UI/Application layer calls. This Order.adjust method would then call the OrderAdjustService passing in required info. This provides a clean interface and separation of concerns.

  3. If a certain domain logic is applicable across multiple entities and you have to work with a single inheritance model (using java for example), then the logic can be exposed as a service.

    For e.g. multiple entities like Order, Shipment etc need to expose MarketPrice behaviour. The logic to create a price includes looking up real time market prices and currency conversion rates and then calculating the price. A MarketPrice service can encapsulates this logic. The entities should be able to refer the MarketPrice service and delegate all MarketPrice related calls to that service.

    I use this when a ValueObject cannot suffice. In this case there were no fields specific to market price in entities and these were runtime generated and consumed values.

    There is a good description of this technique here. However this is not commonly used.

FAQs on Services

  1. Are'nt Services bad and should'nt we use all objects as per OO ?

    Yes, Services tend to stand orthogonal to Object Oriented Design. Services are not always bad since its far worse to force fit a behaviour into some entity/vo just to be more OO compliant. It messes up the class by distorting its conceptual clarity and makes it harder to understand.

    There is a huge tendency in the modelling world to use excessive number of services. It's easy to stop fitting behaviour to appropriate class and instead stick them into meaningless services. This is when services become bad.


  2. What is an application service and how is it different from domain service ?

    An application service layer defines a set of services that act as boundary to the domain layer. Any interaction with the domain layer passes through these application services. The application services interface with domain and infrastructure layers to get the job done. The domain layer also can talk to infrastructure layer.

    Some excellent point about the distinction between the two can be found here and here.


  3. Can an application service directly talk to a domain service ?

    It depends on your preference on whether you want an explicit entity to own the operation or not.

    However one thing to be clear is that application service layer and domain service layer cannot be combined into one layer. It has been covered with good detail and explanations here and I will not go into them.

    My first take on this was that there is no reason for an application service to talk to domain service. However a colleague of mine had the view that if one service is going to call the other, then application service was not adding much value and it could pick up some of the work that domain service was doing.

    For e.g. our previous OrderAdjustService looks up a bunch of entities and calls appropriate methods on them. We got into an argument that if, this was all it did and had no special logic of its own then it may as well become an application service. However the methods being invoked in all cases were not exposed to application layer. So it was in this context we created a Order.adjust() method that delegated the call to OrderAdjust Service. Having Order.adjust() has an advantage that it makes Order own the adjust operation. If you are not particular about it, you could call OrderAdjustService from application service layer.

Domain services are an important part of Domain Driven Design since they give both flexibility and clarity to the model. As with all good things, use it with moderation !


Technorati Tags: ,

Subscribe to comments for this post

Sunday, May 18, 2008

Value Objects in DDD - Part 2 - Creating VO's using Hibernate

This post is part of a series I am writing on Domain Driven Design (DDD).

In my previous post on Value Objects I had mentioned that Value Objects can contain references to other entities and value objects.

I will show how to use Hibernate's features to define and use Value Objects. For illustration purposes I have taken a simple VO. If you look at any price label on any product, there are 2 consituents to it - a numerical price part and a alphabetical currency part. When paying for product, you end up multiplying the numerical part with the conversion rate of currency you pay to cashier.

Building from this example, I have an Order entity which has a Price value object. The price value object contains a reference to the Currency entity.

Order contains Price; Price refers a Currency

Order.java looks like

public class Order {
    
    private long orderId;    
    private String name;    
    private long quantity;    
    private Price price; //This is a reference to a ValueObject
    
    public Order(){}
    
    public Order(String name, long quantity, Price price) {
        this.name = name;
        this.quantity = quantity;
        this.price = price;
    }
    
    public double getUSDValue() {
        return price.getUSDAmount();
    }
}


Definition of Price Value Object

Price is a value object. Notice the lack of any apparent identity columns (Primary keys).

public class Price {
    private long amount;
    private Currency amountCurrency; //This is a reference to an Entity

    public Price() {}
    public Price(long amount, Currency amtCurrency) {
        this.amount = amount;
        this.amountCurrency = amtCurrency;
    }

    public double getUSDAmount() {
        return this.amount * this.amountCurrency.getUsdConvRate();
    }
}


Mapping ValueObjects in hbm files

All details of how to make Hibernate treat price as a value object is added to the hbm mapping files.


<hibernate-mapping schema="shop" default-access="field">

    <class name="org.dddtest.entities.Order" table="ORDERS">
        <id name="orderId" column="order_id">
            <generator class="increment" />
        </id>

        <property name="name"><column name="NAME" /></property>
        <property name="quantity"><column name="QTY" /></property>


        <component name="price" class="org.dddtest.entities.Price">
            <property name="amount"><column name="amount" /></property>
            <many-to-one name="amountCurrency" column="curr_id"
                class="org.dddtest.entities.Currency" not-null="true" />
        </component>


    </class>
</hibernate-mapping>


From the above mapping file the two things of interest are
  1. default-access="field"
  2. Component tag
The field access alleviates the need to expose getters/setters on the entities thus ensuring the class is well encapsulated. This was dealt in the post on entities.

A component is an object that is treated as a value type and not as an entity. This means that the fields of the component/value class would be persisted as part of some entity. In our case, fields of Price were persisted in Order entity/table since the Order owns all values in Price. Hibernate when creating the Order, creates a Price object and maps the values to it. This price is set into the order.

A nice feature with Hibernate components is that the same Price VO can be used with any other entity as well, since the owning entity (Order, XYZ etc) can always override mappings for Price fields. Also one component can contain another component within itself !

Using Components, any combination like Entity -> VO -> Entity or Entity -> VO -> VO etc can be created. This gives us powerful abstraction abilities to keep grouping fields into powerful domain objects and not be bound/limited by data model.



Technorati Tags: , ,

Subscribe to comments for this post

Thursday, May 15, 2008

Value Objects in Domain Driven Design

This post is part of a series I am writing on Domain Driven Design (DDD).

"An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT." [Evans 2003]

Basically it means that a Value Object describes the state or characteristics of an Entity, but it has no identity of its own.

Creating Value Objects

Carving out value objects from entities is quite an art. Those fields of an entity, whose values are what is important, can be moved into separate objects from entity. Value Objects can contain references to other entities and value objects.

When is a class considered as an entity and when as a value object ? This discussion explains it better than anything i have read elsewhere.

If you had looked at my previous post on entities, I had said that the entity should be stripped to its bare minimum fields. So if you were wondering what happens to the rest of the fields the answer is that, they move into value objects.

To validate if a VO created is good. Try swapping one value object with another, containing same values, and if the entity does not care and works as usual, that is sign of a good value object.

Create VO by grouping together related fields

  1. Group related fields of an entity together. Related fields are those where
      • A field change, triggers changes in multiple other fields (or)
      • A Group of fields have a collective/shared meaning
  2. Identify all behaviour which is based around these fields
  3. Move the related fields and its behaviour into its own class
Always ensure that the class you created has some meaning in the domain. Never randomly group fields together for sake of creating a value object.

Create VO for fields with format restrictions
  1. Identify fields in an entity, which have restrictions on values it can hold. E.g price field can be a BigDecimal with restriction that it should have 4 digit accuracy after decimal point or zipcode field has to be of a specific format
  2. Move such fields into separate classes with methods that enforce the restriction.
  3. Add methods that add to concept represented by class. For e.g we can add a currency code to price and the price object can convert its value from the default currency to USD/EUR/INR etc.
This came in quite handy for us. We used JPA with hibernate and one day we decided to make from all prices which were long's to BigDecimal's. Since Price was its own class, changes were limited to Price class alone.

Create VO for business method arguments/return types

I picked up this tip from this video on domain value objects. The presenter says that a good starting point to identify new VO's would be to look at args and return types of domain methods. The argument here is that in most cases they are not just DTO's/some primitive type, but they represent something in the domain.

Tip: Create VO's when you define the entities. If you find that a particular VO is not adding much value, you could always fold it back into the owning entity. Never defer defining entities, since its a vey manual and painful effort. (Imagine changing all annotations, methods etc to use new VO).

Fine-Tuning the VO

Some of the interesting scenarios I faced when defining VO's

1) How to handle when, multiple entities define and use a common set of fields with some field variations ?

In the example scenario defined here, all entities, order, box and container have quantity related fields. All three have open and filled quantities, but the Container object has a maximum allowed quantity and threshold quantity. So a hierarchy of VO's was created

QuantityVO <------ LimitQuantityVO. All common fields went into the base class - QuantityVO and rest of fields went into LimitQuantityVO.

2) Do all value objects have to be immutable?

If VO's are mutable, it would make it harder to understand/control changes to the VO. It also means
the VO 's methods cannot change its own state. So any mutation method on VO has to return an instance of itself with updated values and the caller needs to know how to set this VO back to the owning entity. I don't like the idea of the caller, tracking if a state change occurred or not, and then calling the corresponding update on the entity.

If your VO's rarely change, make them immutable. But making them mutable would save you lot of trouble when coding. So its elegancy vs practicality. I have done both and don't have a strong preference for one over the other. Make your choice based on which tradeoffs you can live with.

Part-2 of this post talks about how to implement VO's using java and hibernate and can be found here.



Technorati Tags: ,

Subscribe to comments for this post

Sunday, May 11, 2008

Layers in DDD

This post is part of a series I am writing on Domain Driven Design (DDD).


Domain Driven Design promotes a layered design with the following layers

  1. User Interface (Presentation Layer) : Displays the information to the user and responds to user commands
  2. Application Layer: Defines the services provided by the application and directs the user commands to the domain layer that actually does the work. This layer does not contain any business rules. However its not simply a facade since it can be responsible for some high level orchestration. This orchestration adds value to this layer.
  3. Domain Layer: All the business processes/rules in the problem domain is contained here.
  4. Infrastructure and Technical Services Layer: Object persistence, messaging and other such technical services needed by the above layers. Will not contain any business logic but will be home to all framework code etc.

Subscribe to comments for this post

Entities in Domain Driven Design (DDD)

This post is part of a series I am writing on Domain Driven Design (DDD).


"An Entity is an Object that represents something with continuity and identity. An entity is tracked through different states and implementations."

This is the definition of an entity according to DDD. So roughly, an entity is any object that is persisted in the database. Any class that is not stored in DB is not an entity.

IMHO an entity is the single most important constituent of DDD, simply because a vast majority of business logic would be owned by the entity. I use the term 'own' broadly to encompass all logic that is triggered by an entity but not necessarily present in the entity.

Creating an Entity

A good entity has to be both, lean and powerful. A normal entity typically has a number of attributes. To make this entity lean and powerful,

  1. Strip the entity to contain only its identifier attributes.
  2. Then add methods which are core to the concept/idea represented by that entity.
  3. Now add only attributes needed by these core set of methods.
Note: All other attributes can either be other entities or value objects. When such smaller entities are made out of a larger one, a tree of entities with one root entity governing the lifecycles of all other entities, is obtained. This is called an aggregate.

This is all that there is to an entity.

Sample Scenario for discussion

The following example will be used for discussion.

A Container contains multiple boxes, each of which contain the same product. A CustomerOrder contains multiple boxes, one of each kind of product.

Customer order (1) ---------> (n) Box
Container (1) ---------> (n) Box

So a customer order indirectly refers to (n) Containers where n is the number of distinct products in the order.

Users are allowed to add/remove a new box to/from the order. Duplicate boxes for same customer order are merged.

Fine-tuning the Entity

To fine-tune the raw entity we have, we add in some more rules. These rules were based upon commonly encountered issues we faced. The main issues/rules are summarized below

1) Exposing Getters/Setters

Exposing attributes publicly, leads to a loss of encapsulation. No other class should be allowed to change the state of an entity, other than that entity itself. Other entities/classes can only trigger a business method and during execution of that business method,the entity itself mutates its state.

Bottom line: Never expose getters/setters in the entities.

Tip: If you use hibernate use field access to avoid setters.

2) Can Entities be exposed to application services ?

Application Layer sits above the domain layer. UI talks to this layer which orchestrates the call with classes in the domain layer. The straightforward answer is yes, the entities have to be exposed to application services so that they can be called when appropriate events are triggered in UI.

However the tricky part is whether the application services has access to all methods in the entity. In my experience, every entity has a bunch of granular methods that are exposed to other entities so that a complex workflow can be built from them. In the example above, removing a box from a container is a method exposed on the container. Typically this will be called by Order when a product is removed from it. But is Container.removeBox a method that needs to be exposed to application tier ? No.

Order needs access to this method but OrderApplicationService does not. When using java, a couple of alternatives possible are

Make method as package private provided Order and Container are in same package.
Have an interface over Container and let OrderApplicationService use only methods specified in the interface.

I prefer using alternative 2, since then, this method can be used throughout my domain layer but it wont be accessible outside of it. This also alleviates the needs to dump all entities into same package.

Bottom line: Entities have to be exposed but not all of its methods have to be.

Tip: Expose only relevant methods from entity to Application service layer

3) If an Entity's core method needs access to data in Db, can it hold a reference to DAOs ?

Yes. There is no harm in an entity using DAO's to look up data from DB. If a subset of some large set of data is to be updated, looking up data to modify is more performant than loading the entire set using the ORMs hydration and then iterating through the entire set.

This question has been discussed in great detail in the DDD forums and can be found here, here and here.

Tip: If using Spring 2.x use @Configurable notation to inject DAO reference into entities (or) if using Hibernate, inject the dependency using the onLoad method in Interceptor. More ways of injecting into Entities is detailed here.

4) Can an entity use domain services ?

Domain services contain methods that do not logically belong in one entity. The only difference between these services and application services is that domain services have access to all domain objects and all operations on them. In contrast application services can see only operations exposed by interface they use.

As with DAOs there is no harm in an entity using domain services. When looking at aggregates we will look at are some interesting scenarios where domain services are used.

5) Few entities need to access properties on another entity, during some of its operations. How to control this.

See 1, 2 above. No direct property access is to be allowed. Expose business methods that can mutate state, which, other entities can call.

There are 2 variants of which entities need access to which method
  • Entities belonging to same aggregate - Typically these are all part of same package, so expose methods as package private methods.
  • Entities from different aggregates - Expose the methods as public but ensure these methods are not present in Interface exposed to application layer
Tip: Expose methods using the strictest access control. You will never go wrong with this.

6) What kind of Entity methods should be exposed to Application layer?

Application layer typically should not act as a low-level orchestrator. It should not be responsible for calling a sequence of fine grained methods in correct sequence. It should only call a few coarse grained methods. These coarse grained methods should hide the complex work flow from the application layer.

Bottom line: Expose only coarse grained methods.

A typical rule of thumb that we used successfully to define coarse grained is - "A method is coarse grained, if it returns leaving the domain objects in a consistent and persistable state". Meaning all entities involved should be left in a valid state i.e. all mandatory params are set, all relationships are valid. The entities involved can be persisted as-is without any changes.

For e.g. in our example above,Container.removeBox is not a coarse grained method since it leaves the removed box without any valid owner. However methods like Container.moveBoxTo(Container newOwner) is valid since all entities are left with valid relationships.




Technorati Tags: ,

Subscribe to comments for this post

Friday, May 09, 2008

A series on Domain Driven Design

In a couple of previous posts I had talked about anemic domain model that were caused by reverse engineering hibernate entities.

The powers that be, took a good interest in all of this and I was able to wrangle this into our schedule. My mandate was simple enough - find a better way to design.

I did a quick round of the top OO guidelines,

  1. Streamlined Object Modelling,
  2. Responsibility Driven Design and
  3. Domain Driven Design.
It really helped my company had a oreilly-safari account since I could skim through all of these books online without having to hunt around for a physical copy.

Of the three alternatives, Streamlined Object Modelling focussed on trying to reduce the design as applying a set of predefined patterns and templates. I felt there was nothing really new and revolutionary in Responsibility driven design. I liked Domain Driven Design since it focussed the whole design process around the domain, something which made a lot of sense.

In the book Domain Driven Design, Eric Evans introduces the basic concepts and moves on to explain the various building blocks and the refactorings that have to be undertaken.

In short term it's easier to stick to a very restrictive set of rules but as the pressure start mounting and you have team churn, people tend to relax their interpretation of the guidelines. So based on my experiences working on multi year projects, I have my own take on what works/not in long term. So I built on top of Eric's guidelines to create my own flavour/take on applying DDD in a contemporary project.

I'd be writing a series of posts on how to apply DDD with detailed instructions for each individual building block. I'll also add my experiences on what worked and what did'nt and some best practices that I came across. The building blocks, I intend to cover would be
If you would like me to touch on anything in detail, let me know.



Technorati Tags: ,

Subscribe to comments for this post

Saturday, May 03, 2008

Spring-DM and OSGi Service Proxy

I've been evaluating spring-dm over equinox for some time now. If your project already has invested in Spring then Spring-DM provides support for injecting dependencies across bundles and manages tx across bundle boundaries.

However the main feature of Spring-DM that I find actually useful is Springs support for OSGi services. Spring adds support for declarative publishing of services and consuming them. Any spring created bean can be published to the service registry using the xml tag osgi:service. Any service from the service registry can be references using the xml tag osgi:reference.

When you refer a service using osgi:reference, spring-dm creates a proxy over the service and injects the proxy into your code. This proxy protects the users of the service from the lifecycle of the service. So if the underlying service goes down, your code need not be aware that it should look up and bind to a new service.

The proxy is either a jdk dynamic proxy or a cglib proxy depending on whether the service has an interface or not. This proxy has a number of interceptors like transaction etc. Imagine the underlying service goes down, the next call to the proxy would trigger the proxy to check if service is up. If service is down, the proxy will block the call for a 'timeout' period at end of which a service unavailable exception is thrown. When a new service that matches the service for which the proxy is created, is registered, this proxy binds to that service and sends all queued requests to that proxy. Voila, your code is blissfully unaware a service went down and came up again.

However things are not all rosy. A couple of issues i faced

1) If the bundle that has the proxies is refreshed, the currently executing method throws an exception with message "service proxy destroyed". There is no way around this. Any new request that comes through would work fine.
2) We cannot add a custom interceptor to spring created proxy since it says configuration is frozen. So I had to create a proxy on top of springs proxy to add my custom interceptor. This is a fairly common case and should have been possible.

PS: The custom interceptor was created to transparently handle the service proxy destroyed issue.

Tags: ,

Subscribe to comments for this post

 
Clicky Web Analytics