If this kind of a problem happens often in the code ("I often find that I need to add new conditional feature to code that already exists."), then the code is not well-designed or it's design is not understood enough.
In general, it is very hard to give an advice.
First, you should start maintain code less surprising: If you do not have time/money/inclination to refactor, then continue using the same ways as were used before, do not introduce obscure ways. (it's easy, for example do something like:
{True: bar_1, False: bar_2}[foo]()
or do the same with a cool hierarchy of Frobnicator classes, which will solve dispatch problems for you, but this coolness does not mean code will become more maintainable.
Second, consider the business domain. Does foo
really belongs to concerns of the bar
? Does it belong to the same level of abstraction? For the code to be cleaner, function should make only one thing, so each provided parameter makes less cleaner code. Good indicator is, whether the bar_1 and bar_2 have their own distinguishable interpretation in the domain model. If, they do, do not hide if in the function. If the foo
is minor parameter, this if be better inside. (The only exception to this I see in scientific modeling software, where functions can have a lot of parameters and a different programming culture). Also, consider how many times the function is called, because each call will need to be touched everywhere to change the function signature.
If you have doubts after the above, one more consideration can be if you have more than one foo
-like parameters. You can ask yourself a question: are those parameters truly independent or possibly belong as attributes to some entity? For example, if you have x
, y
parameters and add z
, you can consider to use an object point
instead. It may then well be, that the choice will become a concern of that new entity.
As the last defense, you may be better off using rules engine or some other declarative approach. It may keep complexity low and easily maintainable.
Even though you have not asked, making logic more complex with ifs may backfire. Tracing the logic will become harder and harder, and the moment come where noone will understand what is going on, regardless on whether you have if inside or outside your function.