Friday, February 20, 2009

Abstraction: The Sunshine of your Code

As part of a "back to basics" kick I'm currently reading Structure and Interpretation of Computer Programs. This book is a gem and although I'm only through the first two chapters I've been fascinated several times by fundamental and obvious programming concepts that I seem to have overlooked as my career progressed beyond those carefree University days. I'm particularly absorbed in the author's consideration of abstraction.

Abstraction is something I have personally taken for granted even in University. Recalling lectures where profs used analogies of the abstraction of cars or TVs I approached the topic with the blasé "Ya, ya, ya we get it... lets get to the code!" attitude. Now seven years later this book has caused me to reflect upon abstraction and realize that it is the fundamental ingredient of nearly every advancement in the construction of software.

The core idea is in creating Abstraction Barriers to speak a different language in each layer. In doing so, we can work most efficiently with the software itself and more importantly with other humans (of which most are computer language illiterate). To steal the authors' example at the highest level we can all speak about rational numbers, create them, add, subtract and multiply them. Anyone can "program" a calculator to make rational numbers dance. But there's a special class of people we try to avoid at parties who know that a rational number is comprised of a numerator and a denominator. Further there are the computer scientists who would look at a rational number as some kind of pairing of two integers. Now consider that each computer scientist may choose to implement a rational number a different way. Does this change the way the mathemetician's work with numerators and denominators? Does it change the way the average person does math? Absolutely not. But it may be the reason us computer science nerds don't even get invited to those parties.

In essence Abstraction Barriers are the driving force beneath Design by Contract and Interface Driven Design. Object Oriented languages are based on abstraction as there is no inheritance or polymorphism with out it. Even the often abused principle of encapsulation is about protecting the abstraction barrier. Abstraction is the foundation of every OO design pattern ever invented as a design pattern is just summarizing algorithms into a vocabulary. Even the cornucopia of patterns that emerged from Fowler's PoEAA and Evan's Domain Driven Design are again just abstraction barriers applied.

Consider, for example, software engineering tenants such those found in the Domain Driven Design camp which are some of the most powerful tools introduced to software engineering. Layered architectures and Bounded Contexts compartmentalize subsets of Ubiquitous Language into abstraction layers. Each layer or bounded context has a particular language used throughout. For example, Persistence Ignorance is keeping the implementation of physically storing data out of the realm of those who speak about domain and into the realm of those who speak about databases. Knowing the power of abstraction its possible to take the fundamental concept and apply it to your own design techniques.

Quite a while ago I learned the exercise of anthropomorphising software components to help break down software design. I've just recently started to consider abstraction barriers as part of the excercise with great success. For instance, I'm always running into the nagging question of "Where does this particular piece of code belong?". Now, while playing the part of each object in the orchestration I pay attention to the language being used (that is the verbs and nouns of each component's vocabulary) along with the data in play and try to find the lines between abstraction layers. It becomes quite obvious when you've crossed a barrier as the language will change and finding where a piece of code belongs is a simple as identifying components that have the same vocabulary.

For example, on my current project we have a 3D control that works in terms of Geometries. We also have components that can be drawn in this control such as Pipes, Elbows and Tees. The 3D control works entirely with Geometries knowing nothing about Pipes, Elbows or Tees. Conversely Pipes, Elbows and Tees know nothing about Geometries. Here we have two abstraction layers, lets call them the 3D layer and the Domain layer. If I find myself with a piece of code that does something with Geometries its fairly obvious that it should be grouped with the 3D layer. Or more likely I'm tempted to throw some code that works specifically with Pipes on the 3D control. During an intense anthropomorphise excersise this would raise a red flag as the 3D layer doesn't include Pipes in it's vocabulary. I should relocate that code to a service in the Domain layer so the language is consistent. I could then inject the service into the 3D control so it can call on the service to achieve its goal.

As you can see abstraction is a powerful tool for software engineers, and definitely not a concept to be overlooked. So for you kids out there, don't be like me. Treat abstraction with the respect it deserves. For those out in the industry who have forgotten about it whether you read SCIP or not give abstraction a second thought.

If you're interested you can also watch the videos at http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/. They're worth a viewing if at least for a chuckle at the stylish '80s stashes.

0 comments:

 
s