From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fac41,2c6139ce13be9980 X-Google-Attributes: gidfac41,public X-Google-Thread: f43e6,2c6139ce13be9980 X-Google-Attributes: gidf43e6,public X-Google-Thread: 103376,3d3f20d31be1c33a X-Google-Attributes: gid103376,public X-Google-Thread: 1108a1,2c6139ce13be9980 X-Google-Attributes: gid1108a1,public From: Owen Fellows Subject: Re: Interface/Implementation (was Re: Design by Contract) Date: 1997/09/16 Message-ID: <341E4679.4BE4100E@calfp.co.uk> X-Deja-AN: 272964771 References: <5vkfb2$f2p$2@trumpet.uni-mannheim.de> X-NNTP-Posting-Host: calfp.demon.co.uk [158.152.70.168] Newsgroups: comp.object,comp.software-eng,comp.lang.ada,comp.lang.eiffel Date: 1997-09-16T00:00:00+00:00 List-Id: Marc Wachowitz wrote: > > Nick wrote via Owen Fellows > about supposedly "pure" OO a la Eiffel vs. Ada-like modules and types as > different concepts and non-method procedures: > > But it it more likely that you just inherit MATHEMATICIAN somewhere in > > your heirarchy to save on typing. > > I find that totally unacceptable, as it creates much too strong coupling > between library modules and their clients. Adding new features to a library > module shouldn't force even the smallest change in any previously existing > clients. The same applies to unavoidable visibility of every parent feature > in children - to avoid potential clashes, one is forced to revert to using > long_feature_names_saying_they_are_only_for_class_X_and_not_for_children, > which is a shame for a somewhat recent language like Eiffel (even in old > K&R C you had private - aka static - functions/variables), in my view. Well, in practice I haven't found this to be a problem at all. This is in a 800,000 line project. Lots of names are the same in different classes, like the use of consistent names in the standard libraries (extend, remove etc ...) This is a strong indication that such name clashes if they happen, are rare events. Visibility in all children. This can be an issue but not as much as you think. It is usually indicative of having an implementation at the high level of a heirarchy and you should, in my opinion, use facility inheritance lower down where necessary. Now other Eiffel programmers would disagree with me, and use facility inheritance at the top of the heirarchy, as there is less typing. > The > point isn't so much about children touching conceptually private features > of parents where they shouldn't do that (though that does get "interesting" > in large projects with say, 50 to 100 programmers of varying quality, and > I'd rather have that checked, too), but about clean separation of concerns > and minimal coupling. Minimal coupling is important. But from practical experience, classes we have written that are used for facility inheritance tend to be very stable, don't have name changes (implementation varies), and are usually only extended. Think about the MATHEMATICIAN for an example. The clashes don't happen any where near the level that one may presume they would happen if you haven't written systems in practice. > > Having the same implementation as inherits is a hint that it probably is > > inherits! > > No more than the implementation of loops via conditional goto is a hint to > drop explicit loops from the language and only provide conditional goto (and > perhaps call/return) as control structure. I expect most people wouldn't > follow the latter reasoning (nor do I), and likewise I disagree with your > above suggestion. In fact, I'd already use inheritance much less than what > seems to be usual in the Eiffel world (if Bertrand Meyer's books are a hint > about general usage): Even if it means more writing, I prefer having a mere > client for an object via a field over implementation inheritance: As long as > the representation type can be used unchanged via its abstract interface, > I'll do so. If it's mostly right, but still no proper "is-a" relation holds, Agreed, there is no is-a relationship! But is is-a the only valid use or description of inheritance. Read the chapter in OOSC II on the taxonomy of inheritance. BM writes better and clearer than I do. > I'll also seriously consider a different subclass with some small changes > for the different need, and then using this adaption as client in that new > type which really isn't a proper subtype. I find this to be much better at > decoupling, more explicit about the essential relations between those types, > and more readable for my taste. The counter-argument about inefficiency due > to another indirection doesn't hold, as the above is only about source level > stuff: If performance is critical, make the compiler sufficiently clever to > inline the respective data and operations for such cases, which should be > quite trivial. The counter-argument about needing all the facilities which > are used for inheritance again for import doesn't really work either, since > the usage of library modules with qualified names for feature access doesn't > need things like renaming, redefinition, re-export or hiding; simply write > e.g. Math.Sin(X) and stop worrying about name space pollution. (Well, you > do have to think about module names, which should ideally be a hierarchical > name space, similar to Ada child packages or Java packages, but it reduces > the amount of relevant names dramatically.) Which is always an choice that you can make as an programmer, you are not forced to use the inheritance for facility inheritance, you can always do this feature {NONE} -- Don't allow clients access Math: expanded MATHEMATICIAN -- A valid use of expanded or feature {NONE} -- Don't allow clients access Math: MATHEMATICIAN is once !!Result.make end If MATHEMATICIAN requires some form of initialisation. You don't pollute name space then. Eiffel gives you the choice. At the end of the day, with things like loops, you want to have loops because it makes reading the code easier. The code ends up closer to the logical view of the world, not its phsical implementation. This was the major argument in my book for the implementation of 'precursor'. Why should you be telling the compiler how to implement something using double inheritance, when the compiler can do it for you, and the results are more readable. Now in the case of facility inheritance. You don't have to use that method, you can get exactly what you want (see above) meeting your criteria for visibility and name spaces. Therefor, I don't think you need extend the language. I would say that 8 months ago I had the same opinions as you have expressed, but I've changed my mind. Nick (From Owen's account)