Question

I had a little debate going on with a coworker. Simply put, is there a good reason to hide/encapsulate functions that are pure?

By "pure" I mean the wikipedia definition:

  • Always returns the same results from the same input. (For the sake of this discussion Foo Create(){ return new Foo(); } is considered impure if Foo does not have value semantics.)
  • Does not use mutable state (except local variables) or I/O.
  • Does not produce side effects.
Was it helpful?

Solution

A pure function could still be an implementation detail. Although the function may cause no harm (from the point of view of not breaking important invariants/contracts), by exposing it both the author and the users of that class/module/package lose. The author loses because now he can't remove it even if the implementation changes and the function is no longer useful to him. The users lose because they have to sift through and ignore extra functions that aren't relevant to using the API in order to understand it.

OTHER TIPS

The question is backwards.

You don't seek for a reason to make a function non-public. It is an incorrect mindset to start with (in my opinion). The reasoning should go the other way.

In other words - don't ask "why would I make it private?". Ask: "why would I make it public?"

When in doubt, don't expose it. It's kind of like Ockham's razor - don't multiply entitites beyond necessity.

EDIT: Addressing counterarguments brought up by @Telastyn in comments (to avoid extended discussion there):

I've heard that over time, and even espoused it for quite some time, but in my experience, things tend to be too private.

Yes, it's a pain sometimes if a class is open for inheritance, but you can't override some private methods (whose behaviour you'd like to alter).

But protected would suffice - and it's still non-public.

It leads to a lot of code duplication and overhead to get at "things that shouldn't be public" yet are accessed indirectly anyways.

If it becomes problematic, then simply make it public! There's the necessity I was talking about :)

My point is that you shouldn't do it just in case (YAGNI and all).

Note that it's always easier to make a private function public than pulling it back to privacy. The latter is likely to break existing code.

I don't think the decision to hide/encapsulate a function should depend on its purity. Just because a function is pure doesn't mean that externals need to know about it. Interestingly enough though if the function is pure and meant to be public maybe it doesn't even need to be an instance member of the interface at all maybe it is better suited as a static. But again all of this depends on the intent of the contract and in this case the logical grouping of functionality, not the purity of the function.

Classes should adhere to the Single Responsibility Principle. While a class may need to call on other functionality to achieve its goals, it should only expose functions that are part of its single responsibility.

Here is just one example of a case where visibility could cause a problem.

Consider a class that frobnicates widgets. Maybe as part of its frobnication code it needs some utility function that parses a string: perhaps it needs to transform the widget name in a way that standard string functions do not support.

Since this is a pure function (string comes in, transform it somehow, return a new string), it could be public or private without consequence. Or could it?

If you make it public, now your class has two responsibilities: frobnicating widgets, and transforming strings. This violates SRP, and can cause problems if other classes come to rely on the function. Since this is something you think is only used internal to the class, perhaps you change its interface or visibility. Now classes in other parts of the system are broken.

By keeping the function private, nobody ever has the opportunity to rely on code that is not part of the class's single responsibility.

Licensed under: CC-BY-SA with attribution
scroll top