Domain Driven Design, The Repository pattern

I’ve seen so many times a heated discussion about Repositories in Domain Driven Design, there is a kind of misunderstanding and/or confusion about what really a Repository is.

People usually disagree about the role of the Repository, if it should be a kind of  “Data Access Layer”, such as a DAO or if it must be something that is injected in the domain class, then it will talk to the DAO in the beneath layer.

I’ve always wondered why people had these fights, but now I can see why ! The thing is, as far as I read in the book (Chapter 10 : Supple Design),  the examples of Reposotory has been shown almost exactly as a DAO implementation. I even downloaded the source code examples from the Domain Driven Design Community, and the example IS a DAO implementation, as I’m showing below :

package se.citerus.dddsample.domain.model.cargo;

import java.util.List;

public interface CargoRepository {

  /**
   * Finds a cargo using given id.
   *
   * @param trackingId Id
   * @return Cargo if found, else {@code null}
   */
  Cargo find(TrackingId trackingId);

  /**
   * Finds all cargo.
   *
   * @return All cargo.
   */
  List findAll();

  /**
   * Saves given cargo.
   *
   * @param cargo cargo to save
   */
  void store(Cargo cargo);

  /**
   * @return A unique, generated tracking Id.
   */
  TrackingId nextTrackingId();

}

and the implementation

package se.citerus.dddsample.infrastructure.persistence.hibernate;

import org.springframework.stereotype.Repository;
import se.citerus.dddsample.domain.model.cargo.Cargo;
import se.citerus.dddsample.domain.model.cargo.CargoRepository;
import se.citerus.dddsample.domain.model.cargo.TrackingId;

import java.util.List;
import java.util.UUID;

/**
 * Hibernate implementation of CargoRepository.
 */
@Repository
public class CargoRepositoryHibernate extends HibernateRepository implements CargoRepository {

  public Cargo find(TrackingId tid) {
    return (Cargo) getSession().
      createQuery("from Cargo where trackingId = :tid").
      setParameter("tid", tid).
      uniqueResult();
  }

  public void store(Cargo cargo) {
    getSession().saveOrUpdate(cargo);
    // Delete-orphan does not seem to work correctly when the parent is a component
    getSession().createSQLQuery("delete from Leg where cargo_id = null").executeUpdate();
  }

  public TrackingId nextTrackingId() {
    // TODO use an actual DB sequence here, UUID is for in-mem
    final String random = UUID.randomUUID().toString().toUpperCase();
    return new TrackingId(
      random.substring(0, random.indexOf("-"))
    );
  }

  public List findAll() {
    return getSession().createQuery("from Cargo").list();
  }

}

This Repository is used by a class called BookingServiceImpl :

package se.citerus.dddsample.application.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Transactional;
import se.citerus.dddsample.application.BookingService;
import se.citerus.dddsample.domain.model.cargo.*;
import se.citerus.dddsample.domain.model.location.Location;
import se.citerus.dddsample.domain.model.location.LocationRepository;
import se.citerus.dddsample.domain.model.location.UnLocode;
import se.citerus.dddsample.domain.service.RoutingService;

import java.util.Collections;
import java.util.Date;
import java.util.List;

public final class BookingServiceImpl implements BookingService {

  private final CargoRepository cargoRepository;
  private final LocationRepository locationRepository;
  private final RoutingService routingService;
  private final Log logger = LogFactory.getLog(getClass());

  public BookingServiceImpl(final CargoRepository cargoRepository,
                            final LocationRepository locationRepository,
                            final RoutingService routingService) {
    this.cargoRepository = cargoRepository;
    this.locationRepository = locationRepository;
    this.routingService = routingService;
  }

  @Override
  @Transactional
  public TrackingId bookNewCargo(final UnLocode originUnLocode,
                                 final UnLocode destinationUnLocode,
                                 final Date arrivalDeadline) {
    // TODO modeling this as a cargo factory might be suitable
    final TrackingId trackingId = cargoRepository.nextTrackingId();
    final Location origin = locationRepository.find(originUnLocode);
    final Location destination = locationRepository.find(destinationUnLocode);
    final RouteSpecification routeSpecification = new RouteSpecification(origin, destination, arrivalDeadline);

    final Cargo cargo = new Cargo(trackingId, routeSpecification);

    cargoRepository.store(cargo);
    logger.info("Booked new cargo with tracking id " + cargo.trackingId().idString());

    return cargo.trackingId();
  }

  @Override
  @Transactional
  public List requestPossibleRoutesForCargo(final TrackingId trackingId) {
    final Cargo cargo = cargoRepository.find(trackingId);

    if (cargo == null) {
      return Collections.emptyList();
    }

    return routingService.fetchRoutesForSpecification(cargo.routeSpecification());
  }

  @Override
  @Transactional
  public void assignCargoToRoute(final Itinerary itinerary, final TrackingId trackingId) {
    final Cargo cargo = cargoRepository.find(trackingId);
    if (cargo == null) {
      throw new IllegalArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
    }

    cargo.assignToRoute(itinerary);
    cargoRepository.store(cargo);

    logger.info("Assigned cargo " + trackingId + " to new route");
  }

  @Override
  @Transactional
  public void changeDestination(final TrackingId trackingId, final UnLocode unLocode) {
    final Cargo cargo = cargoRepository.find(trackingId);
    final Location newDestination = locationRepository.find(unLocode);

    final RouteSpecification routeSpecification = new RouteSpecification(
      cargo.origin(), newDestination, cargo.routeSpecification().arrivalDeadline()
    );
    cargo.specifyNewRoute(routeSpecification);

    cargoRepository.store(cargo);
    logger.info("Changed destination for cargo " + trackingId + " to " + routeSpecification.destination());
  }

}

Well, I cannot deny that I did not dig so deep into the code ( and I did not finish the book ) yet,
but what I can state for sure is that this architecture really looks like this sequence :

Repository Sequence Diagram
Also, the layering :

Layering Repository Diagram
Ok, I know I am over simplifying things here, but my intention is only to communicate my point of view about
the topic. I’m not saying that what is inside this code is wrong at all, I am just skeptical about how “new” or
effective this thing is, because I’ve been developing large scale software systems using the same approach, but with a
different name “DAO”, and so far I could not see anything different from this. I might let you guys twist my arms in the end of the book,
but so far I’m pretty sure the Repository and a DAO pattern are the same thing.

Any idea, suggestions, thoughts and counter-argument are very welcome ! :)

Building a ubiquitous language – 1

The ubiquitous language is one of the crucial parts of Domain Driven Design, because it’s the basis of all communication among all the team. It’s hard to point out how it’s important to a project, because maybe everyone inside a project have a particular “view” about the same project, I mean a business analyst would be closer to the user who is giving the requirements, and afterwords these same requirements will be translated to a bunch of documents and diagrams that will ultimately reach the developers, who will deliver the most waited product, the production code!

As I stated before, the communication is the heart of everything in software development, so, how can we achieve of deliver the software that the customer wants if we can’t completely understand the user language, jargons and way of work ? we simply CAN’T.

I remember a project where I worked, first providing bug fixes, and later working to re-write it, where we had a glossary about all the terms the software had, of course, they were all related to the users terms. This application was a governamental app, that handled some kind of documents and users workflow. So, the users usually talk to us using their language, about how the documents should be “routed” between two departments, how it should be handled, who was responsible for “stamp”, “endorse”, “forward” or “deny” something related to the documents they were receiving. The glossary was a nice tool to capture those things we did not know, because we’re all IT guys, not business owners.

The bad thing was that this was the only place where we had some insight about what the user think or need, and what are their jargons and way to work. Our domain model did not express those things at all, so it was hard to get some clue about what that software was in the first place, because the code did not express the domain model, and worse, the domain model did not express the business case. We only started to have some clue after few meeting with the users, then we started to say “Eureka” this thing is that piece of code !

Domain Driven Design

After a long time, I’m rushing to finish the Eric Evans best seller book Domain Driven Design, and I found very interesting the ideas inside it. I’ve been fan of object-oriented, software architecture and OOAD since the first time I learned OO, a long time ago.

The idea behind Domain Driven Design is very simple :  Put the model to work through a set of techniques that will make the development easier, things more clear, and shield the domain model against things that doesn’t belong to there. As a known issue, the domain model is the most critical issue behind enterprise software development, because it’s the heart of every software written by a human. Every single funcionality comes from it, and the domain is the basis of all external interfaces and services, because is the Domain Model responsibility’s to deal with the business issues.

Seems to be clear and easy to understand ? the answer is yes and no !

Software is about humans writing software ( good or bad ones ), and a software is just a tool to achieve a business goal, such as “place an order” to buy a book. The company’s goal is to sell the book, but it will need a good software that supports their business needs. Coming back to the part of putting the model to work, where a model is an abstraction of the reality, I mean, a way to visualize and communicate the ideas behind that particular software that we’re writing.

I’ve seen so many times a model that has little to say about the software that is running or it completely does not say anything anymore about working program, because someone draw it in the past, but they did not evolve it, in order to keep track of their communication. It’s very frustrating to start work on a software like this, because it looks like there is a documentation or concepts that will guide us to understand the problems the software is supposed to deal with, but in the end what exists is a poor picture about some fact in the past. So, domain driven design tackles this issue, putting the model to work, bringing life to these pictures, in order to communicate what exacly the software is, keeping track of changes, creating a unique vocabulary between technical and non-technical people ( the Ubiquitous Language ), that is a technique to put everybody on the same page, speaking the same language.

Talking about Ubiquitous Language, I answered a post at linkedin few days ago, because there was a person who asked which “Jargons” he should use to present a software architecture, and I just answered him, use a language that the his audience can understand better, preferrably use or build a Ubiquitous Languag, because you can’t have a concept that the user doesn’t understand, because it will lead you to an infinite talk about what is what, there will be lots of misconceptions and you’ll fail to deliver a good software… and I hope he listened to me.

Making your code more testable

Testability is one of the most beautiful, desireable and must have feature that a code must be compliant. Nowadays there is no space for untested and low quality code, that means many problems at production environments, long hours debugging code, and late delivery.

As usual, this is again a farly big subject that I will try to resume in few tips to improve code’s testability as follow :

First of all, start designing and writing a test for your code before you write your business code, just follow test driven development approach.

Never write long methods, because it will probably lead to low quality code and cluttered design, as a result it will make your test very difficult. If there is a need for such a big calculation, temporary variables or things like this, then just split the big method into smaller methods and delegate your calls.

Add the right responsibility to the right object, another smell that will make your tests hard is when one object knows too much about the other object’s internals.

Try to write cleaner and less code, because less you write, less errors you’ll produce/find, and faster will be your program.

Singletons are usually evil for tests, because they usually cache some data that may hurt you.

Letting people work

One and while I catch myself thinking about why the organizations don’t let people work. Indeed, this is a controversial thought, because every single worker is hired to WORK! But in practice this is not what happens in the reality.

I’ve seen many many times, very talented people being blocked by some “rule” or someone that think the person is not able or “was not hired” to contribute on that way. I really like to think on a contrary way of this line, because my coaching personality like to see people evolving, become personally and technically better, it’s a pleasure to me :)

So, this must be a mantra for managers and leaders, if your team can run 100 km/h don’t make them run at 5 km/h, because it’s very frustrating, we should let people be the best they can be, trust them, encourage them, coach and support them.

The bottom line here is to treat people as people, not as robots, because people can see, hear, smell, feel, have emotions, and so one. Sometimes you have only to listen to your team, and that will be enough. Don’t centralize, don’t block creativity, don’t be afraid of trying something new, don’t wrongly control, just follow, coach, support and be part of everything.

A long time ago…

Hi All,

Wow, it has been a long time since my last post. Unfortunately I’ve been doing so many things at once, and I couldn’t even write a single line. But now I have a free time to do this.

So, I promise I will be posting interesting things here again. One thing among the other 10000 is my preparation for the IBM SOA Certification, and I’d like to bring here some discussions about it. I found very interesting things in my studies :)

Another thing I will be posting is about EAI tools, such as IBM MQ, TIBCO, ServiceMix and so on.

So, stay tuned !

See ya.

The Java Development Environment

Well, you can call me nostalgic, but I really miss it :)

What I miss in Java development environment is a tool or a set of tools that makes easy to develop and provide a good workbench for developers, just like the old Delphi or nowadays Visual Studio .NET.

Just to clarify I am not an IDE addicted and I like to perform some manual tunnings in the application as well, but as JEE development gets more complex, like using Spring, Hibernate, EJB 3, WebServices, JSF, and a huge stack of frameworks sometimes it’s difficult to get everything configured, setup, tested and validated quickly.

There are plugins for eclipse, IntelliJ that helps a lot, and NetBeans is doing a great job on this direction trying to build a unified environment ( NetBeans IDE + GlassFish + Frameworks support and so on ) to help developers to have a more consistent environment.

One hard to goal to achieve to bring a good level of productivity to the development team with the tools they are using, I mean, we always have to use lots of things, such as eclipse, maven, and so on, and sometimes the time spent struggling to some problem because they don’t have the right tool. But, I am confident we are getting better with out tools.

The curse of custom code

Somebody might ask me : Marcio, aren’t you a developer as well ?? and I would answer : Yes, of course.

Then this same person can ask me again : Don’t you like to create new code by yourself ? and I would answer : Yes, and tell him a good story…. :)

This real story that happens in many companies is really sad, and probably will keep happening.

I’ve seen many people and companies that simply love develop something new by themselves, well, that’s not a bad idea at first look, but we should always look at other options. Sometimes we try to re-code something that already exists as a tool, application server, monitoring device and so on.

The point is that sometimes it’s way less expensive if we buy something ready to be used, such as a component or integration tool, rather than try to develop it internally in the company. The main problem is related to the TCO, because after ( or while ) developing something new we need to extensively test it to achieve maturity, and there are things that are not so simply to test, like distribution and concurrency.

This is a rule I use, whenever I am architecting/designing something new I always look for reuse something, and this can be something already done by the team or an external componente offered by a vendor.

The calculation is simple, try to measure or to estimate how many hours each developer should spend to develop the new solution, then add more time to test, more time to bug fixes, and then search for a similar product and compare the prices.

Do you do what you say ?

This post is about how open we are about something new. I’ve seen lots of people saying that they like to do new thinks, experiment some new technology/methodology, try to experience a new way of produce something and so one… But the sad fact is that the most part of them feel themselves frightened about do something new. I’m not saying that we should do things without care, or blindly develop a solution based on some esoteric personal wish to deploy some alpha library into production. I am definitely not saying that !

That’s perfectly fine to disagree on doing something stupid or irresponsible, but we should not be afraid of try a new solution, if we can do something better, then let’s do it.

My point is that we should be able to listen, be opened to try, and at least TEST the new proposal we are facing, preferrabily without preconceptions, judgments and prejudices !

A good bookshelf

Well, I’ve been postponing this for so long, but not anymore :)

If you didn’t already read my post about learning, please read it first.

These are the books I consider nice books to learn how to program, what is agile methodologies, OO/OOAD, Java/J2EE/JEE and Software Architecture.

1) To learn learn Java and JEE you should read this books :

Head First Java, 2nd Edition -> This book is a very nice and didactic introduction about Java (Fundamentals).

Test Driven Development: By Example -> The title talks for itself.

SCJP Sun Certified Programmer for Java 6 Exam 310-065 -> If you want to take the certification and have an in depth explanation about some core java subjects, this book is for you. (Fundamentals)

Head First Servlets and JSP -> This book is about Web Development with Java, and also a help to pass in the certification, this book is part of Head First Series, that is a very didactic reading.  When I was studying Java Web Development, I used the next one, but feel free to choose the most convenient 4u. ( Web Dev )

SCWCD Exam Study Kit -> The same subject as the previous one. Actually there is a second edition of this book, but as I don’t read it yet, I’m suggesting the first edition. ( Web Dev )

Head First EJB -> The best book to learn the fundamentals of EJB 2.x spec. Of course this specification became deprecated with the introduction of EJB 3 spec, but there still a lot of things running on the previous spec in the world. So, it’s nice to know how things work if you have to provide some maintenance on this ( Distributed Programming )

Mastering Enterprise JavaBeans, 3rd Edition -> The same as before, but this book will give you another view ( not so didactic ) about EJB 2.x ( Distributed Programming )

EJB Design Patterns: Advanced Patterns, Processes, and Idioms -> Almost the same thing as I wrote for Head First EJB… if you want or need to develop something on that way, take a look at this book. ( Distributed Programming )

Enterprise JavaBeans 3.0 (5th Edition) -> Now we got the an interesting point. In this book you’ll learn the new way of develop distributed components using the EJB 3.0 spec. This book shows how to work with business components as pojos, the life cycle, mapping the database ( JPA ) and more. ( Distributed Programming )

Java Messaging -> Here you will learn distributed programming model in java using asynchronous messages and JMS.

Core J2EE Patterns: Best Practices and Design Strategies (2nd Edition) -> Design Patterns focused on the J2EE world.

2) To learn Software Integration, SOA and EAI :

Service-Oriented Architecture (SOA): Concepts, Technology, and Design -> This is a award winner book about SOA. Here you’ll learn the guts of SOA, the concepts, what is a service, how to build a service, how to compose a service, what is the true and the false SOA. This book is a must read for every one that wants to work with software integration. ( Distributed Programming / SOA )

SOA Principles of Service Design -> A sweet continuation of the above subject. ( Distributed Programming / SOA )

Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions -> A book about Enterprise Application Integration. This book shows lots of design patterns about how to handle software integration using messaging. ( Distributed Programming / EAI / Messaging )

3) If you wanna learn about what UML is and how to use it, then this books will help you :

UML Distilled -> Although this book is about the old UML specification (1.3) I still consider it a good introduction, but feel free to choose any other you want !!!!

4) Learning OOAD :

Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) -> As the book’s title said.

5) To Learn Design Patterns and Software Architecture :

Head First Design Patterns -> An introduction about what design patterns are and how to use it properly. I recommend you to read this book first because it was written on a simple, visual and didactic language, and you won’t have to fight with the complex code that the Gamma’s book will show you ;)

Design Patterns: Elements of Reusable Object-Oriented Software -> This is the design patterns book ! At this point things will become very interesting. Here you’ll learn in depth how to apply design patterns to avoid code duplication, bad designs and make you software flexible enough to accommodate changes easily and keep woking. The down side of this book is the C++ syntax, but indeed this is one of the best books you ever read !

Patterns of Enterprise Application Architecture -> This is an awesome book about Enterprise Software Architecture. This one is a must read for all enterprise software developers. It covers a wide range of topics, such as layering your application, concurrency, domain models, remoting, presentation patterns and more.

Pattern-Oriented Software Architecture Volume 1: A System of Patterns -> Another great book about software architecture, here you’ll learn a more general SA.

Software Architecture in Practice (2nd Edition) -> Another sweet SA book. This one has lots of good contents about what is an architecture, how to create it, how to document, evaluate and analyze the costs. Throughout the book you’ll see very beautiful examples about many different systems challenges and their solution.

Domain-Driven Design: Tackling Complexity in the Heart of Software -> Here Eric Evans brings valuable thoughts and teachings in how to design a good and functional software taking care, modeling and preserving the domain model.

Applying Domain-Driven Design and Patterns: With Examples in C# and .NET -> Maybe the concepts of Evans book will be dense to digest, so this book will help us with some other practical examples.

6) Learning about Agile Software Development :

Extreme Programming Explained: Embrace Change (2nd Edition) -> The roots of XP development.

Agile Project Management with Scrum (Microsoft Professional) -> Scrum from manager’s perspective (Scrum Master).

Agile Software Development with SCRUM -> Scrum for software developers.

Lean Software Development: An Agile Toolkit -> Lean principles in software development management and process.

Well, I’m gonna stop by here, what else I will propose you to buy the whole amazon website + the company :D

I will revisit this subject sooner, trying to bring something else to share with you. Another tip I want to share it that you should not feel unmotivated because there are so many books up there !!!

You don’t need, you can’t and you won’t read everything at once ! what else you’ll need a psychiatrist, in order to help you to recover you mind. As I don’t want you to damage your brain, I will ask you to follow my tips :

I tried to put the books on some kind of “natural” way, kind from beginning to expert, but feel free to choose whatever fit in your needs, you can mix basic ones with distributed computing or even architectural with methodologies. I tried to make it easy for novices to have an “easier” path to go, but you can build your own path and feed your knowledge hungry !

I hope I could help you to learn more and better, feel free to post a comment back !

See Ya !