I just stumbled upon this:
Announcer subclass: #TxEditor .... This is just plain wrong, as wrong as: Shampoo subclass: #Shower because every time you treat inheritance as something else as _specialization_ you doing it wrong. Inheritance is not about importing needed functionality, it should be about specialization and only about it: - a superclass provides generic functionality, while subclasses providing more and more specialized forms of it. Because if we don't follow that, then it is really hard to see and follow a structure in design.. it is just random. And here's why: so since shower uses shampoo, as we concluded, then why not including it via inheritance: Shampoo subclass: #Shower but then, Shower also uses Soap, so maybe it should be like that: Soap subclass: #Shower so, which superclass you prefer most? And how do you pick/prioritize which element should be a superclass of Shower? To solve this dilemma, i think we will need multiple inheritance: (Shampoo, Soap) subclass: #Shower but thankfully, we don't have it in classic smalltalk model :) So, then maybe it should be something like that: Object subclass: #Shower instanceVariableNames: 'soap shampoo' ... Anyways, despite the obvious abuses, i'd like to ask community, in what cases , you think (ab)using inheritance in a way like above is justified? Because maybe it is i, who doing it wrong? -- Best regards, Igor Stasenko. |
On 19 July 2013 15:48, Sebastian Tleye <[hidden email]> wrote:
> > > > 2013/7/19 Igor Stasenko <[hidden email]> >> >> I just stumbled upon this: >> >> Announcer subclass: #TxEditor >> .... >> >> This is just plain wrong, as wrong as: >> >> Shampoo subclass: #Shower >> >> because every time you treat inheritance as something else as >> _specialization_ you doing it wrong. >> Inheritance is not about importing needed functionality, it should be >> about specialization and only about it: > > > Completely agree! > If you inherit only because of reuse functionality, use traits instead :-) > Well, traits, i think, belong more to concern-oriented designs: when you wanna put handle concern in two (or more) different classes, which belong to different inheritance hierarchies. Else, this is just a poor-man's multiple inheritance. -- Best regards, Igor Stasenko. |
In reply to this post by Igor Stasenko
On 19 July 2013 16:17, Tudor Girba <[hidden email]> wrote:
> Hi Igor, > > I love these discussions. I agree that abusing inheritance is > counter-productive. Definitely, "Shampoo subclass: #Shower" does not match > any mental model I can think of. But, I am not seeing "Announcer subclass: > #MyDomainConcept" equally as an abuse. > > Here is why. > > When I say "Object subclass: #MyDomainConcept", my actual intention is not > to reuse types necessarily, but rather the infrastructure needed for the > Smalltalk runtime. From this point of view, it is an implementation > inheritance. I could as well, inherit from ProtoObject, but I do not do it > because Object gives me a bit more technical infrastructure. > > For me, Announcer is nothing but an Object that has an extra technical > capability. Inheriting from Announcer rather than Object seems the same as > inheriting from Object rather than ProtoObject. > > Now, you can shoot. > As i understood, you see nothing wrong in using inheritance as reuse, while i do. The argument with Object does not stands, to my thinking, because it is most generic class, and protocols it implements used by various parts of a system, including reflection etc, and those parts actually expecting that all objects they dealing with is at least implementing Object protocol(s). So, strictly speaking by inheriting from Object you may call it reuse, but to my thinking it is more about having a guarantee that your class will play well with the rest of smalltalk ecosystem (even if it's not your direct concern). While in case of inheriting from Announcer it is something different: you already have specific behavior which is non-universal for all objects in system (otherwise why not implementing Announcer protocol in Object?). Also, i am sure you aware, that by doing this, you introducing a certain degree of rigidness in your model (every time you refer directly to names instead of protocols, little kittie dies ;) because if today, Announcer serves well for your needs, and all is happy.. but maybe tomorrow, one guy will make a better one AnnouncerOnSteroids.. and to reuse it , you will need to change the parent in all numerous classes where you used Announcer originally. And to make it absolutely ridiculous, imagine how you will give user a choice whether use one Announcer or AnnouncerOnSteroids? You will recompile your classes each time? And what if parts of your model insist on using just Announcer while others having no problem with trying to play with AnnouncerOnSteroids? Another aspect of such abuse is when you inherit, you are tempted to use direct access to internal state and private methods, and that leads to really strange and complex problems later.. Just giving you an example: Suppose we have a class Butter, which implements #numberOfCalories and #fatPercentage protocols.. Now we do it like that: Butter subclass: #Fridge and then, of course fridge := Fridge new. fridge fatPercentage or: fridge fatPercentage: 10. ^^^ just look at the above line, how much sense you think this piece of code makes for reader, who will try to reason what is happens in your code? And why you think it is not the same story with Announcer? Because by subclassing from it, you expose its protocol(s) in places where it is not needed and will cause problems and confusion. Because when you inherit to reuse, not to specialize, then users of such class in most cases won't use full protocol of the superclass, nor require it.. and therefore by providing more than necessary, you are basically violating the principle of least authority. To fix that, you will need to override certain methods in your subclass to prevent exposing unwanted/low-level behavior to users. But that's again wrong, because then your model now starting to know too much about Announcer's internals, which should be an implementation detail, and adds even more rigidness to your design. -- Best regards, Igor Stasenko. |
So, on your place, if you really need a lot of classes with announcer
capabilities, you can do it like that: Object subclass: #ObjectWithAnnouncer instvars: 'announcer' then may implement same protocol as in Announcer in it, which will simply delegate to announcer ivar. And i bet, you don't want to expose full Announcer protocol there, while probably you may want to implement some convenience protocols, which Announcer lacking. So, at the end by subclassing from ObjectWithAnnouncer you will be reusing its capabilities in each and every subclass of it, but by delegating real job, you are free from worrying about dealing with implementation detail and exposing unwanted state/protocols to its users. Another aspect of it, is when i see: ObjectWithAnnouncer subclass: #MyDomainObject it tells me, aha.. so some (at least this one) of his domain objects having announcers, and the valid protocols is defined in ObjectWithAnnouncer. but when i see Announcer subclass: #MyDomainObject i starting to be uncertain: is Announcer private there or public? can i send messages like #basicSubscribe: to your domain object and expect that it will be handled correctly? Or do i allowed to subscribe directly at all, because maybe domain object has some specific protocol(s) and ways to do that.. Every such question and uncertainty for coder means more time, more errors, and less productivity. -- Best regards, Igor Stasenko. |
In reply to this post by Igor Stasenko
Igor - could you please explain 'the principle of least authority'?
Thanks, - Paul |
When you inherit, being it for specification or implementation, you're
signing a contract with all what superclasses implement. Sometimes it is worth the risk, other times it isn't. I'm in for composition over inheritance, but Smalltalk is so malleable I wouldn't implement any restriction. Otherwise you'll have to enforce something like interfaces. Regards, Esteban A. Maringolo |
In reply to this post by Igor Stasenko
Great answer Igor!
I'm curious about Doru's response :) On 19.07.2013, at 17:31, Igor Stasenko <[hidden email]> wrote: > So, on your place, if you really need a lot of classes with announcer > capabilities, you can do it like that: > > Object subclass: #ObjectWithAnnouncer > instvars: 'announcer' > > then may implement same protocol as in Announcer in it, which will > simply delegate to announcer ivar. > And i bet, you don't want to expose full Announcer protocol there, > while probably you may want to implement some convenience protocols, > which Announcer lacking. > > So, at the end by subclassing from ObjectWithAnnouncer you will be > reusing its capabilities in each and every subclass of it, but by > delegating real job, you are free from worrying about dealing with > implementation detail and exposing unwanted state/protocols to its > users. > > Another aspect of it, is when i see: > > ObjectWithAnnouncer subclass: #MyDomainObject > > it tells me, aha.. so some (at least this one) of his domain objects > having announcers, > and the valid protocols is defined in ObjectWithAnnouncer. > > but when i see > > Announcer subclass: #MyDomainObject > > i starting to be uncertain: is Announcer private there or public? > can i send messages like #basicSubscribe: to your domain object and expect that > it will be handled correctly? Or do i allowed to subscribe directly at > all, because maybe > domain object has some specific protocol(s) and ways to do that.. > Every such question and uncertainty for coder means more time, more > errors, and less productivity. > > > -- > Best regards, > Igor Stasenko. > |
In reply to this post by Igor Stasenko
Hi
2013/7/19 Igor Stasenko <[hidden email]> So, on your place, if you really need a lot of classes with announcer ObjectWithAnnouncer is exactly what I think about Announcer. I just need class which makes my objects events sources. And I'm wondering why Announcer is bad for this? Just look at Announcer definition:
Object subclass: #AnnouncerinstanceVariableNames: 'registry'classVariableNames: ''poolDictionaries: ''category: 'Announcements-Core' "registry" variable is instance of SubscriptionsRegistry which actually implements all announcements logic. Announcer just adds convenient public api to events subscriptions and delivering. No complex logic. No actual knowledge about how announcements work.
And your argument "why you subclass from Announcer" looks to me like why you subclass from SubscriptionsRegistry. But I'm not. Nobody doing it. So i'm not understand why you want another wrapper around Announcer.
(To me "subscriptions" is better name then "registry". And I prefer composition than inheritance too). then may implement same protocol as in Announcer in it, which will |
How about statefull Traits?
http://scg.unibe.ch/archive/papers/Berg07aStatefulTraits.pdf On 2013-07-20, at 12:48, Denis Kudriashov <[hidden email]> wrote: > Hi > > 2013/7/19 Igor Stasenko <[hidden email]> > >> So, on your place, if you really need a lot of classes with announcer >> capabilities, you can do it like that: >> >> Object subclass: #ObjectWithAnnouncer >> instvars: 'announcer' >> >> > ObjectWithAnnouncer is exactly what I think about Announcer. I just need > class which makes my objects events sources. And I'm wondering why > Announcer is bad for this? > Just look at Announcer definition: > > Object subclass: #Announcer > > instanceVariableNames: 'registry' > > classVariableNames: '' > > poolDictionaries: '' > > category: 'Announcements-Core' > > > "registry" variable is instance of SubscriptionsRegistry which actually > implements all announcements logic. Announcer just adds convenient public > api to events subscriptions and delivering. No complex logic. No actual > knowledge about how announcements work. > And your argument "why you subclass from Announcer" looks to me like why > you subclass from SubscriptionsRegistry. But I'm not. Nobody doing it. > So i'm not understand why you want another wrapper around Announcer. > > (To me "subscriptions" is better name then "registry". And I prefer > composition than inheritance too). > > > >> then may implement same protocol as in Announcer in it, which will >> simply delegate to announcer ivar. >> And i bet, you don't want to expose full Announcer protocol there, >> while probably you may want to implement some convenience protocols, >> which Announcer lacking. >> >> So, at the end by subclassing from ObjectWithAnnouncer you will be >> reusing its capabilities in each and every subclass of it, but by >> delegating real job, you are free from worrying about dealing with >> implementation detail and exposing unwanted state/protocols to its >> users. >> >> Another aspect of it, is when i see: >> >> ObjectWithAnnouncer subclass: #MyDomainObject >> >> it tells me, aha.. so some (at least this one) of his domain objects >> having announcers, >> and the valid protocols is defined in ObjectWithAnnouncer. >> >> but when i see >> >> Announcer subclass: #MyDomainObject >> >> i starting to be uncertain: is Announcer private there or public? >> can i send messages like #basicSubscribe: to your domain object and expect >> that >> it will be handled correctly? Or do i allowed to subscribe directly at >> all, because maybe >> domain object has some specific protocol(s) and ways to do that.. >> Every such question and uncertainty for coder means more time, more >> errors, and less productivity. >> >> >> -- >> Best regards, >> Igor Stasenko. >> >> |
In reply to this post by Igor Stasenko
On 7/19/13, Igor Stasenko <[hidden email]> wrote:
> On 19 July 2013 16:17, Tudor Girba <[hidden email]> wrote: >> Hi Igor, >> >> I love these discussions. I agree that abusing inheritance is >> counter-productive. Definitely, "Shampoo subclass: #Shower" does not >> match >> any mental model I can think of. But, I am not seeing "Announcer >> subclass: >> #MyDomainConcept" equally as an abuse. >> >> Here is why. >> >> When I say "Object subclass: #MyDomainConcept", my actual intention is >> not >> to reuse types necessarily, but rather the infrastructure needed for the >> Smalltalk runtime. From this point of view, it is an implementation >> inheritance. I could as well, inherit from ProtoObject, but I do not do >> it >> because Object gives me a bit more technical infrastructure. >> >> For me, Announcer is nothing but an Object that has an extra technical >> capability. Inheriting from Announcer rather than Object seems the same >> as >> inheriting from Object rather than ProtoObject. >> >> Now, you can shoot. >> > > As i understood, you see nothing wrong in using inheritance as reuse, > while i do. not generally I assume Tudor thinks, only for this particular case of sub classing Announcer. Announcing behaviour may be considered part of a package objects should have and this has been the case in Smalltalk since the beginning, though implemented with the symbol based changed/update mechanism. To restate Yes, I agree that subclasses should specialize the behaviour of the superclass. But there need to be classes first you may subclass to specialize and these inherit general properties of object behaviour. --Hannes > The argument with Object does not stands, to my thinking, because > it is most generic class, and protocols it implements used by various > parts of a system, > including reflection etc, > and those parts actually expecting that all objects they dealing with > is at least implementing Object protocol(s). > So, strictly speaking by inheriting from Object you may call it reuse, > but to my thinking it is more > about having a guarantee that your class will play well with the rest > of smalltalk ecosystem (even if it's not your direct concern). > > While in case of inheriting from Announcer it is something different: > you already have specific behavior > which is non-universal for all objects in system (otherwise why not > implementing Announcer protocol in Object?). > > Also, i am sure you aware, that by doing this, you introducing a > certain degree of rigidness in your model (every time you refer > directly to names instead of protocols, little kittie dies ;) > > because if today, Announcer serves well for your needs, and all is happy.. > but maybe tomorrow, one guy will make a better one AnnouncerOnSteroids.. > and to reuse it , you will need to change the parent in all numerous > classes where you used Announcer > originally. > And to make it absolutely ridiculous, imagine how you will give user a > choice whether use one Announcer or AnnouncerOnSteroids? You will > recompile your classes each time? And what if parts of your model > insist on using just Announcer while others having no problem with > trying to play with AnnouncerOnSteroids? > > Another aspect of such abuse is when you inherit, you are tempted to > use direct access to internal state and private methods, and that > leads to really strange and complex problems later.. > > Just giving you an example: > > Suppose we have a class Butter, which implements #numberOfCalories and > #fatPercentage protocols.. > > Now we do it like that: > > Butter subclass: #Fridge > > and then, of course > > fridge := Fridge new. > > fridge fatPercentage > > or: > > fridge fatPercentage: 10. > > ^^^ just look at the above line, how much sense you think this piece > of code makes > for reader, who will try to reason what is happens in your code? > > And why you think it is not the same story with Announcer? > > Because by subclassing from it, you expose its protocol(s) in places > where it is not needed and > will cause problems and confusion. > Because when you inherit to reuse, not to specialize, then users of > such class in most cases won't use > full protocol of the superclass, nor require it.. and therefore by > providing more than necessary, > you are basically violating the principle of least authority. > To fix that, you will need to override certain methods in your > subclass to prevent exposing unwanted/low-level behavior to users. But > that's again wrong, because then your model now starting to know too > much about Announcer's internals, which should be an implementation > detail, and adds even more rigidness to your design. > > > -- > Best regards, > Igor Stasenko. > > |
In reply to this post by Igor Stasenko
Hi Igor,
Thanks for taking the time to write such a long answer. I think you misunderstood my point :). I simply said that the two examples are not the same (and I can add now that "Butter subclass: #Fridge" is as bad as "Shampoo subclass: #Shower", but they are both different from "Announcer subclass: #MyDomainConcept").
As I understand, you conceded the point that inheriting from Object has reuse reasons, but that it is so because Object provides generic mechanisms that everyone wants. I can imagine scenarios where I want a different reflection support. All of a sudden the generic mechanism is not so generic anymore, and you get in the same situation as the one of wanting a different Announcer kind. Does it mean that inheriting from Object is a bad thing? No. It is a great good enough compromise for 99.9% of the cases.
Then you say that Announcer is not in the Object protocol as if this would be necessarily a good thing. I can argue that every Object should have announcer capabilities just like it has exception handling capabilities, but then we would go even further away from the main point :).
Inheritance as reuse is definitely to be avoided, and indeed the principle of Least Authority (or more known as Principle of Least Privilege) is a relevant point (I concede that :)). However, I guess you agree that having #class defined in Object is not a horrible (it can be better, but it is not horrible) thing even if most objects do not need this information.
Another principle that might be more useful when thinking about inheritance is the Liskov Substitution Principle. From this point of view, as long as MyDomainConcept does not redefine the meaning of Announcer, it is not unreasonable to have it inherit from Announcer.
I stop now. You can continue to shoot :). Cheers, Doru On Fri, Jul 19, 2013 at 4:54 PM, Igor Stasenko <[hidden email]> wrote:
The argument with Object does not stands, to my thinking, because "Every thing has its own flow"
|
In reply to this post by Hannes Hirzel
Thanks, Hannes. I am not completely misunderstood, then :) Doru On Sat, Jul 20, 2013 at 2:02 PM, H. Hirzel <[hidden email]> wrote:
"Every thing has its own flow"
|
In reply to this post by Camillo Bruni-3
Certainly :) Doru On Sat, Jul 20, 2013 at 1:48 PM, Camillo Bruni <[hidden email]> wrote: How about statefull Traits? "Every thing has its own flow"
|
In reply to this post by pdavidow
On 19 July 2013 19:14, Paul Davidowitz <[hidden email]> wrote:
> Igor - could you please explain 'the principle of least authority'? Here the wiki link: http://en.wikipedia.org/wiki/Principle_of_least_privilege > Thanks, > - Paul > -- Best regards, Igor Stasenko. |
In reply to this post by Denis Kudriashov
On 20 July 2013 12:48, Denis Kudriashov <[hidden email]> wrote:
> Hi > > 2013/7/19 Igor Stasenko <[hidden email]> >> >> So, on your place, if you really need a lot of classes with announcer >> capabilities, you can do it like that: >> >> Object subclass: #ObjectWithAnnouncer >> instvars: 'announcer' >> > > ObjectWithAnnouncer is exactly what I think about Announcer. I just need > class which makes my objects events sources. And I'm wondering why Announcer > is bad for this? > Just look at Announcer definition: > > Object subclass: #Announcer > > instanceVariableNames: 'registry' > > classVariableNames: '' > > poolDictionaries: '' > > category: 'Announcements-Core' > > > "registry" variable is instance of SubscriptionsRegistry which actually > implements all announcements logic. Announcer just adds convenient public > api to events subscriptions and delivering. No complex logic. No actual > knowledge about how announcements work. > And your argument "why you subclass from Announcer" looks to me like why you > subclass from SubscriptionsRegistry. But I'm not. Nobody doing it. > So i'm not understand why you want another wrapper around Announcer. > > (To me "subscriptions" is better name then "registry". And I prefer > composition than inheritance too). > There are 3 kinds of roles in context: - subscriber: an object who subscribing for events to receive them later - an event source (the object which announces the event) - an announcer, an object which provides subscription service and through which you can announce events, acting as mediator between 2 parties above the rest, like registry, Announcement (as class) and subscriptions is implementation detail. The main reason for using Announcements model is to have decoupling between event source (the place/object , which producing events) and its handlers. And announcer provides such decoupling. That means, both subscribers and event source(s) don't need to have direct knowledge about each other, all they need is to use same announcer to establish communication channel. Then, subscribers don't really care who triggered an event and why/where while event source don't really cares who will handle the event(s), in what order or how many of them there. Now, what happens when you mixing roles and treating announcer as an event source? (and by subclassing from Announcer you doing that). When you merge event source and announcer, then your subscribers are forced to have direct access to event source, and that means you actually not using/need decoupling at all. In this regard, my question: why then you using Announcements model at all? Because it is there, or because there should be only one? I don't think that either of these reasons are valid. When you don't need decoupling , i do not see much value in using Announcements. I would implement/use something else then. -- Best regards, Igor Stasenko. |
In reply to this post by Tudor Girba-2
On 20 July 2013 21:31, Tudor Girba <[hidden email]> wrote:
> Hi Igor, > > Thanks for taking the time to write such a long answer. > > I think you misunderstood my point :). I simply said that the two examples > are not the same (and I can add now that "Butter subclass: #Fridge" is as > bad as "Shampoo subclass: #Shower", but they are both different from > "Announcer subclass: #MyDomainConcept"). > It is only in your mind. If someone else will look at your code, he won't make any difference (and you can tell me why ;). And that is what matters. You know, i can also (ab)use things in my code and make very strange things, which can be understood only by me.. depending on intent, like having highly optimized code or as a way to code less (making many subclasses can be tiresome sometimes ;) But if there's any chance that anyone else will use this code or will need to change/understand/improve it, i would not do that. Because when i do, i putting them into misery. > As I understand, you conceded the point that inheriting from Object has > reuse reasons, but that it is so because Object provides generic mechanisms > that everyone wants. I can imagine scenarios where I want a different > reflection support. All of a sudden the generic mechanism is not so generic > anymore, and you get in the same situation as the one of wanting a different > Announcer kind. Does it mean that inheriting from Object is a bad thing? No. > It is a great good enough compromise for 99.9% of the cases. > > Then you say that Announcer is not in the Object protocol as if this would > be necessarily a good thing. I can argue that every Object should have > announcer capabilities just like it has exception handling capabilities, but > then we would go even further away from the main point :). > act as event source is quite valuable. That's why, there is already existing protocols for that (see events-blah categories). And dependents mechanism. And that's why we want to eventually unify them.. because there's too many. > Inheritance as reuse is definitely to be avoided, and indeed the principle > of Least Authority (or more known as Principle of Least Privilege) is a > relevant point (I concede that :)). However, I guess you agree that having > #class defined in Object is not a horrible (it can be better, but it is not > horrible) thing even if most objects do not need this information. > > Another principle that might be more useful when thinking about inheritance > is the Liskov Substitution Principle. From this point of view, as long as > MyDomainConcept does not redefine the meaning of Announcer, it is not > unreasonable to have it inherit from Announcer. > Yes, but where are the guarantees that you don't? Just think from outsider's point of view: when he sees Announcer subclass: #Foo what he will think first: - aha, this guy implements own kind of announcer or - aha this guy reusing announcer or - aha, this guy doing both things at the same time (a worst possible alternative) and how many abuses like that, he should see before making a logical conclusion: - aha.. this is the way how i should do as well. > I stop now. You can continue to shoot :). > -- Best regards, Igor Stasenko. |
On Jul 21, 2013, at 2:38 PM, Igor Stasenko <[hidden email]> wrote:
+ 1 Stef |
In reply to this post by Igor Stasenko
Hi Igor.
2013/7/21 Igor Stasenko <[hidden email]>
I understand your position. But I think it is too little and simple place to introduce another object. And original paper about Announcements framework (maybe from Vasiliy Bykov) not described such distinction between event source and announcer as subscription service. Too me subscription service is exactly SubscriptionsRegistry. Interesting how Announcer used in VisualWorks system.
Any way if we agree with your proposals we should add EventsSource class (choose better name) to Announcements package. And we should describe it in announcements chapter in pharo book. Because now there are no documentation where your distinction are explained and that's why now natural way to make event source classes is subclassing Announcer.
Best regards, Denis |
In reply to this post by Igor Stasenko
2013/7/21 Igor Stasenko <[hidden email]>
Interesting how many people in this list think that "Announcer subclass: #TxEditor" provides special implementation of announcer named TxEditor?
Because to me it is not practical design issues when we talk about subclassing Announcer.
|
On Jul 21, 2013, at 5:36 PM, Denis Kudriashov <[hidden email]> wrote:
Many this is composition using inheritance and inheritance should not be used like that. Announcer subclass: #GreedyAnnouncer Announcer subclass: #RemoteAnnouncer Are quite different from Announcer subclass: #Customer This is not because subclassing can be used that we should do it. We suffer during years from Dictionary subclass: #Set and other beauties.
|
Free forum by Nabble | Edit this page |