Thought Experiment: No Private Methods In Object Oriented Design
In the Sandi Metz / Hashrocket lunch-n-learn video, on "The Design of Tests", she says something that I found particularly interesting. While discussing whether or not to test private methods, she mentions:
There's a school of thought that says, you should never have a private method .... anything that's private aught to get moved to another class.
Although she states that she doesn't entirely agree with this sentiment, she admits that it's worth thinking about. And, I tend to agree. I love private methods and I use them all the time. But, the thought of minimizing private methods is fascinating.
While the majority of my private methods feel tightly coupled to their parent class, often providing implementation details for validation and state transformation, some of them are general and could be easily moved to another class. For example, if I'm dealing with a 3rd-party API, I'll often create a private method that deals with hashing and the generation of Message Authentication Codes (MAC). This hashing logic could be factored out and put into something like my Crypto.cfc ColdFusion component.
However, when I move a private method to another class, it means that I now have to inject that class as a dependency into the original class. So, while I remove some duplication, I have an increase in complexity and coupling. I'm not calling this a zero-sum game; but, it's also not a flawless victory either.
Good object design is not something that I have a firm grasp on. So, I love these kind of statements that make me stop and think about how I organize my code and how I might evolve that organization. And, while I am not about to abandon private methods, I think it will be very helpful for me to ask the question: would this private method make more sense as a public method in another class?
NOTE: Sandi Metz has a bunch of great videos - you should be watching them.
Private methods are for functionality that relate only to that class. This is not the purpose of the Strategy Pattern- which is what Mertz is recommending. Encapsulating functionality into its own class is done for reusability across non-inherited classes, which is the exact opposite purpose of private methods.
To be fair, I don't think that she was only talking about the strategy pattern. I think she only brought that up in the context of test design - that if a method is intended to be overridden by a sub-class, she will explicitly test that it breaks if the super-class is called directly... at least I think.
That said, I do use and love private methods. When I was writing about this earlier, I actually opened up a few of my components to see how I was using them and they definitely wouldn't make sense to move outside of the context of the current component.
But, there are some that I felt I could probably move to more "utility" type classes.
Sandi also talks about making methods private if they are "unstable." I think you could interpret "unstable" to mean "handles implementation." If you can change the internal implementation of your logic at any time, then it is an unstable method and should be private.
I say, let an object keep secrets if it wants to.
So, while I still enjoy my private methods, I watched a really good video by Corey Haines the other day:
... called the Rules of Simple Design. After watching it, I took a stab at refactoring a StatsD client that I was building in ColdFusion and, while I still have a few public methods, many of my private methods did become public methods in other classes.
Now, this does add some complexity, of course - one file is less complex than 5 files. But, what I found out was that this actually made the code much more flexible; what was a private method become an *implementation* that I could swap out and inject. So, that was pretty cool!