Wednesday 21 January 2009

Domain Driven Design - The basics

There are a lot of different design techniques in the software development world. At the moment my favorite one is Domain Driven Design (DDD). At my work I was introduced with it two years ago. During those two years I tried to use it to improve my software development and I think I succeeded, although I can improve a lot.

Ok, let me first explain what it is all about.

Eric Evans describes Domain Driven Design in his book Domain-Driven Design: Tackling Complexity in the Heart of Software . He says that the most complex part of software is the business or the domain logic. Software is written to support a business process and the logic that is needed to support this process is called the domain logic. Once this logic is implemented correctly, it is not likely to change very often.

The user interface is more likely to change, especially a web interface like the web site for online banking, therefore it is recommended to separate the domain logic from the user interface and other infrastructure logic (like database or file persistence, logging, etc.).

In DDD the domain logic is designed using a language that is known by the domain experts, and in the implementation (the domain) we will see objects, fields and methods that are using the same language. (Evans calls this the Ubiquitous language) This means the developers and all other people who are working with the domain should know this language.

Ok this can be very abstract, I know, so I will give you an example. For this example I use something everyone is familiar with, a Bank. A bank has clients. These clients have accounts and can do transactions between accounts. The words in bold are important for the bank, without these words/things a bank doesn't exist. Therefore we will add them to out Ubiquitous language. In the domain design we can see the following diagram:


(you can see that I didn't talk about all the details of the classes you see here, but I think they are obvious...)

Now we have the design, we can implement it in any language we want, but it is important that the ubiquitous language is used in the domain itself.

Domain Driven Design is not only about the language. Separating the domain from technical things like user interface is even more important. The complexity of the software is the domain not how we show the domain, or how we implement the persistent. So we should be able to decouple the domain completely from all other things and to test it with some kind of automatic testing framework. (This is needed to get the proof that the implementation of the domain works correctly, but that will be another topic.)

The question is: How do we decouple the domain from the rest of the application? There are a couple of different possibilities here:


  • Layered Architecture

  • Sunflower Architecture


Layered Architecture


In a Layered Architecture there are layers. A layer can communicate with all the layers bellow itself by using method calls. To communicate with layers on top of itself, a layer should use some kind of event based system. (See image) 
In the diagram you can see that the domain is on top of the infrastructure/platform layer, which means it depends on this layer and we can't easily change from platform. An example: When we use the Win32-API for events (messages) we can't use the domain on other systems than Windows. So we can't easily deploy the domain on a Linux machine and the Testing Framework should understand the same platform/infrastructure. Other technical stuff like the user interface are build on top of the domain layer.

Sunflower Architecture


The sunflower architecture I like the most. It looks like the following image.

The domain is completely decoupled from everything and around the domain we see the other technical stuff like logging, persistence, etc. With this model it is even possible to use a product from an other vendor and couple it via adapters to the domain. (An adapter is just a class that translates message to and from the domain.) This way the domain doesn't have to know anything about the infrastructure layer and can be tested without any problems.

Software Architecture


"Ok, we have those nice architectures, but how to implement that in my projects?" you may think. I would say make a library for every single layer or service. So a library for the domain, a library for the GUI and for the persistence. This way the code is physically decoupled as well, which makes it even easier to test and to replace implementations. Even updating an existing service is easy because the file is not cluttered with other things that has nothing to do with the problem.

This is also in line with the OO-rule "Single responsibility". Which tells that every single object (or module, or service or library) should have one task to do and it should do that well.

Ending words


Besides a ubiquitous language, Evans also describes a lot of design patterns that can be used in domain driven design. I will give you a list with patterns, but I will describe them in some other posts, because I still want to describe where the domain could be placed in the application. First the patterns list:


  • Value objects

  • Entities

  • Services

  • Aggregates

  • Factories

  • Repositories


Some of these I will combine in one post, but others I need to take separately.



I realize that I give a very short introduction of Domain Driven Design. For more information you can go to some of the following websites:


Wednesday 7 January 2009

The monitor system

In a previous post I described the basic of the project I worked on and how I would implement it now. When starting a project it is good to write down what to expect from the software that is getting developed, this is something that was not really done for the previous version (at least not that I know of). Because I start the project all over again, I will start this new project by writing down that description.


The context


The broadcaster I worked for is using a complex computer network for distributing and broadcasting radio programs. The complete network is spread across the world and monitoring the whole network can hardly be done by hand and will be automated. (Well we did monitor the whole system by hand for some months because we just implemented the system before the software was ready, but that was not funny...)
On the network there are different kind of devices we have to monitor including: computers, modems (for connecting to the Internet) and UPS-es. All the devices on the network should be monitored (when possible) and it would be nice to keep a history of the state of the devices.
The computers are used for several things: first of all programs are played, but before that schedules should be checked as well as the integrity of the files and a lot of other things. All the programs keep a kind of log (of course) but it is useful to hold some of the information on a central place. There are also some OS things that should be monitored like disk-space and memory usage.
When there is something going wrong (all devices on a site are turned off, the play-out at a site is terminated, etc.) alarms should go off and a hot-line should be called, things should be corrected as soon as possible. (Ideally when computers are not accessible due to a network connection error, other programs in the system should be informed as well so they don't try to distribute file to those computers)
From the network side of the system, the network traffic that is generated by the system should be as small as possible, especially the traffic between locations. Although this can be solved during deployment of the system (run the application on each location) we still need to include support for this during design time.

The requirements

Here is a list of the requirements that comes to my mind. This list is not complete, but that is not a problem because I want the system to evolve over time.
  • The state of device should be monitored
  • The state of applications (play-out, OS, etc.) should be monitored
  • Different kind of alarms should be generated
  • States of devices and applications should be saved
  • It should be possible to configure what and how to check on the network

  • It should be easy to add new locations, devices and applications
  • Visual monitoring should be easy and always up to date
  • Monitoring is critical but less critical then the whole play-out process
  • Network overhead should be as low as possible
These requirements can be split in two areas, architecture requirements and functional requirements. I will mainly focus on the functional requirements because these are the easiest to test automatically and will most likely contain business logic.

Project restrictions

This project is started for learning purposes and not to write a complete and fully functional application. I will use this project to learn (and explain) the following things:
  • Object Oriented programming
  • C# (.NET and Mono)
  • Multi platform development (Linux and Windows)
  • Domain Driven Design
  • Test Driven Development
  • Perhaps some Service Oriented Architecture (if I see it fit)
  • Object Relational Mappers for persistence
  • Agile/Iterative project management
  • (Design) Patterns
  • and probably some other techniques that come on my path

Well that's all for today, next time I will talk a bit about Domain Driven Development and/or Test Driven Development. (which can go hand in hand :))

Monday 5 January 2009

From procedural to Object Oriented programming

When working with Delphi a while ago, I was in need to format dates and times. As far as I know there is hardly any build-in support for that in Delphi. A colleague pointed me to a unit (Delphi is working with units, they are similar to header files of C/C++ or the source files of Java and C#) where he had created functions to convert different types of date/time combinations.
Although they worked very well, inside me everything was screaming. I was working with objects all over the project, and now I needed to use procedural functions in my domain. Today I want to try to convert those functions to a real object, which makes it easy to convert from any date/time format to a specific one that is used in the whole company. Why? to show the power of objects ;)

The procedural interface

The unit that is used to convert a specific date and/or time format to another one, for example: 23122008 to 20081223 or 2008-12-23 to a TDateTime object. The code is made to handle conversion errors, so in the time this unit was created (years ago) it would have been very useful. Now (as far as I know) the standard Delphi library has some functionality to perform the conversions. There are around the 100 functions to choose from and some of these functions looks very similar. Similar code can lead us to code duplication and that can lead us to bugs in multiple places. But even these 100 functions don't give you all the possibilities you can have. Every function is working on its own and every result should be stored in memory. To be able to do some calculations or comparisons or multiple conversions we are in need for some other "magic". This magic are objects.

The object oriented interface

Before I describe the interface of the new object, I will describe some requirements for this class.
  • It should be possible to parse a given date and or time to a TDateTime object.
  • It should be possible to convert a TDateTime object to a specific date and or time format.
  • It should be possible to add or remove time to the object.
Basically these are the things that are done in the original unit. Lets see how we can put this in an object: disclaimer, I don't have a Delphi compiler at hand, so I am not sure this is 100% correct.
type DateTime = class
begin
public:
procedure ParseDateTime(value, format : string);
function ToString(format : string) : string;
function Compare(dt : DateTime) : integer;
end;
The method ParseDateTime is used to convert a string to format that is used internally. The method ToString will convert the internal time value to a specific format. Compare will compare the two different values (by using the internal format).

OK, now we have a basic interface how do we implement this and what is our internal value? The internal value should be (in my opinion) in a format that the computer understands the best. In Delphi we can use the TDateTime type (if I remember correct) which is just a alias for a Long type which can be found in most programming languages.
The parsing of the Date and Time values can be done by using functions that are included in Delphi. We can make sure that errors are caught and we can throw an exception (for example IncorrectFormat exception, or something like that). The same we can do for the ToString function. (I won't show a real implementation, because I don't want to show an example with errors.)
To compare two DateTime objects we simply compare the internal values. If I recall correctly Delphi can access private fields of a class instance (an object) from another class instance of the same type, so this shouldn't be a problem. For convenience and to follow standards we return some kind of value depending on the comparison (0 means self equals dt, negative means self is smaller (earlier) than dt and positive means self is greater (later) than dt). There might be a function for this in Delphi as well, but I am not sure.

Time zones

OK, but what about different time zones you might say. How can a datetime from Europe (GMT +1 and GMT +2) be compared with America (GMT -7)? There are a few solutions for this I think:
  • We don't mind, so we don't implement
  • Convert date and time to UTC (GMT 0)
  • Use region information
This list is probably not complete, the first item is unacceptable when you have that above question. The second and third (converting to UTC and region info) are going hand in hand.

*Disclaimer* What I write here is pure theoretical, I couldn't test it, but by providing this information, the reader can try it out in his/her preferred programming language.
For converting a date and time format we need to know in which time zone the given time is.
There we could use for example the TTimeZoneInformation type form Delphi (_TIME_ZONE_INFORMATION structure in Win32 API). To get the UTC time first convert the datetime-value to a long (as before) and then add the TTimeZoneInformation.Bias value. I am not sure if it is possible to get the TTimeZoneInformation type for other time zones, but it is worth trying.

When you choose to include the timezone info into the DateTime class, you can use this information for comparison as well.

Default formats

Of course there are a couple of default formats you can choose from. The easiest way to do this is to create string constants for them, so they can be included easily.

Conclusion

Although converting programs from procedural to object oriented is very time consuming, it could be done quiet easy when doing it in very small steps. I hope this post gives you a good example of how to approach a typical conversion. When you have questions, please feel free to add a comment :)