Clean Code – Additional Line in Block vs Additional Parameter

clean codesolid

Context

In Clean Code, page 35, it says

This implies that the blocks within if statements, else statements,
while statements, and so on should be one line long. Probably that
line should be a function call. Not only does this keep the enclosing
function small, but it also adds documentary value because the
function called within the block can have a nicely descriptive name.

I completely concur, that makes a lot of sense.

Later on, on page 40, it says about function arguments

The ideal number of arguments for a function is zero (niladic). Next
comes one (monadic), followed closely by two (dyadic). Three arguments
(triadic) should be avoided where possible. More than three (polyadic)
requires very special justification—and then shouldn’t be used anyway.
Arguments are hard. They take a lot of conceptual power.

I completely concur, that makes a lot of sense.

Issue

However, rather often I find myself creating a list from another list and I will have to live with one of two evils.

Either I use two lines in the block, one for creating the thing, one for adding it to the result:

    public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms)
    {
        List<Flurp> flurps = new List<Flurp>();
        foreach (BadaBoom badaBoom in badaBooms)
        {
            Flurp flurp = CreateFlurp(badaBoom);
            flurps.Add(flurp);
        }
        return flurps;
    }

Or I add an argument to the function for the list where the thing will be added to, making it "one argument worse".

    public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms)
    {
        List<Flurp> flurps = new List<Flurp>();
        foreach (BadaBoom badaBoom in badaBooms)
        {
            CreateFlurpInList(badaBoom, flurps);
        }
        return flurps;
    }

Question

Are there (dis-)advantages I am not seeing, which make one of them preferable in general? Or are there such advantages in certain situations; in that case, what should I look for when making a decision?

Best Answer

These guidelines are a compass, not a map. They point you in a sensible direction. But they can't really tell you in absolute terms which solution is “best”. At some point, you need to stop walking into the direction your compass is pointing, because you have arrived at your destination.

Clean Code encourages you to divide your code into very small, obvious blocks. That is a generally good direction. But when taken to the extreme (as a literal interpretation of the quoted advice suggests), then you will have subdivided your code into uselessly small pieces. Nothing really does anything, everything just delegates. This is essentially another kind of code obfuscation.

It is your job to balance “smaller is better” against “too small is useless”. Ask yourself which solution is simpler. For me, that is clearly the first solution as it obviously assembles a list. This is a well-understood idiom. It is possible to understand that code without having to look at yet another function.

If it's possible to do better, it's by noting that “transform all elements from a list to another list” is a common pattern that can often be abstracted away, by using a functional map() operation. In C#, I think it's called Select. Something like this:

public List<Flurp> CreateFlurps(List<BadaBoom> badaBooms)
{
    return badaBooms.Select(BadaBoom => CreateFlurp(badaBoom)).ToList();
}
Related Topic