Code in the Language of the Domain

From WikiContent

(Difference between revisions)
Jump to: navigation, search
(New page: Picture two codebases. In one you come across: <code> if (portfolioIdsByTraderId.get(trader.getId()) .containsKey(portfolio.getId())) {...} </code> and you scratch your head, wonderi...)
Line 1: Line 1:
Picture two codebases. In one you come across:
Picture two codebases. In one you come across:
-
<code>
+
if (portfolioIdsByTraderId.get(trader.getId()).containsKey(portfolio.getId())) {...}
-
if (portfolioIdsByTraderId.get(trader.getId())
+
-
.containsKey(portfolio.getId())) {...}
+
-
</code>
+
-
and you scratch your head, wondering what this code might be for. It seems to be getting an id from a trader object, using that to get a map out of a, well, map-of-maps apparently, and then seeing if another id from a portfolio object exists in the inner map. You scratch your head some more. You look for the declaration of <code>portfolioIdsByTraderId</code> and discover this:
+
You scratch your head, wondering what this code might be for. It seems to be getting an ID from a trader object, using that to get a map out of a, well, map-of-maps apparently, and then seeing if another ID from a portfolio object exists in the inner map. You scratch your head some more. You look for the declaration of <code>portfolioIdsByTraderId</code> and discover this:
-
<code>
 
Map<int, Map<int, int>> portfolioIdsByTraderId;
Map<int, Map<int, int>> portfolioIdsByTraderId;
-
</code>
 
-
Gradually you realise it might be something to do with whether a trader has access to a particular portfolio. And of course you will find the same map lookup code fragment - or more likely a similar-but-subtly-different code fragment - whenever something cares whether a trader has access to a particular portfolio.
+
Gradually you realise it might be something to do with whether a trader has access to a particular portfolio. And of course you will find the same map lookup code fragment &mdash; or more likely a similar-but-subtly-different code fragment &mdash; whenever something cares whether a trader has access to a particular portfolio.
In the other codebase you come across this:
In the other codebase you come across this:
-
<code>if (trader.canView(portfolio)) {...}</code>
+
if (trader.canView(portfolio)) {...}
-
You don't need to know how a trader knows. Perhaps there is one of these maps-of-maps tucked away somewhere inside, but that's the Trader's business, not yours.
+
No head scratching. You don't need to know how a trader knows. Perhaps there is one of these maps-of-maps tucked away somewhere inside. But that's the Trader's business, not yours.
Now which of those codebases would you rather be working in?
Now which of those codebases would you rather be working in?
-
Once upon a time we only had very basic data structures: bits and bytes and characters (really just bytes but we would pretend they were letters and punctuation). Things like decimal numbers were a bit tricky because our base 10 number system doesn't work very well in binary, so we had several sizes of floating point types. Then came arrays and strings - which were just different arrays. Then we had stacks and queues and lists. And array lists and linked lists and skip lists. And maps and sets and iterators and lots of other exciting data structures ''that don't exist in the real world''. "Software engineering" was about spending lots of effort mapping the real world into our restrictive data structures. The real gurus could even remember how they had done it.
+
Once upon a time we only had very basic data structures: bits and bytes and characters (really just bytes but we would pretend they were letters and punctuation). Things like decimal numbers were a bit tricky because our base 10 number system doesn't work very well in binary, so we had several sizes of floating point types. Then came arrays and strings &mdash; which were just different arrays. Then we had stacks and queues and lists. And array lists and linked lists and skip lists. And maps and sets and iterators and lots of other exciting data structures ''that don't exist in the real world''. "Software engineering" was about spending lots of effort mapping the real world into our restrictive data structures. The real gurus could even remember how they had done it.
-
Then we got objects! Ok this isn't news, but it does change the game somewhat. If your domain contains concepts like Traders and Portfolios, you can model them with classes called, say, Trader and Portfolio. But more importantly than this, you can model ''relationships between them'' using domain terms too.
+
Then we got objects! OK, this isn't news, but it does change the game somewhat. If your domain contains concepts like traders and portfolios, you can model them with classes called, say, <code>Trader</code> and <code>Portfolio</code>. But, more importantly than this, you can model ''relationships between them'' using domain terms too.
-
If you compose your objects using the built-in general purpose types - ints, strings, chars, lists and maps - then you are creating a tacit (read: secret) understanding that ''this'' int over here means the way to identify a trader, whereas this int over ''here'' means the way to identify a portfolio. (Best not to get them mixed up!) And if you represent a business concept ("some traders are not allowed to view some portfolios - it's illegal") with an algorithmic snippet, say an existence relationship in a map of keys, you aren't doing the audit and compliance guys any favours.
+
If you compose your objects using the built-in general purpose types &mdash; ints, strings, chars, lists and maps - then you are creating a tacit (read: secret) understanding that ''this'' <code>int</code> over here means the way to identify a trader, whereas that <code>int</code> over ''there'' means the way to identify a portfolio. (Best not to get them mixed up!) And if you represent a business concept ("Some traders are not allowed to view some portfolios &mdash; it's illegal") with an algorithmic snippet, say an existence relationship in a map of keys, you aren't doing the audit and compliance guys any favors.
The thing is, the next programmer along might not be in on the secret, so why not make it explicit? Using a key as a lookup into a map of maps to then use another key to perform an existence check is not terribly obvious. How is someone supposed to intuit that that's where the Chinese Walls business rules are implemented?
The thing is, the next programmer along might not be in on the secret, so why not make it explicit? Using a key as a lookup into a map of maps to then use another key to perform an existence check is not terribly obvious. How is someone supposed to intuit that that's where the Chinese Walls business rules are implemented?
-
Making domain concepts explicit in your code means other programmers can gather the ''intent'' of the code much more easily than by trying to retrofit an algorithm into what they understand about a domain. It also means that when the domain model evolves - which it will as your understanding of the domain grows - you are in a good position to evolve the code. Coupled with good encapsulation, the chances are good that the rule will only exist in one place, and that you can change it without any of the dependent code being any the wiser.
+
Making domain concepts explicit in your code means other programmers can gather the ''intent'' of the code much more easily than by trying to retrofit an algorithm into what they understand about a domain. It also means that when the domain model evolves &mdash; which it will as your understanding of the domain grows &mdash; you are in a good position to evolve the code. Coupled with good encapsulation, the chances are good that the rule will only exist in one place, and that you can change it without any of the dependent code being any the wiser.
The programmer who comes along a few months later to work on the code will thank you. The programmer who comes along a few months later might be you.
The programmer who comes along a few months later to work on the code will thank you. The programmer who comes along a few months later might be you.
 +
 +
By [[Dan North]]
This work is licensed under a
This work is licensed under a

Revision as of 19:22, 9 July 2009

Picture two codebases. In one you come across:

if (portfolioIdsByTraderId.get(trader.getId()).containsKey(portfolio.getId())) {...}

You scratch your head, wondering what this code might be for. It seems to be getting an ID from a trader object, using that to get a map out of a, well, map-of-maps apparently, and then seeing if another ID from a portfolio object exists in the inner map. You scratch your head some more. You look for the declaration of portfolioIdsByTraderId and discover this:

Map<int, Map<int, int>> portfolioIdsByTraderId;

Gradually you realise it might be something to do with whether a trader has access to a particular portfolio. And of course you will find the same map lookup code fragment — or more likely a similar-but-subtly-different code fragment — whenever something cares whether a trader has access to a particular portfolio.

In the other codebase you come across this:

if (trader.canView(portfolio)) {...}

No head scratching. You don't need to know how a trader knows. Perhaps there is one of these maps-of-maps tucked away somewhere inside. But that's the Trader's business, not yours.

Now which of those codebases would you rather be working in?

Once upon a time we only had very basic data structures: bits and bytes and characters (really just bytes but we would pretend they were letters and punctuation). Things like decimal numbers were a bit tricky because our base 10 number system doesn't work very well in binary, so we had several sizes of floating point types. Then came arrays and strings — which were just different arrays. Then we had stacks and queues and lists. And array lists and linked lists and skip lists. And maps and sets and iterators and lots of other exciting data structures that don't exist in the real world. "Software engineering" was about spending lots of effort mapping the real world into our restrictive data structures. The real gurus could even remember how they had done it.

Then we got objects! OK, this isn't news, but it does change the game somewhat. If your domain contains concepts like traders and portfolios, you can model them with classes called, say, Trader and Portfolio. But, more importantly than this, you can model relationships between them using domain terms too.

If you compose your objects using the built-in general purpose types — ints, strings, chars, lists and maps - then you are creating a tacit (read: secret) understanding that this int over here means the way to identify a trader, whereas that int over there means the way to identify a portfolio. (Best not to get them mixed up!) And if you represent a business concept ("Some traders are not allowed to view some portfolios — it's illegal") with an algorithmic snippet, say an existence relationship in a map of keys, you aren't doing the audit and compliance guys any favors.

The thing is, the next programmer along might not be in on the secret, so why not make it explicit? Using a key as a lookup into a map of maps to then use another key to perform an existence check is not terribly obvious. How is someone supposed to intuit that that's where the Chinese Walls business rules are implemented?

Making domain concepts explicit in your code means other programmers can gather the intent of the code much more easily than by trying to retrofit an algorithm into what they understand about a domain. It also means that when the domain model evolves — which it will as your understanding of the domain grows — you are in a good position to evolve the code. Coupled with good encapsulation, the chances are good that the rule will only exist in one place, and that you can change it without any of the dependent code being any the wiser.

The programmer who comes along a few months later to work on the code will thank you. The programmer who comes along a few months later might be you.

By Dan North

This work is licensed under a Creative Commons Attribution 3

Back to 97 Things Every Programmer Should Know home page

Personal tools