2

I have a certain function that uses the same (few, 2-5 depending on how I may change it to accommodate possible future uses) lines of code 4 times.

I looked at this question, but it's not specific enough for me, and doesn't match the direction I'm going for.

Here's some pseudo:

function myFunction() {
  if (something) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else if (somethingElse) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else if (anotherThing) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else if (theLastThing) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else {
  // Not previously used code
  }
}

Those same 3 lines of code are copy/pasted (constructing the same object if any of these conditions are met). Is it a good practice to create a function that I can pass all this information to and return the necessary information when it's finished? All of these conditional statements are inside a loop that could run up to 1000 or so times.

I'm not sure if the cost of preparing the stack frame(?) by jumping into another function is more costly over 1000 iterations to be worth having ~15 lines of duplicated code. Obviously function-alizing it would make it more readable, however this is very specific functionality that is not used anywhere else. The function I could write to eliminate the copy/paste mentality would be something like:

function myHelperFunction(someParameter, someOtherParameter) {
  // Code line 1
  // Code line 2
  // Code line 3
  return usefulInformation;
}

And then call the function in all those conditional statements as 1 line per conditional statement:

myHelperFunction(myPassedParameter, myOtherPassedParameter);

Essentially turning those 12 lines into 4.

So the question - is this a good practice in general, to create a new function for a very small amount of code to save some space and readability? Or is the cost for jumping functions too impacting to be worth it? Should one always create a new function for any code that they might copy/paste in the future?

PS - I understand that if this bit of code were to be used in different (Classes) or source files that it would be logical to turn it into a function to avoid needing to find all the locations where it was copy/pasted in order to make changes. But I'm talking more or less single-file/single-Class or in-function kind of a dilemma. Also, feel free to fix my tags/title if I didn't do it correctly. I'm not really sure how to title/tag this post correctly.

Community
  • 1
  • 1
Chris Cirefice
  • 5,475
  • 7
  • 45
  • 75
  • 2
    Many compilers/interpreters can/will inline functions if possible, meaning that unless your function is recursive (and sometimes even then, see [tail call](https://en.wikipedia.org/wiki/Tail_call)) you can call it with no overhead. – Imre Kerr Jun 27 '13 at 17:03
  • I just read up a little bit on inline functions - is that C/C++/C# specific? Or do Javascript compilers also do this? I haven't specified any flag that I want the function to be in-line, and I'm not sure that a JS compiler would automagically know when to make the function inline or not. Do you have any thoughts? – Chris Cirefice Jun 27 '13 at 17:24
  • I'm not sure about Google's JS service, but IonMonkey (the compiler used by Firefox) has function inlining. So it's definitely possible to do in JS. As for which functions to inline, compilers with inlining switched on will inline every function they deem "simple" enough to be worth inlining. – Imre Kerr Jun 27 '13 at 18:00
  • Okay, well knowing Google I'm sure that their JS service does exactly that! – Chris Cirefice Jun 27 '13 at 18:03
  • Performance-wise I can only say it depends. Many environments (.net and the JVM for example) will likely inline this for you. I'd do it for readability and check if it negatively impacts performance afterwards, but that is unlikely. – confusopoly Jun 27 '13 at 22:36

5 Answers5

3

The answer to any optimization question that isn't also an algorithms/data structures question is: Profile your code! Only optimize things that show up as problem areas.

Which means you should find out if function call overhead is actually a performance problem in the specific program you're writing. If it is, inline the code. If it isn't, don't. Simple as that.

Imre Kerr
  • 2,388
  • 14
  • 34
  • Hmm... I've never actually done any profiling. This is written in Javascript through the Google Apps Script service. I'm not exactly sure how to do that other than setting up timers to see how much of a difference there is in execution time. I highly doubt I can see memory allocation/usage, though that probably doesn't really matter so much in this particular case solely because all the code is running on Google's back-end JS service. But this is also a question for future coding, as I'm new to the scene and want to make sure that I make things as efficient and readable as possible. – Chris Cirefice Jun 27 '13 at 17:20
1

Yes create a function, in general you should follow the DRY principal. Don't Repeat Yourself.

http://en.wikipedia.org/wiki/Don%27t_repeat_yourself

Your stack operations are going to be minimal for something like this. See Imre Kerr's comment on your question.

It's not just for readability. So many reasons. Maintainability is huge. If this code has to change, it will be a pain for someone else to come along and try to figure out every place to change it. It's a lot better to only have to change code in one place.

Dodecapus
  • 391
  • 3
  • 10
  • Exactly, that's what I figured in the first place. I just didn't know if the overhead (if any) was a problem in turning such little code into its own function just to prevent a little copy/pasting. But now I know! Thanks for your response :) – Chris Cirefice Jun 27 '13 at 18:05
1

You're approaching this the wrong way, in my opinion. In the first place, you shouldn't be using multiple (else)ifs that all execute the same code; use one with a compound or precomputed (in this case I recommend precomputed due to all the possible subconditions) condition. Something like this will probably make maintaining the code a lot easier.

function myFunction() {
  bool condition = something ||
                   somethingElse ||
                   anotherThing ||
                   theLastThing;

  if (condition) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else {
  // Not previously used code
  }
}
JAB
  • 20,783
  • 6
  • 71
  • 80
  • These conditions contain multiple comparators i.e. `if (x > y && y < z && b == b)`. Multiply that by 4, and you have 12 conditions. Will declaring one boolean for all of those 4 conditions still work if they have 2+ comparisons for each condition? PS - This is is Javascript, I'm not sure if that's a syntactic limitation of the language, but let me know because this would actually really simplify my code! Thank you also :) – Chris Cirefice Jun 27 '13 at 17:16
  • @ChrisCirefice Yes (as long as order of operations is preserved where it matters, of course). And as boolean algebra is a well-defined field, you might even be able to simplify the compound condition as you would a complex mathematical equation. http://sandbox.mc.edu/~bennet/cs110/boolalg/simple.html (note that `*` = `and` and `+` = `or`, if for some reason you were not already aware of that) – JAB Jun 27 '13 at 17:47
  • I was not aware of the equality of those operators haha, but I'm comparing Javascript Date objects in fact, so I'm only using `<`, `>` and `=`. I'll take a look at re-writing all of my comparisons, I have no idea that you could compound them all like that. Definitely, definitely improves readability for sure! – Chris Cirefice Jun 27 '13 at 18:02
  • PS - I wish I could accept your answer because it definitely solved a giant problem I was having with my code, but it doesn't exactly apply to my original question. I did upvote your answer though, because it was definitely helpful :) – Chris Cirefice Jun 27 '13 at 18:04
  • @ChrisCirefice The *=and, +=or thing applies to representations of boolean algebra, not to actual computer code. You'll want to use `&&` for `and` and `||` for `or` as usual. – JAB Jun 27 '13 at 18:05
  • I just thought I would let you know, since I've implemented it in every situation where I have multiple conditional statements all leading to the same function call (as per my original question), that your pre-initialization of all conditional statements as a single boolean has *really* helped me clean up my code, and has made it much more readable. Now, all the conditions are in a single location instead of being spread out throughout a function, and my code has become much more manageable! So thank you once again. I would vote you up 50 more times if I could! – Chris Cirefice Jul 17 '13 at 15:16
1

I don't know if this apply to the example that you provided, but factoring code is not the only reason to write a function, you can also think in term of tests

A function provides a programming unit that can be tested separately.

So it may happen that you decompose a complex operation into several simpler/more elementary units, even if those functions are only called once.

Since you asked the question for a few lines of code, you could ask yourself:

  • can I reasonnably name this function?
    ( justDoThis should be OK, doThisAndThatAndThenAnotherThing less so)
  • does it have a reasonnable number of parameters?
    (I would say two or three)
  • is it worth testing it as a separate unit?
    (does it simplify overall testing)
  • is the code more readable/understandable with such function call or not?
    (if answer to first two questions is no, it's not necessarily obvious)
aka.nice
  • 9,100
  • 1
  • 28
  • 40
  • Well as far as I know Google's JS engine doesn't have testing capabilities other than manual testing (which I have done extensively). But this answer is helpful - when I get back to Java this summer for my non-work projects I'll definitely keep this in mind! Thanks :) – Chris Cirefice Jun 28 '13 at 16:07
0

This is a wonderful question, and the answer is: It depends.

Personally I would create a function for increased code readability, but If you are looking for efficiency maybe you would want to leave the code copied and pasted.

dakillakan
  • 240
  • 2
  • 9
  • That's exactly why I wanted do see the difference in performance stack frame/execution time/memory usage etc.; although I don't know how to do much profiling, I thought I would add that as a talking point just in case someone familiar with the process had any thoughts on performance :P – Chris Cirefice Jun 27 '13 at 17:22