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

Tuesday, August 21, 2007

Defining service/component interfaces in WSDLs

We have just completed an iteration of the project we have been working on for the past few months. Now it's a good time to summarise the experiences we have gained so far.

Probably the most significant one is defining all service/component interfaces in WSDLs.

The project started with the interfaces of a few services being defined in WSDLs because they are invoked by the web tier as web services call. Since the JAXB-generated Java classes of some complex types defined in the XML schema are reused in some other service interfaces that are not originally intended to be invoked via web services, we finally decided to define all service interfaces in WSDLs, regardless whether they are intended to be invoked as web services or not. And this brought us unexpected benefits and productivity.

So what are the benefits of defining all service interfaces in WSDLs?

First of all, it takes away most of the tedious work of implementing Data Transfer Objects (DTOs), resulting in higher productivity. If you wonder why DTOs are still in use when domain model objects persisted by Hibernate and JPA can be passed back to service clients directly, please read my previoug blog entry: DTOs are a necessary devil in building SOA enterprise applications.

So, how does defining service interfaces in WSDLs take away the boring implementation of DTOs? In a WSDL file, each operation has input messages, output messages and/or fault messages, which in turn are defined as elements in an external or embedded XML schema. And each element is declared in an XML type. The XJC compiler from JAXB can be used to generate corresponding Java classes of any complex types and some restricted simple types. These classes are data holders with absolutely no behaviours; in other words, they are DTOs. Code generation of DTOs has other benefits: no behaviours can be added to the DTOs without subclassing and defining new operations; and these DTOs won't accidentally reference any domain model objects, which is always a concern for hand-coded DTOs.

XML schema allows very rich type definitions, such as abstract types and type inheritance, which has corresponding concepts in object-oriented languages, such as Java, making it a perfect choice to generate Java classes from XML data types.

Not only are no-argument constructors and all public getter and setter methods generated for complex types, but also other useful methods, such as valued constructors, builder methods, hashCode, equals and toString methods can be implemented using XJC extensions. These are to be blogged in a follow-up post.

Moreover, defining service/component interfaces in WSDLs can partially enforce the "contract" using schema validation, promoting the best practice of "Design by Contract" (DBC).

Java, by itself, does not provide native support to DBC. Any acceptable input values, return values and exceptions are only documented using javadoc in the interfaces. The implementation classes have to do all the hard work to validate input values, such as making sure a mandatory parameter is not null, an amount is greater than zero and less than a preset limit, etc.

Meanwhile, XML schema provides a rich basic data types, such as positive integers. It can also specify whether an element is mandatory or not using the "minOccur" attribute. Furthermore, it allows you to add restrictions to simple types, such as the maximum length of a string and regular expression patterns that must be matched by a string. Thus, XML schema validation can catch many simple field validation errors. More complex validations, such as cross-field validations and business rule validations cannot be done by schema validation. However, they can still be documented using annotations, which are generated as Java comments in the generated Java classes.

Another benefit of defining service/component interfaces in WSDLs is that it promotes the best practice of "contract-first" web service design. Because the service interface is defined in a WSDL file, the service is web service ready, even if it is not intended to be used as a web service at this stage. The opposite of "contract-first" is "code-first". When adopting a "code-first" practice, the service interfaces are defined in Java, potentially without using DTOs. When the service needs to be accessed via web services or remotely, it is not as easy as just exposing the service as a web service by, say, wiring up the Spring application context. A proper service interface using DTOs has to be defined and implemented by delegate calls to the original interface and doing all the transformation between DTOs and domain models. Even if DTOs are used in the original Java interface, exposing the service as a web service is not as simple as adding the JSR-181 annotations to the interface and all DTOs: some common Java types do not have a counterpart in XML, such as java.util.Map. Moreover, the methods defined in your original DTOs may not be suitable for JAXB use. You may not have defined a no-argument constructor; you may not have defined a setter method for each property... So, why go the hard way when defining the interfaces in WSDLs can save you the tedious work of implementing DTOs and, at the same time, provide an elegant way to expose it as a web service when the time calls?

Friday, June 29, 2007

Workflow engine integration, where does it go?

In one of the projects I have worked on, OSWorkflow is used to manage workflows. It is integrated to the service layer instead of to the domain objects.

The design feels unnatural somehow:

  • The workflow id is stored in the domain object, passed as a parameter in constructor. However, it is not used by the domain object itself. The domain class provides a getter method so that the service layer can retrieve the workflow id and load the workflow instance from OSWorkflow.
  • After loading the domain object and then the workflow instance, the service layer needs to pass to the workflow engine some properties from the domain object and some properties from the DTO that carries the input of the user for the current request, so that the workflow engine can work out what is the next status for the domain object.
  • The domain class also expose a method to allow arbitrary update of the 'status' field so that the service layer can update the domain object with the status that is come up with by the workflow engine. The domain model loses encapsulation.
  • The service layer becomes thick while the domain model becomes anaemic...

IMHO, this design smells.

The change of state in a domain object should be managed by the domain itself. Any application requirements, such as sending email notifications, can be implemented as state change event listeners.

If the workflow logic gets too complicated, workflow engines like OSWorkflow come to rescue. But even if the workflow logic is delegated or outsourced to a workflow engine, it is still domain logic; thus, the workflow engine should be integrated directly into the domain objects instead of to the service layer.

In order for domain objects to work with a workflow engine, domain objects need to have a reference to the workflow engine, which used to be an issue.

With domain object dependency injection feature introduced in Spring 2, this problem is solved. Even if you are using Spring 1.2 or other IoC Containers that do not support domain object dependency injection, or if you are not using an IoC container at all, you can still use Registry pattern where a domain object can look up a dependency.

In conclusion, state change is part of the domain logic, and even if it is outsourced to a workflow engine, the workflow engine integration should still happen in the domain object, without leaking the implementation details to other layers. And technically, there is no more barrier that prevents injecting the workflow engine into domain objects.

Monday, June 18, 2007

Domain Classes should not be passed to UI layer.

Debasish Ghosh, one of my favourite bloggers, posted an entry titled
Domain Classes or Interfaces? last October. Later he posted a follow-up entry Abstract Classes or Aspect-Powered Interfaces?.

He had this great debate with Sergio Bossa in the mailing list of Domain Driven Design (DDD).

I was surprised to read that both Debasish and Sergio are in favour of passing domain objects to the UI layer and using them as command objects, in the context of DDD discussion, because this kind of usage is code smell of Anaemic Domain Model.

As I understand, one major reason cited by Debasish to use abstract domain classes is to maintain the integrity of domain objects, making sure no constraints are violated.

However, when a domain class is designed following the philosophy of DDD, there are typically few setter methods, making them unsuitable to be used as a command object in the UI layer.

Moreover, there are typically some business methods that you would not like to be exposed to the UI layer, such as those that access database and must be wrapped in a transaction, making it even more undesirable to pass domain objects to the UI layer.

In my opinion, a domain class typically has three interfaces (not necessarily Java interfaces):
* Business interface - these method usually bear domain-specific meaning in their names.
* State Exposure interface - typically getter methods
* State Manipulation interface - these methods update the object state without violating any constraints, and are usually named updateXXX instead of setter.

Business interface should not be exposed to UI layer. If the return value of any of the business methods are to be displayed in a UI, a getter method should be defined in the State Exposure interface, which should then delegate to the business method.

State Exposure interface is usually passed to UI layer for display. In a proper application design, the role to expose domain object states is usually assumed by a Data Transfer Object (DTO). In a Spring+Hibernate application, this Java interface can be implemented by the domain class directly, and the domain objects can be passed to the UI layer without exposing business methods. Typically, Open Session In View (OSIV) is required in this usage.

Even if the domain class implements the State Exposure interface , the domain objects that are passed to the UI layer should not be used as command objects. Each piece of update should be invoked on a facade, which then invokes methods defined in the State Manipulation interface. The piece of information for update is usually passed in as a DTO.

Note that there is difference between the DTO for state exposure and the DTO for state manipulation:
The DTO for state exposure usually captures most, if not all, state of the domain object.
The DTO for state manipulation usually captures only the piece of state that is being updated.

In conclusion, because of the three interfaces a domain object usually has, it is strongly discouraged to pass domain objects to UI layer or use them as command objects, when applying DDD.