Kurser i Domain-Driven Design - Våren 2012




Friday, August 28, 2009

One Man's Entity Is Another Man's Value Object

One activity that we tend to spend some time on when doing Domain-Driven Design is the characterization of our classes into Entities of Value Objects. Entities and Value Objects are two fundamental building blocks that we use to handle complexity and help us further deepen our understanding of the problem domain. Careful characterization can make our design simpler, yet more powerful.

Here are two things that I like to stress during this work:
1) It's not always obvious what type of building block a model item is.

Let the characterization process take time, do not be afraid to experiment. Try out a few different key scenarios, both by "modeling out loud" by expressing scenarios in the words of the Ubiquitous Language as conversations with other people on the team, and in code. Work hard to challenge your initial assumptions, refactor as needed. That said, if you have a choice, bias your design towards Value Objects. We favor Value Objects for their uninteresting life-cycle and immutability, we use them to push down complexity. Imagine if java.util.GregorianCalendar was immutable...

2) The characterization is context-dependent, i.e. one man's Entity is another man's Value Object.

Let's consider money, a popular choice when discussing Value Objects. Imagine I have a SEK 100 note and walk over to a person and ask her if she'd be willing to exchange my note for one of her SEK 100 notes. The person would most likely accept this proposal (after some initial suspiciousness, one can imagine). I get her note and she get's mine. From both our points of view, nothing really happened. I can still go down to the store and buy something priced at SEK 100. She can do the same. The value property of the note is what is important to us, not the particular note instance; as long as they have the same value, they are interchangeable. They are also immutable. When I get a note in my possession, it's value is already set. There is no way I can (legally) change the value written on the note. I pass it along as means of payment and I forget about it. As far as I am concerned it can be garbage collected when I no longer hold on to it.

However, if I walk over to a person and ask her if we can exchange VISA cards, odds are she won't agree. And we all know why. Our cards may be issued by the same bank, have the same shape and color, and both be VISA cards. But they also have a card number, they have an identity. The actual card instance does matter. Credit cards have a complex life-cycle tracked by this identity; they are issued, lost and cancelled, or stolen, or just expired. They are connected to an account, which may have a huge credit just waiting to be spent, or it may be overdrawn. We think twice before handing over the card to someone, because that someone can do things to our card that we don't want. Evil things. Things like (VisaCard) card.clone(), or card.charge(2 * amountAgreedUpon). In short, credit and debit cards are Entities and we need to handle them with care. Entities are high-maintenance. But can be oh so useful.

Now, if we scrutinize that SEK 100 note carefully, we will find a number, a serial numbers. So what is this? Notes do have an identity after all? Perhaps they are not Value Objects at all?! What is going on here? Well, I do not know this domain very well, but it is not that hard to imagine that there is someone somewhere that do care about tracking individual notes. Perhaps Sveriges Riksbank, Sweden's central bank, uses this information to track individual notes, as they enter them into circulation or destroy them when no longer in use. I bet there is a computer software system somewhere, in a different Bounded Context, where banknotes are Entities.

Read more about the Building Blocks of a Model-Driven Design in the DDD Pattern Summaries (.doc file).
Watch Dan Bergh Johnssons presentation The Power of Value from Øredev 2008.

Heldagsseminarium: Domain-Driven Design, 23 september 2009 i Stockholm

Wednesday, August 19, 2009

Jfokus 2010 Call for Paper Now Open

The Jfokus conference is Sweden's premier conference on Java development, organized by the Swedish Java user group Javaforum. As a speaker at both Jfokus 2008 and 2009 I can tell you that Mattias and his team do an excellent work running the conference and it is a really great experience to both attend and speak at the event.

Submit you proposal now and hopefully we will see each other at Jfokus 2010, January 26 and 27 in Stockholm!

Monday, August 10, 2009

Follow The Weak Reference on Twitter

Follow The Weak Reference on Twitter: http://www.twitter.com/weakreference

Laziness IS a Virtue of a Programmer

As it turns out, laziness is a virtue of a programmer...

It is with particular joy I am rediscovering the programming paradigm that once introduced me to the art of software development: Functional programming. I begun my university studies almost 15 years ago. I initially planned to study biotechnology, but for different reasons I ended up with a M Sc degree in Information Technology Engineering instead. I had not really been doing any serious computer programming prior to my university studies, and the first course they threw at us was this monstrous thing called "Program Construction". It sure was a lot of work, but it built a great foundation for our further studies. And it was all tought in ML. 10+ years of Java followed. March this year I attended QCon London to give a tutorial on the DDDSample app, and also had the opportunity to listen to Rich Hickey give a presentation on Clojure. Since then I have slowly been rediscovering the beauty of functional programming; map, reduce/fold, higher-order functions, recursion, and more.

As an example, let's look at Clojure's lazy sequences:

This gives us a lazy sequence of all whole numbers:
(def numbers (iterate inc 1))

If executed it will define a lazy sequence, i.e. its elements will not be evaluated until needed. This is a good thing in this case since this sequence is infinite.

We can now use this infinite sequence, for example by calling:
(take 10 (drop 1000 numbers))

which will return the following (lazy) sequence:
(1001 1002 1003 1004 1005 1006 1007 1008 1009 1010)

Or why not take all the even numbers by filtering the sequence:
(take 10 (filter even? numbers))

returns:
(2 4 6 8 10 12 14 16 18 20)

I think this is pretty sweet!

For an upcoming PNEHM! article I needed to generate data sets of arbitrary sizes consisting of random letters a-z, so I did this:
(def s "abcdefghijklmnopqrstuvwxyz")

(def data-set
(repeatedly
#(nth s (rand-int (dec (count s))))))

From which I can take whatever number of random characters I like and do something with, for instance write 100 chars to file as a string:
(use 'clojure.contrib.duck-streams)
(spit "data-set.txt" (apply str (take 100 data-set)))

Note that the sequence is cached, so I will get the same characters each time (take 100 ...) is called. This may not be what you want. Converting the def to a no-args function, we can call it repeatedly and get different lazy sequences:
(defn data-set []
(repeatedly
#(nth s (rand-int (dec (count s))))))

And do:
(take 100 (data-set))

One final example, a function to calculate the Fibonacci sequence, from http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci:
(defn fib-seq []
((fn rfib [a b]
(cons a (lazy-seq (rfib b (+ a b)))))
0 1))

(take 10 (fib-seq))

Gives:
(0 1 1 2 3 5 8 13 21 34)