Why shorter methods are better

TL;DR
Longer methods are more likely to need to change when the application changes.

The Longer Story
Shorter methods protect my investment in the code, in a number of ways.

First: Testability. I expect there to be a correlation between method length (number of “statements”) and the number of (unit) test cases required to validate the method completely. In fact, as method size increases I expect the number of test cases to increase faster than linearly, in general. Thus, breaking a large method into smaller independent methods means I can test parts of my application’s behaviour independently of each other, and probably with fewer tests. All of which means I will have to invest less in creating and running the tests for a group of small methods, compared to the investment required in a large method.

Second: Cohesion. I expect there to be a strong correlation between method length and the number of unknown future requirements demanding that method to change. Thus, the investment I make in developing and testing a small method will be repaid countless times, because I will have fewer reasons in the future to break it open and undo what I did. Smaller methods are more likely to “stabilize out” and drop out of the application’s overall churn.

Third: Coupling (DRY). I expect that longer methods are more likely to duplicate the knowledge or logic found elsewhere in the same codebase. Which means, again, that the effort I invest in getting this (long) method correct could be lost if ever any of those duplicated pieces of knowledge has to change.

And finally: Understandability. A method that does very little is likely to require fewer mental gymnastics to fully understand, compared to a longer method. I am less likely to need to invest significant amounts of time on each occasion I encounter it.

The Open-Closed Principle says that we should endeavour to design our applications such that new features can be added without the need to change existing code — because that state protects the investment we’ve made in that existing, working code, and removes the risk of breaking it if we were to open it up and change it. Maybe it’s also worth thinking of the OCP as applying equally to methods.

About these ads

27 thoughts on “Why shorter methods are better

  1. Did you hear about sandis rules on RubyRouges? A co-worker wrote them down: https://gist.github.com/4509394

    We’ve followed 1-3 for a few weeks, only sometimes breaking 2 (5 lines per method) by having methods of 6-7 lines.

    You can only break the rules if you convince someone else on your team that it’s the right thing to do.

    We already wrote quite small methods and classes, but this has certainly had a positive effect on the quality of our code (and raised awareness though discussions).

    • @joakimk Yes, Sandi’s rules are cool. My argument above is intended to be about statistical likelihood. I find that my methods tend towards 1 line long as code is refactored and “settles out”; and I find that code to be the most habitable.

    • @matason Yes, shorter methods should do fewer things. Although “thing” is incredibly hard to define, so instead I describe it in terms of likelihood of change. I don’t really care what “one thing” means; I DO really care if unanticipated future requirements force me to break open and change this chunk of tested code.

  2. I fully agree. I also would like to mention that I like to apply SRP to methods as well. If you treat an object like a tiny, narrowed domain then every method could have only one responsibility. This way you will write short methods that are easier to maintain and test. One exercise that I like to do is that every time I introduce a new method in an object I try to describe it with one short sentence. If I can’t do that then I’ll probably extract some parts of it into other method(s).

    • @_solnic_ I wanted to side-step the whole SRP discussion, focussing instead on how the code behaves under changing requirements. I find SRP to be fractal at best, and confusing (or difficult to argue about) at worst.

      • Interestingly, Robert Martin links the SRP to the second way in which you say short methods protect your investment in code.

        In ASD:PPP, Uncle Bob says of the SRP: This principle was described in the work of Tom DeMarco and Meilir Page-Jones. They called it cohesion…we modify that meaning a bit and relate cohesion to the forces that cause a module, or a class, to change.

        To see how the SRP relates to cohesion, consider what Martin said when I asked him how the SRP relates to Fowler’s smell of Divergent Change [1]: “Divergent Change occurs when you group together things that change for different reasons. Shotgun Surgery [2] happens when you keep apart those things that change for the same reason. So, SRP is about both Divergent Change and Shotgun Surgery. Failure to follow SRP leads to both symptoms…SRP says to keep together things that change for the same reason, and separate things that change for different reasons”

        [1] http://sourcemaking.com/refactoring/divergent-change
        [2] http://sourcemaking.com/refactoring/shotgun-surgery

    • Robert Martin’s SRP is formulated at the class level. At the function (method) level he says (in Clean Code) the following:

      Functions should do one thing, They should do it well. They should do it only. (Page 35)
      G30: Functions Should do One Thing (Page 302)

      • What Martin acknowledges (Clean Code page 35) is that it is hard to know what “one thing” is. Maybe that is what you find confusing.

        So how do we know if a method does one thing? Martin’s answer is to use a technique called ‘extract till you drop’, which he describes in https://sites.google.com/site/unclebobconsultingllc/one-thing-extract-till-you-drop and in http://www.cleancoders.com/codecast/clean-code-episode-4/show.

        In brief:

        #1 “a function does one thing if, and only if, you simply cannot extract any other functions from it. What else could “one thing” mean? After all, If I can extract one function out of another, the original function must have been doing more than one thing.”

        #2 Large functions are where classes go to hide. If you want to find all the classes in your application you should keep your functions as small as possible.
        In order for your functions to do one thing, again, you should keep your functions as small as possible, and so we introduced the discipline of extract till you drop.

      • @philip_schwarz Yes, “one thing” and “single responsibility” have the same failing, imo: they can’t be pinned down. Which is why I prefer any treatment of this subject to be cast instead in terms of change.

  3. Hi Kevin,

    Nice Post.

    >Maybe it’s also worth thinking of the OCP as applying equally to methods.

    What do you mean?

    The original formulation of the OCP (by Bertrand Meyer) was “modules should be both open and closed”, and what he meant was that although the principle seems paradoxical, if we partition our software using OO decomposition (i.e. modules=classes), then we can use implementation inheritance to extend the behaviour of a module (class) without having to open it and modify it.

    Later (slightly paraphrasing Scott Bain in ‘Emergent Design’), with their Design Patterns, the Gang of Four suggested an alternative way of applying the OCP, one that did not necessarily overuse inheritance. The patterns are (in Holub’s words in ‘Holub on Patterns’) largely about replacing implementation inheritance (extends) with interface inheritance (implements).

    This is confirmed by Robert Martin who says (in ASD-PPP) that the Template Method and Strategy patterns are the most common ways of satisfying the OCP.
    His (more modern) formulation of the OCP is “Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.”

    You’ll notice that he has replaced (widened) ‘module’ with (to) ‘classes, modules, functions’, so in some sense at least people have already for a while been engaging in what you call ‘thinking of the OCP as applying equally to methods’.

    My current understanding is that what Martin means when he says that ‘functions’ should be open and closed is what Scott Bain calls ‘Open-Closed at the Method Level':
    “if we pay attention to method cohesion, the granularity of our methods will increase the probability that code changes within classes can be limited to adding methods, or if a method does have to be changed, to changing the code in a single method”.

    Is that what you mean when you speak of OCP as applying to methods?

  4. Kevin,

    given the subject of your post, I think you will be interested in the following presentation that I have recently put together: Four Patterns at the Heart of Good Programming Style https://docs.google.com/file/d/0B58HKx0bzlVrOE5WZFh0elZMYUk/edit

    It is rather unusual in that it is heavy on graphics and in that I use the images on the slides as a script for delivering the presentation. If you find the images too distracting, you can mostly just concentrate on the textual notes.

    If you manage to see past my idiosyncratic style, I’d love your feedback on the subject matter.

    Philip

  5. On the subject of testability, if you have a lot of small methods (6-7 lines), and your average class size is under 100 lines, that still means up to 10 methods per class. Unless you open the accessibility of these methods just for testing purposes, how can you test them directly, and so get the benefit you mention in your first point? I’ve wrangled with this problem many times over the years, and decided:

    Small methods + small API = many methods can only be tested indirectly

    So I end up back where I started, at least from a testing perspective. It feels safer this way than testing methods directly that never get invoked this way in production code.

    • One thing I need to do is reread Michael Feather’s treatment of SRP in ‘This Class Is Too Big and I Don’t Want It to Get Any Bigger’ (chapter 20 of WEwLC), in which he says: “The SRP is kind of hard to describe because the idea of a responsibility is kind of nebulous”.

    • To summarise…

      I have laboured at grokking SRP over the years.

      My first understanding was based on the following extracts from Martin’s ASD:PPP:

      ##################################################################

      This principle was described in the work of Tom DeMarco[1] and Meilir Page-Jones.[2] They called it cohesion, which they defined as the functional relatedness of the elements of a module. In this chapter, we modify that meaning a bit and relate cohesion to the forces that cause a module, or a class, to change.

      The Single-Responsibility Principle: A class should have only one reason to change

      each responsibility is an axis of change. When the requirements change, that change will be manifest through a change in responsibility among the classes. If a class assumes more than one responsibility, that class will have more than one reason to change.

      If a class has more than one responsibility, the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class’s ability to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.

      In the context of the SRP, we define a responsibility to be a reason for change. If you can think of more than one motive for changing a class, that class has more than one responsibility.”

      ##################################################################

      Later I complemented that with the following replies (repeated from my earlier comment) I got from Martin:

      ##################################################################

      Divergent Change occurs when you group together things that change for different reasons. Shotgun Surgery happens when you keep apart those things that change for the same reason. So, SRP is about both Divergent Change and Shotgun Surgery. Failure to follow SRP leads to both symptoms…SRP says to keep together things that change for the same reason, and separate things that change for different reasons

      ##################################################################

      Later still, I complemented that with the the following (again, repeated from my earlier comment):

      ##################################################################

      So how do we know if a method does one thing? Martin’s answer is to use a technique called ‘extract till you drop’, which he describes in https://sites.google.com/site/unclebobconsultingllc/one-thing-extract-till-you-drop and in http://www.cleancoders.com/codecast/clean-code-episode-4/show.
      In brief:
      #1 a function does one thing if, and only if, you simply cannot extract any other functions from it. What else could “one thing” mean? After all, If I can extract one function out of another, the original function must have been doing more than one thing.
      #2 Large functions are where classes go to hide. If you want to find all the classes in your application you should keep your functions as small as possible.
      In order for your functions to do one thing, again, you should keep your functions as small as possible, and so we introduced the discipline of extract till you drop.

      ##################################################################

      The final (for me, so far) piece of the SRP puzzle is revealed in Martin’s clean coders screencast (recommended):
      Clean Code, Episode 9 – The Single Responsibility Principle http://www.cleancoders.com/codecast/clean-code-episode-9/show.

      In a few words: The SRP is about users, or better, their different roles. It is about the responsibilities that our classes and functions have to those roles. Specifically roles who will request changes to the software. See the screencast for more details.

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s