1

Me and a co-developer are arguing when it's wise to cast a new function rather than tweaking another one. By tweaking I mean an option or a hidden check in an existing function. The question could be rephrased: How new/different should a new function be?

In the concrete case, it's about a string comparison. Currently, the procedure is written for one list of strings. We also want to compare strings from two different lists with each other. The docs would be very similar, and code changes include just a few lines.

4
  • If you modify the behaviour of your existing function, would that potentially break code that it is relying on the current version of that function? If so, better make it a new function.
    – Brandin
    Apr 20, 2015 at 17:24
  • Trying to be "clever" is a great way to write horrible code. Are you writing code to prove how clever you are, or to accomplish a task? When revisiting "clever" code 3 months later, is it still easy to modify or extend? Maybe being "clever" isn't the most useful thing when it comes to writing code you'll be maintaining for a long time.
    – MetaFight
    Apr 20, 2015 at 17:32
  • I see, you don't like the word clever. Obviously we don't have the same meaning of clever, so I replace the word.
    – MERose
    Apr 20, 2015 at 17:41
  • 2
    @MERose the word "clever" in the context of "software design" has a bad connotation.
    – user22815
    Apr 20, 2015 at 17:44

1 Answer 1

4

If a function performs two tasks, or one task in two different ways, it should be two functions.

This is the single responsibility principle. While the code may "compare strings" in both cases, the inputs might be different or the way in which it compares strings might be different.

The keys to remember when thinking about it being "clever" to overload a function or add parameters to make it work differently:

  1. The public interface of a class or module (of which functions are members) should be simple and easy to use. Avoid parameters that control what a function does: write two functions. These parameters pollute the interface. On the inside of the module they functions might delegate to a single function and that is okay: the key is to avoid confusing users of the interface.
  2. If possible, abstract the input to the function. Example: in C++, standard library algorithms typically accept iterators for the start and end range with which to work. This allows any container to work with the algorithm, as well as a subset of a container. This may remove the need to add more code whether inside the function or a second function.
  3. Once a library or utility function is well-defined, tested, and documented, try to leave it alone unless there is a bug. Prefer to add another function (see my first point). This helps keep the interface stable.
  4. Try to avoid "clever" solutions: that implies something difficult to understand, such as nested ternary operators or template metaprogramming. Go with a solution that is simple and easy to understand by someone who is not on your development team. Clever ideas grow into technical debt.
1
  • Thank you for the convincing arguments. I changed the word clever as I didn't meant to express what you understood.
    – MERose
    Apr 20, 2015 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.