Methods can be public, protected, private or have package scope.
Methods should be public unless they break the ClassInvariant. Proponents of having only public methods argue that:
1. It is harder to test private and protected methods and you should test them anyway, so you need to make them public. The same argument can be used to promote not having package scope methods. Some say that simply changing "private" to "public" (or even package) is the way to fulfill the testability requirement; others disagree, saying that unnecessarily exposing the functionality through that class is wrong, and point out that the class should probably be refactored to some number of classes with all public methods.
2. Having methods that potentially break the ClassInvariant, even if not public, is a smell that is revealing poor design. This is an interesting proposition in favor of FewShortMethodsPerClass.
I'm starting to have the general feeling that MethodsShouldBePublic.
(This observation seems to be "built in" in to the PythonLanguage, although Guido did add the mangling of attributes starting with __ in a moment of weakness.)
The key insight came when I was thinking about JavaUnit, and CallingOneTestCaseFromAnother. I wanted to delegate all the error recording to the calling test case. After coming up with lots of complicated ways to do it, I realized that there is already a protected TemplateMethod named runTest() which would work for me. I just had to make the method public, and call it from inside the calling UnitTest.
Is MethodsShouldBePublic a general principle? Do any of you Smalltalkers wish you had more protection? (Am I just deluded? I've been assuming that in Smalltalk all methods are public). I know that some of my most exasperating moments in C++ are caused by non-virtual functions and private and protected methods in SomebodyElsesFramework.
After all, just who are we protecting? Are there good cases for protected and private methods? I submit that if you are making a method and you are tempted to make it private or protected, it may be because (1) the private method places the object in an inconsistent state that you don't want to publish to the world (which could indicate that you need to refactor more) or (2) you are doing something sneaky.
Could there be anything less extreme than a protected interface?
Is it true that ugly things grow where the sunlight does not reach?
-- MichaelFeathers (not saying I agree with all this, but I offer it for discussion)
I must disagree with the notion that MethodsShouldBePublic. Programmers ought to tightly control the interfaces they expose for a number of reasons, but most especially to resist the creation of external dependencies on features that are intended as targets for later change or refactoring. If you expose the wrong interfaces, you end up in Microsoft's situation where tons of programmers have used 'undocumented' interfaces, or hooked up to the hacks you wrote when trying to DoTheSimplestThingThatCouldPossiblyWork, and then you can't refactor - not without breaking other people's code. And idealism doesn't do a thing for you: even if you have documents saying not to do something, you need to remember that most programmers don't read documentation when they can avoid it; they more often read code and tutorials, and the code will say that a certain interface is exposed, and the tutorials will tell them of the hacks that other programmers found successful.
MichaelFeathers asks: "Is it true that ugly things grow where the sunlight does not reach?". And the answer is yes, because sometimes ugly things are necessary to DoTheSimplestThingThatCouldPossiblyWork. But it is much better to have the ugly things where nobody else can look than to have them readily visible such that other people grow to depend upon some ugly piece of the code - other people whose codebase you don't control. It matters less if you aren't doing this for libraries, services in SOA, Corba objects, et cetera. - about the only place where one can reasonably follow 'MethodsShouldBePublic' is in writing application code that doesn't even make the methods public beyond package scope - i.e. where these 'public' methods still aren't exposed to the user.
The only reasonable argument for keeping things public is to aide in writing tests that need exposure to the inner workings of the class. But even for this, there is an open question: should you even bother unit-testing 'private' code? All that matters, ultimately, is the public code. The equivalent of private methods in a language that uses slot-based objects is this:
let private_fun = fun(self,x,y,z) -> some-operation in mutable_record{exposed public_methods}.I.e. you could create the equivalent of the record with its private methods simply by substituting 'private_fun' for the body of some-operation in every case (a private method is essentially a specialized refactoring that isn't general to more than the object). Private methods aren't about 'premature optimization' or any of the stuff people are saying below; they're about refactoring within an object - extracting conditionals, etc, just as much as some stuff might be refactored within any other collection of methods, such as a package or application.
I've found it is possible to write objects where every method offers some utility beyond the object itself. I try to refactor toward this, and when I'm successful, I find that every statement contributes something important to the computation. When I'm unsuccessful I find more "noise" methods in my objects, and these are the ones I want to make private. Private is my way of saying sorry. -- WardCunningham
Similarly, I notice CodeSmells when I have too many private or protected methods, or data for that matter. I have a tendency to want to specialize base classes by making all sorts of plug in points... being very accommodative for things that may not happen. Then I realize YouArentGonnaNeedIt and I rip them out. So private and protected methods are a RedFlag to me. They tell me I that I'm on the wrong track sometimes. -- MichaelFeathers
There's no doubt that removing protected and private access lets you build structures and behavior that would be difficult otherwise. In C3 and XP we practice CollectiveCodeOwnership, which allows us to change any class we need to and certainly one thing we do is to use methods that were originally private. It requires good judgment, of course, and you are expected to move the method to a different protocol. Sometimes we have a "friend" protocol, which we'd use for changes like the testing ones you're talking about.
Other posters here on wiki seem to be more paranoid about enforcement, preferring to make private really mean private and using CodeOwnership and so on. To each his own, I guess, though i don't understand why they don't just eliminate people who cause trouble. :) -- R
Since we (on SCTWorkflow) also practice CollectiveCodeOwnership, anyone who sees a shortcoming in a framework is free to modify it. In practice, this particular framework has needed very little modification for quite some time, as it is very flexible. -- RussellGold
When you're dealing with one group of developers who are practicing CollectiveCodeOwnership, maybe you can say MethodsShouldBePublic. But when you're a group of developers releasing a framework to other groups, MethodsShouldBePublic can get a little trickier.
The main problem is that you increase exposure. There is no place for a framework designer to hide implementation details and change things later. Perhaps it would be sufficient to use a comment such as /*{private}*/ in the code, as a note to client developers.
Or perhaps in this case the distinction between private and public is a good thing. Public methods are a declaration that you aren't going to change the method in the future without plenty of warning and some ceremony. Private methods are your own playground, and you're explicitly reserving the right to change those implementations at any point in the future.
But one thing that precipitated this page for me was noticing that some frameworks become all the more powerful when the access control is turned off. So powerful that at that point you don't have to invasively change them. Sure enough, there is a downside. No hiding place for the framework developer. -- MichaelFeathers
I would like to think there is no more problem in exposing the implementation methods as public in a framework than in any other code/application. I think correct framework code should provide the client of a framework with an interface. Thus a client will not get direct access to any of the public methods anyway. -- Anon
Private methods may help to NarrowTheInterface. If you're trying to reacquaint yourself with a class - by either browsing the code, or the documentation - being able to ignore private methods may make it easier to focus on the relevant public methods. Some even find it useful to group fields and methods together depending on their accessibility.
Also, protection can make it easier to reason about the code. E.g., it's easier to be sure that a variable has the value it's supposed to have if you know that no other code can modify it. As with other considerations, this matters more if you don't practice CollectiveCodeOwnership.
If you're using a documentation tool that depends on public-vs.-private declarations, such as JavaDoc, then it might be better to make methods public only if you want them to appear in the documentation.
More public methods == more testing - You made the interface so now you must support it in any manner it may be used. This would cause me to write fewer methods, which leads to ugly, unfactored code.
About "more public methods == more testing" I would add that that is actually the real objective for making all methods public. More testing is not really a bad thing unless you are testing methods that YAGNI.
''Why not all methods public? IMHO, the contract for the class (ie: the invariant) is already hard to achieve with not so many public methods. If all methods are public, the contract is a lot harder to achieve, I have to test things I don't really need just because the class is offering behavior I'm not using. The class interface should be kept minimal, I think, so I would only make public the methods I can't keep protected, because I'm actually using them. -- GuillermoSchwarz''
Actually, I suspect that removing protected and private access decreases reusability by allowing a higher degree of coupling. -- RussellGold
Most OO experts believe that scoping is one of the most important aspects of OO. (For you Java people advocating making everything public, check out Josh Bloch's new Effective Java Programming Book, for instance, as well as almost any good OO text.) It is the mechanism that enables encapsulation, after all. One should always make a method or variable as inaccessible as possible. Fewer public items leads to lower coupling and therefore code that is easier to change in my experience. Making everything public only for the sake of being able to UnitTest every single method in isolation seems a bad design trade off in the long run. As far as YAGNI goes, that is the one XP principle that I can't buy. -- JohnPerkins
This touches on one of things that most intrigues me about YouArentGonnaNeedIt, namely, the defaults. In a sense, making something private until some subclass or client actually needs to call it, is working to YAGNI. In other sense, making it private is building a ShieldPattern and you ain't gonna need that. (The dread phrase PrematureOptimization sometimes gets mentioned too.)
It feels like there is some set of ShieldPattern(s) that are so important you should put them in all the time - in fact the language should do it for you. You are gonna need them so often you should have them even if you can't see a need straight away. If you do that then the other shields can and should be discarded. Eg private data and public methods may be how it goes. It may not be consistent but it's what works in practice. What you don't need, then, is deviations from these defaults, whatever they happen to be.
Picking the defaults ought to be a matter of experience and research into the pragmatics. It's possible that there are several different sets, each member of the set forming part of an ecology for other members of the same set while being hostile to defaults from other sets. It's also likely that different contexts need different defaults. This seems to be the cause of the public/private method argument. -- DaveHarris
YAGNI can be argued both ways (--> "You aren't going to need the method to be public."). Or: Making a public method private later on may turn out to be a lot of work, and you surely aren't gonna need that... ;-) -- FalkBruegmann
A thought: It's easier to loosen security, rather than restrict.
I'm often frustrated by C++'s lack of ability to describe the exact level of access I wish to provide: I may have a special relationship with a "friend" class, where I want to give it access to a few methods - but not the entire implementation. -- JeffGrigg
You can use the delegated friend proxy idiom, or you can move the particular interface to a restricted base class, then hand the pointer over to the friend. But in general, I've found whenever I've wanted this selected type of protection, I'm really looking at a candidate to be broken into TightGroupsOfClasses. -- SunirShah
As a bonus, discarding private protections maybe helpful if you need to be concerned about optimization. See UseStructsNotClasses for more.
It is great when you find a way around things... when the abstractions and existing code are suitable and they don't have to be changed.
In general, I like to use SomebodyElsesFramework by extension rather than modification. Often, this is not possible because the framework designer makes his/her intentions known in the code in ways that impede reuse. If you are blackboxing something that is one thing, but if you are distributing source, a comment would seem preferable to any access specifiers. If TheSourceCodeIsTheDesign, then it is interesting that we have designs that protect themselves from other designers, rather than users. -- mf
Perhaps /*{implementation_dependent}*/ and /*{unsupported}*/ (for things that may change in the next release) would help - with compiler or "lint" support, of course. -- JeffGrigg
I don't see what using comments like /*{private}*/ buys you - you still have to change the source to update the comment when the routine is used, right, else the comment will be a lie? Don't use comments for things which can be better expressed within the language, so that the compiler can enforce them. -- DaveHarris
I prefer not to have private methods, since usually I do not know beforehand which methods I will want to use and redefine in the subclasses, therefore I make those methods protected. Besides I think there is a pattern that says that whenever you redefine a method you should call the original method. Is there one already or I can create this new pattern?
Regarding /*{private}*/ being a lie, perhaps /*{intended-private}*/ is better. -- MichaelFeathers
An example of why private is good sometimes: perhaps a method needs to do two complex things. Maybe it has to clean out the boring objects from its cache, and then store the rest on the external file. Good factoring says the two complex things need to be in separate methods; the object's semantics say you can't do one without the other. The solution is to make the two inner methods private. -- RonJeffries
I agree that there are ordering protocols and dependencies. It could be argued that what I was going to with JUnit (call runTest or assert directly) breaks it in a sense. Exceptions thrown by those calls should be caught. In the current design, they are caught by the Test that throws them. Being able to call runTest directly allows the possibility that they could be caught by another test. This is not what the designers intended, but it is possible. Frankly, the only reason this is possible is because the code is so well factored to begin with. runTest is a separate method. In your cache/external file example, It seems that if a caller is willing to take on the responsibility of calling private method B after A, then it should be okay to externalize the protocol. If it is externalized, they could doing something meaningful between A and B if they need to.
In JUnit there are two protected methods: setUp and tearDown. They are used in run () to initialize and destroy the fixture state. To me, it is less likely that they would be useful externally, but I could imagine someone externalizing the way that tests are run for some reason or another. Making them public would make that possible. You can go in and modify a framework but then you are caught with versionitis if you want to upgrade. I suspect that removing protected and private access increases the amount of reuse that one can do short of modification.
Wouldn't it be better to extract this complexity into a separate InnerClass?
Wouldn't it be nice to have nested methods? (I miss the nested function in PASCAL)
Interesting debate. But, actually, if you write a complex visual class of a thousand lines or so, you're going to want to call subprocedures (for instance to draw things on the screen) and you don't want the state of your object getting toyed with while it's in the middle of something. I declare my internal helper methods (things that aren't part of the contract, but allow me to do things OnceAndOnlyOnce) as protected. This means that someone can come along later and add safety features and make it public, but in the short term the work of keeping the object consistent through all of that is something I don't need. -- NickArgall
You're dealing with thousand-line classes? Doctor, it hurts when I do that. -- francis
I would argue that helper classes and utility functions should be either segregated into a utility class or exposed as public static methods. See comments several discussions down. -- WayneMack
Is it true that private is just a comment in Smalltalk? -- mf
Yes, private in Smalltalk is generally just a comment. I believe there have been experimental Smalltalks where it was actually checked. -- R
It would be nice to add this to SqueakSmalltalk. -- GuillermoSchwarz
Regarding machine support for private methods, I would like for Smalltalk to have a warning when you use a private method externally from a class. (Notwithstanding that this isn't quite possible.) Why? Because it would alert me to an anomaly in the system, which I would then have an opportunity to correct, by refactoring, by making the private method public, whatever. I would not, however, want the world to stop until I fixed it. -- RonJeffries
You could just have a tool to test this condition in the whole system, so fix when it hurts only. OTOH the compiler should be modified so that it complains when you try to accept code like that. -- GuillermoSchwarz
A quick examination of a recent project revealed a couple of patterns (not Patterns, yet). In some cases, private methods can be replaced by private objects that do the same thing, something I shall add to my refactoring toolkit. In other cases, the private methods could in theory be implemented with a private object, but their function would be so trivial it isn't worth the effort. I can think of a third case, where private methods have functionality that couldn't be put in its own object, but I honestly couldn't find any examples. -- CraigPutnam
I will concur with the above observation. I am finding that private methods are a strong indicator of a lower-level class just waiting to be defined. -- WayneMack
For the brave C++ programmer: -Dprivate=protected
In C++, I have really found that "protected" is unnecessary beyond constructors and possibly destructors. "Protected" is usually used in one of two ways, to break encapsulation and allow a higher level class modify internals of a base or lower level class, or to provide utility functions.
For the first case, violating encapsulation in this manner indicates some refactoring is in order. You typically have a poorly-defined division between your base and higher level class and either methods should be pulled down or variables pushed up in the hierarchy. (This concept also applies to overloading of functions. Define a pure virtual in your base class and only overload it once in any hierarchy.)
In the second case, where you are providing some utility functions, if the function is used only once in the hierarchy, put it in the appropriate class. If it is used in multiple places and is loosely coupled, create a utility class. If it is tightly coupled, expose some public static utility functions. In either case, the functions are likely applicable outside of the classes currently using them.
-- WayneMack
I have always been using "protected" keyword for private methods and variables as it provide me the flexibility to call any helper function in the parent class. Also, I am not here to start a war but, using "protected" would be the only way to use DirectVariableAccess? technique for people who need it. More over, if protected methods are provided for the child class to use or further specialize, I do not see this as breaking any encapsulation. The "protected" keyword is in a sense public to the hierarchy but private to other classes, so there's no reason that it means breaking encapsulation. I can't think of any examples right now, but feel free to give inputs or examples. -- ChaoKuoLin
Consider using an encapsulated class rather than an inherited class provide utility methods. I usually find that it works best to use inheritance when I want to expose something to the outside world and use encapsulation when I want to hide something from the outside world. I can only assert that I find my code clearer after taking this approach, but I would urge others to try this and see if they do not find similar results. -- WayneMack
You can have my private methods when you pry them from my cold, dead hands. A lot of my methods are complicated mathematical algorithms. I ExtractMethod to make them readable. Those extracted methods like being private. They depend on the state of the object being just so. Making them robust enough to be public would clutter the code and provide no additional value. Later on, if I realize one of those methods could be reused I usually extract a whole new class to share the behavior with the original class and the new class. -- EricHodges
I'm really happy to see this subject. I've been thinking along these lines lately and I've been discussing it with others and getting blank stares. My general thought is that I don't need all those levels of protection in Java. Perhaps two would be sufficient for me, public and notPublic. And I would use notPublic sparingly. This is based on having done a lot of test-first programming in either full-XP or partially-XP contexts in the last 18 months. I'm getting smaller classes, smaller methods, etc... I've noticed less need for different levels of protection and in fact, visibility issues are sometimes getting in my way. So without any hesitation, I make something public if I need to. Then, when refactoring, I'm looking at the public interface of the class and determining if the class is "too big" or somehow, not cohesive. If so, I break it up into multiple classes. -- MikeCorum
This is confusing public/not-public with published/not-published which I feel are distinct concepts. See MartinFowler's article PublicVsPublished? at http://martinfowler.com/ieeeSoftware/published.pdf as a starting point. There are legitimate uses for protected which should still be published. TemplateMethod being a good example of using protected when it should be published. And sometimes, legitimate uses for public which should not be published (which is seen in large programs like Eclipse). Once a class/interface/method is published then its structure should not be altered in any way regardless of its visibility. I believe JavaDoc makes an error in assuming that visibility should determine whether or not a class/interface/method is published. -- DouglasHawkins
Non-public methods are good (simpler interface). When we create test cases for a private Java method, we change the visibility of the method to be package (default). The method is still hidden from outside the package; the test cases are in the same package, of course.
I wonder whether JavaMethodsShouldHavePackageVisibility?... -- JyrkiHeikkinen?
The security of Java depends not only on public/private/protected, but on the VM enforcing these distinctions. Imagine the havoc that would result if an applet could, via nasty inheritance tricks and the like, set the current SecurityManager to null.
When it's entirely trusted code, encapsulation can be handled by naming convention (ala Python), by ThisIsPrivateComment?, and other means which aren't enforced by the implementation. When it's untrusted code, it's good for the implementation to provide a lock-solid ChastityBelt? to protect the private parts. :)
PrivateMethods? are an AntiPattern, as well as PublicInstanceVariables? and ProtectedInstanceVariables?.
PrivateMethods? should not exist because of the following:
So you really want to expose your low level link list or database handling code when the only method you want people to be able to call is AddUser?? You want code to be tightly coupled to your implementation so you can't change the implementation without breaking all code that used any methods other than AddUser?? That is bad design. Making methods public unnecessarily radically increases coupling. Your public interface is the contractual service you are providing and is what you pledge you will try to change as little a possible. Private methods have no such guarantee. Otherwise refactoring would be impossible because it would be impossible not to break interfaces because everything is part of the interface.
All the book keeping can change and nobody should care. In addition, private methods have different locking behaviours. All public methods should be thread safe, for example. Whereas private methods can be called from multiple contexts so won't lock because they make certain assumptions. Pushing the safety back on to clients is dangerous as hell. The same for state machines. Private methods may assume a lot about the current state in which they operate, assumptions you don't want to expose to the client. Making all methods public is bad design.
Having only public methods in a class doesn't mean that it also contain all the methods that were private too. Those private methods should be farmed out to some utility class, or made free functions.
Too often the 'private' methods are hiding useful functionality which others could use. The method isn't intrinsically coupled to the class, but to the class's data. Calling a free function with arguments or a private function that implicitly takes its arguments from the class instance only differs in that the free function can be reused where the 'private' cannot.
Although I support the premise, I disagree with this particular supporting argument. Coupling to a class is based on the coupling to the data within the class. One cannot say the a method is coupled to a class's data and then say the "method isn't intrinsically coupled to the class".
'Too often the 'private' methods are hiding useful functionality which others could use.'
Opportunistic reuse isn't a good idea because:
Perhaps it's us, and we are atypically terrible. But I've just opened a class header at random (well not quite at random because I had an inkling it would be fertile grounds), and it has a couple of public methods and about 15 private methods. The class creates geometry from other geometry, and much of the analysis involved is trying to determine the relationship between circular objects that aren't circles. I see private methods like:
Then there is another class which has a private function that given a parameter position between 0 and 1 and two vectors returns the interpolated vector at the parameter position. Now I'm damn sure that is useful elsewhere and I'm also damn sure that the self same code resides in at least a dozen other places within our codebase.
In the past, when I knew no better, I stuck stuff in private methods, when I learnt the errors of my ways and liberated the stuff, others found a good use for it.
Looks like you have some more learning to do.
Could you explain this? What further learning is required? They have learned that in their case the use of private methods has prevented code-reuse. They are advocating using public methods to avoid this problem. Are you suggesting that there is another method?
What further lessons are there from this example?
Without looking at the code I'm pretty sure that most of this is reusable in other contexts, either within our team, or within other product teams.
It's not reusable unless somebody takes the time to productize and support it. Otherwise it's just code. You are "pretty sure" and won't even take the time to look at the code. That's why random code can't be made public. Public reusable code happens on purpose, not by accident.
How public do you mean by public? Released to the world as a for-pay library? Released open-source as a use-at-your-own-risk library? Released to other project teams in your company? Released to the programmer at the next cubicle? -- francis
Well I looked at the arc based methods and none of them are intrinsically specific to the class in which they are private methods. Some of them could be promoted to public utility methods without change, the remainder with minimal changes. Basically what we have is methods that given a 3D curve (could be a bezier, polyline, spline, nurb, arc, circle) determine whether it is circular when projected onto a 2D plane. Whilst original class context behaviour is in some of the methods it is minimal and could well be factor out.
The point being that if private methods are, in general, deprecated the result of the original work would have had greater benefit than that provided by the original requirements.
It's not reusable unless somebody takes the time to productize and support it.
Code is always supported, even if it is private, and private code is also productized via the public class methods that use it. By opening it out to a larger community for reuse any bugs that lurk within have a greater chance of being flushed out.
It is not supported for change. A change to specialized code, which is what you are saying something is by making it private, can easily destabilize the system. Code shouldn't have bugs regardless of the number of people who see it.
What if that code had lots of AutomatedTest's that warned you when changes to your code broke it? -- francis
What if people didn't write bugs? I don't want my code to be dependent on code that i think is correctly private, that i can make very object specific, yet someone can change at any time for any reason with any quality of development. If something is general, then make it general. But private code should be class specific, or why else make it?
Code contains bugs, reused code contains fewer.
I don't understand the point being made about anyone being able to change public code but not private. Surly if I have access to the change the code in the public interface, I have access to the code in the private interface too.
It's a dependency management decision. Do you want to let everything depend on everything else, or do you want to restrict that a bit? There are advantages to both choices.
It's a dependency management decision. True enough. It is actually quite easy. There are two scopes for code within a dependency context. It is the code that share Common Closure (see CommonClosurePrinciple) and the code that don't. (It has to be said that this scoping is a relation that is reflexive and symmetric). The encapsulation of the classes should be such that they don't expose information that include users of the public interface in their closure. Classes within the closure could just as well have access to any and all of the internal secrets of any other asset in the closure, and use of protected and private beyond this point looks more like nitpicking to me.
However; C++ don't have any good mechanism for declaring common closures (except the friend declaration which makes the user a victim of your avariciousness as she cannot make herself a friend of your stuff). Java offers the use of the (implicit) package protection, that allows any class access to all of the package protected stuff of any other class within the same package.
-- DanielBakkelund? it is possible to make two classes friends of each other in c++, you use a forward declaration -- JamesKeogh
Personally, I like to avoid even public member functions in c++. Where possible, you should use a global (in a namespace) function that takes an object-pointer as its first parameter.
As a rule of thumb: if it is possible to implement a function without making it a member (or a friend), then you should do so. Also, declare your functions in a different file from the class/interface.
Hooray for re-inventing pseudo-object implementations as used in X and GTK/Gnome.
Yes, except that you're still using real objects. The syntax might look similar to these CeeLanguage approaches, but the semantics of C++ means that it works properly. The appropriate comparison is to the concept of MultiMethods.
What is the difference between "x->y()" and "y(x)", other than a few characters of typing? For the former, the definition of class typeof(x) must be visible to the compiler. For the latter, a forward declaration suffices. Even if the implementation of y(X*) is simply to call a method, the decoupling of the method from the class can greatly speed up compile times, both by making a simple compile simpler; and by reducing the number of compiles needed (because of the reduced number of dependencies.
Is this getting into a LanguageSmell? -- ChrisDailey?
An idea that I had a few months ago, but haven't had a chance to do much with, is that private methods can often indicate the need for another class. This was in the context of looking for opportunities to ReplaceInheritanceWithAggregation?. For example, if I have public methods that are part of the interface for manipulating an object, and private methods for manipulating internal bits of the object, WhatIreallyMeanIs? I have an object with a public interface, which implements itself in terms of a private member object which also has a public interface.
This means that both objects still have all public methods and all private data, and users of the outer object can never call the methods on the inner object. Is this a solution to the objections in this page? Maybe not a general one, but it seemed to fit my case pretty well. -- TimLesher
I think Tim has it absolutely right. Use aggregation to reuse methods within an object. Use inheritance to "reuse" external methods by sharing a common interface across a family of objects.
See also: CompositionInsteadOfInheritance
But all this discussion regarding private and public and stuff. If everything is to be public, what happens with ReplaceTempWithQuery? Is it a cool thing to expose this to the users of the class?
I am just wondering...
-- dannyboy
Personally, ReplaceTempWithQuery is one of the few MartinFowler refactorings I'm not fond of. I agree with one of the sentiments on that page: ReplaceTempWithQuery strikes me as a transformation which should only be applied extremely cautiously and infrequently. -- TimLesher
I added a couple of sentences to assertion #1 in the summary trying to summarize some of the arguments presented here. I hope they're okay, please correct if I've incorrectly changed the spirit of it. I'm intrigued by MethodsShouldBePublic, and will experiment with it in my own coding, but I'm not yet convinced by it. -- ChrisDailey? 2005-05-25
You're only supposed to unit test that which can break. If you write methods which can be proven to work for their inputs (it's not as hard as it might seem at first), these are ideal for flagging as private. As it happens, these kinds of methods are precisely the kind you'd use to make the implementation of a public method, since they factor out what, precisely the public method actually does. In the context of functional programming, private methods occupy the same semantic space as "where" clauses in, e.g., HaskellLanguage. In other words:
class Foo { int computeA(void) { ...; return A; } int computeB(void) { ...; return B; } public: int compute(void) { return computeA() + computeB(); } }is analogous to:
compute = computeA + computeB where computeA = ... computeB = ...E.g., private methods should support the public methods which use them. However, they are "2nd-class citizens" when it comes to testing; they provide a mapping from high-level, human-readable names to compiler-grokkable code, for the purposes of making the public methods which use them more easily understood.
I've found that code which smells is perfectly acceptable, provided it doesn't outright stink. --SamuelFalvo?
Surely this is what is meant by MethodsShouldBePublic:
class Bar { public: int computeA(void) { ...; return A; } int computeB(void) { ...; return B; } }; class Foo { Bar bar; public: int compute(void) { return bar.computeA() + bar.computeB(); } };All public methods, all methods are testable. --quamrana
See also: CppHeresy, WellFactoredCode, ShouldOrShouldNot, MethodObject, TightGroupOfClasses, CommonClosurePrinciple