Monday, June 16, 2008

Domain Driven Design without AOP

Ramnivas Laddad, in this presentation during SpringOne, makes the assertion that "Domain Driven Design cannot be adequately implemented without help of AOP and DI".

I don't quite agree with this. I believe you can get by fine and do good DDD without using AOP.

According to the talk, AOP can be roughly used for the following purposes

  1. Dependency Injection in Domain entities and vo's
  2. Handling domain logic
  3. Handle Cross Cutting concerns
Of these, IMHO the only 'real' need for AOP is to handle cross cutting concerns like transaction management, auditing etc.

Dependency Injection without AOP

DI'ing services/policies/repositories into an Entity/VO can be done without using AOP in other simpler ways like
  1. Using callbacks methods like onLoad in Hibernate's Interceptor, which contains the injection logic based on the entity type. This is a slightly intrusive solution though.

    A better way is to have interfaces for each service/repository that is to be injected and making the entity implement the required interfaces.



    public interface OrderRepositoryAware {
         public void setRepository(OrderRepository orderRepo);
    }

    public interface CreditRatingAware {
         public void setCreditRatingSvc(CreditRatingSvc svc)
    }

    public class Order implements OrderRepositoryAware,CreditRatingAware { ... }

    public class DependencyInjectingInterceptor extends EmptyInterceptor {

         public boolean onLoad(Object entity,
            Serializable id,
            Object[] state,
            String[] propertyNames,
            Type[] types) {

              if(entity instanceof OrderRepositoryAware) {
                   ((OrderRepositoryAware) entity).setRepository(...);
              }
    ......

    }



    However the same logic needs to be replicated in Factory objects which creates new Entities. This is the drawback of this issue.


  2. Use a ServiceRegistry to get a reference to required service/repository etc. To unit test you just need to stub out ServiceRegistry.



    public class Order {
         public void validatePayments() {
              ServiceRegistry.getRepository().getPaymentHistory();
         }
    }


    The singleton initialization would have to change to create mocks when used in testing.
Domain Logic without AOP

In his presentation Ramnivas takes the example of a PaymentAuthorization service failure.
  1. If PaymentAuthorization fails, try authorizing using other service providers.
  2. In case all providers fail, do a temp auth based on payment history. When product is about to be shipped secure payment.
The example uses an around advice for PaymentProcessor.process which has retry logic. To do temp auth an Inter-type declaration is used.

In my mind, the clarity of code is vastly reduced by using AOP here. This domain logic that is weaved, is not be apparent and visible when looking at Order class. The domain class Order, is incomplete without considering the two aspects. This breaks the clarity of the code and model that is offered by DDD. There is no apparent gain using AOP here.

In this example, both aspects are core domain logic and in on real world model some object would have ownership of these bits of functionality. Either Order or a Domain Serice like OrderProcessSvc, would be the best objects to own this logic. Choosing between entity and service to host this logic, depends on whether the Order should own PaymentAuthorization (which I think it should) or not. But main thing is to encapsulate this logic into its rightful owner.


To me aspects in DDD can be used for things like enforcing rules (augmenting java's limited support for scoping - use an aspect that throws a compilation error whenever an entity is constructed using 'new' operator), handling service failures/issues etc at boundary with infrastructure services.

I believe Domain Logic should only be contained in POJOs to maintain clarity and readability. Any thoughts?


Technorati Tags: ,

Subscribe to comments for this post

Saturday, June 07, 2008

Associations in Domain Driven Design (DDD)

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

Associations between objects are typically not well thought out during design. Most of the time, the associations are dictated by the underlying data model. This results in addition of a lot of associations and traversal paths that may not make sense in a domain.

For e.g. an Order has an associations to multiple Products. Your natural traversal would be from an Order to Product. I am yet to see a usecase where you pick a product and 'traverse' to a list of Orders to which it is associated to. Normally the kind of functionality supported would be to list 'all open orders for product' or 'all orders for this product from a given customer' etc and these typically would be queried from DB using a DAO.

According to Eric Evans, associations should

  1. Impose a traversal direction
  2. Add qualifiers and reduce multiplicity
  3. Not be present if it is non-essential
Moving from a bi-directional association to a uni-directional association is one of my favourites since its generally easy to accomplish and offers biggest 'bang for buck' so to say. The other two are quite simple enough.

Unidirectional vs Bidirectional associations

A bidirectional association means that both Objects can only be understood together. There are real world usecases where such a necessity exists. For e.g. an Order needs to have a bi-directional association with its Settlement object. However in many cases like the first example a uni-directional association would suffice.

The advantages of unidirectional associations are
  1. It brings out the natural bias of the domain to one particular traversal direction
  2. Makes the association more communicative
  3. Provides a natural constraint on where to place domain logic since you can only place logic on the class which can reach out to all classes involved.
When to prefer Bi-directional over Uni-directional

However there were some scenarios where I started using unidirectional associations but in the end wound up reverting them to bi-directional since it felt more natural.
  1. Use Uni-directional associations if your usecases dictate there are multiple entry points for same operation.

    For e.g. an OrderList was initially modelled with a uni-directional association to list of Orders. Any domain logic that affects multiple orders can only be triggered from the OrderList.

    One of the usecases detailed that cancelling the last Order in a OrderList, cancels the entire list. Another usecase said that cancelling an OrderList should in turn call cancel on each Order within the list.

    If we had bi-directional associations, supporting the above 2 usecases led to some circular call issues.Order.cancel() calls OrderList.cancel() which internally would end up calling Order.cancel for all Orders ! One solution was to have Order.cancel and Order.doCancel where one would not trigger call to OrderList. This is plain ugly.

    The best solution is to make all cancel Order calls be handled by the OrderList. So let Order.cancel() delegate the cancel call to OrderList.cancelOrder(OrderToCancel).

    Since the Order does not have a back pointer to its OrderList, the Order had to use a repository to look up its OrderList. Moving to bi-directional we could use Hibernate's hydration support to get a reference to OrderList from Order and vice versa.

  2. Use Uni-directional association if there are usecases which require data from other object even though entry point is a different Object.

    The problem is compounded when having *-to-many relationships and many is actually quite a large number which causes a resource drag during Object hydration.

    For e.g. over course of a year, a single Customer can have thousands of Orders. Loading all Orders every time a customer object is created is bad for performance. But you would obviously need Customer data to fulfil a given Order and all Order data for a given customer to find credit worthiness.

    In such cases maintain a bi-directional association indirectly by having Customer.getOrders load Order data, on demand by querying from database.

Associations when modelled correctly ensure that there is always only one way to access data. This enhances readability and as a consequence maintainability of code.


Technorati Tags: ,

Subscribe to comments for this post

Tuesday, June 03, 2008

Alan Kay's Metaphor for OO

Alan Kay, one of the creators of SmallTalk has this to say about Object Oriented Programming


The most obvious parallel is the human body, which is divided into
trillions of cells, each performing its own specialized task.

Like objects in software produced with object-oriented programming,
human cells do not know what goes on inside one another, but they can
communicate nevertheless, working together to perform more complex
tasks. "This is an almost foolproof way of operating", Kay says.

By mimicking biology in this way, we can minimize many of the problems
inherent to the construction of a complex computing system. A developer
can focus on one simple module at a time, making sure it works
properly, and move on to the next. Not only is building a system this
way easier, but the system will be much more reliable. And when it does
break down, it is simpler to fix, because problems are typical
contained within individual modules, which can be repaired and replaced
quickly. By contrast, a monolithic system is like a massive mechanical
clock containing innumerable turning gears, none of which has its own
internal logic or communicates information. Each gear functions
unintelligently and only in relation to other gears. The design is
hopelessly flawed. When building gear clocks, eventually it
will reach a certain level of complexity and it falls in on itself.


Great crisp description. No cludgy words like blacboxes, blueprints etc. It clearly highlights the pitfalls in a procedural style of development.

I like the way in which he weaves in the concepts of Encapsulation(Info Hiding) and Message Passing.

Encapsulation is drilled into everyone doing OO. But most of the developers have still not got the subtle difference between message passing and method invocation. Can't say I blame anyone (i too did'nt know till recently), since you dont need to know about something they can't see/use when using java, c++ etc.

A message is a signal from one object to another that requests the receiving object to carry out one of its methods. The message consists of the name of the receiving object and its arguments, that is, the method it is to carry out and any parameters the method may require to fulfill its charge. Hence the end state of a message is "method invocation".

Ideally every object will get a message, check if it can respond to this message. If it can, the appropriate method for this message is invoked. Else the object can respond in whatever way it seems fit. When using Java this is not evident and not exposed at all. In Ruby atleast you have some access to this using the method_missing feature.

I digress. Coming back, I still remember my first OO concepts course, and the convuluted/over-simplified examples that were presented. I just wish I had come across stuff like this at that time.

Subscribe to comments for this post

 
Clicky Web Analytics