0

I strive to have single-responsibility consise functions, but regularly I have functions that flow like this:

logic part1 (~5 lines of code)
logic part2 (~5 lines of code)
return (the results of part1 and part2)

In JavaScript, I have found this style of programming very self-declaring and easy to read (perhaps in an AMD-flavored environment):

performCalculation: function() {
    function part1() {
        // 5 lines of code
        return ...
    }

    function part2() {
        // 5 lines of code
        return ...
    }

    return part1() + part2();
}

Is this good form? Or, is using "function foo() {}" clunky?

Jonathan.Brink
  • 23,757
  • 20
  • 73
  • 115
  • this looks good to me! but you can try promise to flatten your structure and seperate the responsibility, thou this comes with more overhead! – Tim Mar 05 '15 at 02:03
  • 4
    See [var functionName = function() {} vs function functionName() {}](http://stackoverflow.com/q/336859/1048572) for the difference, and [Is there any advantage to naming function declarations?](http://stackoverflow.com/q/28696744/1048572) on which is better form / less clunky. – Bergi Mar 05 '15 at 02:07
  • 1
    This isn't really an appropriate question for the stackoverflow format. If you can reword it as being about a programming principal rather than just a survey of opinions it could be appropriate for programmers.stackexchange.com – George Mauer Mar 05 '15 at 02:10
  • 1
    Personally I would think that for only 5 lines of code you wouldn't need a local function (and if the logic is that different it might better be its own method), but if you like this declarative style **there is nothing wrong with it**. – Bergi Mar 05 '15 at 02:10
  • I understand that this question seems very opinion-oriented, but I was thinking there was perhaps a _correct_ answer, with regard to performance or some other definable metric. – Jonathan.Brink Mar 05 '15 at 02:16
  • 1
    If you'll be invoking this in a loop, you may feel that the overheads of so many function invocations is too costly. Similarly if you're recursing you may find you hit the stack limit too soon. – Paul S. Mar 05 '15 at 02:17
  • @Tim...true, at times using Promises can really clean up logic, but that's not really related to this question...nothing in the question brought up async operations... – Jonathan.Brink Mar 05 '15 at 02:20
  • @PaulS. do you know for sure that first part about function invocation i realistically true? My understanding is that v8 does a pretty good job of optimizing away something like this using function inlining and hotspot compilation. – George Mauer Mar 05 '15 at 02:44

4 Answers4

2

Function invocation is quite pricey in JS if to compare with local blocks of code. Check this http://jsperf.com/anonymous-vs-named-function-passing/3 for example

And I do not see how this

performCalculation: function() {
    var part1; {
        // 5 lines of code
        part1 = ...;
    }

    var part2; {
        // 5 lines of code
        part2 = ...
    }

    return part1 + part2;
}

is worse than what you have.

c-smile
  • 26,734
  • 7
  • 59
  • 86
  • 1
    I up-voted your answer, but I find the syntax you suggested to be awkward... – Jonathan.Brink Mar 05 '15 at 02:23
  • @Jonathan.Brink if it makes you feel better, this code has errors, and I can't determine what the author intended it to be. – m59 Mar 05 '15 at 02:24
  • 2
    If we were going to worry about the cost of a function call, we'd all be writing 500-line functions. That should be the least of your worries. The primary "cost" to worry about is not CPU time, but human time in writing, debugging, and maintaining the code. I would worry about function call overhead only if a function were being called 10M times inside a tight loop (but in many cases, the JIT might in-line it for me anyway). WRT your jsperf, this is not apples-to-apples. `reduce` does a variety of checks, handles sparse arrays, etc. etc. Of course it will still be slower, but so what. –  Mar 05 '15 at 02:55
  • @torazaburo your, my and Jonathan's circumstances can be different. If that performCalculation is invoked more than once you'd better avoid inner functions. Just to minimize CPU consumption and so maximize battery life and so to harmonize our aesthetic feelings with environment footprint, cheers :) – c-smile Mar 05 '15 at 06:37
  • @c-smile No, I don't need to minimize CPU consumption. That is entirely misguided. I need to write nice, clean code which I and other people can understand easily and maintain, and if I decide to structure it using functions the overhead is absolutely minimal. –  Mar 05 '15 at 13:11
1

You seem to be asking two questions:

  1. Is it a good idea to decompose logic into smaller functions and combine them?

  2. Is it better to use var f=function( or function f(?

With regard to the first point, yes, yes, and yes. This makes your code easier to read, provides a form of self-documentation, and is going to be easier to maintain and extend.

@c-smile points out the cost of a function call. Well, if we were going to worry about the cost of a function call, we'd all be writing 500-line functions. That should be the least of your worries. The primary "cost" to worry about is not CPU time, but human time in writing, debugging, and maintaining the code. I would worry about function call overhead only if a function were being called 1M times inside a tight loop (but in many cases, the JIT might in-line it for me anyway). The jsperf he cites is not apples-to-apples. reduce does a variety of checks, handles sparse arrays, etc. etc. Of course it will still be slower, but so what.

With regard to the second point, this has been well answered here, see var functionName = function() {} vs function functionName() {}.

Community
  • 1
  • 1
0

In essence you are creating private functions that you don't want others to use. This is valid from an object oriented point of view. See this stackoverflow answer for more details about private functions and their usage.

In regards to the 'var function name' vs 'function function name' this answer has good arguments.

Community
  • 1
  • 1
Jerome Anthony
  • 7,823
  • 2
  • 40
  • 31
  • 1
    Pretty weak answer. I'd post stuff like this as comments. This question really should be closed rather than answered. If you're going to answer, though, make it a teaching opportunity and get deep. – m59 Mar 05 '15 at 02:07
-1

One big advantage of using the function declaration format is that you can take advantage of perhaps the only use of function hoisting.

performCalculation: function() {
    // What's key here is that the calculation is part1 + part2
    // not the details of implementation so put that first
    return part1() + part2();

    function part1() {
        // 5 lines of code
        return ...
    }

    function part2() {
        // 5 lines of code
        return ...
    }    
}

even better

//someone reading your module likely wants to know what it's returning
//and what its major parts are, so show that at the top of the file
return {
    performCalculation: performCalculation
}

//...

function performCalculation() {
    return part1() + part2();

    //these can now go outside of performCalcuation if that makes it look nicer.
    function part1() {
        // 5 lines of code
        return ...
    }

    function part2() {
        // 5 lines of code
        return ...
    }    
}
George Mauer
  • 117,483
  • 131
  • 382
  • 612
  • IMO code that references variables/functions before they are declared is harder to read... – Jonathan.Brink Mar 05 '15 at 02:18
  • 1
    @Jonathan.Brink When you read a paper do you see the details of their experimental method first? No, you see the introduction that clearly states "these are the takeaways that the author considers important". That is the way the human brain works, it relates position toward the top to higher-level and more important concepts. I have never heard any reason to avoid this in code other than it being merely unfamiliar. – George Mauer Mar 05 '15 at 02:24
  • Well spoken, but I guess I have been conditioned in JavaScript to always declare before invoking/using (b/c of hoisting). – Jonathan.Brink Mar 05 '15 at 02:27
  • ...and code patterns being "merely unfamiliar" in code should be a code smell with regard to readability/maintainability. – Jonathan.Brink Mar 05 '15 at 02:28
  • Yeah, I don't deny the reality of you finding it harder to read. I'm suggesting that this might be something that can become comfortable with minimum effort that could be worth it. As for maintainability, the most important thing for this is communicating to the person coming after you your intention in writing the code. This is simply another tool for enabling this communication. – George Mauer Mar 05 '15 at 02:30