Thursday, August 15, 2013

Demeter and the Inventor's Paradox

So I've been writing code for a long time, over 15 years professionally. Occasionally I come across a concept that I've read about in the past but that just didn't hit home. Today that concept was the Law of Demeter and the related principle: the Inventor's Paradox. In this post I am going to share my indirect experience with the Inventor's Paradox. I say indirect because, although this concept has possibly been glossed over by me in the past, I have never applied its principles in a conscious manner.

The Inventor's Paradox summarized simply is that often times it is easier to solve a more general problem than a more specific one. Stated another way, solving a general problem is likely to lead to a much more elegant solution. I started applying this principle about 12 years ago after a quick introduction to (the GOF) Design Patterns. Design Patterns opened up my mind to what Object Oriented Programming (OOP) really is and how it can be made to work to my advantage. In particular, I began to think about programs at different levels of abstraction. I continued on my journey via the internet and published tutelage of Bob Martin, Grady Booch and Hunt and Thomas (among many others). Very quickly the concepts that I read and studied began to pay dividends. Namely, my code
  • Grew smaller, MUCH smaller than some of my peers,
  • Began to suffer fewer bugs,
  • Became easier to maintain,
  • Was easier to extend.
One particular area where I've seen application of these principles that reaps huge benefits is with Data Modeling. I happen to work in a field that is singularly unique in the way software is created and works. In my field it is not uncommon to communicate with dozens of other software systems that are each a part of a very complicated coordinated system. The components of the system have evolved over long periods of time. And each component is unique in its language, structure, build environment, hardware requirements, etc. Integrating these systems is a huge chore and often amounts to building unique adapters or bridges between any two components. Sometimes, however, we have the opportunity to design a model for integrating multiple components.

On occasion these opportunities have yielded really intelligent solutions that continue to evolve over time due to their elegance and simplicity. Many times however these opportunities are squandered and the interfaces/bridges end up having a very short lifespan before being reinvented and replaced.

The best data models I've used are ones that hide away the numerous pedantry of data specifics particular to an originating system. Poor models, which unfortunately are very prevalent, are peppered with detail oft-times unnecessary to downstream components. The worst models have data members that mix concepts or ontologies. In other words, a field may convey special information when a value is within some range or another field is at some value.

However, the overarching issue with poor models is lack of a general specification. A proper specification should attempt to formalize the needs of the components in the most general sense. That specification needs to satisfy the immediate needs of its current clients but also to imagine the needs of any future clients. Additionally, the specification needs to include areas for data providers to squirrel away details that are not part of the formal interface but are critical to the needs of system development and maintenance. I usually refer to these areas as Metadata extensions. They are metadata in the sense that they provide information about the data itself. As an example, metadata fields might include details about the algorithm that produced the data for downstream clients.

Reading the Inventor's Paradox reminded me of these situations where a more general approach to data sharing was so much more powerful and easier at the same time!

References:
Adaptive Programming and Demeter