Clean functions

Caturday will not be stopped!
Y U NO LOAD

Clean functions

Presentation by @JeroenDeDauw

bit.ly/clean-functions

Function size and naming

How big should a function be?

  1. It should be SMALL
  2. It should be SMALLER than that


A function should do one thing.
It should do it well, and it should do it only.

4 - 5 lines

What is "one thing"?

One level of abstraction


function onFirstPost() {
    $messageText = $this->getWelcomeMessageBody();
    if ($this->addFooter()) $messageText.=$this->getWelcomeMessageFooter();
    $this->emailer->send( $messageText );
    foreach ( $this->getReviewers() as $reviewer ) {
         $this->reviewerNotifier->notify( $reviewer );
    }
}
                    

function onFirstPost() {
    $this->sendWelcomeMessage();
    $this->notifyReviewers();
}
                    

Predicates of if and while statements


if ( $foo === 'bar' && ( $user->isAllowed( '' ) || $baz )
    && $this->bah() ) {
    $this->sendWelcomeMessage();
}
                    

if ( $this->isFirstPost() ) {
    $this->sendWelcomeMessage();
}
                    

Bodies of control structures


if ( $this->isFirstPost() ) {
    $this->sendWelcomeMessage();
}
                    

foreach ( $this->getReviewers() as $reviewer ) {
    $this->notifyReviewer( $reviewer );
}
                    

How much indenting / nesting?

Name length rule


$user->remove();

function remove() {
    // ...
    $this->removePostsFromDatabase();
    // ...
}
                    

Well written prose


if ( $this->isFirstPost() ) {
    $this->sendWelcomeMessage();
    $this->notifyReviewers();
}
                    

function notifyReviewers() {
    foreach ( $this->reviewers as $reviewer ) {
        $reviewer->notify( $this->post );
    }
}
                    

Big functions

  • Have multiple functional areas
  • Functions define scopes
  • Have variables used throughout
  • That is what classes are for
  • Group of functions that use a common set of variables

Panic! Lots of small functions!

  • Function call overhead
  • Long time to write all those functions

Silly!

Well named methods, classes and namespaces act like signposts

So what makes small functions unsettling?

The landscape metaphor

Long functions are familiar.
Like landscapes, we recognize the landmarks

New people

  • Do not recognize anything
  • Can only start wandering around aimlessly

New people + signposts

  • Establish themselves quickly
  • Start being productive fast

The bedroom metaphor

  • Everything lying around at some place well known to you
  • Mom gets upset and forces you to clean room
  • You rebel and put things back
  • Part of growing up is realizing this does not work in teams

Call time overhead

  • Nanosecond
  • Compilers are good at optimizing
  • Time better spend on real performance issues
I'm sorry I had to write you such a long letter,
but I did not have time to write you a short one

-- Blaise Pascal


  • Takes time and effort
  • Places burden of breaking down on ALL readers
  • You are a reader as well

Example from gerrit

Function arguments

How many?

  • Ideally none, the fewer the better
  • Arguments are hard to understand
  • More then 3 requires very special justification

Flag arguments

Make functions do multiple things!


                            renderHtml( true );
                        

function renderHtml( $userIsLoggedIn ) {
    // ...
    if ( $userIsLoggedIn ) {
        // ...
    }
    // ...
}
                       

function renderHtmlForLoggedInUser() {

}

function renderHtmlForAnonUser() {

}
                        

renderHtmlForLoggedInUser();
                        

Argument objects


function drawCircle( $x, $y, $radius ) {}
                    

function drawCircle( Point $center, $radius ) {}
                    

Output arguments


appendFooter( $report );
                    

$report->appendFooter();
                    

Side effects

Either do something OR answer something, not both!


public boolean set( String attributeName, String value );
                   

if ( set( "username", "NyanCat" ) )
                    

Same for returning error codes. Error handling is one thing.

Conclusion

  • Small!
  • Small well named functions act like signposts
  • Classes hide in big functions
  • Functions do one thing, extract till you drop
  • Minimize arguments
  • Command query separation

These slides

CC BY-SA 3.0, Jeroen De Dauw

Clone from GitHub or view at bit.ly/clean-functions


Attribution

Slide engine: reveal.js, Copyright (C) 2014 Hakim El Hattab


A lot of the material in these slides is based on works by Robert C. Martin.
In particular his book Clean Code , and Clean Coders video series.

Instead of me