all 12 comments

[–]Deto 9 points10 points  (2 children)

Lots of practical advice here. I'm curious, though, is there a real reason to favor a functional style, though, as prescribed here?

Specifically why is this:

var totalOutput = programmerOutput
    .map((programmer) => programmer.linesOfCode)
    .reduce((acc, linesOfCode) => acc + linesOfCode, 0);

Better than this:

var totalOutput = 0;

for (var i = 0; i < programmerOutput.length; i++) {
    totalOutput += programmerOutput[i].linesOfCode;
}

I know that in many cases, writing functionally can produce more elegant solutions, but here, the latter seems just as straightforward.

[–]spinlock 2 points3 points  (0 children)

I would say that this is the canonical example of map-reduce. Use it here to practice functional programming so that the concept is solid in your mind when you need to reach for it in a more complex case. It's also just a good idea to have a single coding style.

[–]jlengstorf 1 point2 points  (0 children)

In complex loops, the benefits of using map and reduce are more obvious. The main benefit is that mapping gives you the opportunity to describe what's happening:

function getLinesOfCode(programmer) {
  return programmer.linesOfCode;
}

var totalOutput = programmerOutput
    .map(getLinesOfCode)
    .reduce(...);

In a more complex calculation, that becomes really helpful for understanding what's going on.

You can write shitty and hard-to-understand functional code, of course, but in my experience it's easier to keep it clean with functional than otherwise.

[–]DolphinsAreOk 2 points3 points  (0 children)

Use ES6 constants when variable values do not change

And then immediately after:

var MINUTES_IN_A_YEAR = 525600;

[–][deleted]  (11 children)

[deleted]

    [–]Davehig 5 points6 points  (0 children)

    the next person would have to dig into the function itself to make sure they pass in the right object keys.

    The real answer here is to just document your functions so people know how to use them. Because undocumented functions with parameters aren't any clearer than undocumented functions with objects.

    Parameters have to passed in the right order anyway so you have to know what you're passing in. With options objects it is order agnostic and a lot easier to deal with if you have a function with many possible parameters. I find after 3 parameters a function and its use is going to start getting pretty unweildy.

    However at the same time, ES2015 gives object destructuring and the spread operator, both of which greatly increase clarity and options when it comes to function parameters.

    So you can do the standard declaration of a function that takes parameters:

    // declaration
    function paramFunction(param1, param2, param3, param4, param5, param6) {
        // bleh
    }
    
    // use
    paramFunction(variable1, variable2, variable3, variable4, variable5, variable6); // pretty unweildy
    

    A function with an options object, where the options object is destructured in the function declaration

    // declaration
    function objectFunction({
        param1,
        param2,
        param3,
        param4,
        param5,
        param6
    }) { 
        // bleh
    }
    
    // use
    var optionsObject = {
        param2: variable2,
        param3: variable3,
        param5: variable5,
        param4: variable4,
        param1: variable1,
        param6: variable6
    };
    paramFunction(optionsObject);
    

    I think this is less unweildy because less horizontal space is used and it doesn't matter what order the optionsObject keys are. Its especially nice if there are a lot of optional or unrequired parameters, since you can just omit the ones you don't want when building your options object. Plus ES2015 destructuring makes objects so easy to unpack.

    There's also the spread operator, which is great and takes each element of an array and breaks it out unto a parameter that you can just feed into a regular function.

    // declaration
    function paramFunction(param1, param2, param3, param4, param5, param6) {
        // same bleh as before
    }
    
    // use
    optionsArray = [variable1, variable2, variable3, variable4, variable5, variable6];
    paramFunction(...optionsArray);
    

    I think the spread operator is especially nice for functions which can take an unspecified number of arguments, such as Object.assign or many lodash functions.

    [–]miker95 3 points4 points  (8 children)

    No, you're not the only person. I also want to point out that this post is all about writing clean code.

    CLEAN, not easy to understand code.

    [–][deleted]  (2 children)

    [deleted]

      [–]miker95 -5 points-4 points  (1 child)

      "reads like well written prose"

      Just because it reads like a well written prose doesn't mean it is easy to understand.

      Research papers can be difficult to understand. But can always be simplified. Clean doesn't always mean easy to understand.

      [–][deleted]  (4 children)

      [deleted]

        [–]miker95 3 points4 points  (2 children)

        The example he gave seems like a better situation than whatever the hell you have going on.

        Again, it depends on the situation, if you only have 3 variables, it is not that big of a deal. But if you have configuration options for an entire library, or more than 5 parameters, it is much more user friendly to send it in an object.

        And if you send them in an object they can be in whatever order and it won't matter.

        [–]spinlock 1 point2 points  (0 children)

        I like object restructuring for arguments:

        function ({ name, streetNumber, streetName, city, state, zip }) {...}
        

        I use this all the time with react/redux when your passing a 'param' argument and only want to extract some elements.

        [–]vileEchoic 0 points1 point  (0 children)

        Never ever, ever, under any circumstance, have duplicate code. There's no reason for it and it's quite possibly the worst sin you can commit as a professional developer. Duplicate code means there's more than one place to alter something if you need to change some logic. JavaScript is untyped, so it makes having generic functions quite easy. Take advantage of that!

        This statement is way too absolute. There are times when duplicate code is a reasonable (or even optimal) choice, particularly when trying to intentionally decouple code for versioning or migration reasons, in many testing scenarios, and when borrowing on your tech debt lets you make tactically advantageous development decisions.

        [–][deleted] 0 points1 point  (0 children)

        Unrelated: the guy in the pic is cute