Archive for the ‘architecture’ Category.

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.

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.

Code Quality

One kind of cancer in software development is undoubtedly the lack of code quality. I’ve seen a lot of simple and complex applications suffering with bizarre algorithms, crazy logic flows, anti-patterns, ugly & unreadable code, and something else I cannot remember right now :)

I believe that code quality must be one of top things a developer must bear in mind. Quality means a lot of different things, such as :

  • your code works perfectly.
  • it does exactly what it is supposed to do
  • it’s testable
  • it’s readable
  • it’s maintainable
  • it’s extensible
  • it has a nice design
  • and more…

Every software project started on earth is to solve a customer problem, and it implies deadlines, pressure, new requirements, more pressure again and so on. But, we can’t let things like business complexity or pressure to affect our code quality, because every little hack left behind will become a dragon in the future, ready to eat us when we are out of the blue. :)

To achieve quality, a software must be simple, that means we should do things as simple as possible, for the sake of these things above. But, unfortunately simple does not mean “easy”. I can show an example of “simple” and “easy” :

I can state a simple development, as a software that is well designed, that has passed through some analysis, that has a good architecture, where the developers use unit tests and so on. It may forces you to spend a little more time to do these things, but the ROI will be that your life will be very simple whenever you try to extend or change your software.

On the other hand, an “easy” way would be to put every code inside the JSP file, or create a strong coupling among your classes and components, don’t respect any design pattern, and all of this for the sake of a “false agility”. But in this case this developer will have a very hard life whenever he or she try to change the software.

So, let’s have a very nice code with high quality !

Will a persistence framework always be enough ?

Indeed, persistence is always a nice topic to discuss, and I’d like to bring here more one round about this so nice subject.

In the early Java days, we used to create our persistence layer programatically, we simply used an Active Record design pattern ( or something closer to it) to make our classes “persistable”. Some time later, we introduced the DAO design pattern inside our applications, creating an abstraction to separate our “dirty work” to access any data resource, in this case, most common a database connection, and CRUD operations.

Nowadays, we’ve seen the advent of Object-Relational mapping tools, such as Hibernate, TopLink, Kodo, among many others. Nobody can deny that these tools are becoming better and richier every day, adding new features, development plugins, database support and so on. The best advantage of using them is the bridge they make between our application to the database, solving or trying to solve the well known object-relational impedance mismatch problem. Besides that they have some mechanisms that facilitate our lives as developers. I can point out Hibernate features :

  • Transparent Persistence
  • Flexible Mapping
  • Query Facilities
  • Metadata Facilities, among others.

You can know more looking into Hibernate’s website.

In opposition what people tend to believe, an object-relational mapping tool will be enough when we won’t need some in depth database specific capability. But, sometimes we need more. Depending on what kind of system we are dealing with, we’ll need care more about performance, we may have some legacy database to deal with, there might have some company policy that forces us to access data through stored procedures, or issue some special SQL statement, a PL/SQL block, a Transact-SQL block, or something related.

In these cases, I’d like to stand against the myth about portability between databases !

As I told before, there are people who believe that a persistence framework will shield their applications about every single database system, or evey every single different problem found in an Enterprise Software. That’s indeed a really wrong ideia about enterprise software.

Instead, I do prefer to give an appropriate solution for each case. The the role of any software developer, is to choose the most suitable solution for a given problem. We should not limit everything to a single solution, doing so, we might be making things more difficult to solve than it should be.

It’s not a sin to use a separate DAO and make JDBC calls, and it WON’T prevent you to migrate your application to another database. Of course a dose of common sense, analysis and good design are always welcomed. There are design patterns and guidelines to help us in how to develop a better data access layer using both a persistence framework and plain sql/jdbc access, and the effort to migrate your application won’t be a big deal, as long as you didn’t build your entire software inside your database.

I consider two nice actions dealing with this situation :

  1. Keep any specific sql inside your database ( as a stored procedure ). Doing so,you’ll have a centralized repository, you can have your sql tested and validated for free, instead of keeping strings inside your application, that can change and break your functionality.
  2. Issue any batch operation to your database, because in most cases it’s is easier and cheaper to call a procedure/function to query and calculate something ( that is already there in the database), rather than try to load this data on a distributed environment, passing through a network, and summarize your information in memory.

So, my answer is NO, there are situations where a persistence framework won’t be enough to solve your problems. You should bear in mind that there is more than one way to solve a problem, and keep your view as pragmatic as possible, in order to don’t limit your solution to a single vendor / product / architecture / etc.

In this first post, I provided some ground about this discussion, there are a lot more to discuss about this subject, and I will be posting more about this sooner. ;)