Avoiding Private MethodsFri 01 June 2018 by Moshe Zadka
MyClass._dangerous(self) is a private method.
We could have implemented the same functionality without a private
method as follows:
- Define a class
InnerClasswith the same
InnerClass.dangerous(self)with the same logic of
MyClassinto a wrapper class over
InnerClass, where the wrapped attribute is private.
- Proxy all necessary work into
This might seem onerous,
but consider that now,
dangerous is part of the public
interface of a class,
and would need to be explicitly documented as to assumptions and guarantees.
This documentation would have had to have been in comments around
_dangerous anyway --
in order to clarify what its assumptions are,
and what invariants it is violating in
otherwise, maintaining the code that calls
would be hard.
this documentation is almost certain to be missing.
The existence of
implies this was an almost mechanical refactoring
of similar code into a method,
with the excuse of "its private"
used to avoid considering the invariants and interface.
Even if the documentation did exist,
now it is possible to unit-test that the documentation is correct.
if we use best practices when we define
in other words,
avoid creating an
InnerClass object in the initializer,
and only creating it in an
we are also in a good position to unit test
presented the worst case:
the code for
_dangerous touches absolutely every data member
In real life,
the worst case is not often encountered.
When we look at a private method as a code smell,
and contemplate the best way to refactor it away,
it turns out that we often can find a coherent set of attributes
that really does make sense as
InnerClass on their own merits.
Credit: This is based on an off-handed comment Glyph made in his blog post about attrs. I am also grateful to him for reviewing a draft copy of this post, and making many useful suggestions. All mistakes in interpretation or explanation are mine alone.