From: Christian Szegedy Date: 2002-09-06T21:30:41+09:00 Subject: Re: Ruby aesthetics Reimer Behrends wrote: > > However, if we first factored out the functionality of the queue, we can > now subclass the implementation of the queue separately (the queue > having no private members), and substitute the new implementation for > the old one. But the queue should have private data since its implementation is hidden from its interface. If you derive from this quese, then the hidden data becames visible. If you instanciate it, you generate data, you can't hide :( I agree with you, that too much private methods can be harmful, but I don't see here a subtitute for data hiding. > > >> In Ruby, the situation is even worse, as all methods may introduce new >> data memebers, so you have to check the body of all methods, if you >> want to avoid name collisions for sure. > > > Why would somebody create such a mess in the first place? Information > hiding does not exempt the implementation side from documentation and > clean design. I can easily occur if you do meta-programming. (In Eiffel it is not an issue, but in Ruby it is common practice to enhance your classes with generated functionality. The data members of the generated functionality is necessarily outside the initialize method.) >> It may be OK for small projects, but if you have to work in a large >> class hierarchy written by someone else, it can become hopeless, >> and you can only hope that nothing goes wrong. > > > If the parent class you're inheriting from is too convoluted to be > understood, then you have a far bigger problem on your hand. I'd > suggest that it isn't safe to inherit from the class at all, and > that you should use aggregation instead. I think it is fairly common and necessary to derive from complicated Objects, and I see no problems with it, as long as information hiding (i.e. name collisions) are cleanly solved. Besides there are often functionality which requires that you derive from the class and overload some functions in the derived class for communication. I don't think you want to prohibit it. > The reason is that by inheriting you make the promise that you implement > the same contract as the parent class, and that you do typically by > reusing part of the implementation. I do strongly disagree here: My contract says to ***enhance*** the functionality not to ***reimplement*** it! I have to enhance the class by using a well defined interface to its parent and not by messing around with its internal details. (Of course it should be made possible, but I think it whould be the exception rather than the rule.) > For what it's worth, if you introduce private variables, the problem > is only transferred to the functions accessing it. Redefine 'put' > in the queue example above by accident, and you have the same problem; You can make the access methods private, so that you get at least an error when you redefine it. (At least I can guarantee that there is no name collision.) > This leads us to the real underlying problem: We have a trade-off > between two alternatives: Making classes fully extensible by inheritance > or limiting that extensibility. In fact, if all variables were private, > then we could essentially do no more with inheritance than composing the > functions of the parents, but not add any real new and non-trivial > functionality. I do strongly disagree. You will have a bit more design decision : you can determine which details are hidden from outside and which are hidden from the derived class. You can allow the derived class access those private data which you consider to be necessary by defining protected attribut accessors. If you do this, you limit the knowledge needed by the derived classes to reimplement features and so make programming easier. > > The openness, the extensibility of classes through inheritance plays a > critical part in object-oriented programming. I do agree, but it only supports my position. > Yet that doesn't mean that we want our subclasses to mess around with > instance variables introduced by their parents at will. But rather than > throwing out the baby with the bathwater -- disallowing any and all > changes -- it is much more sensible to just disallow those changes that > are actually illegitimate. I do agree, but it only supports my position. I am for a selective prohibition and not for a complete one (altough I could live with a completely restrictive modell better than with the current situation, since I could grant access by accessor methods.) > As I said, it is largely a religious issue, and this has become much > longer than I wanted it to be. But there is more to the problem > than you think. I disagree: It is a practical problem. If I can't guarantee name collision, (and therefore working code), then it is a problem that disturbs me all the time. It is far from a philosophical or theoretical issue. Regards, Christian