Avoid Public Functions Calling Other Public Functions
When creating a software module, it's common to have a public function, let's call it "foo," that relies on another public function, "bar," to handle a portion of its work. This approach, guided by the DRY principle, seems logical and efficient at first glance. However, doing so can lead to issues down the road.
The primary concern is that a public API is meant to provide an interface that is optimal for the user at the point of call. If we rely on this shared function to implement the rest of the API, there's a conflict between making the interface user-friendly and making it easy to use internally. This conflict can result in functions developing optional parameters that should never be set by the user. Over time, this can cause the parameters to grow and the interface to degrade.
Moreover, this problem can manifest after the initial code sharing has taken place. By keeping the shared implementation private, we can prevent this tension from arising. Although we might need to adjust the helper function's signature to ensure it performs its tasks effectively, doing so privately minimizes the impact of these changes.
There is one notable exception to this rule: "shortcut" APIs. In these cases, a public function is defined as a chain of commonly used calls to other public functions. In such scenarios, the rule is reversed; private calls are allowed. This ensures that the API is genuinely a shortcut and not a midlayer mistake.
In testing, there's an exception to this rule as well. While it may seem counterintuitive, one shouldn't mock individual methods but rather the software functionality. This approach prevents mocking your methods and focusing on testing the actual functionality, which is a more effective way to ensure the system's reliability.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.