A Longer Post on Shorter Functions

It’s funny how you can hear something over and over again but it doesn’t really ‘click’ until you actually sit down and play with it for a while.

This has been the case with me and using small functions (< 4 or 5 lines). It’s something that I hear people say, and I look at and think “Yeah, that’s a good idea and it makes sense.” Then it comes to implementation and I end up writing methods that range from 5 to 20 lines of code(or sometimes even more I’m ashamed to admit).

I just want to take a minute to show what can happen when we refactor the code to be clear and easier to follow. Let’s say we have a function as follows:


function InitializeModal(){
    if(typeof lookup !== 'undefined'){
        $scope.lookup = lookup;
        if(lookup.Disabled === true){
            $scope.ModalType = 'Enable';
        }else{
            $scope.ModalType = 'Update';
        }
    }else{
        $scope.lookup = {};
        $scope.ModalType = 'Create';
    };
}

To figure out what this function is doing, we can just write what it’s doing in plain English, step by step. To determine the clarity of what we’re actually doing (as opposed to what we want to do) we should write everything out without condensing ‘obvious’ sections of code.

We check if 'lookup' is undefined, if it isn't, 
we assign a scope variable to its value and if the 
lookup is Disabled we set the Modal Type to Enabled 
otherwise we set the Modal Type to Update, if it is 
then we initialize the scope lookup value and assign 
Modal Type to Create.

That sounds simple enough, but look at that sentence. You may have had to go through and read it twice to make sure that we’re talking about the same thing. Well that’s a pretty good sign that A) we’re doing more than one thing, and B) our code isn’t as clear as we initially thought it was.

So now we put on our refactor hat and we just pull out functionality to make the sentence shorter. Let’s start with the else part of the outer if statement as it’s smaller and less intimidating (intimidating code is a pretty good sign that it’s not very clear).

So, let’s create a function that does what we wanted that else to do. We’ll call it SetUpModalAsCreateLookup

function SetUpModalAsCreateLookup(){
    $scope.lookup = {};
    $scope.ModalType = 'Create';
};

Perfect, it’s pretty small, it’s easy to understand

Now our if else looks like this:

if(typeof lookup !== 'undefined'){
    $scope.lookup = lookup;
    if(lookup.Disabled === true){
        $scope.ModalType = 'Enable';
    }else{
        $scope.ModalType = 'Update';
    }
}else{
    SetUpModalAsCreateLookup();
};

Now lets rewrite what this does in English again, then we can compare our sentences. 

First, we check if 'lookup' is undefined, if it isn't, 
we assign a scope variable to its value and decide if 
the Modal Type should be set to Enable or Update, 
if it is then we Set Up Modal As Create Lookup.

Hmm, already that’s making more sense, and note that we’re not focusing on the details as much here, we’re just talking about what happens, we don’t have to talk about how it’s happening.

Let’s do this again, but this time, we’ll focus on the first part of the if statement. Now, it’s a little bit more code, and it’s a little bit less clear… so how do we start? Well, what do we want to do? We want to set up the modal with the lookup value.

function SetUpModalWithLookupValue(){
    $scope.lookup = lookup;

    if(lookup.Disabled === true){
        $scope.ModalType = 'Enable';
    }else{
        $scope.ModalType = 'Update';
};

Now our main function looks like this:

function SetUpModal(){
    if (typeof lookup !== 'undefined') {
        SetUpModalWithLookupValue()
    }else{
        SetUpModalAsCreateLookup();
    };
};

Written in English it looks like this:

If lookup is not undefined we Set Up the Modal With 
the Lookup Value, otherwise we Set Up the Modal As a 
Create Lookup.

That definitely does make sense, but I don’t like that double negative (and you probably don’t either): “is not undefined” — that just sounds… off. So let’s change that to “is undefined.”

function SetUpModal(){
    if (typeof lookup === 'undefined') {
        SetUpModalAsCreateLookup();
    }else{
        SetUpModalWithLookupValue();
    };
};

That’s better, and note that this can easily be turned into a nice clean ternary statement:

//note that spacing has been changed to 
//fit in this block cleanly
function SetUpModal(){
    typeof lookup === 'undefined' ? 
                  SetUpModalAsCreateLookup() :
                  SetUpModalWithLookupValue(); 
};

Now let’s turn our attention to that function that we just created.

function SetUpModalWithLookupValue(){
    $scope.lookup = lookup;

    if(lookup.Disabled === true){
        $scope.ModalType = 'Enable';
    }else{
        $scope.ModalType = 'Update';
};

Now that if else at the end there looks like just a simple assignment with a ternary statement, so let’s see what that looks like.

function SetUpModalWithLookupValue(){
    $scope.lookup = lookup;

    $scope.ModalType = lookup.Disabled ? 'Enable' : 'Update';
};

Okay, so now that we’ve done some refactoring, let’s look at how these small, simple changes have helped. Let’s start off by going back and writing our sentence. Here’s our method:

function SetUpModal(){
    typeof lookup === 'undefined' ? 
                  SetUpModalAsCreateLookup() :
                  SetUpModalWithLookupValue(); 
};

And here’s our sentence:

If the 'lookup' is undefined, we Set Up the Modal As a Create Lookup, otherwise we Set Up the Modal With the Lookup Value.

Well shoot, that’s downright understandable. Like, to everybody. You could say that to your sentence to your mother and she wouldn’t bat an eye. That’s the type of clarity that we want. That’s what we’re aiming for. Now, in a similar fashion we could construct other sentences for the methods that we’ve created, and you could go a step further and put them together to create a paragraph, and guess what. It would be clear and understandable (depending on the order that you put them together).

Okay, so our code is more clear. But does that help us? To answer this, let’s look at the ternary operators that we’ve ended up using. We’ve got two of them,
1:

typeof lookup === 'undefined' ? 
              SetUpModalAsCreateLookup() :
              SetUpModalWithLookupValue(); 

and 2:

$scope.ModalType = lookup.Disabled ? 'Enable' : 'Update';

Where we even able to use these before our refactor? Well with the second one, yes, absolutely, but what about the first? Yes, technically… however, it would have been even more convoluted, it definitely wouldn’t be our best option, but even more harmful than that, it may not have even occurred to use that we could. So what? Well, by refactoring into smaller blocks of code, we’ve discovered areas within our code that can make use of aspects of our language/toolset that were not even options before. By having larger functions we were actually limiting the choices that we could reasonably make in our design.

The example used in this post is obviously very simple, and is only used as a demonstration (after all, that is what examples are for). The point that I was attempting to illustrate is this: by reducing the size of our functions/methods we are not only able to make our code clean and concise, which has many obvious benefits (go read anything on the internet by anyone ever, you don’t need me to prove this to you), but we’re also able to free ourselves from self-imposed, unintentional constraints. These constraints can dirty a class, slow down a project, and reduce the overall health of a development team (I don’t know any developer who is happy to be on a team in which their hands are tied to a subset of a language’s functionality).

Advertisements
A Longer Post on Shorter Functions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s