Levels of Abstraction – How to Determine the Levels of Abstraction

abstraction

I was reading a book today called "Clean code" and I came across a paragraph were the author was talking about the levels of abstraction per a function, he classified some code as low/intermediate/high level of abstraction.

My question is what is the criteria for determining the level of abstraction?

I quote the paragraph from the book:

In order to make sure our functions are doing “one thing,” we need to make sure that the
statements within our function are all at the same level of abstraction. It is easy to see how
Listing 3-1 violates this rule. There are concepts in there that are at a very high level of
abstraction, such as getHtml(); others that are at an intermediate level of abstraction, such
as: String pagePathName = PathParser.render(pagePath); and still others that are remarkably
low level, such as: .append("\n").

Best Answer

The author explains that in the "Reading Code from Top to Bottom" subsection of the part that talks about abstractions (hierarchical indentation mine):

[...] we want to be able to read the program as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.

  • To include the setups and teardowns, we include setups, then we include the test page content, and then we include the teardowns.
    • To include the setups, we include the suite setup if this is a suite, then we include the regular setup.
      • To include the suite setup, we search the parent hierarchy for the "SuiteSetUp" page and add an include statement with the path of that page.
        • To search the parent ...

The code that'd go along with this would be something like this:

public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}

And so on. Every time you go deeper down the function hierarchy, you should be changing levels of abstraction. In the example above, IncludeSetups, IncludeTestPageContent and IncludeTeardowns are all at the same level of abstraction.

In the example given in the book, the author's suggesting that the big function should be broken up into smaller ones that are very specific and do one thing only. If done right, the refactored function would look similar to the examples here. (The refactored version is given in Listing 3-7 in the book.)

Related Topic