[Pharo-dev] About abuse of inheritance

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
42 messages Options
123
Reply | Threaded
Open this post in threaded view
|

[Pharo-dev] About abuse of inheritance

Igor Stasenko
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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

pdavidow
In reply to this post by Igor Stasenko
Igor - could you please explain 'the principle of least authority'?
Thanks,
- Paul

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Esteban A. Maringolo
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

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Max Leske
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.
>


Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Denis Kudriashov
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
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.


Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Camillo Bruni-3
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.
>>
>>


Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Hannes Hirzel
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.
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Tudor Girba-2
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:
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.




--

"Every thing has its own flow"
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Tudor Girba-2
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:
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.
>
>




--

"Every thing has its own flow"
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Tudor Girba-2
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?
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.
>>
>>





--

"Every thing has its own flow"
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Igor Stasenko
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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

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 :).
>
Not at all, i also think that having a generic way for any object to
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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Stéphane Ducasse

On Jul 21, 2013, at 2:38 PM, Igor Stasenko <[hidden email]> wrote:


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

+ 1


Stef

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Denis Kudriashov
In reply to this post by Igor Stasenko
Hi Igor.

2013/7/21 Igor Stasenko <[hidden email]>
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.

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


Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Denis Kudriashov
In reply to this post by Igor Stasenko
2013/7/21 Igor Stasenko <[hidden email]>
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.

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.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] About abuse of inheritance

Stéphane Ducasse

On Jul 21, 2013, at 5:36 PM, Denis Kudriashov <[hidden email]> wrote:

2013/7/21 Igor Stasenko <[hidden email]>
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.

Interesting how many people in this list think that "Announcer subclass: #TxEditor" provides special implementation of announcer named TxEditor?

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.




Because to me it is not practical design issues when we talk about subclassing Announcer.


123