Tuesday, August 23, 2016

Law of Demeter and perhaps something more strict that isn't quite

Looking at a piece of code today and thinking about the consequences of discovering things about objects a method is passed.

If I have a method that is responsible for performing a mapping, let's call it from type A to type B so

A -> B

or to use a more Scala-ish syntax:

f(A): B

then I might argue that the method f, should not attempt to enhance in any way the object of type A.  If the properties that require the construction of B are not immediately present in A as per the law of Demeter, or if we recast the system slightly such that A may represent a composite, the set of objects represented by A, then there should be an intermediary method that gathers the required information for the mapping operation and creates an enhanced context.  This would be a separation of concerns, one being the enhancement of the object of type A, and the other the operation of generating a B.

A -> B then expands to A -> C -> B

where C is the set of information required to construct B, so we might get two methods:

constructB(C): B so that our type arrow is C -> B

and enhance(A): C so that the type arrow is A -> C

This means that should somebody construct logic that does some kind of side-effecting operation in enhance(), that operation can be isolated from the mapping.

This means that when we look at a mapping function, we can say it should not contain ANY additional type arrows within.  It should only access and map properties from the composite C to create an object of type B.  Any additional mapping or derivation that occurs within, or the processing of a type arrow breaks separation of concerns.

This feels pretty strict, but I'm looking at code today where if that rule had been followed, a very nasty side-effecting piece of code that was buried several levels deep in an abstraction would never have been permitted!