[squeak-dev] Future of Squeak, and outsider's view

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

[squeak-dev] Future of Squeak, and outsider's view

David Goehrig
Yet another lurker here.

While I'm not at all qualified to speak for the seasoned Squeaker communities, I am qualified to comment on the issues I've found attempting to implement some sample applications for contract bids on top of Squeak.  I've also tracked the progress of Pharo with great anticipation, and have spent a lot of time pondering what needs to change to make it useful for my production work.

Here's a few thoughts, inspired by Dan Ingalls's famous 1981 Byte article on the principles of Smalltalk.

Principle 9:
Modularity: No component in a complex system should depend on the internal details of any other component. 

Well if you look in the latest Pharo image, you'll find there's around 38 methods of the Object class that amount to:

isFoo
^ false

Each of these methods violate this principle, not only in spirit but also in practice.  While this has been common practice for ages, it means that building downloadable modules that can be easily merged with any given image is practically impossible.  As soon as you have two packages that define their own class that wants to use
the same name, and register its own methods in a "base object", you both violate the principle of modularity AND break other packages.

Principle 12:
Factoring: Each independent component in a system would appear in only one place.

This is probably the single greatest reason for moving towards Traits across the board.  But look at this concept in the context of two seemingly entirely different methods:

Object acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph

Object hasLiteralSuchThat: testBlock

If you look at both of these methods, you'll quickly realize that they are in fact the exact same method!  This is because they have the exact same bytecode representation.  These two methods are also exactly the same as the 38 isFoo methods I mentioned above.  The only different is the semantics as viewed by the programmer, but the reality is none of these methods should be necessary, and should be factored out.  These methods only exist due to a flaw in the design of the API and its semantics.  This brings up the issue of

Principle 2:
Good Design: A system should be built with a minimum set of unchangeable parts; those parts should be as general as possible; and all parts of the system should be held in a uniform framework.

If you look at the problems of creating packages (see principle 9 above) or the excessive verbosity which leads to inordinate redundancy (see principle 12), these ultimately stem from lapses in principle 2.  Over the years, cruft has accumulated, people's code has become fragile and dependent on that cruft (remember message passing's and modularity's purpose is to reduce fragility), and result in an inertia against fixing the fundamental design flaws.  We end up with arguments over Squeak vs. Pharo vs. Etoys because the design of the core system has lapsed into disrepair, much like the US's infrastructure.  A serious effort to address this short coming,
and re-examine old design decisions to improve the core infrastructure would dramatically impact the future of all of these projects (as they all inherit the same problems).

Principle 17:
Natural Selection: Languages and systems that are of sound design will persist, to be supplanted only by better ones.

The concept of forking the language, fixing core issues, and addressing design flaws is a core principle of Smalltalk.  Maybe it is time for a better one.

Just my two cents,

Dave

-- 
-=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Ralph Johnson
On Mon, Jun 29, 2009 at 9:16 AM, David Goehrig<[hidden email]> wrote:

I agree that Squeak has accumulated a lot of cruft and it needs to be
removed.  This happens to most systems as they age.  But I disagree
with a lot of the detailed things you said.

> Modularity: No component in a complex system should depend on the internal
> details of any other component.
>
> Well if you look in the latest Pharo image, you'll find there's around 38
> methods of the Object class that amount to:
> isFoo
>
> ^ false
>
> Each of these methods violate this principle, not only in spirit but also in practice.

No, they do not.   You are assuming that Object is a component.
Classes in Smalltalk are not necessarily components.  Often a
component is a set of classes.  Sometimes it is a set of classes plus
some methods on other classes.  Components often add methods to
existing classes.

> Principle 12:
>
> Factoring: Each independent component in a system would appear in only one place.
>
> This is probably the single greatest reason for moving towards Traits across
> the board.

Maybe.  This is certainly the purpose of traits, but there is
disagreement about whether traits actually succeed.

>But look at this concept in the context of two seemingly entirely different methods:
>
> Object acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph
>
> Object hasLiteralSuchThat: testBlock
>
> If you look at both of these methods, you'll quickly realize that they are
> in fact the exact same method!  This is because they have the exact same
> bytecode representation.

Again, I disgree.  They are not the same method.  They are just
methods with the same implementation.  There is much more to a method
than its byte-code.  The name of the method is important.  The type of
the argument is important.  The number of arguments is important.  The
meaning of the the method is important, i.e. what is its precondition
and what do you expect to be true after you call it.

-Ralph Johnson

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
In reply to this post by David Goehrig
2009/6/29 David Goehrig <[hidden email]>:

> Yet another lurker here.
> While I'm not at all qualified to speak for the seasoned Squeaker
> communities, I am qualified to comment on the issues I've found attempting
> to implement some sample applications for contract bids on top of Squeak.
>  I've also tracked the progress of Pharo with great anticipation, and have
> spent a lot of time pondering what needs to change to make it useful for my
> production work.
> Here's a few thoughts, inspired by Dan Ingalls's famous 1981 Byte article on
> the principles of Smalltalk.
> Principle 9:
>
> Modularity: No component in a complex system should depend on the internal
> details of any other component.
>
> Well if you look in the latest Pharo image, you'll find there's around 38
> methods of the Object class that amount to:
> isFoo
>
> ^ false
>

I feel uneasy each time, when adding own isXXX methods to Object.
But i don't know another plausible way how to make a difference
between an objects which having a certain capability vs rest of
objects in a universe.

Here the code snippets of CVLambda class ( a quick & dirty lambda
calculus implementation, which i using in own project).
This class represents a lambda-message-send, i.e. it keeps all what a
message send needs:
receiver, selector, arguments.
any of its slots can be a free variable or, in own turn, be another
lambda and so on, without any limitations.

I need to compare, if two lambdas are equivalent:

= aLambda

        ^ aLambda isCVLambda and: [ aLambda isCVLambdaSlot not and: [ self
size = aLambda size and: [ self do: [:i :obj | obj = (aLambda at: i)
ifFalse: [
                        ^ false ]]. true ]]]


Sometimes i need to not reduce the lambdas immediately (because some
of them could have a side effects), but keep them for a while as a
message send, not yet performed , even if there is no free variables
left, but i want to test, if it can be reduced:

hasSlots
        self do: [:i :obj |
                ( obj isCVLambda and: [ obj hasSlots ]) ifTrue: [ ^ true ] ].
        ^ false

Sometimes i need to walk over all lambdas (contained in a topmost one):

lambdasDo: aBlock
        | copy |
        copy := self class basicNew: self size.
        self do: [:i :obj | copy at: i put: (obj isCVLambda ifTrue:[aBlock
value: obj] ifFalse:[obj]) ].
        ^ copy

so, here the question, can i implement the same behavior w/o using
#isCVLambda , and
without putting any additional methods to Object class?

Maybe the design is plainly wrong! Maybe i don't need any of the above
behavior in correctly designed class.
I don't know.


> Each of these methods violate this principle, not only in spirit but also in
> practice.  While this has been common practice for ages, it means that
> building downloadable modules that can be easily merged with any given image
> is practically impossible.  As soon as you have two packages that define
> their own class that wants to use
> the same name, and register its own methods in a "base object", you both
> violate the principle of modularity AND break other packages.
> Principle 12:
>
> Factoring: Each independent component in a system would appear in only one
> place.
>
> This is probably the single greatest reason for moving towards Traits across
> the board.  But look at this concept in the context of two seemingly
> entirely different methods:
>
> Object acceptDroppingMorph: transferMorph event: evt inMorph: dstListMorph
>
> Object hasLiteralSuchThat: testBlock
>
> If you look at both of these methods, you'll quickly realize that they are
> in fact the exact same method!  This is because they have the exact same
> bytecode representation.  These two methods are also exactly the same as the
> 38 isFoo methods I mentioned above.  The only different is the semantics as
> viewed by the programmer, but the reality is none of these methods should be
> necessary, and should be factored out.  These methods only exist due to a
> flaw in the design of the API and its semantics.  This brings up the issue
> of
> Principle 2:
>
> Good Design: A system should be built with a minimum set of unchangeable
> parts; those parts should be as general as possible; and all parts of the
> system should be held in a uniform framework.
>
> If you look at the problems of creating packages (see principle 9 above) or
> the excessive verbosity which leads to inordinate redundancy (see principle
> 12), these ultimately stem from lapses in principle 2.  Over the years,
> cruft has accumulated, people's code has become fragile and dependent on
> that cruft (remember message passing's and modularity's purpose is to reduce
> fragility), and result in an inertia against fixing the fundamental design
> flaws.  We end up with arguments over Squeak vs. Pharo vs. Etoys because the
> design of the core system has lapsed into disrepair, much like the US's
> infrastructure.  A serious effort to address this short coming,
> and re-examine old design decisions to improve the core infrastructure would dramatically impact the future of all of these projects (as they all inherit the same problems).
> Principle 17:
>
> Natural Selection: Languages and systems that are of sound design will
> persist, to be supplanted only by better ones.
>
> The concept of forking the language, fixing core issues, and addressing
> design flaws is a core principle of Smalltalk.  Maybe it is time for a
> better one.
> Just my two cents,
> Dave
> --
> -=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Cameron Sanders-2
I didn't read  your example closely, but, generally....

(obj respondsTo: #isCVLambda) and: [ obj isCVLambda ]

is very general (independent of hierarchy), or if you want to trap  
people on a class tree...

obj isKindOf: CVLambda

or trap exceptions for when something doesn't respond to isCVLambda ...

or...

--
BUT, it will be slower.

an intriguing idea is having Object always respond to any pattern  
isXXX with false, unless the method is explicitly defined. (Now there  
I go, changing the root behavior...)

-Cam


On Jun 29, 2009, at 1:18 PM, Igor Stasenko wrote:

> so, here the question, can i implement the same behavior w/o using
> #isCVLambda , and


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Stéphane Rollandin
In reply to this post by Igor Stasenko
> This class represents a lambda-message-send, i.e. it keeps all what a
> message send needs:
> receiver, selector, arguments.
> any of its slots can be a free variable or, in own turn, be another
> lambda and so on, without any limitations.

are you aware of this:
http://www.zogotounga.net/comp/squeak/functionaltalk.htm

... one of my mostly unnoticed contribution to Squeak :)

Stef


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

David Goehrig
In reply to this post by Cameron Sanders-2
What I typically what I've been doing to eliminate all of these methods with a single simple change:

Object
     doesNoUnderstand: aMessage
         ^ false

Occasionally, I'll add a line in there to log the message to a transcript just to see if I'm doing something stupid, but 99.9 out of 100, the edit time method checks are enough to catch most typo bugs.   Surprisingly enough, this breaks incredibly little existing code, since anything that would fire off the exception ends up user trapped  :)  And false is a pretty good default, following the principle "when in doubt return false"!

Then again I also like replacing "respondsTo: canUnderstand: and canPerform:" with a single "can:" method, because semantically they're all asking the same basic question.  There's so much of the system that can be refactored this way, where you have multiple methods with the same semantic meaning but slight variations in implementation that you could squash the vocabulary to a more manageable base with some careful thought.

Of course, I'm not married to a large existing code base :)

--
-=-=-=-=-=-=-=-=-=-=- http://blog.dloh.org/


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
In reply to this post by Stéphane Rollandin
2009/6/29 Stéphane Rollandin <[hidden email]>:

>> This class represents a lambda-message-send, i.e. it keeps all what a
>> message send needs:
>> receiver, selector, arguments.
>> any of its slots can be a free variable or, in own turn, be another
>> lambda and so on, without any limitations.
>
> are you aware of this:
> http://www.zogotounga.net/comp/squeak/functionaltalk.htm
>
> ... one of my mostly unnoticed contribution to Squeak :)
>

Of course i am. And your package inspired me to use lambdas in own project.
But i did own. Because i don't need so much generality as in your
implementation.
And i wanted it to behave a little differently. Don't want to go in
details right now.

> Stef
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
In reply to this post by Cameron Sanders-2
2009/6/29 Cameron Sanders <[hidden email]>:
> I didn't read  your example closely, but, generally....
>
> (obj respondsTo: #isCVLambda) and: [ obj isCVLambda ]
>

can't do that for lambdas, because it traps all DNU's and in this case
a send of #respondsTo: (or any other unknown message) will be
converted into a lambda message send instead of answering expected
result.
Because:

lambda := LambdaSlot id: #x.
lambda foo  ==> lambda( <x> #foo)

> is very general (independent of hierarchy), or if you want to trap people on
> a class tree...
>
> obj isKindOf: CVLambda
>

sorry, but this even worse than using #isXXX

> or trap exceptions for when something doesn't respond to isCVLambda ...
>
> or...
>
> --
> BUT, it will be slower.
>
> an intriguing idea is having Object always respond to any pattern isXXX with
> false, unless the method is explicitly defined. (Now there I go, changing
> the root behavior...)
>

Exactly :)

Maybe it worth add and standardize the #is:
message for Object ?
Which by default can be implemented as:

Object is: object
  ^ self == object

and if you need to add the differentiation, then could be something like:

Object is: object
  ^ object == #lambda or: [ super is: object ]


> -Cam
>
>
> On Jun 29, 2009, at 1:18 PM, Igor Stasenko wrote:
>
>> so, here the question, can i implement the same behavior w/o using
>> #isCVLambda , and
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
2009/6/30 Igor Stasenko <[hidden email]>:

> 2009/6/29 Cameron Sanders <[hidden email]>:
>> I didn't read  your example closely, but, generally....
>>
>> (obj respondsTo: #isCVLambda) and: [ obj isCVLambda ]
>>
>
> can't do that for lambdas, because it traps all DNU's and in this case
> a send of #respondsTo: (or any other unknown message) will be
> converted into a lambda message send instead of answering expected
> result.
> Because:
>
> lambda := LambdaSlot id: #x.
> lambda foo  ==> lambda( <x> #foo)
>
>> is very general (independent of hierarchy), or if you want to trap people on
>> a class tree...
>>
>> obj isKindOf: CVLambda
>>
>
> sorry, but this even worse than using #isXXX
>
>> or trap exceptions for when something doesn't respond to isCVLambda ...
>>
>> or...
>>
>> --
>> BUT, it will be slower.
>>
>> an intriguing idea is having Object always respond to any pattern isXXX with
>> false, unless the method is explicitly defined. (Now there I go, changing
>> the root behavior...)
>>
>
> Exactly :)
>
> Maybe it worth add and standardize the #is:
> message for Object ?
> Which by default can be implemented as:
>
> Object is: object
>  ^ self == object
>
> and if you need to add the differentiation, then could be something like:
>
> Object is: object
>  ^ object == #lambda or: [ super is: object ]
>

Sorry.. it can be confusing, because i wrote it not very clear:

Object>>is: object
  ^ self == object

SomeOtherThing>>is: object
  ^ object == #otherThing or: [ super is: object]

>
>> -Cam
>>
>>
>> On Jun 29, 2009, at 1:18 PM, Igor Stasenko wrote:
>>
>>> so, here the question, can i implement the same behavior w/o using
>>> #isCVLambda , and
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

keith1y

>>    
>>> is very general (independent of hierarchy), or if you want to trap people on
>>> a class tree...
>>>
>>> obj isKindOf: CVLambda
>>>
>>>      
>> sorry, but this even worse than using #isXXX
>>
>>    

Hence my preference for askFor:

http://bugs.squeak.org/view.php?id=5319

anObject askFor: #isRectangle

where askFor: returns the value if it is defined and false otherwise.


Keith

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Michael van der Gulik-2
In reply to this post by David Goehrig


On Tue, Jun 30, 2009 at 7:43 AM, David Goehrig <[hidden email]> wrote:
What I typically what I've been doing to eliminate all of these methods with a single simple change:

Object
     doesNoUnderstand: aMessage
         ^ false


/me runs away screaming.

Gulik.

--
http://gulik.pbwiki.com/


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Cameron Sanders-2
In reply to this post by David Goehrig
What you write (down below) is close to what I was thinking when I  
said have all #isXXX return false by default;
although I would test that the first two characters match 'i' and 's'  
and that more characters exist, if so, return false, otherwise, normal  
#doesNotUnderstand: behavior.

I would treat #is by itself differently... it is ... or it couldn't be  
tested! So I would do nothing for simple #is. and I don't like #is:  
because it looks like a class type test... but that is part of the  
point, eh?

I'll have to go back to the original example (by [hidden email],  
and read more about lambdas) but I thought that CVLambda would  
implement #isCVLambda  to return true when it can be verified to be  
one. The example did not illustrate #doesNotUnderstand:.

Back to the question of adding behavior to classes that you don't own.  
VisualWorks has a means to extend a class in a different package ...  
as I recall. As I recall, squeak has no such capability, right?

Thanks. You have given me food for thought...

Ciao,
Cam

On Jun 29, 2009, at 3:43 PM, David Goehrig wrote:

> What I typically what I've been doing to eliminate all of these  
> methods with a single simple change:
>
> Object
>    doesNoUnderstand: aMessage
>        ^ false


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
2009/6/30 Cameron Sanders <[hidden email]>:

> What you write (down below) is close to what I was thinking when I said have
> all #isXXX return false by default;
> although I would test that the first two characters match 'i' and 's' and
> that more characters exist, if so, return false, otherwise, normal
> #doesNotUnderstand: behavior.
>
> I would treat #is by itself differently... it is ... or it couldn't be
> tested! So I would do nothing for simple #is. and I don't like #is: because
> it looks like a class type test... but that is part of the point, eh?
>

I wouldn't say that. It is more trait-based approach than class-based.

The concept of #is: are: When object foo having some trait, it should
answer true on 'foo is: sometrait ', otherwise false.
Obviously since most subclasses inherit the behavior & traits of base
class, you should honor this rule in overrides of #is: method
i.e.:

Someclass>>is: object
  ^ (your tests here) or: [ super is: object ]

otherwise, if you omit the super send, some of the traits will become
unavailable. But of course, except when you doing this intentionally.


> I'll have to go back to the original example (by [hidden email], and
> read more about lambdas) but I thought that CVLambda would implement
> #isCVLambda  to return true when it can be verified to be one. The example
> did not illustrate #doesNotUnderstand:.
>
> Back to the question of adding behavior to classes that you don't own.
> VisualWorks has a means to extend a class in a different package ... as I
> recall. As I recall, squeak has no such capability, right?
>

MC having this capability for a years.

> Thanks. You have given me food for thought...
>
> Ciao,
> Cam
>
> On Jun 29, 2009, at 3:43 PM, David Goehrig wrote:
>
>> What I typically what I've been doing to eliminate all of these methods
>> with a single simple change:
>>
>> Object
>>   doesNoUnderstand: aMessage
>>       ^ false
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Michael van der Gulik-2
In reply to this post by Cameron Sanders-2
Please reply under posts. It makes things less confusing.



On Jun 29, 2009, at 3:43 PM, David Goehrig wrote:

What I typically what I've been doing to eliminate all of these methods with a single simple change:

Object
  doesNoUnderstand: aMessage
      ^ false
 
On Tue, Jun 30, 2009 at 3:26 PM, Cameron Sanders <[hidden email]> wrote:
What you write (down below) is close to what I was thinking when I said have all #isXXX return false by default;
although I would test that the first two characters match 'i' and 's' and that more characters exist, if so, return false, otherwise, normal #doesNotUnderstand: behavior.

I would treat #is by itself differently... it is ... or it couldn't be tested! So I would do nothing for simple #is. and I don't like #is: because it looks like a class type test... but that is part of the point, eh?

I'll have to go back to the original example (by [hidden email], and read more about lambdas) but I thought that CVLambda would implement #isCVLambda  to return true when it can be verified to be one. The example did not illustrate #doesNotUnderstand:.

Back to the question of adding behavior to classes that you don't own. VisualWorks has a means to extend a class in a different package ... as I recall. As I recall, squeak has no such capability, right?


Squeak certainly has that capability, but I would discourage you from using it.

Changing the implementation of doesNotUnderstand: is a code smell. You're starting to play with voodoo and you need a *very* good reason to do it. Otherwise you'll have made yourself a very difficult application to debug.

In my opinion (which doubtless isn't shared by everyone here), base classes such as Object should not have a lot of >>isXXX methods. >>isBoolean and >>isString are okay (although I never use them), but >>isMorph or >>isColor or anything not related to the Kernel classes are pollution.

If you're using an >>isXXX method, then your code probably needs refactoring. It means you're implementing class specific behaviour using conditional >>ifTrue: blocks. Typically, your code will be working with subclasses of a specific class, and you'd invoke polymorphic methods to get class specific behaviour rather than using conditional blocks such as >>ifTrue:, >>ifFalse: etc.

If your code really does handle an object of any possible class (which is rare but does occur), then you can use >>isKindOf:, >>isMemberOf: and >>respondsTo:.

Igor's lambda example was a bit complex for me to work through so I can't really comment on it.
  
Gulik.

--
http://gulik.pbwiki.com/


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Cameron Sanders-2
In reply to this post by Igor Stasenko
Oh... ... oh... the CVLambda class was/is trait based. Confession: I  
haven't done my homework on traits. That might explain a little!

I was not aware of the rules/origin for #is:  -- thank you!

<more down below>

On Jun 29, 2009, at 11:59 PM, Igor Stasenko wrote:

> 2009/6/30 Cameron Sanders <[hidden email]>:
>>
> The concept of #is: are: When object foo having some trait, it should
> answer true on 'foo is: sometrait ', otherwise false.
> Obviously since most subclasses inherit the behavior & traits of base
> class, you should honor this rule in overrides of #is: method
> i.e.:
>
> Someclass>>is: object
> ^ (your tests here) or: [ super is: object ]
>
> otherwise, if you omit the super send, some of the traits will become
> unavailable. But of course, except when you doing this intentionally.
>
>
>> I'll have to go back to the original example (by  
>> [hidden email], and
>> read more about lambdas) but I thought that CVLambda would implement
>> #isCVLambda  to return true when it can be verified to be one. The  
>> example
>> did not illustrate #doesNotUnderstand:.
>>
>> Back to the question of adding behavior to classes that you don't  
>> own.
>> VisualWorks has a means to extend a class in a different  
>> package ... as I
>> recall. As I recall, squeak has no such capability, right?
>>
>
> MC having this capability for a years.

So how do I do extend a class. Simply define it again for a given  
package?

I did not know this was in Squeak.

Again, thank you... now I am glad I offered up answers to things I  
didn't understand!

Cheers,
Cam


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
In reply to this post by Michael van der Gulik-2
2009/6/30 Michael van der Gulik <[hidden email]>:

> Please reply under posts. It makes things less confusing.
>
>>
>>
>> On Jun 29, 2009, at 3:43 PM, David Goehrig wrote:
>>
>>> What I typically what I've been doing to eliminate all of these methods
>>> with a single simple change:
>>>
>>> Object
>>>   doesNoUnderstand: aMessage
>>>       ^ false
>
>
>>
>> On Tue, Jun 30, 2009 at 3:26 PM, Cameron Sanders
>> <[hidden email]> wrote:
>> What you write (down below) is close to what I was thinking when I said
>> have all #isXXX return false by default;
>> although I would test that the first two characters match 'i' and 's' and
>> that more characters exist, if so, return false, otherwise, normal
>> #doesNotUnderstand: behavior.
>>
>> I would treat #is by itself differently... it is ... or it couldn't be
>> tested! So I would do nothing for simple #is. and I don't like #is: because
>> it looks like a class type test... but that is part of the point, eh?
>>
>> I'll have to go back to the original example (by [hidden email], and
>> read more about lambdas) but I thought that CVLambda would implement
>> #isCVLambda  to return true when it can be verified to be one. The example
>> did not illustrate #doesNotUnderstand:.
>>
>> Back to the question of adding behavior to classes that you don't own.
>> VisualWorks has a means to extend a class in a different package ... as I
>> recall. As I recall, squeak has no such capability, right?
>>
>
> Squeak certainly has that capability, but I would discourage you from using
> it.
>
> Changing the implementation of doesNotUnderstand: is a code smell. You're
> starting to play with voodoo and you need a *very* good reason to do it.
> Otherwise you'll have made yourself a very difficult application to debug.
>
> In my opinion (which doubtless isn't shared by everyone here), base classes
> such as Object should not have a lot of >>isXXX methods. >>isBoolean and
>>>isString are okay (although I never use them), but >>isMorph or >>isColor
> or anything not related to the Kernel classes are pollution.
>
> If you're using an >>isXXX method, then your code probably needs
> refactoring. It means you're implementing class specific behaviour using
> conditional >>ifTrue: blocks. Typically, your code will be working with
> subclasses of a specific class, and you'd invoke polymorphic methods to get
> class specific behaviour rather than using conditional blocks such as
>>>ifTrue:, >>ifFalse: etc.
>
> If your code really does handle an object of any possible class (which is
> rare but does occur), then you can use >>isKindOf:, >>isMemberOf: and
>>>respondsTo:.
>
> Igor's lambda example was a bit complex for me to work through so I can't
> really comment on it.
>

Your suggestion is correct , except from situations like with my lambdas:

sometimes you need to differentiate a single kind of objects from the
rest of objects in universe.
isKindOf: doesn't helps , because then if we go that road , we're soon
will need
isKindOf:orOf:

simply because different objects could have same trait but belong to
different class hierarchies.

Concerning #respondsTo: - its also smells a bit, because you are
depending not on a specific behavior (by invoking some method) but
rather testing the class method dictionary, which is mostly static.
This approach (use of #respondsTo:) also doesn't fits well with
proxies (and we need them sometimes).

> Gulik.
>
> --
> http://gulik.pbwiki.com/
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Cameron Sanders-2
In reply to this post by Michael van der Gulik-2

On Jun 30, 2009, at 12:22 AM, Michael van der Gulik wrote:

> Back to the question of adding behavior to classes that you don't  
> own. VisualWorks has a means to extend a class in a different  
> package ... as I recall. As I recall, squeak has no such capability,  
> right?
>
>
> Squeak certainly has that capability, but I would discourage you  
> from using it.

Why?

> Changing the implementation of doesNotUnderstand: is a code smell.  
> You're starting to play with voodoo and you need a *very* good  
> reason to do it. Otherwise you'll have made yourself a very  
> difficult application to debug.

I have done it a fair amount for mapping symbols in broker objects...  
so that symbols may look like unary messages. It is slower than simply  
invoking some keyword message directly, but it really gives the right  
feel for some objects. e.g. ResultsSet.

And you are right, it will likely lead to a debugging nightmare. In  
some cases I have built symbol stacks to aid in debugging -- i'm  
tired, this is hurried.... my apologies if it is unclear. (Besides, I  
doubt you care...)

> In my opinion (which doubtless isn't shared by everyone here), base  
> classes such as Object should not have a lot of >>isXXX methods.  
> >>isBoolean and >>isString are okay (although I never use them), but  
> >>isMorph or >>isColor or anything not related to the Kernel classes  
> are pollution.

I agree with you here too.

> If you're using an >>isXXX method, then your code probably needs  
> refactoring. It means you're implementing class specific behaviour  
> using conditional >>ifTrue: blocks. Typically, your code will be  
> working with subclasses of a specific class, and you'd invoke  
> polymorphic methods to get class specific behaviour rather than  
> using conditional blocks such as >>ifTrue:, >>ifFalse: etc.

Some specialized containers may wish to process some things  
differently than others. But I agree that OO code should not  
frequently be branching on type-tests.

Cheers,
Cam

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
In reply to this post by Cameron Sanders-2
2009/6/30 Cameron Sanders <[hidden email]>:
> Oh... ... oh... the CVLambda class was/is trait based. Confession: I haven't
> done my homework on traits. That might explain a little!
>
> I was not aware of the rules/origin for #is:  -- thank you!
>

Don't take a 'trait' word literally. I didn't mean an implemetation
specific Traits (introduced in Squeak 3.9)
but rather some 'label' which you, as developer want to put on some
kind/group of objects.
The main point is, that often, such labels not in sync with class
hierarchy (imagine you could treat a Number subclasses and
DatabaseConnection subclasses as objects which share some common
trait).

But of course, my #is: proposal lays perfectly on Traits basis.
If you implement this method in Trait, and then use this trait in
multiple different classes - then it will work exactly as i
describing.

> <more down below>
>
> On Jun 29, 2009, at 11:59 PM, Igor Stasenko wrote:
>
>> 2009/6/30 Cameron Sanders <[hidden email]>:
>>>
>> The concept of #is: are: When object foo having some trait, it should
>> answer true on 'foo is: sometrait ', otherwise false.
>> Obviously since most subclasses inherit the behavior & traits of base
>> class, you should honor this rule in overrides of #is: method
>> i.e.:
>>
>> Someclass>>is: object
>> ^ (your tests here) or: [ super is: object ]
>>
>> otherwise, if you omit the super send, some of the traits will become
>> unavailable. But of course, except when you doing this intentionally.
>>
>>
>>> I'll have to go back to the original example (by [hidden email], and
>>> read more about lambdas) but I thought that CVLambda would implement
>>> #isCVLambda  to return true when it can be verified to be one. The
>>> example
>>> did not illustrate #doesNotUnderstand:.
>>>
>>> Back to the question of adding behavior to classes that you don't own.
>>> VisualWorks has a means to extend a class in a different package ... as I
>>> recall. As I recall, squeak has no such capability, right?
>>>
>>
>> MC having this capability for a years.
>
> So how do I do extend a class. Simply define it again for a given package?
>

you can put an extension method to any class, by putting it into a
category named by your package name, prepended by '*' character:

*MyPackage


> I did not know this was in Squeak.
>
> Again, thank you... now I am glad I offered up answers to things I didn't
> understand!
>
You welcome :)

> Cheers,
> Cam
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
Since multiple people seem don't grok my example, let me simplify it a bit:

Suppose you have a special collection of objects over which you can iterate.

The items in that collection could be anything - you don't really care
on almost any of them, except those ones which is also a special
collections of same kind as a container.

so, then you could have a method, which by iterating through your
special collection, ignores all objects except those who
also can be iterated in same manner:

MySpecialCollection>>mySpecialCollect: aBlock
     ^ self collect: [:each |
          each isMySpecialCollection ifTrue: [ each mySpecialCollect:
aBlock] ifFalse: [each]
      ]

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Future of Squeak, and outsider's view

Igor Stasenko
2009/6/30 Igor Stasenko <[hidden email]>:

> Since multiple people seem don't grok my example, let me simplify it a bit:
>
> Suppose you have a special collection of objects over which you can iterate.
>
> The items in that collection could be anything - you don't really care
> on almost any of them, except those ones which is also a special
> collections of same kind as a container.
>
> so, then you could have a method, which by iterating through your
> special collection, ignores all objects except those who
> also can be iterated in same manner:
>
> MySpecialCollection>>mySpecialCollect: aBlock
>     ^ self collect: [:each |
>          each isMySpecialCollection ifTrue: [ each mySpecialCollect:
> aBlock] ifFalse: [each]
>      ]
>

oops. looks like aBlock is not used :)
Okay.. how about that:

MySpecialCollection>>mySpecialCollect: aBlock
   | copy |
  copy := self collect: [:each |
          each isMySpecialCollection ifTrue: [ each mySpecialCollect:
aBlock] ifFalse: [each]
     ].
  ^ aBlock value: copy


> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

123