BT

Domain Driven Design and Development In Practice

Posted by Srini Penchikala on Jun 12, 2008 |

Background

Domain Driven Design (DDD) is about mapping business domain concepts into software artifacts. Most of the writings and articles on this topic have been based on Eric Evans' book "Domain Driven Design", covering the domain modeling and design aspects mainly from a conceptual and design stand-point. These writings discuss the main elements of DDD such as Entity, Value Object, Service etc or they talk about concepts like Ubiquitous Language, Bounded Context and Anti-Corruption Layer.

The objective of this article is to cover the domain modeling and design from a practical stand-point on how one would go about taking a domain model and actually implementing it. We will look at the guidelines, best practices, frameworks and tools that the technical leads and architects can use in the implementation effort. Domain Driven Design and Development is also influenced by several architectural, design, and implementation aspects such as:

  • Business Rules
  • Persistence
  • Caching
  • Transaction Management
  • Security
  • Code Generation
  • Test Driven Development
  • Refactoring

This article talks about how these different factors affect the implementation project throughout its lifecycle and what the architects should look for in realizing a successful DDD implementation. I will start off with a list of characteristics a typical domain model should have, and when to use a domain model in an enterprise (versus not using a domain model at all or using an anemic domain model).

The article includes a sample loan processing application to demonstrate how design aspects and development best practices discussed here, can be used in a real-world domain driven development project. The sample application uses frameworks like Spring, Dozer, Spring Security, JAXB, Arid POJOs and Spring Dynamic Modules in implementing the loan processing domain model. The example code will be in Java, but it should be fairly easy to understand for most developers, regardless of language background.

Introduction

A domain model offers several benefits some of which are:

  • It helps the team create a common model, between the business and IT stakeholders in the company, that the team can use to communicate about the business requirements, data entities, and process models.
  • The model is modular, extensible and easy to maintain as the design reflects the business model.
  • It improves the reusability and testability of the business domain objects.

On the flip side, let's see what happens when IT teams don't follow a domain model approach for developing medium to large size enterprise software applications.

Not investing in a domain model and development effort leads to an application architecture with a "Fat Service Layer" and an "Anemic Domain Model" where facade classes (usually Stateless Session Beans) start accumulating more and more business logic and domain objects become mere data carriers with getters and setters. This approach also leads to domain specific business logic and rules being scattered (and duplicated in some cases) in several different facade classes.

Anemic domain models, in most cases, are not cost-effective; they don't give the company a competitive advantage over other companies because implementing business requirement changes in this architecture take too long to develop and deploy to production environment.

Before we look at different architectural and design considerations in a DDD implementation project, let's take a look at the characteristics of a rich domain model.

  • The domain model should focus on a specific business operational domain. It should align with the business model, strategies and business processes.
  • It should be isolated from other domains in the business as well as other layers in the application architecture.
  • It should be reusable to avoid any duplicate models and implementations of the same core business domain elements.
  • The model should be designed loosely coupled with other layers in the application, meaning no dependencies on the layers on either side of domain layer (i.e. database and facade layers).
  • It should be an abstract and cleanly separated layer enabling easier maintenance, testing, and versioning. The domain classes should be unit testable outside the container (and from inside the IDE).
  • It should be designed using a POJO programming model without any technology or framework dependencies (I always tell the project teams I work with in my company, that the technology we use for software development is Java).
  • The domain model should be independent of persistence implementation details (although the technology does place some constraints on the model).
  • It should have minimum dependencies on any infrastructure frameworks because it will outlive these frameworks and we don't want any tight coupling on any external framework.

In order to achieve a better Return On Investment (ROI) on software development efforts, the senior management in Business Units and IT has to commit to the investment (of time, money, and resources) in business domain modeling and its implementation. Let's look at some of the other factors that are required for implementing a domain model.

  • The team should have regular access to business domain subject matter experts.
  • IT team (modelers, architects, and developers) should possess good modeling and design skills.
  • Analysts should have good business process modeling skills.
  • Architects and developers should have strong Object Oriented Design (OOD) and Programming (OOP) experience.

Role of Domain Driven Design in Enterprise Architecture

Domain modeling and DDD play a vital role in Enterprise Architecture (EA). Since one of the goals of EA is to align IT with the business units, the domain model which is the representation of business entities, becomes a core part of EA. This is why most of the EA components (business or infrastructural) should be designed and implemented around the domain model.

Domain Driven Design and SOA

Service Oriented Architecture (SOA) is gaining more and more momentum in the recent past to help the teams build software components and services based on the business processes and to speed up the time to market for the new products. Domain driven design is a key element of SOA architecture because it helps in encapsulating the business logic and rules in domain objects. The domain model also provides the language and context with which the service contract can be defined.

An SOA effort should include the design and implementation of the domain model if one doesn't already exist. If we put too much emphasis on the SOA services and ignore the importance of domain model, we will end up with an anemic domain model and bloated services in the application architecture.

An ideal scenario is the one where DDD effort is implemented iteratively with developing the application layer and SOA components at the same time as these are the direct consumers of domain model elements. With a rich domain implementation, SOA design will become relatively simple by providing a shell (proxy) to the domain objects. But if we focus too much on the SOA layer without a decent domain model in the back-end, the business services will be calling an incomplete domain model, which can result in a brittle SOA architecture.

Project Management

A domain modeling project typically includes the following steps:

  • Model and document business processes first.
  • Select a candidate business process and work with the business domain experts to document it using the Ubiquitous Language.
  • Identify all the services that are required for the candidate business process. These services can be atomic (single step) or orchestrated (multi-step with or without work-flow) in nature. They can also be business (e.g. Underwriting or Funding) or infrastructure (e.g. E-mail or Job Scheduling).
  • Identify and document the state and behavior of the objects used by services identified in the previous step.

It's important to keep the model at a high-level initially focusing on the core elements of the business domain.

From a project management stand-point, a real-world DDD implementation project comprises the same phases as any other software development project. These phases include:

  • Model the domain
  • Design
  • Development
  • Unit and Integration Testing
  • Refine and refactor the domain model based on the design and development (Continuous Integration (CI) of model concepts).
  • Repeat the above steps using the updated domain model (CI of domain implementation).

An agile software development methodology is a great fit here because agile methodologies focus on the delivery of business value just like DDD focuses on the alignment of software system with business model. Also, with the iterative nature of DDD, agile methodologies such as SCRUM or DSDM are better frameworks to manage the project. Using SCRUM (for project management) and XP (for software development purposes) methodologies is a good combination for managing a DDD implementation project.

This project management model of DDD iteration cycle is shown in Figure 1 below.


Figure 1. DDD Iteration cycle diagram (Click on the screen shot to open a full-size view.)

Domain driven design effort begins where domain modeling ends. Ramnivas Laddad recommends the following steps on how to go about implementing a domain object model. He emphasizes on putting more focus on domain objects than services in the domain model.

  • Start with domain entities and domain logic.
  • Start without a service layer initially and only add services where the logic doesn't belong in any domain entity or value object.
  • Use Ubiquitous Language, Design by Contract (DbC), Automated Tests, CI and Refactoring to make the implementation as closely aligned as possible with the domain model.

From the design and implementation stand-point, a typical DDD framework should support the following features.

  • It should be a POJO (or POCO if your company is a .NET shop) based framework.
  • It should support the design and implementation of a business domain model using the DDD concepts.
  • It should support concepts like Dependency Injection (DI) and Aspect Oriented Programming (AOP) out of the box. (Note: These concepts are explained in more detail later in the article).
  • Integration with unit testing frameworks such as JUnit, TestNG, Unitils etc.
  • Good integration with other Java/Java EE frameworks like JPA, Hibernate, TopLink etc.

Sample Application

The sample application used in this article is a home loan processing system and the business use case is to approve the funding request of a home loan (mortgage). When a loan application is submitted to a mortgage lending company, it first goes through the Underwriting process where the underwriters approve or deny the loan request based on customer's income details, credit history and other factors. If the loan application is approved by underwriting group, it goes through Closing and Funding steps in the loan approval process.

Funding module in the loan processing system automates the process of disbursement of funds to the borrower. The funding process typically starts with mortgage lender (typically a bank) forwarding the loan package to a title company. The title company then reviews the loan package and schedules a date with seller and buyer of the property for closing the loan. Borrower and the seller meet with the closing agent at the title company to sign the paperwork to transfer the title of the property.

Architecture

A typical enterprise application architecture consists of the following four conceptual layers:

  • User Interface (Presentation Layer): Responsible for presenting information to the user and interpreting user commands.
  • Application Layer: This layer coordinates the application activity. It doesn't contain any business logic. It does not hold the state of business objects, but it can hold the state of an application task's progress.
  • Domain Layer: This layer contains information about the business domain. The state of business objects is held here. Persistence of the business objects and possibly their state is delegated to the infrastructure layer.
  • Infrastructure Layer: This layer acts as a supporting library for all the other layers. It provides communication between layers, implements persistence for business objects, contains supporting libraries for the user interface layer, etc.

Let's look at the application and domain layers in more detail. The Application layer:

  • is responsible for the navigation between the UI screens in the application as well as the interaction with the application layers of other systems.
  • can also perform the basic (non-business related) validation on the user input data before transmitting it to the other (lower) layers of the application.
  • doesn't contain any business or domain related logic or data access logic.
  • doesn't have any state reflecting a business use case but it can manage the state of the user session or the progress of a task.

The domain layer:

  • is responsible for the concepts of business domain, information about the business use case and the business rules. Domain objects encapsulate the state and behavior of business entities. Examples of business entities in a loan processing application are Mortgage, Property, and Borrower.
  • can also manage the state (session) of a business use case if the use case spans multiple user requests (e.g. loan registration process which consists of multiple steps: user entering the loan details, system returning the products and rates based on the loan parameters, user selecting a specific product/rate combination, and finally the system locking the loan for that rate).
  • contains service objects that only have a defined operational behavior which is not part of any domain object. Services encapsulate behavior of the business domain that doesn't fit in the domain objects themselves.
  • is the heart of the business application and should be well isolated from the other layers of the application. Also, it should not be dependent on the application frameworks used in the other layers (JSP/JSF, Struts, EJB, Hibernate, XMLBeans and so-on).

Figure 2 below shows the different architecture layers used in the application and how they relate to DDD.


Figure 2. Layered Application Architecture diagram (Click on the screen shot to open a full-size view.)

Following design aspects are considered as the main ingredients of the current DDD implementation recipe:

  • Object Oriented Programming (OOP)
  • Dependency Injection (DI)
  • Aspect Oriented Programming (AOP)

OOP is the most important element in the domain implementation. Domain objects should be designed using Plain Java Classes and Interfaces by taking advantage of OOP concepts like inheritance, encapsulation, and polymorphism. Most of the domain elements are true objects with both State (attributes) and Behavior (methods or operations that act on the state). They also correspond to real world concepts and can fit right in with OOP concepts. Entities and Value Objects in DDD are classic examples of OOP concepts since they have both state and behavior.

In a typical Unit of Work (UOW), domain objects need to collaborate with other objects whether they are Services, Repositories or Factories. Domain objects also need to manage other concerns such as domain state change tracking, auditing, caching, transaction management (including transaction retry) which are cross-cutting in nature. These are reusable non-domain related concerns that typically tend to be scattered and duplicated all over the code including the domain layer. Embedding this logic in the domain objects leads to tangling and cluttering of the domain layer with non-domain related code.

When it comes to managing the code dependencies without tight-coupling between objects and isolating cross-cutting concerns, OOP alone cannot provide an elegant design solution for domain driven design and development. This is where design concepts like DI and AOP can be used to complement OOP to minimize tight coupling, enhance modularity and better manage the cross-cutting concerns.

Dependency Injection

DI is a great way to move the configuration and dependency code out of the domain objects. Also, the design dependency of domain classes on Data Access Object (DAO) classes and service classes on domain classes makes DI a "must have" in DDD implementation. DI facilitates a cleaner and loosely coupled design by injecting the other objects such as Repositories and Services into Domain Objects.

In the sample application, the service object (FundingServiceImpl) uses DI to inject the Entity objects (Loan, Borrower and FundingRequest). Also, Entities reference Repositories via DI. Similarly, other Java EE resources like DataSource, Hibernate Session Factory and Transaction Manager are injected into Service and Repository objects.

Aspect Oriented Programming

AOP helps in an even better design (i.e. less cluttering in the domain model) by removing the cross-cutting concerns code like auditing, domain state change tracking etc from the domain objects. It can be used to inject collaborating objects and services into domain objects especially the objects that are not instantiated by the container (such as the persistence objects). Other aspects in the domain layer that could use AOP are caching, transaction management and role based security (authorization).

Loan processing application uses custom Aspects to introduce data caching into the Service objects. Loan product and interest rate information is loaded from the database table once (the first this information is requested by the client) and is then stored in an object cache (JBossCache) for subsequent product and rate lookups. Product and rate data is frequently accessed but it's not updated that regularly, so it's a good candidate for caching the data instead of hitting the back-end database every time.

The role of DI and AOP concepts in DDD was the main topic in a recent discussion thread. The discussion was based on a presentation by Ramnivas Laddad where he made the assertion that DDD cannot be implemented without help of AOP and DI. In the presentation, Ramnivas talked about the concept of "fine grained DI" using AOP to make domain objects regain smart behavior. He mentioned that domain objects need access to other fine grained objects to provide rich behavior and a solution to this is to inject Services, Factories, or Repositories into Domain Objects (by using Aspects to inject dependency at constructor or setter invocation time).

Chris Richardson also discussed about using DI, objects, and Aspects to improve the application design by reducing coupling and increasing modularity. Chris talked about "Big Fat Service" anti-pattern which is the result of coupling, tangling and scattering of the application code and how to avoid it using DI and AOP concepts.

Annotations

A recent trend to define and manage Aspects and DI is to use Annotations. Annotations help in minimizing the required artifacts for implementing the remote services such as EJB or Web Services. They also simplify the configuration management tasks. Spring 2.5, Hibernate 3 and other frameworks take full advantage of Annotations to configure the components in different layers of a Java enterprise application.

We should take advantage of annotations to generate the boiler plate code where it adds value in terms of flexibility. At the same time, annotations should be used with some caution. They should be used where they are not confusing or misleading in understanding the actual code. A good example of using Annotation is Hibernate ORM mapping where it adds value to specify the SQL table or column name right next to the class or attribute name. On the other hand, details like JDBC driver configuration (driver name, jdbc url, user name, and password) are better suited to be stored in an XML file rather than using Annotations. This is based on the assumption that the database is in the same context. If significant transformations are required between the domain model and the database tables, then the design should take that concern into consideration.

Java EE 5 provides JPA annotations like @Entity, @PersistenceUnit, @PersistenceContext, etc. to add persistence details to plain Java classes. In the context of domain modeling, Entity, Repository and Service are good candidates for using Annotations.

@Configurable is Spring's way of injecting Repository and Services into a Domain Object. Spring framework extends the "Domain Object DI" idea beyond the @Configurable annotation. Ramnivas recently blogged about the latest improvements in upcoming Spring 2.5.2 release (available starting with project snapshot build 379). There are three new aspects (AnnotationBeanConfigurerAspect, AbstractInterfaceDrivenDependencyInjectionAspect, and AbstractDependencyInjectionAspect) to provide simple and more flexible options for Domain Object DI. Ramnivas said the main reason behind introducing the middle aspect (AbstractInterfaceDrivenDependencyInjectionAspect) is to allow domain-specific annotations and interfaces to play a role. Spring also provides other annotations like @Repository, @Service, and @Transactional to help in the design of the domain classes.

Some of the annotations used in the sample application, Entity objects (Loan, Borrower, and FundingRequest) use @Entity annotation. These objects also use @Configurable annotation to wire the Repository objects. And the Service classes use @Transactional annotation to decorate the service methods with transactional behavior.

Domain model and Security

Application security in the domain layer ensures only authorized clients (human users or other applications) are calling the domain operations as well as accessing the domain state.

Spring Security (a sub-project in Spring Portfolio) provides a fine-grained access control in both presentation (URL based) and domain (Method Level) layers of the application. The framework uses Spring's Bean Proxy to intercept method invocation and apply security constraints. It offers a role-based declarative security for Java objects using MethodSecurityInterceptor class. There is also instance level security in the form of Access Control Lists (ACL's) for domain objects to control the user access at the instance level.

The main advantage of using Spring Security for managing the authorization requirements in the domain model is that the framework has a non-invasive architecture so we can have a clean separation between the domain and security aspects. Also, the business objects are not cluttered with security implementation details. We can write common security rules in one place and apply them (using AOP techniques) wherever they need to be implemented.

In domain and service classes, authorization is managed at the class method invocation level. For example, the "loan approval" method in an Underwriting domain object can be invoked by any user with an "Underwriter" role for loans up to 1 million dollars whereas the approval method in the same domain object for loan applications with a loan amount greater than 1 million dollars can only be called by a user with "Underwriting Supervisor" role.

The following table is a summary of various application security concerns in each layer of the application architecture.

Table 1. Security Concerns in Various Application Layers

Layer Security Concern
Client/Controller Authentication, Web Page (URL) Level Authorization
Facade Role based authorization
Domain Domain instance level authorization, ACL
Database DB object level authorization (Stored procedures, Stored functions, Triggers)

Business Rules

Business rules are an important part of the business domain. They define data validation and other constraints that need to be applied on domain objects in specific business process scenarios. Business rules typically fall into the following categories:

  • Data validation
  • Data transformation
  • Business decision-making
  • Process routing (work-flow logic)

The context is very important in DDD world. Context specificity dictates the domain object collaboration as well as other run-time factors like what business rules to apply etc. Validation and other business rules are always processed in a specific business context. This means the same domain object, in a different business context, will have to process different set of business rules. For example, some attributes of a loan domain object (such as loan amount and interest rate) cannot be changed after the loan has been through the Underwriting step in the loan approval process. But the same attributes can be changed when the loan is just registered and locked for a specific interest rate.

Even though all the domain specific business rules should be encapsulated in the domain layer, some application designs put the rules in facade classes, which leads to domain classes becoming "anemic" in terms of business rules logic. This may be an acceptable solution in small size applications, but it is not recommended for mid-size to large enterprise applications that contain complex business rules. A better design option is to put the rules where they belong, inside the domain objects. If a business rule logic spans two or more Entity objects, then it should become part of a Service class.

Also, if we are not diligent in the application, design business rules will end up being coded in the form of several switch statements in the code. And over time as the rules get more complex, developers don't take time to refactor the code to move "switch" statements into a more manageable design. Hardcoding the complex routing or decision-making rules logic in the classes leads to longer methods in the classes, code duplication, and ultimately a rigid application design which will become a maintenance nightmare in the long run. A good design is to place all the rules (especially complex rules that change frequently as the business strategy changes) into a Rules engine (using a rules framework like JBoss Rules, OpenRules, or Mandarax) and invoke them from the domain classes.

Validation rules are usually implemented in different languages like Javascript, XML, Java code, and other scripting languages. But due to the dynamic nature of business rules, scripting languages such as Ruby, Groovy, or Domain Specific Languages (DSL) are a better choice to define and manage these rules. Struts (Application layer), Spring (Service) and Hibernate (ORM) all have their own validation modules where we can apply the validation rules on the incoming or outgoing data objects. In some cases, validation rules can also be managed as Aspects (link AOP rules article here) that can be weaved into different layers (e.g. Service and Controller) of the application.

It's important to keep in mind the unit testing aspect when writing the domain classes to manage business rules. Any changes in the rules logic should be easily unit testable in isolation.

The sample application includes a business rule set to validate the loan parameters are within the allowed product and rate specifications. The rules are defined in a scripting language (Groovy) and are applied on the loan data passed to FundingService object.

Design

From a design stand-point, the domain layer should have a well defined boundary to avoid the corruption of the layer from non-core domain layer concerns such as vendor-specific translations, data filtering, transformations, etc. Domain elements should be designed to hold the domain state and behavior correctly. Different domain elements are structured differently based on state and behavior. Table 2 below shows the domain elements and what they contain.

Table 2. Domain elements with state and behavior

Domain Element State/Behavior
Entity, Value Object, Aggregate State and Behavior
Data Transfer Object State only
Service, Repository Behavior only

Entities, Value Objects, and Aggregates which contain both state (data) and behavior (operations), should have clearly defined state and behavior. At the same time, this behavior should not extend beyond the limits of the object's boundaries. Entities should do most of the work in the use case acting on their local state. But they shouldn't know about too many unrelated concepts.

Good design practice is to only include the getters/setters for the attributes that are required to encapsulate the state of domain objects. When designing the domain objects, only provide setter methods for those fields that can change. Also, the public constructors should contain only the required fields instead of a constructor with all the fields in the domain class.

In most of the use cases, we don't really have to be able to change the state of an object directly. So, instead of changing the internal state, create a new object with the changed state and return the new object. This is sufficient in these use cases and it also reduces design complexity.

Aggregate classes hide the usage of collaborating classes from callers. They can be used for encapsulating complex, intrusive, and state-dependent requirements in the domain classes.

Design Patterns that Support DDD

There are several design patterns that help in domain driven design and development. Following is a list of these design patterns:

  • Domain Object (DO)
  • Data Transfer Object (DTO)
  • DTO Assembler
  • Repository: The Repository contains domain-centric methods and uses the DAO to interact with the database.
  • Generic DAO's
  • Temporal Patterns: These patterns add time dimension to rich domain models. Bitemporal framework, which is based on Martin Fowler's Temporal Patterns, provides a design approach to dealing with bitemporal issues in the domain models. The core domain objects and their bitemporal properties can be persisted using an ORM product such as Hibernate.

Other design patterns that are used in DDD include Strategy, Facade, and Factory. Jimmy Nilsson discussed Factory as one of the domain patterns in his book.

DDD Anti-Patterns

On the flip side of the best practices and design patterns, there are some DDD smells that architects and developers should watch out for when implementing the domain model. As a result of these anti-patterns, domain layer becomes the least important part in application architecture and facade classes assume a more important role in the model. Following are some of these anti-patterns:

  • Anemic domain objects
  • Repetitive DAO's
  • Fat Service Layer: This is where service classes will end up having all the business logic.
  • Feature Envy: This is one of the classic smells mentioned in Martin Fowler's book on Refactoring where the methods in a class are far too interested in data belonging to other classes.

Data Access Objects

DAO's and Repositories are also important in domain driven design. DAO is the contract between relational database and the application. It encapsulates the details of database CRUD operations from the web application. On the other hand, a Repository is a separate abstraction that interacts with the DAOs and provides "business interfaces" to the domain model.

Repositories speak the Ubiquitous Language of the domain, work with all necessary DAOs and provide data access services to the domain model in a language the domain understands.

DAO methods are fine-grained and closer to the database while the Repository methods are more coarse-grained and closer to the domain. Also one Repository class may have multiple DAO's injected. Repositories and DAO's keep the domain model decoupled from dealing with the data access and persistence details.

The domain objects should depend only on Repository interfaces. This is the reason why injecting the Repository instead of a DAO results in a much cleaner domain model. DAO classes should never be called directly from the client (Services and other consumer classes). The clients should always call the domain objects which in turn should call the DAO's for persisting the data to the data store.

Managing the dependencies between domain objects (for example, the dependency between an Entity and its Repository) is a classic problem that developers often run into. The usual design solution to this problem is to have the Service or Facade class call a Repository directly and when invoked the Repository would return the Entity object to the client. This design eventually leads to the afore-mentioned Anemic Domain Model where facade classes start accumulating more business logic and domain objects become mere data carriers. A good design is to inject Repositories and Services into domain objects using DI & AOP techniques.

Sample application follows these design principles in implementing the loan processing domain model.

Persistence

Persistence is an infrastructural aspect from which the domain layer should be decoupled. JPA provides this abstraction by hiding the details of the persistence implementation from the classes. It is annotation driven so no XML mapping files are required. But at the same time, the table and column names are embedded in the code which may not be a flexible solution in some cases.

With grid computing products such as Oracle Coherence, WebSphere Object Grid, and GigaSpaces that offer data grid solutions, the developers don't even need to think about a RDBMS when they model and design the business domain. The database layer is abstracted from domain layer in the form of an in-memory Object/Data Grid.

Caching

When we talk about the state (data) of the domain layer, we have to talk about the aspect of caching. Frequently accessed domain data (such as products and rates in a mortgage loan processing application) are good candidates for caching. Caching speeds up the performance and reduces the load on the database server. Service layer is ideal for caching the domain state. ORM frameworks like TopLink and Hibernate also provide data caching.

Loan processing sample application uses JBossCache framework to cache product and rate details to minimize the database calls and improve application performance.

Transaction Management

Transaction management is important to keep the data integrity and to commit or rollback the UOW as a whole. There has always been a debate about where the transactions should be managed in the application architecture layers. There are also the cross-entity transactions (that span multiple domain objects in the same UOW) that affect the design decision of where the transactions should be managed.

Some developers prefer managing the transactions in the DAO classes which is a poor design. This results in too fine-grained transaction control which doesn't give the flexibility of managing the use cases where the transactions span multiple domain objects. Service classes should handle transactions; this way even if the transaction spans multiple domain objects, the service class can manage the transaction since in most of the use cases the Service class handles the control flow.

FundingServiceImpl class in the sample application manages transactions for the funding request and executes multiple database operations by calling the Repositories and commits or rolls back all database changes in a single transactions.

Data Transfer Objects

DTO's are also an important part of the design in an SOA environment where the Domain object model structurally is not compatible with the messages that are received and sent from a business service. The messages are typically defined and maintained in as XML Schema Definition documents (XSD's) and it's a common practice to write (or code generate) DTO objects from the XSD's and use them for data (message) transfer purposes between domain and SOA service layers. Mapping the data from one or more domain objects to a DTO will become a necessary evil in distributed applications where sending the domain objects across the wire may not be practical from a performance and a security stand-point.

From a DDD perspective, DTO's also help maintain the separation between Service and UI layers where DO's are used in the domain and service layers and DTO's are used in the presentation layer.

Dozer framework is used for the assembly of one or more domain objects into a DTO object. It is bi-directional which saves a lot of extra code and time when converting domain objects into DTO's and vice-versa. The 2-way mapping between DO and DTO objects helps eliminate the separate DO -> DTO and DTO -> DO translation logic. The framework also correctly handles the type and array conversion.

The sample application uses Dozer mapping files (XML) to split the FundingRequestDTO object into Loan, Borrower, and FundingRequest Entity objects when the request comes in for fund processing. The mapping also takes care of the aggregation of the funding response data from the Entities into a single DTO object on the way back to the client.

DDD Implementation Frameworks

Frameworks like Spring and Real Object Oriented (ROO), Hibernate, and Dozer aid in designing and implementing a domain model. Other frameworks that support DDD implementation are JMatter, Naked Objects, Ruby On Rails, Grails, and Spring Modules XT Framework.

Spring takes care of instantiating and wiring together the domain classes such as Services, Factories, and Repositories. It also injects Services into Entities using @Configurable annotation. This annotation is Spring specific, so other options for achieving this injection is to use something like Hibernate Interceptor.

ROO is a DDD implementation framework built on "domain first and infrastructure second" philosophy. The framework was developed to reduce the boiler-plate coding of the patterns found in web application development. When using ROO, we define the domain model, and then the framework (based on Maven Archetypes) generates the code for Model-View-Controller (MVC), DTO's, Business Layer Facade and DAO layers. It even generates the stubs for unit and integration tests.

ROO has some very useful practical implementation patterns. For example, it distinguishes the state managed fields, the persistence layer uses field-level access, and the public constructors only reflect the mandatory fields.

Development

A model is no good without the actual implementation. The implementation phase should include automating the development tasks as much as possible. To see what tasks can be automated, let's look at a typical use case involving the domain model. Following is the list of steps in the use case:

Request In:

  • Client calls a Facade class sending data as an XML document (which is XSD compliant); Facade class initiates a new transaction for the UOW.
  • Run validations on the incoming data. These validations include the primary (basic/data type/field level checks) and business validations. If there are any validation errors, raise appropriate exceptions.
  • Translate the descriptions to codes (to be domain friendly).
  • Make the data formatting changes to be domain model friendly.
  • Make any separation of attributes (like splitting a customer name into first and last name attributes in a Customer Entity object).
  • Disassemble the DTO data into one or more domain objects.
  • Persist the state of domain objects.

Response Out:

  • Get the state of domain object(s) from datastore.
  • Cache the state if necessary.
  • Assemble the domain object(s) into application friendly data objects (DTO).
  • Make any merge or separation of data elements (such as combining first and last names into single customer name attribute).
  • Translate the codes into descriptions.
  • Make the data formatting changes necessary to address the client data usage requirements.
  • Cache the DTO state if necessary
  • Transaction commits (or rolls back if there was an error) as the control flow exits.

The following table shows different objects that carry the data from one layer to another in the application.

Table 3. Data flow through the application layers

Layer From Object To Object Framework
DAO Database Table(s) DO Hibernate
Domain Delegate DO DTO Dozer
Data Transfer DTO XML JAXB

As you can see there are few layers in the application architecture where same data flows through in different forms (DO, DTO, XML, etc). Most of these objects (Java or XML) that hold data as well as other classes like DAO, DAOImpl, and DAOTest are infrastructural in nature. These classes and XML files that have boiler-plate code and structure are great candidates for code generation.

Code Generation

Frameworks like ROO also create a standard and consistent project template (using Maven plugin) for new projects. Using a pre-generated project template, we can achieve consistency in the directory structure on where to store the source and test classes, configuration files, and dependencies on internal and external (third-party) component libraries.

It could be overwhelming when we consider the myriad of classes and configuration files needed to develop a typical enterprise software application. Code generation is the best way to go about this problem. Code generation tools typically use some kind of template framework to define the templates or mappings from which a code generator can generate the code. Eclipse Modeling Framework (EMF) has several sub-projects that aid in the code generation of various artifacts required in a web application project. Model Driven Architecture (MDA) tools like AndroMDA use EMF to generate the code based on architecture models.

When it comes to writing the delegate classes in domain layer I have seen developers writing these classes manually (mostly writing the first one from scratch and then following "Copy And Paste" pattern to create the required delegate classes for other domain objects. Since most of these classes are basically facades to domain classes they are good candidates for code generation. Code generation option is a good long-term solution even though it involves some initial investment (in terms of coding and time) to build and test the code generator (engine).

For the test classes generated, a good option is to create abstract methods for the methods with complex business logic in the main class that need to be unit tested. This way, developers can extend the generated base test class and implement custom business logic which cannot be auto-generated. The same goes for any test method that has testing logic which cannot be auto-created.

Scripting languages are a better choice for writing code generators as they have less overhead and they support template creation and customization options. If we take advantage of code generation in a DDD project, we only need to write a few classes from scratch. The artifacts that must be created from scratch include:

  • XSD
  • Domain Object
  • Service

Once we define the XSD and Java classes, we can code generate all or most of the following classes and configuration files:

  • DAO interface and implementation class
  • Factories
  • Repositories
  • Domain Delegate (if needed)
  • Facade (including EJB and WebService classes)
  • DTO's
  • Unit Tests for the above classes (including test class and test data)
  • Spring configuration files

Table 4 below lists different layers in a web application architecture and what artifacts (Java classes or XML files) can be generated in that layer.

Table 4: Code generation in DDD implementation project

Layer/Function Pattern Code You Write Generated Code Framework
Data Access DAO/Repository    DAO Interface,
DAO Implementation class,
DAOTest,
Test Seed Data
Unitils,
DBUnit
Domain DO Domain class DomainTest   
Persistence ORM Domain Class ORM Mappings,
ORM Mapping Test
Hibernate,
ORMUnit
Data Transfer DTO XSD DTO JAXB
DTO Assembly Assembler Mapping DO-DTO Mapping Dozer
Delegate Business Delegate Code to translate DO's to DTO's      
Facade    Facade    Remote Service,
EJB,
Web Service
Controller MVC Controller Mapping Files Struts/Spring MVC   
Presentation MVC View configuration files Spring MVC   

Delegate layer is the only layer that has knowledge of both Domain Objects and DTO's. Other layers such as Persistence layer should be unaware of DTO's.

Refactoring

Refactoring is changing or restructuring the application code without changing the functionality or behavior of the application. Refactoring can be either design or code related. Design refactoring is done to continually refine the model and refactor the code to improve the domain model.

Refactoring plays an important role in the DDD project due to its iterative and evolutionary nature of domain modeling. One way to integrate refactoring tasks into the project is to add it in each iteration of the project before calling the iteration done. Ideally, refactoring should be done before and after every development task.

Refactoring should be done with strict discipline. Use the combination of refactoring, CI, and unit testing to make sure the code changes didn't break any functionality and at the same time the changes did help with the intended code or performance improvements.

Automated tests play a vital role in refactoring the application code. Without good automated developer tests and Test Driven Development (TDD) practices, refactoring can be counter-productive since there will be no automated way to verify that the design and code changes made as part of refactoring effort didn't change the behavior or break the functionality.

Tools like Eclipse help in implementing the domain model in an iterative way with refactoring as part of the development effort. Eclipse has features like extracting or moving a method to a different class or pushing down a method to a subclass. There are also several code analysis plugins for Eclipse that can help in managing the code dependencies and identifying the DDD anti-patterns. I rely on plugins like JDepend, Classycle, and Metrics when I do the design and code review of projects, to assess the quality of domain and other modules in the application.

Chris Richardson talked about applying code refactoring to transform a procedural design into an OO design using refactoring features provided by Eclipse.

Unit Testing/Continuous Integration

One of the goals we talked about earlier is that the domain classes should be unit testable (during the initial development as well as later when refactoring the existing code) without too many dependencies on the container or other infrastructure code. TDD approach helps the team in finding any design problems early in the project as well as verifying that the code is in alignment with domain model. DDD is ideal for Test-First development because the state and behavior are contained in domain classes and it should be easy to test them in isolation. It is important to test the state and behavior of domain model and not focus too much on the implementation details of data access or persistence.

Unit testing frameworks like JUnit or TestNG are great tools to implement and manage the domain model. Other testing frameworks like DBUnit and Unitils can also be used to test domain layer especially to inject test data into DAO classes. This will minimize writing extra code for populating test data in unit test classes.

Mock objects also help in testing the domain objects in isolation. But it's important to not go crazy with using mock objects in the domain layer. If there are other easy ways to test domain classes, you should use those options instead of using mock objects. For example, if you can test an Entity class using a real DAO class in the back-end (instead of a mock DAO implementation) with an in-memory HSQL database instead of the real database; it will make the domain layer unit tests run quicker which is the main idea behind using mock objects any way. This way, you will be testing the collaboration (interaction) between domain objects as well as the state (data) exchanged between them. With mock objects, we will only be testing the interaction between the domain objects.

All unit and integration tests created during the development phase (with or without using TDD practices) will become part of the automated test suite once the development tasks are done. These tests should be maintained and executed frequently in the local and higher development environments to find if the new code changes introduced any bugs into domain classes.

Eric Evans covers CI in his book saying that CI effort should always be applied within a Bounded Context and it should include the synchronization of people as well as code. CI tools like CruiseControl and Hudson can be used to set up an automatic build and test environment to run the application build script (created using a build tool such as Ant or Maven) to checkout the code from a SCM repository (like CVS, Subversion etc), compile the domain classes (as well as the other classes in the application) and if there are no build errors, then automatically run all the tests (unit and integration). CI tools can also be setup to notify the project teams (via e-mail or RSS feeds) if there are any build or test errors.

Deployment

Domain models are never static; they change as business requirements evolve during the lifecycle of the project and new requirements come up in the new projects. Also, as you develop and implement the domain model you constantly learn and improve, and you want to apply the new knowledge to the existing model.

Isolation is the key when packaging and deploying the domain classes. Since domain layer has dependencies on DAO layer on one side and Service Facade layer on the other (see the application architecture diagram in Figure 2), it makes lot of sense to package and deploy the domain classes as one or more modules to manage these dependencies elegantly.

While design patterns such as DI, AOP and Factories minimize the coupling between the objects at design time and make the application modular, OSGi (formerly known as Open Services Gateway initiative) addresses modularity at runtime. OSGi is becoming a standard mechanism to package and distribute the enterprise applications. It nicely handles the dependencies between the modules. We can also use OSGi for domain model versioning purposes.

We can package DAO classes in one OSGi bundle (the DAO bundle), the service facade classes in another bundle (service bundle), so when DAO or Service implementations are modified or a different version of the application is being deployed, thanks to OSGi, no application restarts are required. We can also deploy two different versions of the same domain class if we have to support the existing and new versions of certain domain objects for backward compatibility.

To take advantage of OSGi capabilities, the application objects have to be registered with OSGi platform before being consumed (i.e. before the client can do a lookup for them). This means that we have to use OSGi APIs to do the registration but we also have to deal with failure scenarios as services are started and stopped using OSGi container. Spring Dynamic Modules framework helps in this area by allowing any type of object to be exported and imported in the application without any code changes.

Spring DM also provides test classes to run OSGi integration tests outside the container. For example, AbstractOsgiTests can be used to run integration tests directly from the IDE. The setup is handled by the testing infrastructure so we don't have to write a MANIFEST.MF file for the test, or do any packaging or deployment. The framework supports most of the OSGi implementations currently available (Equinox, Knopflerfish and Apache Felix).

Loan processing application uses OSGi, Spring DM, and Equinox container to manage the module level dependencies and the deployment of domain and other modules. LoanAppDeploymentTests shows the use of Spring DM test module.

Sample Application Design

The domain classes used in the loan processing sample application are listed below:

Entities:

  • Loan
  • Borrower
  • UnderwritingDecision
  • FundingRequest

Value Objects:

  • ProductRate
  • State

Services:

  • FundingService

Repositories:

  • LoanRepository
  • BorrowerRepository
  • FundingRepository

Figure 3 shows the domain model diagram for the sample application.


Figure 3. Layered Application Domain Model (Click on the screen shot to open a full-size view.)

Most of the DDD design concepts and techniques discussed in this article are applied in the sample application. Concepts like DI, AOP, Annotations, Domain Level Security, and Persistence are used. Also, I used several open source frameworks to help in DDD development and implementation tasks. These frameworks are listed below:

  • Spring
  • Dozer
  • Spring Security
  • JAXB (Spring-WS for marshalling and unmarshalling the data)
  • Spring Testing (for unit and integration testing)
  • DBUnit
  • Spring Dynamic Modules

The domain classes in the sample application are deployed as an OSGi module using Equinox and Spring DM frameworks. The following table shows the module packaging details for the sample application.

Table 5. Packaging and Deployment Details

Layer Deployment Artifact Name Module Contents Spring Configuration File(s)
Client/Controller loanapp-controller.jar Controller, Client Delegate classes LoanAppContext-Controller.xml
Facade loanapp-service.jar Facade (Remote) Service, Server Delegate classes, XSD's LoanAppContext-RemoteServices.xml
Domain loanapp-domain.jar Domain classes, DAO, Common DTO's LoanAppContext-Domain.xml, LoanAppContext-Persistence.xml
Framework loanapp-framework.jar Framework, Utility, Monitoring (JMX) classes, Aspects LoanAppContext-Framework.xml, LoanAppContext-Monitoring.xml, LoanApp-Aspects.xml

Conclusion

DDD is a powerful concept that will change the way modelers, architects, developers, and testers will look at the software once the team is trained in DDD and start to apply "domain first and infrastructure second" philosophy. As different stakeholders (from IT and business units) with different backgrounds and areas of expertise are involved in the domain modeling, design and implementation effort, to quote Eric Evans, "it's important not to blur the lines between the philosophy of design (DDD) and the technical tool box that helps us fulfill it (OOP, DI, and AOP)".

Advancing Frontiers

This section covers some of the emerging approaches that impact the DDD design and development. Some of these concepts are still evolving and it will be interesting to see how they will affect DDD.

Architecture rules and Design by Contract enforcement plays an important role in the governance and policy enforcement of domain model standards and implementation best practices. Ramnivas talked about using the Aspects to enforce the rule of creating a Repository object only through Factories; this is an easy to violate design rule in domain layer.

Domain Specific Languages (DSL) and Business Natural Languages (BNL) are gaining more attention in the recent years. One can use these languages to represent business logic in the domain classes. BNL's are powerful in the sense that they can be used to capture business specifications, documenting the business rules, and as executable code as well. They can also be used to create test cases to verify the system works as expected.

Behavior Driven Development (BDD) is another interesting concept that has been discussed lately. BDD helps focus development on the delivery of prioritized, verifiable business value by providing a common vocabulary (Ubiquitous Language) that spans the divide between Business and Technology. By using terminology focused on the behavioral aspects of the system rather than testing, BDD attempts to help direct developers towards a focus on the real value to be found in TDD at its most successful. If practiced correctly, BDD can be a great complement to DDD where the development of domain objects is positively influenced by BDD concepts; after all domain objects are supposed to encapsulate state and behavior.

Event Driven Architecture (EDA) is another area that could play a role in domain driven design. For example, an event model to notify of any state change in the domain object instance would help in handling the post-event processing tasks that need to be triggered when the state of a domain object changes. EDA helps in encapsulating the event based logic from getting embedded in core domain logic. Martin Fowler documented about Domain Event design pattern.

Resources

  • Domain-Driven Design, Tackling Complexity in the Heart of Software, Eric Evans, Addison Wesley
  • Applying Domain-Driven Design and Patterns, Jimmy Nilsson, Addison Wesley
  • Refactoring to Patterns, Joshua Kerievsky, Addison Wesley
  • Can DDD be Adequately Implemented Without DI and AOP?

The sample application code can be downloaded here.

Hello stranger!

You need to Register an InfoQ account or to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

It's wonderful! by Geng Laurence

It's really great!I have never seen so wonderful DDD implementation,especially it bases on many mainstream frameworks such as hibernate,spring and so on. For the DDD,Eric Evans gives us theoretic guidance,and I am sure,this simple application gives us practical demonstration!Thank you Srini,I sure hope talking about some details of your article and demo project after I seriously reviewed the project.

One observation. by Leonard Petrica

In your class Loan you have CRUD functions like add(Loan loanData) which are applying to other objects. I think is ok to have functions like add() which are operating for the current instance of its class.
E.g.
public void add() {
loanRepository.add(this);
}

No asserts in the tests by Peter Bona

The article is great, but your sample application doesn't have asserts in the tests. How can you test then if your application and domain model behaves correctly?

Mixed feelings by Yuriy Zubarev

First of all I have to admit it's a great article and I enjoyed reading it. I also looked at the source code and got mixed feelings about FundingServiceImpl class.



What's the advantage of
loan.add(newLoan);

over
newLoan.add();
for example?



You have "loan" object auto-wired in this class for a sole purpose of persisting "newLoan" as it seems. A domain object is used as a service to persist another domain object of the same type. May be I'm missing something but it doesn't feel quite right.



Thank you.

Re: It's wonderful! by Geng Laurence

After reviewed your source code,and viewed other peoples' comments,I think it is not very well that the domain object contains the CURD operation.I think it is the repository's responsibility. In a aggregation,we should get objects' refference by navigation from the aggregation root,if the we want to get the aggregation root,I think maybe we can provide a service.

Re: It's wonderful! by Srini Penchikala

Hi Laurence, Thanks for the good comments. We, as enterprise developers (Java, .NET or some other technology), focus too much on technical infrastructure details when designing and developing applications. Techniques likes DI, Annotations and Code generation and frameworks like Hibernate and Spring help move away from this paradigm and start focusing more on business domain concerns. This article is an attempt to highlight this paradigm shift and some best practices to implement it.

What am I missing? by Rob Rudin

So I read all these grand declarations about DDD in the article, and then I look at the source code, and the domain objects look awfully similar to so-called "anemic" domain objects which are purportedly the scourge of software systems today (I was stunned to not find the requisite link to Fowler's article on the subject). All I saw in these "rich" domain objects were getters/setters for private attributes, some JPA annotations, and then some CRUD methods. What's the big deal here?



And am I the only one who finds a method such as ProductRate.findProductRates() to be a bit awkward in a grammatical sense? Does it really make sense to ask an instance of an object to return a list of instances of its class type? Does anyone actually talk like that in their business domain?



I also found the rhetoric at the top of the article to be conspicuously absent of any proof. "Not investing in a domain model" will "not give the company a competitive advantage over other companies because implementing business requirement changes in this architecture takes too long"? Really? Where's your evidence to back this up?



I've used Spring/Hibernate/AOP/DI/TDD/CI/insert-your-favorite-buzzword/etc on a daily basis for almost the past 5 years. I've followed the DDD movement with some curiousity, but if this code sample is indicative of what it amounts to, I honestly don't understand what the fuss is about.

Not even close to DDD by Kaushik Selvaraj

There are lots of flaws on many levels.



  • >> Ramnivas Laddad where he made the assertion that DDD cannot be implemented without help of AOP and DI.

    You got it wrong. He said DDD cannot be "adequately implemented" without AOP. I have posted on how you could use DDD without AOP here .




  • In your example code, none of your entities exhibit any encapsulation. Why do nearly every field have a getter and setter exposed ? There is absolutely no domain business methods in them. By just exposing CRUD methods in addition to getter/setters how can you even call these domain objects? As a previous commenter had posted, are'nt these still anemic?

    Main concept behind Domain Driven Design is adding power to your domain classes which you have not brought out at all. The examples are woefully shallow and cannot be called as DDD examples at all. It is more an example of using spring's DI to inject repositories into DDD. This article does not do justice to elegance and simplicity of DDD.



PS: Next time do some proper research before suggesting matching up various technologies like OSGi with DDD/AOP/Spring etc. If you had any experience implementing either DDD or OSGi you would know that using AOP in OSGi is severly limited. For e.g. aspects have to exist in every single bundle where it has to be applied.

Re: What am I missing? by Phatthana Sitthideth

@srini
nice article

@Rob
Yeah i know exactly what you mean by "what the fuss is about".
From my experiences 80% of these Spring/Hibernate/AOP/DI/TDD/CI/insert-your-favorite-buzzword/etc projects don't need
DDD, it's just CRUD stuff.

As Eric Evans told me, DDD is for the 10%-20% percent of a system -> the truely complicated sh*t.
That logic should be implemented by developers with strong design skills with the help of open minded business analyst -> DDD is a sophisticated
technique for that.

My point is people tend to "ddd"-everthing, i.e.
if anyone tells you: "yeah our system is completely build upon/using DDD".....yeah ok, dream on

None the less i think DDD is great stuff and definitely changes your view of perspective on design/oo/teamwork.


Cheers
Phatthana

It *completely* misses the point... by Ronald Miura

It seems that the author thinks a 'rich domain' is just 'inject DAOs into hibernate-mapped objects'...

Looking at the source code, you can see the domain is just the plain old anemic model, with DAOs (disguised as Repositories) injected.

At least in the examples, it doesn't make sense to use an instance of an entity to 'find' others, which don't even have any relation (but its class) to the first. It is just being used as a Repository (yeah, 'loan.add(newLoan)' IS stupid). And the domain logic, which should be inside the entities, are externalized to the services, which are just glorified procedures.

Where is the 'insight'? Where is the 'objects model the business'? Where is the 'ubiquitous language'?

If you are looking for a DDD example, take a look at the TimeAndMoney (timeandmoney.domainlanguage.com/) library. No, it doesn't have a 'persistence layer', but DDD is not about these, it's about capturing the business into objects. It isn't about CRUD, it's about creating a language in code that matches the language in business (the core of it). It's not about DI or Spring or Hibernate, it's about good, careful, insightful, relentless design.

Re: It *completely* misses the point... by Dustin Woods


If you are looking for a DDD example, take a look at the TimeAndMoney (timeandmoney.domainlanguage.com/) library. No, it doesn't have a 'persistence layer', but DDD is not about these, it's about capturing the business into objects. It isn't about CRUD, it's about creating a language in code that matches the language in business (the core of it). It's not about DI or Spring or Hibernate, it's about good, careful, insightful, relentless design.



"TimeAndMoney" makes a nice example of a library but it is far from any help at all when building an entire application. I personally appreciate samples like these because is shows the struggle that people have trying to apply DDD to real world problems. Without seeing samples that have gotten the blessing of being DDD maybe DDD is for small libraries only and doesn't apply to real world problems. It's easy to criticize Srini for sharing an interpretation of DDD without opening yourself up to criticism with any sample of your own.

Re: It *completely* misses the point... Not! by Geert Pante


If you are looking for a DDD example, take a look at the TimeAndMoney (timeandmoney.domainlanguage.com/) library. No, it doesn't have a 'persistence layer', but DDD is not about these, it's about capturing the business into objects. It isn't about CRUD, it's about creating a language in code that matches the language in business (the core of it). It's not about DI or Spring or Hibernate, it's about good, careful, insightful, relentless design.



"TimeAndMoney" makes a nice example of a library but it is far from any help at all when building an entire application. I personally appreciate samples like these because is shows the struggle that people have trying to apply DDD to real world problems. Without seeing samples that have gotten the blessing of being DDD maybe DDD is for small libraries only and doesn't apply to real world problems. It's easy to criticize Srini for sharing an interpretation of DDD without opening yourself up to criticism with any sample of your own.

Hear, hear!


Having fooled around a bit myself with DDD and Java, I hoped to find a way to do three things at once. Do DDD, avoid having to write a lot of duplicate boiler plate code, and keep Spring/Hibernate/JUnit best practices. In doing so, I independently did the same discovery as mr. Laddad: that AOP could be the missing link.


Indeed, Domain Driven Design is not tied to particular use of any framework, but if Hibernate allows you to auto-generate DAO's and Repositories, and Spring's @Configurable annotations with AOP allows you to auto-generate Factories, why wouldn't you go with the flow?


Srini, I haven't checked your sample code thoroughly, but if you managed to get it all connected and working, you did an excellent job, and it could provide the basis of a lot of our future projects' designs.

Re: No asserts in the tests by Srini Penchikala

Hi Peter, the unit tests for repository classes in the sample application have asserts inside test methods, but you are right, the other test classes like LoanDomainTest should have assert statements to verify state and behavior of domain objects. Also, if you are not already using them, check out the additional assert's available in JUnit 4.4 version (Hamcrest asserts) that add a great value to write and understand the assert logic in test methods. The other unit testing guideline (which is a given to TDD followers) I try to follow is: No log.debug() or log.error() method calls in the test classes, these should be replaced by appropriate assert statements.

It's Great by Ravi Koda

Thanks srini , This is what i am looking for my project.

Regards
Ravi

Re: Mixed feelings by Lindsay Holman

A lot of people have mentioned the presence of CRUD methods on entities. I think this is a fairly fundamental and very important aspect of DDD. The standard reference by Eric Evans specifically states that you should not so this, and for a very good reason - it violates OO design principles. A class should have one responsibility - persistence is not the responsibility of an entity. While it farms the work out to a repository, an object's interface is just as important to defining its responsibilities as the actual implementation.



It is extremely important that when undertaking this approach, the principle are kept in mind and adhered to, as there are pitfalls waiting around the corner for those who don't.



As far as this being more an anaemic model, it is just because of the lack of hard core business logic, and in itself isn't a problem. I don't see a problem with creating an anaemic model from a DDD focus - at least the focus remains on the ubiquitous language.



I have just been involved in rescuing an SOA development. SOA services can be equated to Eric Evans' idea of an application service. This is essentially a gateway into the business logic, or the domain model. The development in question used JAXB to generate classes from an xsd defining the service interface, and to populate objects from the xml message. The services were extremely long, procedural, untestable methods which utilised the generated classes. There was a layer of DAOs which also used these generated classes!! Something to shift focus onto the domain and reinforce the fact that the SOA service is a thin layer whose responsibility is integration - not business logic, would have avoided this.



I find it perplexing the number of SOA oriented developers who dismiss the idea of a rich domain model. It seems to me to highlight a lack of understanding of the very essence of the architecture they are implementing. These two approaches are not mutually exclusive - there are distinct responsibilities in each layer.



Anyway, sorry about the waffle. This is my first post - hi everyone :)

Domain-Obects Java Classes not so intuitive by venkataramana madugundu

Article is great in promoting Domain Driven Design, but the sample application code does not express the domain concepts in java objects so well. For example, typically if there were no automation, a bank which offers loans would typically have a LoanRegister (a loan folder where each loan offered to a borrower is a page) for adding loans, updating loan info etc., So as per my tastes, I would prefer to have a LoanRegister class on which methods like addLoan(Loan), updateLoan(Loan) are exposed.

Re: Mixed feelings by Srini Penchikala

Hi Yuriy, In the sample code, I wanted to show that the Entity objects are first-class citizens in the domain model, they should also take care of the persisting the object's state (by calling a repository or a DAO behind the scenes). Hence the call to the (wired) Loan entity object to add a new loan record. You definitely want to use the domain object that has been associated with DAO and other persistence resources (Hibernate SessionFactory etc) for creating and updating the domain objects. In the example, I could have set the loan data in loan object itself and then call loan.add() method w/o any input arguments (in which case, the domain would act on its own instance).

Re: It's wonderful! by Srini Penchikala

Hi Laurence, Domain objects should also be responsible for persisting the data (CRUD) in addition to encapsulating the state and behavior of business domain entities and the business logic. This way, clients can call the domain objects directly to create and manipulate the domain state instead of relying on DAO's (which are infrastructure related classes in my opinion) to take care of the persistence. Repositories, just like Entities, are domain objects that are there for a purpose (of hiding the DAO implementation details behind the repository classes). It's not always required for the Entities to call Repositories for CRUD functions. You mention Aggregates and Services, these domain elements also have their own characteristics on when to use them in domain model implementation. Eric Evans book is the best source for learning more about all these domain elements.

Re: It's wonderful! by James Bao

Hi Srini, I disagree with you that persistence is the responsibility of Domain objects. Stripping out the data persisting logic from the domain object will make the code more readable and maintainable.

Re: Mixed feelings by Yuriy Zubarev

Another argument against having Persistence CRUD in domain objects is that you have a circular dependency between "domain" and "repository" sub-packages. Circular dependency is never a good thing regardless what kind of xDD you are practicing.

Re: Mixed feelings by Lindsay Holman

Hi Yuriy,

I don't agree with you here. Circular dependencies just signify poor design. You can quite legitimately have a domain object deal with persistence without circular references. Note, a domain object which is an entiy should not be responsible for it's own persistence, a repository object should (Not a DAO - this is rooted in deficiencies of EJB).

The underlying priciple is that the domain model is supposed to be a model of your business. Does it make sense within that domain that you need to store and retrieve entities (say, a loan). Absolutely yes, so this should be handled by a domain object. When you do store a loan in the real world, do you get the loan to do it? No, you stick it in some sort of repository. You can see here, the domain model is modelling the real world.

Typically, as per good design practice, the repository will be comprise an implementation and an interface. All domain type references are confined to the domain layer (model).

The repository will then farm off the technology specific aspects to an object in the infrastructure layer. This can be achieved through extension, delegation, template pattern etc. Whatever way you choose, avoiding cirulcar references is just down to good design.

Typically in a hibernate environment for example, you would have a generic persistence object, or a base persistence object for instance, which takes a class type and an object. Though not really correct, but in line with many codebases, let's call this the HibernateGenericDao class. It implements the interface GenericDao which defines the method "add(String className, Object value)". In the domain model, we have a LoanRepositoryImpl class which wraps GenericDao and implements LoanRepository. LoanRepository defines the method add(Loan loan). The LoanRepositoryImpl.add(Loan loan) implementation delegates to genericDao.add(Loan.getClass().getName(), loan). The HibernateGenericDao then takes care of the hibernate specifics.

LoanRepository, Loan and LoanRepositoryImpl are members of the domain layer. GenericDao and HibernateGenericDao are in the infrastructure layer. The domain layer knows about the infrastructure layer, but the infrastructure layer knows nothing of the domain layer. Perfectly layered, no circular references. If we want to change the persistence mechanism, we plug in a different implementation of GenericDao into LoanRepositoryImpl.

Then, when we want to add a loan, a ui object may collect the details, an application service object collates the details into a loan object, and call loanRepository.add(loan). I don't see what is not clear about this implementation where persistence is handled by a domain object.

Re: It's wonderful! by Lindsay Holman

Persistence is absolutely the resposibility of a domain object - though an entity is not responsible for its own persistence. (see my next post) This distinction between a domain object and an entity object is crucial.

Misleading by Ilya Boyandin

The sample app in this article has little to do with DDD. Chris Richardson's aop-ood is a way better in that sense.

Re: What am I missing? by Srini Penchikala

Hi Rob, In the sample application I focused more on the domain injection capabilities offered by Spring framework and the role AOP in DDD. I agree with you that the Entity objects should have more business logic than what the sample application shows. Also, the method to get the list of ProductRate Value Object's should be in a Repository rather than the Value Object itself.

Re: It's wonderful! by Srini Penchikala

Hi James, if persistence is not the responsibility of Domain objects, where would CRUD logic be handled? We don't want the clients to be calling DAO classes directly, they should be ideally calling some business object which fronts the DAO because data access logic, in my opinion, is an infrastructure concern that the client shouldn't know anything about.

Re: It's wonderful! by Lindsay Holman

Hi Srini,


I really think having repositories and an infrastructure layer, and dao's and a data access layer is a massive overcomplication of a simple problem. As far as why persistence belongs in the domain model (re your reply to James), the simple explanation somes from the domain we are trying to model. Given a traditional paper based office, we have a new client say, we collect their details (at least enough to identify them), we create some sort of file for them, then we store them in a repository of some sort, organised in such a way that we can easily retrieve those details. This obviates the necessity for a repository in the domain layer.



The repository should farm off technical aspects of the persistence to an object in the infratructure layer. There is no need for DAO's, or a data access layer. Data access layers are all about removing that functionality from the domain, which is specifically what we do not want to do. DAO's only came into being because of the shortcomings of the EJB spec. Nobody uses Entity EJB's anymore, so please stop using DAO's.

DDD on 3 tiers (Differents JVM) by iury ribeiro

Hi Srini,

Great discussion! I enjoyed a lot.

I would like to clarify the following case:

As you said that the CRUD methods belong to entity objects(domain object)and to get the others objects through the navigation, So I released in the case where the application is split on 2 JVM accessing a stateless session bean, We need to convert ours POJO on Proxy Pojo to access the facede session.

Am I right?

Regards,

Iury

Sculptor by Patrik Nordwall

Nice article! Looking for a tool that supports this type of design? Take a look at Sculptor...



Sculptor is an Open Source tool that applies the concepts from Domain-Driven Design and Domain Specific Languages.



You express your design intent in a textual specification, from which Sculptor generates high quality Java code and configuration. Sculptor takes care of the technical details, the tedious repetitive work, and let you focus on delivering more business value – and have more fun.



The generated code is based on well-known frameworks, such as Spring Framework, Spring Web Flow, JSF, Hibernate and Java EE.



The DSL and the code generation drives the development and is not a one time shot. It is an iterative process, which can be combined with Test Driven Development and evolutionary design.



Sculptor home: fornax-platform.org/cp/x/aAQ

Re: It's wonderful! by iury ribeiro

Hello Lindsay,

May you clarify my question?

In the following case: where the application is split on 2 (tomcat and jee server) JVM accessing a stateless session bean, We need to convert ours POJO on Proxy to access the facade session. Am I right?

Re: It's wonderful! by Lindsay Holman

Hi Iury,

I'm not entirely clear on exactly what it is you need to do, but I'll take a guess and put something forward.


Typically, our front end will call a SLSB Facade on tier 2. The traditional, and still somewhat sensible way of doing this is implementing an application service via the SLSB. If for instance we want to get a Loan object, tier 1 would call the tier 2 SLSB application service. The application service would have access to the domain model, querying the LoanRepository to find the required Loan object and passing it back.


This type of arrangement allows you to incorporate an SOA implementation alongside the rich domain model. The SLSBs can be thought of as gateways to the model.

Re: DDD on 3 tiers (Differents JVM) by Srini Penchikala

Hi Iury, Sorry for the delayed reply. DDD design and development concepts remain valid even if you are architecting your application as a 2-tier or multi-tier application. Domain objects live (at run-time) behind the facade layer (implemented using stateless session beans or POJO's). One thing to keep in mind (if you have a choice) is to work on the domain layer first to capture the business logic, business rules, persistence etc first and then work on the facade classes which should be just proxy classes to the domain layer (i.e. they shouldn't have business logic, only the orchestrate type of logic).

Re: Sculptor by Srini Penchikala

Hi Patrik, Thanks for info on Sculptor. It looks very interesting. I am currently working on a research project on DDD and Code Generation topic and I have been looking OpenArchitectureWare tool for code generation and MDA purposes. Sculptor has Hibernate and Spring integration which is very coo. I will read about it in more detail and check with you if I have any questions.

Re: It's wonderful! by Mattias Fagerström

Can you explain the difference between an entity object and a domain object?

Re: It's wonderful! by Srini Penchikala

Hi Mattias, Entity object is a type of domain object (Value Object, Service, Repository etc being the other types). I use the terms and definitions covered in Eric Evans' book Domain Driven Design.

Naming throwing by Eduardo Miranda

I got confuse if the idea was give a real example of DDD or just throw all the tools and practices names.

Do you really need all these tools to develop a DDD application?

Re: I *completely* agree by Dimitris Menounos

The article declares the anemic model as an anti-pattern (is it really?) but then, if you look at the source, implements the "rich domain objects" as Entities + embedded DAOs.

Re: Naming throwing by Srini Penchikala

Hi Eduardo, It's not the intention of this article to suggest that every business domain out there in the real world requires all the tools and techniques mentioned in the article. If OOP by itself can represent a business domain and support DDD adequately then no other tools are needed for implementing such a domain. But after working on few domain implementation projects (of various sizes and scopes), I found that other techniques such as DI and AOP can complement OOP in addressing the business domain requirements especially in terms of persistence, transaction management and application security. If you could share your thoughts and experiences on what tools you used in implementing domain driven design projects, that would be great.

Re: I *completely* agree by Srini Penchikala

Hi Dimitris, From my experience after working on few J2EE projects involving different sizes of business domains, I found that anemic model is an anti-pattern to DDD implementation. Most of J2EE developers are still designing the applications with a stateless session bean (facade) that has all the business logic and leaving the domain objects (Entities) with just getters/setters. Can you elaborate more on why you think anemic model is not an anti-pattern? I am thinking may be there are some use cases where anemic model makes sense, but I am curious know more about those use cases. Regarding the sample application, I spent more time in focusing on how to use DI and AOP in a DDD application. You are right, in a real-world DDD application, Entities which should have lot more business logic and domain state manipulation logic than what's included in the code examples.

What about the Grails approach? by Goran Oberg

Thanks for a good article. I have used JPA and the standard DAO approach in a couple of projects (not DDD but still an OK approach), but I'm now involved a Grails based project and that have definitely made me to take a more serious interest in DDD.



What I like about Grails and more specifically the GORM, is the domain centric approach to data access. No daos and no repositories to be implemented, just plain domain classes! A dynamic language like Groovy giving the possibility to constructs like User.findAllByNameAndTimeBetween(name,start,end) without implementing the finder method (dynamically created), just adds to the plus side.



Of course Grails have downsides as well (some of them quite serious to), but it will not stop me from using Grails on certain projects and it will definitely give me some architectural inspiration when I'm back on my next Spring-hibernate project.



Just a small comment on the source code in the article:



Shouldn't finder related methods be static and operations like save act on the object it self?

Re: What about the Grails approach? by Soner Dastan

Hi Srini. First of all thanks for this good article.
I read several articles about DDD but still I could not find out, when to use the DDD approach
makes sense and why the "anemic" principle is an anti-pattern. I can not see that using the anemic model causes issues to call it an anti-pattern.
In the anemic model we also have the separation of responsibilities and so on.
What are the differences except that the domain model in case of DDD includes business logic?
Both models has a similar architecture layering.

Is there an article comparing both approaches with their pro and contras and showing sample use cases where which design style should be used?

Re: What about the Grails approach? by Srini Penchikala

Hi Soner, Thanks for the comments on the article. The main principle that I learned from using DDD in my projects is that Domain comes first and Infrastructure comes second. With this philosophy, I have seen a big difference in how I and other developers approach the design and coding tasks. Regarding the resources for DDD, the best place is to start is Domain Driven Design website. Also, feel free to post this question on DDD yahoo group which is a great forum to discuss DDD related questions and ideas.

DDD and agile by Nima n

agile methodology use user story for gathering requirement, what is user story role in domain driven design?

Re: DDD and agile by Srini Penchikala

Hi Nima, Agile methodologies is a better fit for DDD implementation in the sense that Agile methodologies encourage iterative and incremental development. Modeling, design, development, and unit testing phases in a DDD project are best done using the Agile and Iterative approach.

Domain objects should not call CURD operations by Sandeep akhare

Hi Srini,
Article's starting was good and even i sent this link to my friends saying great implementation for DDD. But when we saw the code in the domain entities method you are calling CURD operation which smells some wrong implementation. You are neglecting basic rule of domain driven design which says that your domain should be persistance ignorent.

Please let me know if my understanding is wrong. What should is say to my friends whome i sent this link .

Re: Mixed feelings by H S

Srini,
First thanks a lot for good article. I followed through your article and reviews of different people.

I still have one question (as Lindsay said) and you also agreed that persistence should be the responsibility of the repository rather than the entity. We need one domain object which would be acting as a (service) creating a entity and persisting the entity to DB.
e.g
Loan newLoan = CreateLoanWithBusinessRequirements()
loanRepository.save(newLoan)
Which domain object will you add this kind of behavior, and do we require such domain object for each entity in our domain?

don't inject repository into model by Peng Sunny

the sample is not perfect, don't inject any technology into business model, decouple "What" from "How". we can use Domain Events pattern to do communication with them. all these have implemented in my famework(DDD framework for Java) jdon.dev.java.net

Re: Not even close to DDD by 李 引

eclipse aspectj can worked in osgi style.

Domain Layer uses the Infrastructure Layer. The layer below it. by Roy Oliver

I am highly confused by the implementations I'm seeing all over the net. Recall this? www.herrodius.com/blog/wp-content/uploads/2010/... - Eric's Layered Architecture? The domain layer uses the infrastructure layer and has the ability to inherit objects from it. Not the other way around. Did I read it wrong? Why are projects referencing the domain layer from the infrastructure layer? That seems to be a direct violation of DDD.

Could some of you attempt to explain this?

I'm seriously confused.

A comment on the sample application by Enrique Molinari

I found DDD interesting, but I also think that Object Oriented Programming is DDD by definition. And with this in mind, I don't understand why the domain objects in the sample application are full of getters and setters and without any interesting behaviour. Probably the implemented requirements are too simple and that does not help to create a rich object model ? The process loan funding might have an interesting business logic that, from my understanding, should be modeled in your domain objects, rather than in a service method. I have posted an example related with object oriented design here: www.copypasteisforword.com/notes/object-oriente....

Re: It's wonderful! by Felipe Guarneri

Great!

Very bad example application, practically anti-DDD example by Georgi Danov

I was going to read the article, but colleague showed me the sample application first. The sample application is total s**t and has nothing to do with DDD so I am totally not going to waste my time reading the article. Read the book man...

Re: Very bad example application, practically anti-DDD example by Roman Tmk

When saying that something is not good, you should point out what exactly you disagree with, otherwise your comment has no meaning.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

52 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2013 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT