Ronaldo Vitto Lewerissa

Software engineering learning documentation.

Clean Function

I have learnt for a couple of days prior about how to write a clean function from Robert C. Martin or otherwise known as Uncle Bob.

The whole idea in my opinion always embarks on how expressive it needs to be. If your code is readable and easy to understand, then you have written a clean code.

Sometimes we as a programmer wants to show our co-workers and the readers of our code how smart we are. We tend to provide fancy ways of doing stuff. Making everything as one-liner as it can. If they can't comprehend what we have written, well, they are just plain dumb!

Uncle Bob said that this is a work of an amateur. Professional work the other way around.

Professional want their code to be expressive, understandable, and readable. It needs to be as concise and simple as much as possible!

Why? Because we work as a team, we want to ship fast avoid bugs! If you are the only person responsible for that part of code you written (because nobody understand it except you), then what happen if you leave?

Got the idea?

Let's dive in.

Naming

Naming function is critical to your program.

It should be a verb and it needs to clearly explain what is the intention of the function you are writing, so fellow programmers does not need to dive inside your function to see what it does, a glance from the name itself should be enough!

Do not present hidden implementation (side effects) that goes beyond the function name. Don't say that your function does A, but turns out it also does B.

Small

The first rule he aligns is that function has to be small! Functions needs to be two, three, or four lines long.

Do one thing

Function has to have one responsibility only! It needs to focus on one specific thing and abstract other implementation into a separate function.

Extract big function into smaller chunks, but do not over extract function if a restatement is the only effect it yields.

Sometimes it's hard to do it all from the beginning. Rule of thumb is, write all your implementation function first, then when you are finished, refactor it.

First make it work, then make it right!

Big function that polished into small abstracted steps seems to do more than one thing. It might look as follows:

function foo() {  
  doA();
  doB();
  doC();
}

This little abstractions made the function look like as if it does a lot.

So does it does one thing or three things?

One level of abstraction per function

Well, Uncle Bob state that if the statements within our functions are all at the same level of abstraction, they are definitely do "one thing".

What does it mean abstraction, anyway?

Well, each function you extract from the big function is an abstraction, because you are hiding it's implementation detail by wrapping it to a new function.

Making use of the function does not require you to know how it does it, only what it does (from the name).

So, what is level of abstraction?

appendToArray() and parseHTML() is two different level of abstraction. appendToArray() has simpler implementation therefore lower abstraction level. You certainly know how it does the way it does. Meanwhile parseHTML() is much more complex, more magic is going on, you are not entirely sure how it parse HTML.

Making sure your function has the same level of abstraction is key. One way to look level of abstraction is through LOC (lines of code) it has.

Another way is that a function and all it's extracted method should read well like a paragraph.

Here's the snippet from Clean Code book by Uncle Bob.

To include the setups and teardown, we include setups, then we include the test page content, and then we include the teardown.

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. . .

Arguments

The best number of argument for a function is zero. More arguments means more confusion. You need to remember what to pass, the order of what to pass, and more testing.

Less is better.

Except, if the system you are trying to create has a natural order and requirements. For instance is a coordinate number setCoordinate(x, y).

Exceptions

Exceptions are beneficial since it's able to simplify error handling.

But handling error itself is a specific one thing of what a function does.

Uncle Bob wants you to extract your try/catch block.

function foo() {  
  try {
    doBar();
  } catch (err) {
    logError(err);
  }
}

Written by Ronaldo Vitto Lewerissa

Read more posts by this author.