Showing posts with label DDD. Show all posts
Showing posts with label DDD. Show all posts

Thursday, February 3, 2011

Mixin Composition

I think one of the best features in Scala is traits. Using traits it is possible to compose small pieces of behavior and state in an elegant way. I miss traits when I use Java. To mitigate that problem I have implemented support for traits in Sculptor. This article illustrates how this tool can be used for designing good, rich, domain models with traits.

Traits provide a mixin composition mechanism that is missing in Java. Similar to interfaces in Java, traits are used to define object types by specifying the signature of the supported methods. Unlike interfaces, traits can be partially implemented; i.e. it is possible to define implementations for some methods. Similar to abstract classes, but you don't have to wast your single inheritance opportunity.

How many times have you stared at java code like this:
if (p1.compareTo(p2) <= 0)

Why not spell it out, to make the code more readable:
if (p1.lessThanOrEquals(p2))

We seldom do that, because implementing 4 methods, lessThan, lessThanOrEquals, greaterThan and greaterThanOrEquals, in each and every class that needs to be compared is too much work. We stick to the cryptical compareTo.

What if I say you only have to implement them once and then you can easily mixin the methods in each and every class that needs to be compared or sorted in some way.

I hope I don't have to elaborate on how bad idea it is to try to use inheritance (base class) for these kind of reusable pieces of code.

In Sculptor's textual DSL model traits are defined like this:

Trait Ordered {
def boolean greaterThan(@Ordered other);
def boolean greaterThanOrEquals(@Ordered other);
def boolean lessThan(@Ordered other);
def boolean lessThanOrEquals(@Ordered other);
def abstract protected int compare(@Ordered other);
}

Entity Product with Ordered {
String name
}

After code generation this means that you can implement the 4 comparison methods once, in the Ordered trait, and they will be available in Product and other domain objects that are defined 'with Ordered'. The compare method must still be implemented in Product, because it is there you know what to compare with. The internal, generated, implementation is based on delegation, i.e. no magic.

Let us define another trait, which illustrates that traits also can hold state.

Trait PriceTag {
- protected Money normalPrice
protected double discount
def Money price;
def Money price(String currency);
}

Entity Product with PriceTag {
String name
}

BasicType Money with Ordered {
BigDecimal amount
String currency
}

This means that normalPrice and discount will be mixed in to Product. You implement the price methods in the PriceTag trait. Product and all other domain objects that are defined 'with PriceTag' will have those fields and methods.

Wouldn't it be nice to be able to compare product by price? Let us do that by combining the two traits. First add the compare method in PriceTag, so that you only have to implement it at one place.

Trait PriceTag {
- protected Money normalPrice
protected double discount
def Money price;
def Money price(String currency);
def protected int compare(Ordered other);
}

Then mixin both traits into Product

Entity Product with Ordered with PriceTag {
String name
}


That's it. We have designed products with a rich price and compare interface.
Note that compareTo is no longer implemented in Product, only in PriceTag.

Try this new feature in latest Sculptor 2.0.0-SNAPSHOT.

Wednesday, April 28, 2010

MongoDB with Sculptor - Associations

This post is part of a series of articles describing the support for MongoDB in Sculptor. This post explains how associations and inheritance are managed.

MongoDB is not a relational database and there is no such thing as joins. You can still use associations between domain objects. Associations can be of two main categories, either embedded or reference by id.

Aggregates

Aggregates are one of the core building blocks in Domain-Driven Design (DDD). MongoDB has perfect support for aggregates, since an associated object can be stored as an embedded document, i.e. it belongs to parent object and cannot be shared between several objects.

Let us repeat what DDD says about aggregates:
An Aggregate is a group of associated objects which are considered as one unit with regard to data changes. The Aggregate is demarcated by a boundary which separates the objects inside from those outside. Each Aggregate has one root. The root is an Entity, and it is the only object accessible from outside. The root can hold references to any of the aggregate objects, and the other objects can hold references to each other, but an outside object can hold references only to the root object.
- from DDD Quickly


Sculptor will validate the reference constraints described in the quote above. Repositories are only available for aggregate roots. Aggregates are defined with belongsTo or not aggregateRoot in the owned DomainObjects.

A typical aggregate in the blog sample is that Comment belongs to BlogPost

Entity BlogPost {
String slug key
String title
String body
DateTime published nullable
- List comments opposite forPost
}

ValueObject Comment {
not aggregateRoot
- BlogPost forPost opposite comments
String title
String body
}


An aggregate can of course include several classes as in this sample:

Entity Cargo {
- TrackingId trackingId key;
- Location origin required;
- Location destination required;
- Itinerary itinerary nullable opposite cargo;
- Set<HandlingEvent> events opposite cargo;

}

BasicType TrackingId {
String identifier key
}

ValueObject Itinerary {
belongsTo Cargo
- Cargo cargo nullable opposite itinerary
- List<Leg> legs
}

ValueObject Leg {
belongsTo Cargo
- CarrierMovement carrierMovement
- Location from
- Location to
}


In above sample the TrackingId, Itinary and Leg are all stored toghether with the Cargo. BasicTypes are also stored as embedded documents.

Reference by Id

The other alternative is to store ids of the referred objects. In the domain objects there are generated getters that lazily fetch associated objects from the ids. This means that you don't have to work with the ids yourself, you can follow associations as usual, but be aware that an invocation of such a getter might need to query the database.


Set writers = blog.getWriters();


In the same way you can modify unowned associations by working with objects rather than ids.


Author pn = new Author("Patrik");
pn = authorService.save(getServiceContext(), pn);
blog.addWriter(pn);
Author ak = new Author("Andreas");
ak = authorService.save(getServiceContext(), ak);
blog.addWriter(ak);
blogService.save(getServiceContext(), blog);


Referential integrity of the stored ids are not enforced. It must be handled by your program. Lazy getters of associations will not fail if referred to object is missing, they will return null for single value references and ignore missing objects for collection references. This means that you can cleanup dangling references by fetching objects, populate associations by invoking the getters and then save the object.

Inheritance
The MongoDB feature of Sculptor has full support for inheritance. It is even possible to do polymorphic queries.


abstract Entity Media {
String title !changeable

Repository MediaRepository {
List<@Media> findByTitle(String title);
protected findByCondition;
}
}

Entity Book extends @Media {
String isbn key length="20"
}

Entity Movie extends @Media {
String urlIMDB key
Integer playLength
- @Genre category nullable
}

Tuesday, April 27, 2010

MongoDB with Sculptor - Introduction

MongoDB bridges the gap between key-value stores (which are fast and highly scalable) and traditional RDBMS systems (which provide rich queries and deep functionality).

Would you like to?
  • Use a rich persistent domain model à la DDD with automatic mapping to MongoDB data structures.
  • Use associations even though the underlaying data store is not relational.
  • Express queries in refactoring safe terms of the domain model.
  • Get CRUD operations, and GUI, for free.
Then you should try Sculptor with the brand new MongoDB target implementation.

In the next few days I will describe the features one-by-one, but first an brief overview of what Sculptor provides for efficient development of a typical enterprise or web application with MongoDB as persistent store.

Sculptor is a productivity tool that let you express your design intent in a textual DSL, from which Sculptor generates high quality Java code and configuration. Read more in What is Sculptor?

Sculptor generates data mapper classes that converts domain objects to/from MongoDB data structures, DBObjects.

Sculptor provides generic repository operations for use with MongoDB. This includes operations such as save, delete, findById, findByKey, findByCondition, and some more.

Queries can be expressed with a slick fluent api that support code completion and refactoring.

Rich support for associations. Aggregates are stored as a embedded documents. Other associations are stored with referring ids. In the domain objects there are generated getters that lazily fetch associated objects from the ids. This means that you don't have to work with the ids yourself, you can follow associations as usual.

A sample blog application may look like this when defined in Sculptor textual DSL:


Visualization, generated by Sculptor, of the above model looks like this:


Read the other posts that describes the features in more detail:

More hands on instructions of how to use Sculptor is available in the Sculptor MongoDB Tutorial.

Thursday, August 27, 2009

Screencast: Introduction to Sculptor

During the summer I have published a series of articles that illustrate basic usage of Sculptor. They include screencasts so that you get a feeling of what it looks like when using Sculptor.

If you are totally new to Sculptor you might need to read What is Sculptor? before looking at the practical example.

The series illustrates the following, step-by-step:

  1. Jump Start - Initial creation of maven and eclipse projects. Persistent entity and CRUD GUI are created in a few minutes.


  2. The World is Changing - Adding more to the application. Quick development round trip, short feedback loop, it is not a one time shot.


  3. Testing is Simple - Testability is crucial and is of course supported.


  4. Adding Behaviour - Generated code is well separated from hand written code.


  5. Say Hello - Entity, Repository and Service are some of the available building blocks. Yes, it is real DDD-style.


  6. Introducing a Type - Developing a high quality domain model is the core of Sculptor. Small type objects are typically part of a good domain model.


  7. Refactoring - How is refactoring done when having a mix of hand written and generated code?


Thursday, August 20, 2009

Introducing a Type

An important building block when creating a high quality domain model is to create small type objects. In this article we will create a Length type for the diameter of the Planet of the helloworld application.



Alternative video format (mpg)

Length is a typical Quantity with a value and unit, e.g. meter, kilometer.

In the design model it looks like this:
BasicType Length {
BigDecimal value min="0"
-@LengthUnit unit
}

enum LengthUnit {
cm, m, km
}

Entity Planet {
gap
scaffold
String name key
Long population min="0"
-@Length diameter nullable
-Set<@Moon> moons opposite planet

Repository PlanetRepository {
findByKey;
}
}


We also need to convert between different units. The behaviour expressed as a JUnit test:
public class LengthTest {

@Test
public void shouldConvertFromMeterToKilometer() {
Length length = new Length(new BigDecimal("31000"), m);
Length lengthInKilometer = length.to(km);
assertEquals(new Length(new BigDecimal("31"), km),
lengthInKilometer);
}

@Test
public void shouldConvertFromKilometerToMeter() {
Length length = new Length(new BigDecimal("44"), km);
Length lengthInMeter = length.to(m);
assertEquals(new Length(new BigDecimal("44000"), m),
lengthInMeter);
}

@Test
public void shouldNotConvertSameUnit() {
Length length = new Length(new BigDecimal("17"), km);
Length length2 = length.to(km);
assertSame(length, length2);
}
}

BasicType objects may contain business logic in the same way as other domain objects. The following screencast illustrates how to implement the conversion.



Alternative video format (mpg)

BasicType is a stored in the same table as the Domain Object referencing it. It corresponds to JPA @Embeddable.

There are a lot of cases when it is a good idea to introduce types.
  • Identifers, natural business keys. It is more readable to pass around an identifier type instead of a plain String or Integer
  • Money
  • Range
  • Quantity
I can recommend reading When to Make a Type, Martin Fowler.

Saturday, August 15, 2009

Say Hello

In previous article our Planet is capable of constructing a greeting message. This article shows how to make it possible for a client application to say hello to the Planet.



Alternative video format (mpg)

Let us create a PlanetService to expose the sayHello method to clients. We lookup the Planet from its name using the built in findByKey repository operation. In Sculptor model file this looks like this:
      Service PlanetService {
String sayHello(String planetName) throws PlanetNotFoundException;
}

Entity Planet {
gap
scaffold
String name key
Long population min="0"
Long diameter min="0" nullable
-Set<@Moon> moons opposite planet

Repository PlanetRepository {
findByKey;
}
}

All hand written java code we need to add is for testing and two trivial lines in PlanetServiceImpl:
    public String sayHello(ServiceContext ctx, String planetName)
throws PlanetNotFoundException {

Planet planet = getPlanetRepository().findByKey(planetName);
return planet.greeting();
}

Tuesday, August 11, 2009

Adding Behaviour

In previous articles we created a simple helloworld application without any hand written code. This article shows how to add some hand written business logic.



Alternative video format (mpg)

The behaviour to implement is that the Planet should be able to construct a greeting message based on its population. Test for this behaviour looks like this:
public class PlanetTest {

@Test
public void shouldSayHelloWhenHasPopulation() {
Planet earth = new Planet("Earth");
earth.setPopulation(7000000000L);
String message = earth.greeting();
assertEquals("Hello from Earth", message);
}

@Test
public void shouldBeQuietWhenNoPopulation() {
Planet pluto = new Planet("Pluto");
String message = pluto.greeting();
assertEquals("", message);
}
}
The video illustrates how to implement this.

As you see nothing special, you add the business logic in Java as usual.

Separation of generated and manually written code is done by a generated base class and manually written subclass, a gap class. It is in the subclass you add methods to implement the behavior of the Domain Object. The subclass is also generated, but only once, it will never be overwritten by the generator.

The gap class is not generated initially. When you need a gap class you specify that in the DSL with gap keyword.

Saturday, August 8, 2009

Testing is Simple

In previous articles we created a simple helloworld application without any tests. This article shows how to do integration testing of services with Sculptor.



Alternative video format (mpg)

We turn on generation of junit test and complete the failing tests from previous articles. For each Service there is a generated JUnit test class that we are encouraged to implement. It uses Spring transactional test fixtures and DbUnit.

Spring beans are injected in the test with ordinary @Autowired annotations.

public class PlanetServiceTest extends AbstractDbUnitJpaTests
implements PlanetServiceTestBase {
private PlanetService planetService;

@Autowired
public void setPlanetService(PlanetService planetService) {
this.planetService = planetService;
}

@Test
public void testFindById() throws Exception {
Planet found = planetService.findById(getServiceContext(), 1L);
assertEquals("Earth", found.getName());
}

@Test
public void testFindAll() throws Exception {
List<Planet> found = planetService.findAll(getServiceContext());
assertEquals(2, found.size());
}

@Test
public void testSave() throws Exception {
int countBefore = countRowsInTable("PLANET");
Planet planet = new Planet("Pluto");
planet.setPopulation(0L);
planetService.save(getServiceContext(), planet);
assertEquals(countBefore + 1, countRowsInTable("PLANET"));
}

@Test
public void testDelete() throws Exception {
int countBefore = countRowsInTable("PLANET");
Planet planet = planetService.findById(getServiceContext(), 2L);
planetService.delete(getServiceContext(), planet);
assertEquals(countBefore - 1, countRowsInTable("PLANET"));
}
}


The initial test data is defined in DbUnit xml file. The database is refreshed for each test method.
<?xml version="1.0" encoding="UTF-8"?>

<dataset>
<PLANET ID="1" NAME="Earth" POPULATION="7000000000" VERSION="0"/>
<PLANET ID="2" NAME="Jupiter" POPULATION="0" VERSION="0"/>
<MOON/>
</dataset>


Above tests only covers the normal cases so far and we should of course do more tests for exceptional cases and validation boundaries, such as negative population.

The tests illustrated here are kind of integration tests and you should do ordinary unit tests for domain objects and other classes of importance.

Tuesday, July 28, 2009

The World is Changing

In the previous article the simple helloworld application consisted of one single domain object, the Planet. In this article I will add some more features to the picture, including an association to the Moons of the Planet.



Alternative video format (mpg)

It is good to have a natural business key, which is used for equals and hashCode. The name of the Planet is a candidate. Let us add some properties for the population and diameter of the Planet also. Hibernate validator is supported and validations can be defined directly in the model, e.g. min="0".



We add the Moon Entity and its association to Planet.



Build and start Jetty. The changes are immediately reflected in the generated CRUD GUI.



The DSL and the code generation drives the development and is not a one time shot. The application can be developed incrementally with an efficient round trip loop.

Wednesday, July 22, 2009

Jump Start

This article illustrates the first basic steps of how to use Sculptor. We will create a simple hello world application. It will only have one simple domain object and some CRUD operations.



Alternative video format (mpg)

We start by firing off some maven archetype commands to create the business and presentation tier projects. The sculptor archetypes creates maven pom files with needed dependencies. We generate eclipse projects from those maven projects using the ordinary maven-eclipse-plugin. These projects are imported into Eclipse. You find the commands for this in the wiki.

We open the design model that is the input to the code generator. It is a textual DSL that defines the application structure. We define the Planet Entity in a Module.



We also need some CRUD operations to be able to do something with the Planet in the to be generated GUI. It is easiest to add those with the scaffold keyword. Note that the DSL editor has support for code completion, error highlight and outline view (including ctrl+O).

Now it is time to generate code, but first we will turn off one feature. Sculptor promotes writing junit tests, but for this demo we turn off that by adding a property to sculptor-generator.properties.
generate.test=false
We build the application by executing mvn install from the -parent project. The code generation is part of the maven build cycle.

We start the web application server by running mvn jetty:run from the -web project. Note that this is also a maven command, and no specific installation of an application server and database is required. Hsqldb inmemory database is used.

The generated CRUD GUI is available at http://localhost:8080/helloworld-web/



That was everything needed to create a minimal application. It illustrates how easy it is to get started. Within 15 minutes you can go from scratch to a running application, including build scripts, Eclipse projects, domain model, JPA persistence, services, Web Flow application and much more. Thereafter you can continue by evolving the design, add manual code and regenerate.

This was an extremely simple example. Sculptor can be used for much more advanced applications. The CRUD GUI is useful for administrative sections of the application or to serve as a scaffolding for your manually crafted user interface. The major strength of Sculptor is in the business tier when developing typical enterprise or web applications that benefit from a rich and persistent domain model.

Saturday, June 27, 2009

What is Sculptor?

Sculptor is an open source productivity tool that applies the concepts from Domain-Driven Design and Domain Specific Languages.

You express your design intent in a textual DSL, from which Sculptor generates high quality Java code and configuration. It is not a one time shot. The application can be developed incrementally with an efficient round trip loop.

Sculptor is useful when developing typical enterprise or web applications that benefit from a rich and persistent domain model. Sculptor also provides a sophisticated CRUD GUI for administrative sections of the application or to serve as a scaffolding for your manually created pages.

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

Product characteristics:
  • Easy to learn, intuitive syntax of the textual DSL, editor with error highlight, code completion, and outline
  • Quick development round trip, it is not a one time generation
  • Existing IDE tools, such as refactoring, code assist and debugger will continue to be of service to you
  • High quality of generated code, based on well known frameworks, best practices, and a lot of experience
  • Great extensibility and customization options
  • Easy to remove the tool, no runtime magic
Visit the Fornax Sculptor web site to learn more and try it.