Software Developing: More About Domain Driven Design 
The idea of this post is to explore ideas that have been previously mentioned on
Software Developing: Domain Driven Design and may were seen as unclear thoughts. In that post, I've answered
jff with an example of a Library Management System, we'll look in that example in detail.
Before going any further I want to clarify some points.
What is the business logic?All applications have one or more goals, even really simple ones like
hello world have one (which is printing
hello world on the screen).
These goals reflect the needs of a real life problem within a certain scope. This scope can be identified as the business and all the rules that are applied in it are what is called
the business logic.
When using an object oriented approach - specially when using a domain driven approach - is common to identify the entities involved in the business and map them in objects (the so called domain objects). The relation established between domain objects will also be part of the business logic.
When should Domain Driven Design (DDD) be used?DDD is most effective when we have a large and complex domains. This happens because when DDD is well applied not only the model is well scalable but also self-contained. We'll see more about this below when the library management example starts.
Though, since there are no perfect solutions, DDD might not be the best solution to every software design problem. When having a simple domain - should be understood as few domain objects and not very complex business logic - using design patterns such as
Transactional Script might be simpler and more effective.
I won't go into detail of Transaction Scripts since it's out of this post scope, but if anyone wants to discuss about them feel free to post comments.
How do we model a certain problem?This is definitely the trickiest question. There is no formula to find the best model for a certain problem but there's a procedure on how to build a model.
- Identify involved entities;
- Define relations between those entities;
- Map business logic in the entities.
In my opinion, the best way to show how the modelling process works is by example. So, as has been said before I'll use the Library Management System(LMS) example which will be divided in four stages. This division is due to two main reasons, first because showing all the process in a constructive way is easier for the reader to follow and also because it shows that the concept of model design is scalable.
Stage 1: So you want to build a LMSProblem: a system to manage library users and the books they reserve is needed. Should be kept in mind that a given user at any time can have a maximum of five reserves. If a book belongs to the adult section it can only be reserved by users who are over 18.
First we identify the entities related with the problem: there's the
library user and the
book (step 1). We have a relation between both, the act of an user reserve a book.
An user can reserve
many books and a book can be reserved by
many users in different periods of time (step 2).

With this information we can already sketch a really simple model, as the one present at the right.
Now we collect the business logic in the problem. In this simple case, the business logic is the following:
- maximum of five reservations for user;
- users under 18 cannot reserve books from the adult section.
- underlying logic, a book can only be reserved at a certain moment if it's not already reserved by an user.
After the identification of the business logic, the decision about where to put has to be made. The 1st rule is related with the user, the other two rules are related with the book.
Here's a suggestion for the implementation (I hope there's no problemin joining two classes in the same code block)(step 3):
package net.pabrantes.example.library.model
public class LibraryUser {
//other fields
private List<Book> reservedBooks;
// more Code
public addReservation(Book book) {
if(reservedBook.size()<5 && book.canBeReservedBy(
this)) {
this.reservedBooks(book);
book.isReserved(
true);
}
}
}
public class Book {
// code here
String section;
boolean reserved;
public boolean isReserved() {
return reserved;
}
private boolean acceptedAge(
Integer age) {
return (!section.equals(
"adult")) ?
true : age > 18;
}
public boolean canBeReservedBy(LibraryUser user) {
if(!isReserved() && acceptedAge(user.getAge());
}
// more code
}
A book is reserved only if the user as less than five books (rule number 1) and if the book can be reserved by the user, notice that it's the Book that
knows if can be reserved by a given user (implements rule 2 and 3).
Should be kept in mind that this kind of operations are called within a transactional context - for example, a service layer - that's why the variables aren't synchronized (a race condition on the
isReserved can happen if the method isn't run as an atomic instruction).
In my opinion the worst problem in this solution is the lack of time tracking in the reservations, but since it's an example it's not that bad.
Stage 2: Registered and unregistered users
Problem: After a first implementation (stage 1) the concept of registered and unregistered library users is introduced. The main difference is that the registered user has no limit on book reservation.
Since both kind of library users are
library users, a good way of modelling this part of the problem is by using
inheritance. The new model can be seen in the schematic on the right. The super class will be abstract and contain all the shared behaviour.
On the
Registered User there's only the need to override the
addReservation method in order to remove the size verification.
Stage 3: The library also allows DVD reservationProblem: The library also allows DVD reservation, but only for registered users.
We have a new entity, which is a DVD. Being the DVD and Book both items that the library allows reservation, it makes sense to create them as sub-classes of a new object called Library Item.
The
Registered User has a relation - the reservation - with
Library Item instead of Book, since it can reserve Books and DVDs. On the other hand the
Unregistered User will keep the relation with Book only.
The model onces again changes and the result is:

Now the good thing is that the model applies the restrictions, there is no need for extra code. With such clean design there is no need for the use of the "
ugly" instanceof operator in order to identified which type of library item an user is trying to reserve.
Stage 4: A bigger system, now only the users but also the employeesImagine that the LMS domain is bigger than a simple the library users management with users, books, DVDs and reservations. It also has an administrative part, for example it has the concept of employee and all the accounting domain.
The subdomains could intersect each other if necessary, though, the employee subdomain and the reservation subdomain probably wouldn't!
The only common point is that library users, and employees are both Person.
Leaving most of the accounting domain apart here is the new domain model:

A question that might be asked is why aren't employee and library user sub-classes of person instead of having relations with it. Well the answer is simple, imagine that you have a Person that is employee and a library user at the same time. If you used inheritance you would have two different instances (one for employee and another one for library user) of the same person!
ConclusionsWith this post I tried to give more detail about DDD, also an example of DDD was shown. With the previous example, it was not only showed how the process of domain modelling works, but also that DDD can simplify the domain grown and create self contained code.
Hope you've found this interesting.