38

Is it better to write many small methods (or functions), or to simply write the logic/code of those small processes right into the place where you would have called the small method? What about breaking off code into a small function even if for the time being it is only called from one spot?

If one's choice depends on some criteria, what are they; how should a programmer make a good judgement call?

I'm hoping the answer can be applied generally across many languages, but if necessary, answers given can be specific to a language or languages. In particular, I'm thinking of SQL (functions, rules and stored procedures), Perl, PHP, Javascript and Ruby.

Michael Mrozek
  • 169,610
  • 28
  • 168
  • 175
Pistos
  • 23,070
  • 14
  • 64
  • 77
  • 1
    Splitting things up helps code readability. if( Convert.ToBoolean(row["IsActive"])) is less readable than "if(obj.IsActive)". :) – Maxime Rouiller Oct 30 '08 at 14:27
  • Hm. Related SOF question: http://stackoverflow.com/questions/20981/how-many-lines-of-code-is-too-many – Pistos Oct 30 '08 at 14:51
  • 1
    I personally dislike it when code has many very small functions (1-3 lines) that are only called from one place (stuff like `int foo(){ return do_foo(); } int do_foo(){ /*actual code*/ }` is the worst, IMO) Then, to understand an actual useful function composed of these pieces, I have to chase each subfunction and it's a) easy to get lost in b) easy to lose sight of possible optimizations. I'd say if it nicely fits in a screenful and and there's no potential for reuse, don't split it. – Petr Skocik May 23 '17 at 10:23
  • 2
    @PSkocik The main benefit I've found (to making methods smaller) is that they are more easily testable, because their scope/responsibility is smaller, and it fits "into" a human mind more easily. – Pistos May 25 '17 at 20:02
  • @Pistos It's a balance. Large monolithic functions are definitely a no-no, but too many unecessary micro-functions can harm readability too -- at least for me they do. – Petr Skocik May 25 '17 at 20:10
  • @PSkocik I totally hear you, and I respect that you're entitled to your opinion. I'll just share with you that I used to think that way a few years ago as well, but have converted over to the small method camp. I haven't found it that hard to traverse execution paths in files. grepping (or equivalent) gets the job done most of the time. I've just found the benefits of keeping things small to be quite tangible. – Pistos May 30 '17 at 14:41
  • One of the problems with long method programming is that it temps programmers, especially beginning programmers, to not write modular code. Code should be located in the classes with the data it works on--sometimes called "object based programming". This helps reduce code duplication. Long method programming tends to create a culture where object based programming is not emphasized. – user2367418 Jan 07 '19 at 17:44

12 Answers12

47

I always break long methods up into logical chunks and try to make smaller methods out of them. I don't normally turn a few lines into a separate method until I need it in two different places, but sometimes I do just to help readability, or if I want to test it in isolation.

Fowler's Refactoring is all about this topic, and I highly recommend it.

Here's a handy rule of thumb that I use from Refactoring. If a section of code has a comment that I could re-word into a method name, pull it out and make it a method.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
14

The size of the method is directly linked to its cyclomatic complexity.

The main advantages to keep the size of the method small (which means dividing a big method into several small methods) are:

  • better unit testing (due to low cyclomatic complexity)
  • better debugging due to a more explicit stack trace (instead of one error within one giant method)
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Agreed. In other words, deep nesting of blocks makes code hard to understand. One way to reduce deep nesting of blocks is to break up a method into multiple smaller methods. There are other ways too, such as early and multiple returns. – user2367418 Jan 07 '19 at 17:31
  • i'm not sure functional breakdown makes the stack trace more explicit. "instead of one error within one giant method" - the errors come with line numbers along with the context of error type and message. – methodsignature Mar 14 '22 at 13:50
  • @methodsignature 14 years later, I think what I meant at the time is that, if the smaller methods are well named (a challenge in itself), reading the stack trace would help "tell a story" of "how did we get there". As opposed to a flatter stack trace and one line in the middle of pages of code for a giant function. – VonC Mar 14 '22 at 15:21
9

As always you can say: it depends. It's more a question of naming and defining the task of a method. Every method should do one (not more) well defined task and should do them completely. The name of the method should indicate the task. If your method is named DoAandB() it may be better to have separate methods DoA() and DoB(). If you need methods like setupTask, executeTask, FinishTask, it may be useful to combine them.

Some points that indicate, that a merge of different methods may be useful:

  • A method cannot be used alone, without the use of other methods.
  • You have to be careful to call some dependent methods in the right order.

Some points that indicate, that a splitup of the method could be useful:

  • Some lines of the existing method have clear independent task.
  • Unit-testing of the big method gets problematic. If tests are easier to write for independent methods, then split the big method up.

As an explanation to the unit-test-argument: I wrote a method, that did some things including IO. The IO-part was very hard to test, so I thought about it. I came to the conclusion, that my method did 5 logical and independent steps, and only one of them involved the IO. So I split up my method into 5 smaller ones, four of them were easy to test.

Mnementh
  • 50,487
  • 48
  • 148
  • 202
8

Small methods every time.

They are self documenting (er, if well named)

They break down the problem into manageable parts - you are KeepingItSimple.

You can use OO techniques to more easily (and obviously) plug in behaviour. The large method is by definition more procedural and so less flexible.

They are unit testable. This is the killer, you simply can’t unit test some huge method that performs a load of tasks

Chris Brooks
  • 289
  • 1
  • 2
  • 2
    +1 for simplicity and ease of testing. Add reusable and you've got a job. :-) – Adam Liss Oct 31 '08 at 04:32
  • regarding "you are KeepingItSimple". a method call within an algorithm is a form of abstraction and therefore more complex than an algorithm that does the same thing but doesn't have such abstraction. i think maybe putting things in terms of contextual load is a better framing for your argument. – methodsignature Mar 14 '22 at 13:56
4

Something I learnt from The Code Complete book:

  • Write methods/functions so that it implement one chunk(or unit or task) of logic. If that requires breakdown into sub tasks, then write a seperate method/function for them and call them.
  • If I find that the method/function name is getting long then I try to examine the method to see it it can be broken down into two methods.

Hope this helps

omermuhammed
  • 7,365
  • 4
  • 27
  • 40
3

Some rules of thumb:

  • Functions should not be longer than what can be displayed on screen
  • Break functions into smaller ones if it makes the code more readable.
JesperE
  • 63,317
  • 21
  • 138
  • 197
  • Your first comment would work in most cases, but I have a 30 inch screen. Also, I saw a coworker with his monitor turned vertically. So I think a new rule of thumb is needed. – kevindaub Feb 20 '09 at 00:13
3

I make each function do one thing, and one thing only, and I try not to nest too many levels of logic. Once you start breaking your code down into well named functions, it becomes a lot easier to read, and practically self-documenting.

JamShady
  • 2,914
  • 1
  • 21
  • 22
3

I find that having many small methods makes code easier to read, maintain and debug.

When I'm reading through a unit that implements some business logic, I can better follow the flow if I see a series of method calls that describe the process. If I care about how the method is implemented, I can go look in the code.

It feels like more work but it ultimately saves time.

There is an art, I think, to knowing what to encapsulate. Everyone has some slight difference of opinion. If I could put it in words I'd say that each method should do one thing that can be described as a complete task.

Bob Probst
  • 9,533
  • 8
  • 32
  • 41
1

The bigger the method, the harder to test and maintain. I find its much easier to understand how a large process works when its broken down into atomic steps. Also, doing this is a great first step to make your classes extensible. You can mark those individual steps as virtual (for inheritance), or move them into other objects (composition), making your application's behavior easier to customize.

1

I usually go for splitting functions into smaller functions that each perform a single, atomic task, but only if that function is complex enough to warrent it.

This way, I don't end up with multiple functions for simple tasks, and the functions I do extract can typically be used elsewhere as they don't try to achieve too much. This also aids unit testing as each function (as a logical, atomic action) can then be tested individually.

Codebeef
  • 43,508
  • 23
  • 86
  • 119
1

It depends a bit ... on mindset. Still, this is not an opinionated question.

The answer rather actually depends on the language context.

In a Java/C#/C++ world, where people are following the "Clean Code" school, as preached by Robert Martin, then: many small methods are the way to go.

A method has a clear name, and does one thing. One level of nesting, that's it. That limits its length to 3, 5, max 10 lines.

And honestly: I find this way of coding absolutely superior to any other "style".

The only downside of this approach is that you end up with many small methods, so ordering within a file/class can become an issue. But the answer to that is to use a decent IDE that allows to easily navigate forth and back.

So, the only "legit" reason to use the "all stuff goes into one method/function" is when your whole team works like that, and prefers that style. Or when you can't use decent tooling (but then navigating that big ugly function won't work either).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
0

Personally, I lean significantly in the direction of preferring more, smaller methods, but not to the point of religiously aiming for a maximum line count. My primary criterion or goal is to keep my code DRY. The minute I have a code block which is duplicated (whether in spirit or actually by the text), even if it might be 2 or 4 lines long, I DRY up that code into a separate method. Sometimes I will do so in advance if I think there's a good chance it will be used again in the future.

On the flip side, I have also heard it argued that if your break-off method is too small, in the context of a team of developers, a teammate is likely not to know about your method, and will either write inline, or write his own small method that does the same thing. This is admittedly a bad situation.

Some also try to argue that it is more readable to keep things inline, so a reader can just read top-down, instead of having to jump around method definitions, possibly across multiple files. Personally, I think the existence of a stack trace makes this not much of an issue.

Pistos
  • 23,070
  • 14
  • 64
  • 77