One of the more interesting code smells is changing our level of abstraction. This one requires a bit of context before we can really dig into it.
First, we need to define what an abstraction level is. Think of an abstraction level the way you think of drilling down into a program if you approach it from a top-down perspective. Here we see three levels of abstraction
Let's use an example of an algorithm for making lunch:
First is our highest level:
- Make Lunch
Next, we ask ourselves how do we do this task? Here are the subtasks on the next level down:
- Retrieve Ingredients
- Retrieve Utensils
- Retrieve Dishes
- Apply Ingredients
- Clean Up
And now we can dig down into the next level. Let's do the Retrieve Ingredients task.
- Get Peanut Butter
- Get Bread
- Get Jam
- Get Milk
- Get Cookie
We can continue this through the other tasks, some of which we would drill down to further levels. At each level, there is an appropriate type of work to be done. When on a given level, we should stay on that level. Going higher or lower creates more confusing and less maintainable algorithms and applications.
For example, If our Retrieve Ingredients algorithm did the following:
- Get Peanut Butter
- Get Jam
- Open Refrigerator
- Retrieve Milk
- Close Refrigerator
- Get Cookie
Then we have a strange mismatch of levels. We are at one level, and for just some of the items, we drill down a level.
Or if we did the following:
- Get Sandwich Ingredients
- Get Milk
- Get Cookie
Here we are at a given level, and we drill up for some of the tasks, and down for others.
This code smell applies to methods. We want each method to be written at one level of abstraction, not more than that. Let's look at a more concrete example now using actual code.
Look at this algorithm for creating an invoice. Do you see the problem? We only want one level in each given method, but this one has two.
We can fix this situation by applying the following change:
And now we have a single level of abstraction.
This code smell can be a bit difficult to spot, but there are a few heuristics. Branches are a good place where the abstraction level often changes. Sometimes loops are the same way. Or even a spot where the code just "looks" significantly different than the other parts of the method. Usually, we need to read the code a bit closer to spot this code smell, but in all our coding we should look out for it and address it when we can.
Happy Coding!
Enjoy this discussion? Sign up for our newsletter here.
Visit Us: thinkster.io | Facebook: @gothinkster | Twitter: @gothinkster
Top comments (0)