This post originated from an RSS feed registered with Agile Buzz
by Keith Ray.
Original Post: Modifying the Rules
Feed Title: MemoRanda
Feed URL: http://homepage.mac.com/1/homepage404ErrorPage.html
Feed Description: Keith Ray's notes to be remembered on agile software development, project management, oo programming, and other topics.
We all have various rules in our heads, acquired on our life journey from many sources. Learning new techniques sometimes involves "unlearning" (or modifying) some of those rules. On April 5, 2005, in the XP mailing list, Dale Emery wrote of an example of this. He and Elisabeth Hendrickson were teaching a class on unit testing. He wrote:
We ran an exercise where people track down a defect using only unit tests. As part of locating the defect, people end up writing tests for four or five
different methods. Some of the methods are private, and in order to test them, you gotta make them public. Some people are queasy about making stuff public just so you can test it.
To surface what rules are in play here, Dale asked a "why" question thusly: "What concerns do you have about making methods public?"
"Well, then we lose control of the methods."
"What do you mean when you say that you lose control?"
"Other people might call the methods."
"And if people were to call the methods, what concerns you about
that"? (Another "why" question)
"Suppose you need the methods to be called in a certain order.
If people call them out of order, it might mess up the object."
As we explored in this way, the concern became clear: Exposing
the methods might make the object's integrity vulnerable.
We asked a lot more questions in a similar style, and got several
flip charts full of concerns. We summarized these down to these
key concerns: Making private methods public:
Exposes the object to security violations
Makes the integrity of the object vulnerable
Inflates the class's interface:
Commits the class to responsibilities we don't want to commit it to
Confuses users ("which method should I call?")
It seems to me that any one of these is a damned good reason not
to make a method public.
So I said, "What if we could make the method public without any
of these bad effects? Would you still feel queasy about that?"
"Probably not, but you'll have to show us first."
Having gotten their permission, Dale and Elisabeth demonstrated the refactorings Extract Class and Move Method... creating a new class, and moving those private static methods into the new class, making them public along the way. The original class would contain a local or private member variable of the new class type, and would call those public methods using that new local or member variable.
Now, as I understand it, the code being used in the training class didn't have security concerns. And, as it turns out, the private methods were static, so they did not mess with the object-state, and therefore making them public would not make the integrity of the object's state vulnerable to misuse. So the last issue of making these private static methods public was that they would "inflate" the class's interface/responsibilities...
We also offered the idea that if exposing a method inflates the
class's interface to include responsibilities we don't want to
commit the class to, that may be a hint that the responsibilities
belong elsewhere. Moving the method actually makes the original
class more understandable by getting that
"non-core-responsibility" code out of the class. So we not only
avoided that concern, but actually improved things.
Dale and Elisabeth didn't invalidate the rules these people had about private methods, but added a refinement to them... the idea that private methods can be a "design smell" indicating a class has too many responsibilities. Dale sums up:
By eliciting peoples concerns fully, we were able to show how we
could make the code testable AND address their concerns. And in
order to understand their concerns, we asked various forms of
"why" questions (but none that began with "why").
Michael Feathers has an article dealing with a similar situation - code that seemed well-designed, but was not testable. Making it testable improved the design: beforeClarity.pdf