In response to http://blog.8thlight.com/colin-jones/2012/06/05/on-obsessions-primitive-and-otherwise.html
"Connascence
between two software elements A and B means either:
1. that you can postulate some change that would require B. to be changed (or at least carefully checked) in order to preserve overall correctness, or
1. that you can postulate some change that would require B. to be changed (or at least carefully checked) in order to preserve overall correctness, or
2. that you can postulate some change that would require both A and B to be changed together in order to preserve overall correctness."
I
think it’s fair to say that the reason we organize primitives and
operations on them in larger structures, encapsulate them in modules or
as separate entities, is to make sense of them - as humans. We need some
way of having them meaningfully catalogued, so we can wrap our brains
around the concepts of a domain. We require to continuously enable
ourselves to understand what the program does by growing and constantly
refactoring the design. We need to make it easy to identify the parts of
it that require alteration when the business finds a program behavior
necessary to change. And again, we do all of this only because we as
humans need it, because this is how our brains work, how we think, learn
and reason.
The
computers could hardly care whether we introduce the domain concepts to
the program design. If it weren’t for us, the programs could as well be
still written in Assembler, or even in the machine code. As much as the
previous sentence seem blatantly obvious, it should help me make my
point - by having connascence as a tool we can more easily make the
conscious decision of using either the primitives or the domain objects.
I truly believe that the most important factor for choosing either of
the solutions, is to help us to minimize the number of the
interconnections required by a potential change (ie. make the “total
connascence” lower, and better localized).
Example:
Where
there is no (or minimal) ambiguity what a “price” means, and how to
operate on it, it may be safe to just let it be “BigDecimal”. But then,
if the application grows larger and larger, it may so happen that the
other concepts will start appearing, such as “taxedPrice”, or “weight”,
etc. Then it may become more difficult to perform a change related to
“price”, because many entities are connascent, ie. “BigDecimal” and
operations on “BigDecimal” mean different things in different contexts.
Consequently a programmer may use incorrect methods on wrong data,
change parts of code which are semantically unrelated, or do not change
these parts that are related.
All in all based on the definition of connascence in order make a “perfect modification” in a program I want to:
- carefully check as little of it as possible,
- be as certain as possible that I checked enough,
- change as little of my program as possible,
- be as certain as possible that I changed enough.
The
list above may not be exhaustive, and I confess to actually creating it
a bit ad hoc, but it can be extended as needed based on a definition of
connascence. IMHO all that matters is that we keep connascence
localized (ie. easy for a human reader to spot), and minimize the number
of connascent software elements. That of course as a rather generic
statement surely may be applied not only to the problem of primitive
obsession, but to a large number of design decisions.