Very rarely, a case comes up where a new function is required even if it is functionally identical to another one. In these cases another meaning is attached to these functions beyond their interface, and machine instructions; reusing it will actually be counterproductive. We examine such a case I encountered at my workplace.
Assertions
I’m sure you’re wondering what the heck I’m talking about- reuse is a
cornerstone of programming! Well, consider the case of assertions. Peppered
throughout the codebase of a project, are macro invocations to
FOO_ASSERT
, which is defined thus:
The assert macro provides information on the failure, including a message, and all is good. It also allows one to disable the assertion if required, during compilation. If we consider the interface and functionality of this macro, it achieves the following:
- Check a condition
COND
- On failure:
- Print a nice
MESSAGE
- Exit the program
Handling errors
As it turns out, given the above functionality, the macro started being used in smaller applications to do regular error handling.
The macro simplified handling errors such as opening files, while inadvertently corrupting its original meaning:
Assertions check invariants which have to hold during normal program execution. If a condition is not satisfied, the logic of the program broken.
Failing to open a file is not an invariant, and is not under the program’s
control. The FOO_ASSERT
macro is being abused to handle regular
errors, and as a consequence, disabling assertions would now break these
applications- the check has to be there to preserve functionality.
After doing some profiling on the algorithms used, more than 50% of the time was spent checking (legitimate) assertions. Without being able to remove their usage, the code is stuck with the assertions. Granted, speed/efficiency was not a requirement, but that is a lot of wasted cycles simply due to the misuse of a macro.
Conclusion
Handling assertions and regular errors are fundamentally different, even if functionally they are the same from the perspective of the source code. This suggests that the usage/semantics of a construct is not only tied to its functionality, but also to its documentation and project coding style.