
Functions Should Be Short And Sweet, But Why? - AndreyKarpov
http://sam-koblenski.blogspot.ru/2014/01/functions-should-be-short-and-sweet-but.html
======
yason
Functions should be short and sweet, to an extent, because by thinking in
terms of functions you're building a new language in which you write your
program.

If you're writing big functions by habit then you're just laying more code
after existing code to build a program. If you split your code in functions
and, instead, start _talking_ in the language you've just invented then you're
composing a program. And I think compilers should do the building while I
refrain myself to composing.

Of course, one-line functions don't have inherent value but sometimes they're
needed. For example, to present a higher-level concept that just effectively
happens to be a simple assignment or an inc.

Short functions themselves don't have an inherent value either: if you manage
to write your function with less tokens, possibly due to composing it out of
other functions, then that's all good but isn't the real value of doing it.
Shortness for the sake of shortness only matters until you're down to a
screenful or so.

The real value of defining and writing functions is thinking of the proper
words for your language. As soon as you're making your own language, then
you're just using functions as vehicles to represent words in that language.
Some words might take 30 lines to code, some words might take 3 lines. It
doesn't matter as you've got your language together in a way that is concise
and beautiful which is the real point.

~~~
TeMPOraL
Right to the heart of matter.

This is something Abelson & Sussman were trying to teach us in the 80-s
(stacking abstractions-as-languages on top of each other is one of the main
themes of SICP). Unfortunately this insight got somehow lost in between people
parroting design patterns and repeating things without understanding them
(programming pop-culture?). I've personally seen only a handful of programmers
who know of this concept, and even less of folks who understand it.

------
sdegutis
On the flip side, I've seen people take this to the extreme. They often
separate lines of code that intrinsically belong together, necessary parts of
an algorithm get spread around for no other reason than to try and keep
functions small. It leads to code that's really hard to work with and somehow
more brittle than when it started.

I'm not saying this happens all the time. But I'm more concerned about it,
because I see it more often than the inverse, and it's more damaging to the
codebase. At least long spaghetti methods can be refactored into something
nice. This kind of mess has to be refactored into a single area first, which
is much harder.

~~~
mironathetin
>>On the flip side, I've seen people take this to the extreme.<<

indeed, I have seen functions that contain only one line of code. Even if that
is intended for reuse, it makes no sense, because the function call is one
line too. Readability goes down the drain this way.

If a reader tries to understand a logic and thinking has to be interrupted by
searches and trying to find the right code window, split-ups don't do good
things.

Polymorphism, if applied wrong, is a notorious tool to hide the logic from the
readers too. If the code decides at runtime, which implementation is used,
comments become really important. Especially when this decision is made
completely elsewhere in the code. Think strategy pattern, for example.

The underlying problem is IMHO developers blindly following rules. This can be
seen a lot. If you ask them 'why' and you get a textbook answer, be careful.

~~~
yummyfajitas
A single line function makes sense because it allows you to alter
functionality later without worrying you forgot about some instance of that
pattern:

    
    
        def logUnexpectedError(t: Throwable) = log.error("Oops: {}", t)
    

After I get it together and start keeping proper metrics:

    
    
        def logUnexpectedError(t: Throwable) = {
          log.error("Oops: {}", t)
          statistics.errorCounterByClass(t.getClass()).inc()
        }

~~~
ufo
but on that opther hand, this means added complexity in all the cases where
you _dont_ overload it. Whoever reads the program will always have to keep
overloading in mind.

~~~
pedalpete
hence a good naming convention. If the function name is clear, than it
shouldn't be a mind drain at all, particularly if it is only a one line
function.

------
cheshire_cat
My (quite oldschool) professor taught me about this top-down design. This kind
of "write as if you have all the methods you want/need" style is sometimes
called "Wishful Programming"
[http://blog.thesoftwarecraft.com/2013/11/wishful-
programming...](http://blog.thesoftwarecraft.com/2013/11/wishful-
programming.html)

Bart Bakker references "Structure and Interpretation of Computer Programs" as
an early source and I'm somewhat positive that I read about an similar
approach in "How to design programs 2nd ed", called "programming with a wish
list".

Edit: I found the mention in HtDP but as I understand it it's not exactly the
same as wishful programming:
[http://www.ccs.neu.edu/home/matthias/HtDP2e/part_one.html](http://www.ccs.neu.edu/home/matthias/HtDP2e/part_one.html)

under "3.4 From Functions to Programs"

~~~
agumonkey
I remember doing something similar in college using Eclipse/Java (but any
static analysis friendly language with on-the-fly type checker would do) and
it was pure fun. You just write the code as you'd want it to be, the IDE will
flag missing classes/interfaces and generate them on the go if you tell them,
and if down the road you use one interface differently the IDE will extend or
~reparameterize it for you. You end up with an abstract system/algorithm that
works by type checked interfaces you can now implement.

------
lstamour
This reminds me strongly of some concepts I've heard of in TDD Ruby circles
though I'm certain they're not unique to that. The bit on writing your
function names first is like the practice of "write the test with the API you
want to use, then make it pass with an implementation that does just that."
It's a kind of planning-by-wishful-thinking that just seems to work in certain
scenarios. But I think for it to be successful, you need to read enough best-
practices code in your target language to understand better approaches. That
said, using your phantom code first will give you a better API design. The
trick, as in this article, is to keep writing ideal implementations like
turtles all the way down. If your logic is complicated enough that you'll need
notes or comments, descriptive function names are wonderful. Particularly in
languages like Objective-C with named parameters.

~~~
cheapsteak
I've thought about it as the programming equivalent of writing outlines before
starting on an essay. It requires more forethought, but you can recognize
early on if a line of thought / solution is a dead end, and also makes
restructuring and fixing it much easier

~~~
henrik_w
I often end up factoring out things into common methods in the end. That's
when I see what parts are common, something I don't always recognize in the
beginning (or even in the middle of it).

------
chipsy
I think it's a Goldilocks problem. There's an optimal average size for any
group of related functions, but the skill of planning it is not in nailing it
on the first try, but in determining whether the refactoring will benefit more
when the initial estimate is padded higher or lower.

The main reason for going small at first, I think, is that it creates more
names. Names especially help with very simple calculations that appear
repeatedly and turn into visual noise(true of a lot of UI code). The naming
process can point you towards an instant design change as you discover what
you are "actually" doing in the code. A big function acts as a bigger black
box, thus it can hide these issues. Sometimes you want the black box, but it's
the exceptional case.

------
noir_lord
> Functions Should Be Short And Sweet, But Why?

In my case the why (as well as many of the arguments here) is because I'm not
a "superstar/rockstar ninja coder" and by keeping functions short, clear and
with a descriptive name in 6 months when I open the file to fix the change
request I won't have to spend 2 hours building a mental model of the system to
fix the bug.

~~~
mercurial
If your rockstar coder makes functions five screen longs as a matter of habit,
you may consider changing bands.

------
lucaspiller
I've been doing this in client side Javascript for the last year or so. Rather
than having 20 lines of nested jQuery callbacks on a page, I make each
callback a function and group the event bindings together:

e.g.:

    
    
        var showPreview = function() { ... };
        var calculate = function() { ... };
        $('a.preview').click(showPreview);
        $('a.calculate').click(calculate);
    

Even nicer is to split this out into a separate CoffeeScript file. Then just
call `new SuperAwesomeCalculator()` on the page.

I think what made me do this was Erlang. After a point it gets annoying to
type NewNewNewNewNewParams, so it's easier just to split it out into a
separate function :)

------
kingrolo
I worked on a massive codebase once many years ago (C#/.NET) which had been
built by a relatively competent outsourced team. Somewhere along the way some
consultant on the UK side of the business had insisted that each function
could be no more than 5 lines long. It was horrible to work with - it took so
long to find the place you actually needed to make changes, and it seems like
they'd just started inventing layer names in order to facilitate it.

So yeah, small functions good, but you can take it to extremes.

~~~
sigmaml
I worked on a similar project; the US consultant insisted that each method
should be less than 25 lines. The code involved several decision trees. This
rigid limit made the code quite inconvenient to follow and enhance. After much
sweat and swearing on both sides, the limit was increased to 40 lines!

------
mildtrepidation
Functions should be exactly as long as they need to be to accomplish their
purpose. The _purpose_ is the important part: A function should have a concise
and easily-understood purpose (or very small and logically inseparable set of
purposes) and, tangentially, a name that describes it well.

You can have a fairly long function that's readable and maintainable; those
last two are the important part, and, to a point, they hinge more on how much
work is being done than how much code it takes.

Of course, if you're just plain writing more code than is needed, that's not a
problem with the function itself.

~~~
JoeAltmaier
Yes, the idea of writing straightforward code is critical. If you can do it in
less lines, even at expense of speed or space, you benefit many-fold. Its
easier to understand, read, explain to someone else, remember, debug, compile.
The slowest processor in the system is the wetware between your ears. Funny we
rarely talk of optimizing for speed or space in that engine!

------
rtpg
I think most design patterns and 'best practices' exist because, without them
being explicit, people will tend to do the opposite. Obviously, there are
always use cases where going against the pattern might make sense. But you
should be able to justify it.

Would you rather have mostly short functions with a couple long ones or the
opposite?

------
henrik_w
I completely agree - I made the same points in "7 Ways More Methods Can
Improve Your Program" [http://henrikwarne.com/2013/08/31/7-ways-more-methods-
can-im...](http://henrikwarne.com/2013/08/31/7-ways-more-methods-can-improve-
your-program/)

------
VexXtreme
I just had to deal with extending an absolutely massive C++ function the other
day and it was a nightmare. The function was 2500 lines long and littered with
_several dozen_ exit points - all of which execute under slightly different
conditions. Throw in a couple several hundred lines long switch-case
statements and you can see what I'm getting at. Figuring out the right place
to put a breakpoint that will actually fire due to a maze of conditions and
returns took me a couple hours.

Of course, I've seen many cases where people take this to the opposite extreme
and start breaking up functionality that logically belongs together and can't
be reused in other contexts. It makes it pretty apparent that writing decent
readable code is hard (for many people anyway).

~~~
virmundi
"start breaking up functionality that logically belongs together and can't be
reused in other contexts"

I know you said you're in the C++ world, so I don't think what I'm doing fits
yours, but I've responded to the same behavior in the Java world in a way that
tends to confuse and mystify my co-workers. In Java I've started to declare
classes within methods. These classes can compute complex processes, but are
nicely tucked away in the only logical place they make sense, that method.

My reason for this is that the method really belongs to the containing class.
I can't break it down or abstract it out. I could use composition, but the new
method-class isn't usable by anything else. The sub steps in the method aren't
usable by any other method within the housing class. I could put them there,
but they would just muddy the outer class. So now the code looks something
like this.

public class Outer { void doSomethingComplex(final params) { class
ComplexThing { private void step1() {...} private void step2() {...} public
void goToTown() {...} }

    
    
        new ComplexThing().goToTown();
      }

}

ComplexThing gets access to the outer params. This cuts down on constructor
complexity and cements the intricate bond between the two entities, method and
inner class. The logic is broken down nicely. Finally, nothing is needlessly
shared.

This might make the outer class a bit larger, but I find this structure
pleasant.

It's also a useful pattern for writing tests. Each test method gets a class
(could have inheritance) that has a setup, test, tear down. All of that is
encapsulated in one place.

------
cdelsolar
I recently started messing around with Clojure, and I love the language. I
noticed that you are pretty much basically forced to write lots of short
functions if you want to stay idiomatic and readable. It is pretty good in a
way.

------
dschiptsov
This is why decent schools in old days taught students Lamda Calculus and
Scheme or even Haskell. It helps do develop a strong aversion to verbose
spaghetti code very early.)

------
chj
All the reasons boil down to one: human brains can not hold too much working
memory.

~~~
taeric
Is it a form of irony when programs wind up overwhelming this memory with too
many functions? :)

~~~
AnimalMuppet
Where do you spend your time? I spend some of my time trying to find the right
function, and that gets harder if there are more functions. But I spend more
of my time trying to understand and/or modify that function, and that gets
easier with smaller functions.

So more, smaller functions winds up being a net win (up to some limit, of
course...)

~~~
taeric
This depends on how connected they are. If every function is a "leaf"
function, then yes this is straight forward. However, that isn't possible as
you have to have some functions that call other functions. At this point, you
then need to worry not just about the function you are touching, but all
functions that touch it. It isn't unheard of to spend the time trying to find
all of the subtleties of all functions that rely on the one you are looking
at.

To that end, I would think the more segmented the call trees the better. But
this is often hard to see when looking at a single function/data structure.
This also seems to imply that having duplication of a function is not as evil
as it would seem, since it can free up many of the dependency lines you have
to consider.

All of this is to say that I do not disagree with the premise; though I do
think it is less clear cut.

------
NicoJuicy
For everyone that didn't knew this,
[http://amzn.to/1hhI37v](http://amzn.to/1hhI37v)

You should read it..

PS. It's the book Code Clean ;)

------
avdd_
So why does the main function in this example violate the principle ... i.e.
where is the dispatch table?

