Subtitel

A blog by Juri Urbainczyk | Juri on Google+ | Juri on Twitter | Juri on Xing

Showing posts with label domain model. Show all posts
Showing posts with label domain model. Show all posts

Monday, July 15, 2013

Software Architecture - more than documents

As I read the following sentence in an IT magazine some days ago it immediately caught my attention: „Also, in smaller projects architecture (the documentation of the software solution) is obligatory. “.

That is, where I have to object: architecture is not only the documentation. Architecture even exists without any documentation, and it can be a good one, mind you. These days, many people tend to overly concentrate on the documentation of the architecture rather than on the methods and processes needed to conceive it. For instance, the arc42 template is a good one (and I don’t want to be misunderstood on that) but it also only focuses on documentation.

According to my understanding (and I am talking mainly about software architecture here – as opposed to business architecture, for instance), architecture refers to three different aspects:
-         the process of conception of the software system (some people call that “technical design”)
-         the inner structure of a software system (and its sources)
-         the documents needed to describe that structure (e.g. component view)

These three aspects are correlated. The following diagram depicts this relationship.
Picture 1: The three aspects of software architecture
Although correct and sound documentation is necessary to understand and communicate the architecture, it is not the same as the architecture. If we would conceive, design and build an app with an excellent architecture and install it and after that throw away all the documentation, the architecture would still be in existence, would still be splendid and would hopefully still exhibit all the nice quality criteria it was designed to. Our app would still be very stable and would respond to user input very quickly.

As I wrote in another post, software architecture is a set of concepts which resolve the functional and non-functional requirements of the system (cf. http://juriswritings.blogspot.de/2012/03/what-is-software-architecture.html). Therefore, these decisions must be safe and sound. In order to make sensible decisions the architects above all need experience and good requirements documentation (e.g. domain models and use cases).

As the project progresses and the bigger the project gets, the architects also need models of the architecture, because they may have to make decisions which change parts of the architecture already discussed. Thus, documentation is important, not only to help new people to get on the project and to let people do maintenance later. But – and that is my point here – it is not the same as the architecture and it is also not the first thing which needs to be created. Architects have to decide and they have to invent sensible concepts. Documentation is merely a tool to help them do their work – and we should keep that in mind when documenting.

BTW: the said article is “Architecture for eternity” in “Entwickler Magazin 04/2013” by Nils Arndt. The sentence is below the fourth sub heading, which is on page 2 of the article.

Sunday, July 1, 2012

Should Domain Objects contain business logic?


Recently I started a discussion with another software architect about where to implement the business logic in a SOA-like business layer. There would be service classes with methods which implement service functions like "bookFlight" or "upgradeFlight". We also introduced a "model" which consists of domain objects, holding the data to be manipulated by the services. The domain objects would also be stored in and read from a database and would serve as parameters for our service, meaning that they would be transferred via JSON or XML to the service consumer. Now, the question is: where should we implement the business logic? Should all of it be in the service functions or should all logic go into the domain objects or should we have a mix?

The picture below shows two services using two domain objects each. One domain object is used by both services. Should the logic be distributed? It can get even more complicated, since domain objects may also call one another, thereby using the logic of the other domain object.
But what is business logic anyway? Validation is often cited here, but that’s not all of it. More important are algorithms, calculations, rule evaluations and transformations which are driven by business requirements. Consider a domain object “passenger” which represents the customer of an airline. The passenger might have a method “getSignificance()” which returns the value of importance that the passenger has for the airline. This significance can depend on many things, for example his frequent flyer status, his age, his flight frequency, his marital status, the people he know at the airline etc. The algorithm to calculate this value also can be very complicated and it can change frequently. The significance of the passenger is so important, that it is calculated very often and it always refers to one single passenger. Makes it sense to implement “getSignificance()” at the passenger domain object?

The other solution would be to implement it in the service, e.g. in the “bookFlight” service, which uses it to calculate the price. But what if “upgradeFlight” also needs to know the significance of the passenger? Would you just duplicate the code and put it in the other service as well? That would lead to messy maintenance problems and a lot of discussion with the QA people (and for good reasons!).

Many people argue that domain objects without business logic would lead to a “clear separation of logic and data”. But, what are we talking about? It is just that, namely the combination of data and logic in objects, what the object oriented programming once set out to achieve. Thus, logic-less domain objects would rather indicate procedural programming, leading to something old-fashioned like a transaction script which is encoded in the service methods. It really reminds me of the old C programming style, putting all data in “structs” and just weaving some procedural code around it. But after all, we want to be object-oriented, don’t we?

The term “domain object” comes from “domain model”, meaning that all these classes make up the model which represents the business and problem domain. In object oriented modeling you simply identify all the objects which occur in the business domain and then you create one class for each object type found. Of course, the business domain not only contains information (“data”) – it also contains actions and activities (“methods”). Thus, domain objects naturally should contain logic as well.

Martin Fowler once coined the term “anemic domain model”
(http://martinfowler.com/bliki/AnemicDomainModel.html) for domain objects without logic. He calls it an “anti-pattern”. And I think he is right. But on the other hand, I don’t think that all the logic always should go into domain objects.

Domain objects should contain only the business logic, which is closely related to the data of the object and to the business entity’s meaning which corresponds to the current domain object. E.g., the basic logic to upgrade a passenger should not go into the passenger domain object (Although language seems to indicate that the passenger is upgraded that is not so. The booking is upgraded.). If there is a “booking” domain object the logic belongs there or into the service if not. Also, if many other domain objects are involved in the algorithm, this kind of logic should also go rather into the service class.

I would expect a service method implementation to look something like this:
myServiceMethod() {

     domainObject do1 = dao.fetchNeededDomainObject();
     do1.doSomething();

     if (do1.getSomething()) == someValue) {

         // some logic goes here    
         domainObject do2 = dao.fetchNeededDomainObject();
         do2.doSomethingElse();
         do1.alter ();     
     }

     // maybe some more logic goes here as well
     return do1;
}
As one can see, there is business logic in the service method. It is that logic, which is needed to coordinate the work of the domain objects and to drive the overall process. The services delegate most of their work to domain objects. Or, to put it another way, only that logic, which is not clearly bound to one domain object but rather to the overall process, should be found in the service. Nevertheless, domain logic must stay separate from persistence and presentation logic. This can be achieved easily e.g. by using the DAO pattern and by adding an extra presentation layer on top of the services. .

One further point: what about using the domain objects to transfer data? They could e.g. be transformed into JSON or XML and streamed to a client. Would that indicate that we should get rid of all the logic, since it could not be transferred so easily? But, as I just described, it is not the domain object that is transferred, it is a marshaled representation of it – meaning that only the data of the domain object is transferred. If the client was a Java client, the data could be un-marshaled into another domain object on the client, which would feature its method and business logic again.

So, I am absolutely in favor of solid object oriented modeling, with a well formed domain model. And this means, that domain objects must be able to hold logic, since otherwise they are nothing more than primitive data types in disguise.