From: Thomas Kowalski on 3 Aug 2006 10:51 Hallo Rick, thanks for your answer! > Might I suggest a little ooa/d before you go into technical > refactoring like this ? Yes, you might :) Although I am programming already quite long, I never really tried to explore the concepts of OO enough it seems. Most of my code looks like ugly c-style code. Therefore I am trying now to grasp as much of the "real" OO as possible with the goal to make my code more easy to understand. > If you have huge classes probably your problem > domain is insufficiently analysed and their is not sufficient "domain > language" to talk about different use case realizations of your > software. In code that shows like a few monsterous classes or like > a few monsterous classes delegating everything out( facades). Well, the software I am currently working on is settled in computer graphics. It's a high performance calculation software. Therefore some concepts of business OOA/D are difficult to apply for me. Basicly I am working on the assumption that an object encapsulates the methodes to manipulate itself, with might be not really right on second thought. > You might miss the whole point about inheritance/delegation. I guess you are right. I treat inheritance like a way to add functionality to a class and "group" it this way. > Instead try to concentrate on behavior first( or as you call it functionality) > Attributes/aspects should not drive design but should be encapsulated > , and that encapsulation is a driving force of your design. The way I understand this is: Instead of (over)-using inheritance and delegation rather try to create a seperate class managing the additional functionality. Is that correct? > Mixins is a nice implementation certainly when you have clients who > only receive one of the mixins instead of the whole monster. Basicly I want to use it to provide a way to safe memory ressources in case application that base on a similar datastructure are merged to one application. This way "customized" classes can be created and "boxed" on the former border between the two applications. Regards, Thomas Kowalski
From: H. S. Lahman on 3 Aug 2006 10:58 Responding to Kowalski... > recently I was thinking about the concepts of delegation and > inheritance. > My idea was to simplify huge classes by dividing them in a base class > and additional class that provide other attributes / aspects / > functionality. This way it would be possible to create small > customizable classes easily and reduce complexity. Since I am using C++ > most of the time multiple inheritance is no problem and different > "mixes" of aspects could be realized. While inheritance and delegation are often used together, such as in most of the GoF Design patterns, they are quite different things. Inheritance is simply a <rather simple> set of rules for determining what properties a particular member of the root class actually has. That is very handy for generalization/specialization where the same basic entity can come in different flavors that have a few unique properties. OO subclassing and inheritance are defined in a manner that also allows polymorphic access of the /common/ properties. However, a member of every leaf subclass is always a member of the root superclass, hence the appellation is-a. Delegation, OTOH, is used to decompose a complex problem space entity into multiple distinct component entities. The component entities are identifiable in their own right because they exist at a lower level of abstraction than the original entity. Thus the notion of a Car can be decomposed into components like Wheel, Body, Drive Train, etc. that are not cars. Thus when one looks at a pattern like Strategy, * R1 1 [Context] ------------------ [Strategy] A | R2 +--------------+-------.... | | [StrategyA] [StrategyB] The delegation lies in the fact that a Strategy was decomposed from Context so that it is a standalone entity related to the original Context through a simple association. (If [Strategy] were not subclassed, one would still have delegation at this point.) One then subclasses [Strategy] to provide somewhat different behavior implementations in different situations. (I.e., the GoF pattern is solving a more complex problem of dynamic differences based on run-time situation.) Inheritance and polymorphism then allow those behaviors to be accessed the same way, regardless of which implementation of the behavior is relevant in a given situation. In this case the same basic behavior is always accessed; only the implementations change. So that behavior is a common property of all [Strategy] members. That is quite different than using subclassing directly to define disparate components of [Context]. IOW, the acid test of any subclassing relation is that it should be quite clear a member of any leaf subclass is a member of the root class (e.g., a StrategyB is a Strategy). However, the delegatee (Strategy) is not a delegator (Context) because the level of abstraction has changed where we view what a Context is; Context is now essentially a conceptual container of standalone components. > > Is such a concept basicly a "good" idea? If yes, should it be realized > using delegation or inheritance? I have already read about the LSP, but > are there any other guidelines then to use inheritance and then > delegation? Last one is really tedious to implement and don't > necessarily reduce complexity (since the methode stubs are still part > of the code). On the other hand inheritance is a pretty strong > relationship. Whether it is good or bad depends upon whether delegation is being /combined/ with subclassing. If so, it is bad; if not, it is just subclassing. (As Freud said, sometimes a cigar is just a cigar.) LSP is really an issue for polymorphic dispatch. In the OO context one can provide different implementations for the same superclass property semantics. If one accesses the superclass property, one needs to ensure that those implementations are acceptable to the client's expectations for the superclass property semantics across all subclasses. (Note that if one only accesses leaf subclass members via direct relationships, then LSP does not matter because one always goes directly to the implementation the client expects.) > > Another occurance that let me thing about that problem is corba, there > two different approaches are used to create proxy objects (tie = > delegation and interfaces = inheritance). Is there any reason to use > ties, beside the fact that java doens't support multiple inheritance? I don't want to go here because it ("canned" interoperability and layered model infrastructures) is a controversial topic in OO; I consider many of then to be object-based, not object-oriented. [I am going on vacation so if you respond to this my response will be a tad tardy.] ************* There is nothing wrong with me that could not be cured by a capful of Drano. H. S. Lahman hsl(a)pathfindermda.com Pathfinder Solutions http://www.pathfindermda.com blog: http://pathfinderpeople.blogs.com/hslahman "Model-Based Translation: The Next Step in Agile Development". Email info(a)pathfindermda.com for your copy. Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php. (888)OOA-PATH
From: Daniel T. on 3 Aug 2006 11:23 In article <1154599408.592501.29750(a)b28g2000cwb.googlegroups.com>, "Thomas Kowalski" <th-ko(a)gmx.de> wrote: > recently I was thinking about the concepts of delegation and > inheritance. In a statically typed language, like C++, public inheritance does double duty. It is used to share implementation and it is used to statically determine if types are substitutable. When we actually *use* public inheritance for both jobs, we can have conflicts. For example, in the engine I'm using right now the Graphic class has something like 80 bytes of data that must be maintained. It is often the case that such data ends up being redundant because it must also also held in some delegate that my sub-class contains. However, I must inherit from Graphic and I can't remove the member-variables in question. This is a poor design, but one I think shows up often in C++ programs. > My idea was to simplify huge classes by dividing them in a base class > and additional class that provide other attributes / aspects / > functionality. This way it would be possible to create small > customizable classes easily and reduce complexity. Since I am using C++ > most of the time multiple inheritance is no problem and different > "mixes" of aspects could be realized. > > Is such a concept basicly a "good" idea? If yes, should it be realized > using delegation or inheritance? Yes, I think it's basically a good idea. When you have a class with non-communicating behavior, you should break it up into delegate classes that each do a more refined job. IMHO, despite the inevitable delegation involved, this will simplify the design. As to your second question, things are a bit tougher on C++ developers because of the double duty issue I mentioned above. Much depends on how reusable the code you're working on needs to be. The more extensively it is used, the more likely the implementation/interface split will cause problems. One heuristic I use is that if a class is being derived from, it should contain no data. This way, my objects don't need to lug around a bunch of data they never use. So how do I remove duplication? That's where delegates come in... > I have already read about the LSP, but > are there any other guidelines then to use inheritance and then > delegation? Last one is really tedious to implement and don't > necessarily reduce complexity (since the methode stubs are still part > of the code). On the other hand inheritance is a pretty strong > relationship. All the delegation that goes on in OO code does take a bit of getting used to. As I recall, Martin Fowler once said something about people new to OO complaining that nothing seems to ever do the job, most functions just seem to delegate the job to some other function. I think all the delegation does reduce complexity, because (assuming the member-functions are named well) you don't have to trace down the delegation hierarchy to "figure out what the function does." But yes, it tends to be tedious to implement. Indirection in general is tedious to implement, but that's what we need to do to gain flexibility.
From: Sasa on 3 Aug 2006 13:29 Thomas Kowalski wrote: > Hi Sasa, > thanks for your reply! Maybe you can eleborate the answers a little bit > more? You're welcome. I'll try, and if it's still not enough, don't hesitate to ask. >>a) Is there a code which works with base class interface? > > > If the dividing in base and derived class simplifies the understanding > of the concept the class represents, when why not using it? You also have delegation at your disposal. Consider following situation: - class A has set of methods S1 - class B derives from A and adds its own set of methods S2 Now B offers all methods. However, if interface of A changes, then it might introduce breaking changes to the clients of B. IMHO if one wants to create class with big interface, then it amounts to Facade pattern - make one class with all methods relevant to the interested clients. Make it delegate to each class. The fact that the work is subdivided in classes is implementation detail. One should IMHO avoid classes with big interfaces. Small classes with small interfaces should usually suffice. >>b) Can that code work with my derived class? > > > This is basicly the LSP, isn't it? > > >>c) Can my derived class work with base class methods? I.e. if I invoke base >>class method, will something unexpected happen because my derived class >>doesn't count with it. > > > Seems to be something like LSP, too. The way I understand LSP, a/b/c cover it, maybe a most of all. >>d) Did I override anything in derived class? > > > Why this is important? If you just add functionallity, doesn't it > justify the use of inheritence? To restate the issue raised earlier - when you inherit, you get a whole lot, maybe even too much. You receive the entire interface of the base class, and access to its protected members. The question is - do the clients of your new class really want that? Another issue: if you add functionality via inheritance, the added functionality applies only to the derived class. But since you are not overriding, you really don't change the behavior of the base class, you only add new features. However, even though your code might work for all instances of base class, you miss this opportunity if you use inheritance (because everyone who want's to use new feature might derive). Example: In .NET WinForms you have the TextBox class which represents simple edit box control. Now let's assume that I must add feature that every time I enter a character a beep must be heard. One way could be to implement BeepableTextBox by deriving from TextBox. However, if I do that, every user which wants to have this feature must use BeepableTextBox. But what if I have another derivate - MaskedTextBox which accepts some kind of masked input? How can I make MaskedTextBox beepable? How can I make BeepableTextBox masked (considering that multiple inheritance is not supported)? To generalize: let us say you wan't to extend the class A with some behavior (and not change the behavior of the class A). You can do following: a) Static helper method - the method which takes the instance of the class A, and additional arguments, and performs operation on the base class. b) Holding the instance of the class A in your wrapper (adapter) and making your implementation delegate to the instance of A. >>...you have more access to class members. >>However, this has its darks side - the clients of my (derived) class are >>completely unshielded from the specifics of the base class. > > > Not if you declare the members private instead of protected. Which > might be most usefull if just few or none members of the class is > overridden. I agree that visibility should be as minimal as possible, ideally private (another one of many of my sins was making members protected, because "some derivate might want to access them someday" - looking back on that, all I can say is: LOL) However, I was making general point. E.g. if I inherit from the TextBox class (which I didn't write, and have no access to its source code), I will receive protected members. >>Nowadays, I am more fan of the delegation approach, even if it is somewhat >>tedious. > > > What caused the shift in attitude? The example I gave above is simplification of the real situation my team had. We had couple of features which we added via inheritance, and it seemed cool, we were inheriting, and inheritance is very OO. At the end when we had to combine those features, we ended up having inheritance level of about 7-8 (!), it was very hard to maintain, analyze and debug. The paradox is that most of the clients needed only couple of those features (i.e. only subset, but different clients would require different subsets). But it is not just one example. Many times have I inherited to add functionality (and not to override, which is actually changing the implementation). And looking back on that code (which I do every now and then), it really seems clumsy to say the least. >>I regard inheritance vs. delegation as having two different purposes: in >>inheritance, we reuse the interface and provide our own implementation, in >>delegation we provide our own interface and reuse implementation. > > > I really like this explaination! That really seems to bring it to the > point :) I read it somewhere (probably not those exact words, only the overall meaning), but it's hard to keep track of who sad what, so if anyone knows the source, feel free to cite. Sasa
From: adaworks on 3 Aug 2006 16:21
"Thomas Kowalski" <th-ko(a)gmx.de> wrote in message news:1154599408.592501.29750(a)b28g2000cwb.googlegroups.com... > Hi everybody, > > recently I was thinking about the concepts of delegation and > inheritance. > This would be a good opportunity for some of the experts in this forum to elucidate on delegation versus inheritance. At the theoretical level, we can model it. How is it actually implemented in languages that don't explicitly support it? C++? Eiffel? Ada? Smalltalk (well that one is easy, I guess). Java? Richard Riehle |