1

Since what matters is not how the code does it but what it does, would you consider wrapping a function with a different name just to clarify it's behavior in certain situations a good practice?

Real life example with pseudo-code:

Let's say I have a small module to generate hardware signals. Now naturally one expects to find somewhere in the API a function to start a signal once all the configurations are done and the hardware is ready to fire:

startSignal(myProperlyConfiguredInstance);

Now, my user would naturally ask himself what happens if this function is called multiple times.

  • Does the code detects the signal is running and ignores the call?
  • Does it throw an exception because it assumes it's an error to try to start the signal multiple times?
  • Does it cause hardware glitches?
  • Does is reset the hardware and starts a new signal?

The obvious answer seems to be "specific behavior should be in the doc" but we all know how documentation seems to decay faster than we write it and clear code is better than clear doc.

My solution to this problem was to do this:

void restartSignal(Instance myInstance){ 
    startSignal(myInstance);

}

Now it seems to me that it is clear that the intended behavior is the 4th bullet and my user doesn't have to ask himself this question; he can just call restart if the signal is running or start if it's not.

But now I have redundant code which doesn't actually acomplishes anything no? It seems like I'm repeating myself and it's perfectly fine to call restart to start an idle signal and start on a running signal!

Which do you prefer? Richer API vs simpler API that requires a peak at the doc / tests / source code?

Asics
  • 239
  • 1
  • 5
  • possible duplicate of [One-line functions that are called only once](http://programmers.stackexchange.com/questions/107669/one-line-functions-that-are-called-only-once). See also: [Should I extract specific functionality into a function and why?](http://programmers.stackexchange.com/questions/166884/should-i-extract-specific-functionality-into-a-function-and-why) – gnat Jul 03 '14 at 20:13
  • 1
    "Which do you prefer? Richer API vs simpler API that requires a peak at the doc / tests / source code?" An API *always* requires a peek at the docs if you want to be sure your program does what you think it does. – Doval Jul 03 '14 at 20:16
  • *"Now, my user would naturally ask himself what happens if this function is called multiple times."* - what does it actually do? – Matthew Jul 03 '14 at 20:18
  • @gnat I read those questions and they don't fully address my problem. The first link is explicitly about functions called once while it's not the case with mine. The second link concerns splitting large functions into smaller functions which is not what I'm doing. – Asics Jul 03 '14 at 20:19
  • With two functions, the user has two opportunities to ask himself what happens if they are called multiple times. (plus the opportunity to ask himself what happens if they are called one after the other, possibly several times). – mouviciel Jul 04 '14 at 07:40

3 Answers3

6

would you consider wrapping a function with a different name just to clarify it's behavior in certain situations a good practice?

Absolutely.

The key thing here is that for almost all code, the interface matters more than the implementation. If it makes sense to have a Restart method in your interface, then add it. Because while it's true that for this class, today the implementations are the same... it's not exactly uncommon for other implementations of the interface to differ, or for changing requirements to cause your implementations to drift apart.

All that said, I would do this as a relatively last resort. Having two different methods that do the same thing is a sign that my design/naming is poor. Users of the interface will often think "What is the difference between these things?".

Telastyn
  • 108,850
  • 29
  • 239
  • 365
1

In general, I'm against writing a method with a semantically different name that simply calls another method but does not have different behavior, unless you're implementing the Adapter Pattern.

The only way this might makes sense is if you name the method something like:

restartSignalIsReallyJustAStart()

which completely explains what you're doing without making the programmer after you wonder why you wrote another method with a different name that does nothing but call the original method.

...except that it's kinda ridiculous, isn't it? Avoid this, and just make sure you have good documentation that explains why "start" and "restart" are the same thing.

Further Reading
Is it a good idea to provide different function signatures that do the same thing?

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • I see your point of how a programmer would read the wrapper and go "why? what does it accomplishes?". What happened is that I did a module to generate signals on a microcontroller and it was eventually used by technicians who don't code often. What happened is that nobody bothered to read the doc and said they didn't get what they expected because they were calling startSignal() in a loop but it would reset the timer counters managing the signal. – Asics Jul 03 '14 at 20:25
0

I like the question. It's definitely an idea that merits some thought. I have seen similar code in the wild, but only in cases like restart being a part of a public interface you are implementing for one of several chips, some of which require different logic to accomplish a clean restart.

For the sake of argument, let's assume for a moment that your intention behind adding restart was completely clear to any future maintainers, which is probably not a valid assumption considering all the confusion just from people commenting on this question.

You still haven't accomplished your original goals, as a lot of open questions remain just from looking at the function signatures, and you might have even created new ones. Your first two questions still very much apply. You still don't know what happens if you call start twice. Adding restart actually would make me more wary of accidentally calling start twice. How important is it to check if it's already started before calling start?

Your second two questions just got moved to the restart function. You still haven't communicated whether a restart causes glitches, does a complete shut down and restart, or whatever.

In the end, you can't avoid documenting certain aspects of your code in the comments. Don't mistake the admonition to avoid over-commenting as an admonition to never comment. The sorts of questions you mention are perfect candidates for API docs.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479