(This diatribe is motivated by comments to the effect that YouArentGonnaNeedIt is countered by OnceAndOnlyOnce.) OnceAndOnlyOnce isn't quite enough. We also need encapsulation. By that I mean everything which talks about X must be in the same module. For example, it's not enough if the database is only opened in one place and only closed in another if those places are different; in other words, if all the low-level database code is spread throughout the system. We want a single module that keeps all the database handling in one place. Then when/if we add a new database, it's easy to find all the places that are directly affected. This is part of good refactoring and undoubtedly part of XP, but I don't think it's been given enough emphasis on these pages. It's been taken for granted. Maybe that's because it's just plain object-oriented common sense, nothing new. OK. One problem is, what kinds of thing are X? Sometimes you have an X which you don't notice. Y2K is an example (albeit a poor one because it's so obvious). Bandwidth may be another: if the app becomes distributed and you want to treat big objects differently to small ones, you will have to identify all places where objects get transferred between processors. Before you can make something a module, you have to make it explicit. And you can't make everything explicit. Sometimes power comes from making things implicit and letting the system work them out; a form of abstraction, hiding detail. Knowing what details to hide and what to make explicit can be a hard judgement call. By making a database module, you are, in fact, anticipating database-related changes. (See also AspectOrientedProgramming, which argues that even the things which need to be explicit can't all be explicit at once. Different aspects of the system need to be made explicit by different views.) (See also MetaObjectProtocol, which argues that the underlying machinery of message-sends and object layout, etc., sometimes needs to be explicit.) (RefactoringYtwok and ActiveObjectModel, especially the comment by RalphJohnson on the latter, are relevant too.) -- DaveHarris ---- Note: Some people use "encapsulation" to mean that instance data should not be manipulated directly from outside the class. In some ways, this is a special case of the more general notion I use above. In other ways, it is confusing encapsulation with InformationHiding. I hope my use is clear enough. -- DaveHarris ---- I would suggest, Dave, that OAOO and Demeter are [nearly] enough to ensure encapsulation. We do have guidelines (not rules) that identify utility methods and other hints at broken encapsulation, but OAOO will kill utility methods as soon as you build them twice. It is amazing how often poor factoring will cause duplication of code segments. Anyway, no disagreement, just the observation that OAOO+Demeter yields quite good encapsulation. -- RonJeffries Ah, well. This exposes my complete failure to grok LawOfDemeter. Most of the benefits claimed on that page seem to derive from OnceAndOnlyOnce. I think by encapsulating the database I mean replacing: this.owner().context().openDatabase(); with: this.owner().context().database().open(); which seems orthogonal to the Demeter concern about the number of dots in either expression. If anything, my preferred version is worse because it has more dots. You could reduce the number of dots by adding a "context()" method to "this" without inventing a database class. What am I missing? -- DaveHarris ---- Can we drill it down a little? If you are in a method of some class, the choice would be between: openDatabase (); and m_database.open (); // m_database is an instance variable neither of which breaks Demeter. Or, am I missing your intent, Dave? -- MichaelFeathers ---- Seems to me that in context, openDatabase is necessarily implemented something like m_database.open(), since if context can open the database, it must have it. I, too, am missing the point, I guess. -- RonJeffries ---- I'm looking for an example of Demeter producing better encapsulation than OAOO would on its own. I don't think openDatabase() is such an example. As far as I can tell, the two comments above are agreeing with me. Does anyone have a better example? Incidentally, I agree that XP does have guidelines for promoting good modules. The process whereby a long method becomes a new class, with the stack frame becoming the instance variables, is an example. It's good stuff; I just don't see how it follows from OAOO or Demeter. Maybe I'm splitting hairs? -- DaveHarris ---- Actually, there are a lot of refactorings that are commonly used. The one you're mentioning here is (if I recognize it) MethodObject. Beck says: * ''How do you code a method where many lines of code share many arguments and temporary variables?'' * The behavior at the center of a complex system is often complicated ... Gradually that [single] method grows and grows, gaining more lines, more parameters, and more temporary variables, until it is a monstrous mess. * ... ComposedMethod only obscures the situation ... * ... create an object to represent an invocation of the method and use the shared namespace of instance variables ... to enable further simplification ... * This is the last pattern I added to this book. I wasn't going to include it because I use it so seldom. ... when you need it, you REALLY need it. So, to your point, does OAOO explain MethodObject. I would have to agree that it doesn't. Code clarity and communication are the point of using this refactoring, so they are part of the final simplicity implied by DoTheSimplestThingThatCouldPossiblyWork. (ie. make the simplest (clearest) code ...). Clearly we haven't expressed this well enough yet. Good catch. -- RonJeffries ''Yes, that's what I meant. -- DaveHarris'' Nope. MethodObject is often a step towards OAOO. I have this huge method. It contains all these repeated statements, but using ExtractMethod produces sub-methods with too many parameters to be helpful. So I first apply MethodObject. Then I can apply ExtractMethod to create methods with no parameters, serving OOAO. It doesn't happen often, but when it does the results can be surprising (and valuable). -- KentBeck But wait. While MethodObject is often a step towards OAOO, is that why we do it? Do we move a method to another class when we see several sends to the same object not self due to OAOO, etc? Certainly these things tend to leave us well-positioned for OAOO, it seems to me that a number of our refactoring cues are not pointing directly to OAOO. Say more. -- RonJeffries ---- Before MethodObject you have a complex class. After MethodObject you have two simpler classes. It appears that simplicity is the goal. MethodObject has some very nice effects: * you now have a new class and a new role in your software * new classes and roles are variation points; they increase the latent potential of your system * it lets you see your system in a different way; you learn * it makes your system simpler while doing all the above and not planning ahead In Kent's book he talks about breaking big things into little things. These are the advantages. To me, the double win of aiming for simplicity and getting flexibility as a side-effect is too cool for words. -- MichaelFeathers