What are some best practices for using functions to break up large blocks of code into discrete chunks of logic when those functions are only ever going to be used once within the lifetime of a function?

The canonical example for web development is the initialization of a home page. When the page loads, you might do something like check some credentials and authentication, make an API call to get some data, and parse that data. Naturally, this could all be written in a procedural format within a large function called initialize(). None of the logic will foreseeably be re-used anywhere else within the program.

When I'm confronted with such scenarios, my initial instinct is to divide each piece of logic into a discrete function and simply call the functions from an initialize() function, with a few lines of code within initialize() performing some clean up and tear down duties. So I'd have something like an authenticate(), get_data(), and parse_data() function, as well as perhaps a few helper functions for the main functions.

In my opinion, that makes the code easier to understand from a high level, makes unit tests more meaningful, and helps organize your thinking as you're writing your code.

However, I recently clashed with a guy who essentially thinks the opposite. He feels too many functions lead to "annoying jumping around", functions should never be used if code is not going to be re-used, and that the over-use of functions/classes/modules/any kind of modularity amounts to over-engineering. I was put off by his argument and felt that it leads to the shitty procedural PHP that so often makes web development a nightmare, but perhaps there is some validity in what he's saying?

  • 8
    No. There isn't any validity on what he's saying. – Tulains Córdova Oct 13 '13 at 18:34
  • As much as I like the question, it's got at least 3 duplicates - and the one @MichaelT links has a great top answer: "Testing code that does lots of things is difficult. Debugging code that does lots of things is difficult..." – BrianH Oct 13 '13 at 18:51

Executive Summary: He's an idiot. There's no validity to what he's saying.

Code is ALWAYS modified eventually, it is ALWAYS "maintained" eventually, it is ALWAYS reused eventually.

It is always tested and retested.

You always want to design your code for testability and reusability, because, sooner or later, someone is going to need to test it and reuse it, even over your most vociferous objections.

Yes, you can make an over-engineering argument. The problem is that no two engineers will ever agree on what constitutes over-engineering, and over-engineering something generally gives better results than under-engineering it.

| improve this answer | |
  • 1
    Your point about over-engineering is valid, except if the time taken to over-engineer results in the market opportunity getting lost. – Donal Fellows Oct 13 '13 at 19:24
  • 3
    +1: You never mentioned the plain old, most common task performed by a developer - Reading code.....Its done dozens of times before anyone gets to test let alone reuse it. – mattnz Oct 13 '13 at 20:10
  • 1
    @DonalFellows, if the window of market opportunity is perceived to be that short, your company probably should reconsider whether it should be competing in that niche. – John R. Strohm Oct 13 '13 at 20:21

It is better to decompose into smaller functions. If these functions are named clearly, it will make the code much more readable and it will make debugging much easier as well. Think about what the stack trace would look like using this more modular approach vs. the all in one function approach. The fact that these functions are only called in one place doesn't reduce any of these benefits.

Each function should do one thing and do that one thing well. That one thing may include combining the results of some of the functions into a simple interface for the consumer of the functionality. Ultimately, this approach will lead to more compact functions which will make your code much easier to understand. Much worse than having to jump around from one function definition to another (which your IDE should facilitate) is having to scroll through screen after screen of code within one method and trying to keep track of what exactly is going on in your head.

Bob Martin has a great post about this with a detailed example.

| improve this answer | |
  • 2
    Bob Martin's example is debatable, many developers think he is taking it too far. – Doc Brown Oct 13 '13 at 20:07
  • @DocBrown Fair enough. The example at least lays out the mechanics of extracting and some of the rationale, but there is a point at which you can start losing clarity. Good point. – DemetriKots Oct 13 '13 at 20:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.