#begin

How nice of you to join me on another blog about A philosophy of software design. Today’s topic is chapter 7 Different Layer, Different Abstraction. A fundamental aspect of software is layered design, there is simply no escaping it. Let’s find ou what Prof. Ousterhout has to say about this.

 

Different Layer, Different Abstraction

John starts with the simple notion that software is always built in layers of abstraction. Each layer provides a different abstraction than the layer above and below it. If a system contains adjacent layers with similar abstractions, that’s often a red flag that suggests a problem with the class decomposition.

The first concept in this chapter is called pas-through methods. These are very simple, often one to three line functions that wrap something like library calls. The example he gives in the book is of a text document that has functions like `getCursorOffset()` which simply calls the member variable’s textArea.getCursorOffset. He says that this is a red flag and should be avoided since it makes modules or classes very shallow. The interface gets very wide for the functionality it provides and thus complexity increases.

And, well I somewhat agree with him, not entirely though. Remember that in clean code, uncle bob often talked about writing code in a really understandable way. So wrapping cumbersome logic into functions that have nicer names seems good to me. Although, this is not always the case! When you simply wrap all the logic of private members and expose them through functions you will end up with really fragile and exposed code. John will call this information leakage. I quickly want to refer back to a section of clean code where uncle bob explains how you should hide implementation details through encapsulation. This also includes clever workarounds for exposing these one-liner functions. Remember Uncle-bobs advise to turn questions into commands. So some code that involves some question that needs information from the getCursorOffset function might be able to be turned into a command which the call to the getCursorOffset function can be made private. This way you don’t need to expose all this logic. But I still do believe that extracting simple short functions for the sake of documentation and easy to read code is good practice.

So what do you think about this? Do you agree with John or Uncle Bob. I personally am somewhere in the middle, you need to apply these things where they fit best, and keep the single responsibility principle in the back of your mind while doing it.

A way to identify that you are working with a pass-through functions is when two, or more functions have the exact same arguments, and are being called in sequence. Keep an eye out on that and try to remove the ones that do not make sense.

John also quickly discusses some situation where pass-through function might be OK and that’s when these pass-through function provide meaningful functionality. He says that web-servers sometimes are implemented this way. He’s probably right, I’m not sure. Maybe he means how some web-servers implement some middleware to serve the requests. But he also specifically mentions the Decorator design pattern. This is a simple wrapper pattern used to create complex objects which also encourages duplication across layers. It basically provides an API where it takes an existing object and extends its functionality and returns an object of the same type. This way you can “decorate” an object with additional functionality so to say.

I personally do not use the decorator pattern often because I don’t like the way the abstraction works. I prefer using an abstract factory pattern more. But that’s just me, how about you, let me know in the comments if you like.

Next John touches on the subject of Interfaces should expose different abstractions than they use internally. This is not always the case, but still often. He explains how often the IO of an interface is defined in specific objects which do not necessarily represent how the data is processed or used internally of that interface. This might relate back to DTO objects we talked about in a previous blogs about clean code. Here we talked about how DTO’s are used for communication purposes to break dependencies. This is a good practice however, maybe not so between modules you design your own, that run on the same machine and not on a network. What john basically means is that you should note expose the internal data structures you use inside an abstraction for management to the outside. This can lead to really awkward to use API’s. Not to mention they lead information as well.

He then also mentions the concept of pass-through variables, which are basically the same as pass-through functions. Try to avoid this and use only the meaningful parts of the objects you need to use. This will turn your functions into more general-purpose functions!

I hope you enjoyed it and learned something. Let’s see you for the next blog as well.

#end

01010010 01110101 01100010 01100101 01101110.

Hey, sorry to bother you but you can subscribe to my blog here.

Never miss a blog post!

You have Successfully Subscribed!