Hi,
2010/3/4 Stéphane Rollandin <[hidden email]>: >> base (false) -> parent(true) -> subclass(false). > > I have this mostly in class-side methods; an example in Squeak proper (that > is, not my code), is TestCase class>>isAbstract ah, but that's a different story; there may well be multiple abstract classes along one inheritance chain. A MyMorph subclass that will respond with false to isMyMorph is another thing. Best, Michael |
In reply to this post by Michael Haupt-3
Le 04/03/2010 22:41, Michael Haupt a écrit :
> Hi, > > 2010/3/4 Stéphane Rollandin<[hidden email]>: >> That's my style. > > http://gbracha.blogspot.com/2008/03/monkey-patching.html ;-) ;-) ;-) Note this sentence at the end of the paper: "So far, I have no firm conclusions about how to best address the problems monkey patching is trying to solve." call me monkey all right, then... I will look at you from the trees until some of you guys find the solution, then I will probably evolve :) Stef |
Best,
2010/3/4 Stéphane Rollandin <[hidden email]>: > "So far, I have no firm conclusions about how to best address the problems > monkey patching is trying to solve." take a look at Newspeak. ;-) > call me monkey all right, then... I haven't even seen you yet, how could I? > I will look at you from the trees until > some of you guys find the solution, then I will probably evolve :) Toss me some coconuts, please. Love those things. Good night, Michael |
In reply to this post by Bert Freudenberg
On Thu, 4 Mar 2010, Bert Freudenberg wrote:
> On 04.03.2010, at 22:21, Stéphane Rollandin wrote: >> >>> If you have a lot of protocols you can use the super fast >>> primitive supported #pointsTo: and have a lot cleaner (and possibly >>> faster) code: >>> >>> is: aSymbol >>> >>> ^#(Morph MySpecializedMorph FooMorph BarMorph) pointsTo: aSymbol >>> >> >> >> wow. thanks for the pointer, I wasn't aware of this one :) >> >> Stef > > It's also less readable. If you replace #pointsTo: with #includes: I know right away what it means. If you use this low-level optimization I have to think twice which object points where. MethodDictionary >> #includesKey:. We also have #identityIncludes: which is not so fast, but could be overridden in SequenceableCollection for better performance. In Cuis #is: could be implemented only in Object as something like #is: aSymbol "#pointsTo: is used here for better performance" ^self implementedProtocols pointsTo: aSymbol and #implementedProtocols could just return a literal Array, though it's has an extra message send. Levente > > - Bert - > > > > |
In reply to this post by Michael Haupt-3
> 2010/3/4 Stéphane Rollandin<[hidden email]>:
>>> base (false) -> parent(true) -> subclass(false). >> >> I have this mostly in class-side methods; an example in Squeak proper (that >> is, not my code), is TestCase class>>isAbstract > > ah, but that's a different story; there may well be multiple abstract > classes along one inheritance chain. A MyMorph subclass that will > respond with false to isMyMorph is another thing. again because you equate the semantics of #isMyMorph to isKindOf: Morph this may not be the case. I could have Morph -> MyMorph -> YourMorph -> MyOtherMorph and want both MyMorph and MyOtherMorph answer true to #isMyMorph yes I could ! remember I'm a monkey :) Stef |
In reply to this post by Stéphane Rollandin
On 3/4/2010 11:44 AM, Stéphane Rollandin wrote:
> I don't see how #is: can work in the large. > > suppose I need test selectors like isMorph, isBorderedMorph, isMyMorph > and isMySpecializedMorph Here is what you'd do: . . . . . . Nothing. All that you're describing is already there. To wit: Morph new is: #Morph => true. BorderedMorph new is: #Morph => true. BorderedMorph new is: #BorderedMorph => true. Array new is: #Morph => false Works out of the box. You can then start to have fun, say: SystemDictionary>>is: aSymbol ^aSymbol == #Squeak or:[super is: aSymbol] and now: Smalltalk is: #Dictionary => true Smalltalk is: #Squeak => true Smalltalk is: #Cuis => false > every Morph must have > > is: aSymbol > aSymbol == #Morph ifTrue: [^ true]. > ^ false No. See above. > then BorderedMorph must implement > > is: aSymbol > (super is: aSymbol > or: [aSymbol == #BorderedMorph]) ifTrue: [^ true]. > ^ false No. See above. > now MyMorph (supposedly a BorderedMorph) has > > is: aSymbol > (super is: aSymbol > or: [aSymbol == #MyMorph]) ifTrue: [^ true]. > ^ false No. See above. > so far so good, although at the moment all this code would be replaced with > > isMorph > ^ false > > isBorderedMorph > ^ false > > isMyMorph > ^ false > > in Object, and the corresponding > > > isMorph > ^ true > > isBorderedMorph > ^ true > > isMyMorph > ^ true > > at the proper places Which is the point here. These six methods are being removed without replacement. You get all of this for free. > let's now consider MySpecializedMorph, a subclass of MyMorph that I *do > not* want to be considered as MyMorph: > > is: aSymbol > (super is: aSymbol and: [aSymbol =~ #MyMorph]) > or: [aSymbol == #MySpecializedMorph]) ifTrue: [^ true]. > ^ false > > see the problem ? This is the first situation where you'd actually have to implement is: MySpecializedMorph>>is: aSymbol ^aSymbol ~~ #MySpecializedMorph and:[super is: aSymbol] I fail to see any problem whatsoever. > I have to be aware of the behavior of each implementation of #is: in the > upward inheritance chain if I want to produce the proper tests. Going > down, those tests will become more and more complex and hard to grok. This is a valid concern but rather unlikely from my point of view. You don't have to use #is: if you don't want to. It's entirely optional. You can still go ahead and monkey-patch those isMethods where you'd like to - in some cases this will be advantageous for clarity, in others for performance, and where that's true, we should absolutely use them. The use of #is: isn't a dogma, it's a tool that will be helpful for situations that we currently don't have a good approach for. > Plus, reimplementing any of the #is: can possibly break any of the #is: > in subclasses. So all #is: implementations in a given hierarchy are > actually dependent. It's pure spaghetti code, as far away from OOP as it > gets. > > I guess I'm missing something. how is this supposed to work ? See above. It's straightforward. Some of your concerns are valid, but the current situation is highly undesirable: Hard code class references, and gazillions of isFooBar methods don't make the system any more OOP either. We need to find a middle ground here and the #is: protocol helps with that. Cheers, - Andreas |
In reply to this post by Stéphane Rollandin
2010/3/4 Stéphane Rollandin <[hidden email]>:
>> Then, please , give me a concrete example, where you will have 3 classes, >> answering to isXXX message differently: >> >> base (false) -> parent(true) -> subclass(false). > > I have this mostly in class-side methods; an example in Squeak proper (that > is, not my code), is TestCase class>>isAbstract > I think this is a bad example. #isAbstract used for different purpose, not what we're discussing here, i.e. it doesn't tells what kind of protocol an object may support, but rather used to test the state of object (in this case object is a class being abstract or not). In same way, as using #isClosed, or #isOpen to test whether file is open or closed. And besides, a base implementation (TestCase isAbstract) answering true. > Stef -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Levente Uzonyi-2
2010/3/4 Levente Uzonyi <[hidden email]>:
> On Thu, 4 Mar 2010, Bert Freudenberg wrote: > >> On 04.03.2010, at 22:21, Stéphane Rollandin wrote: >>> >>>> If you have a lot of protocols you can use the super fast >>>> primitive supported #pointsTo: and have a lot cleaner (and possibly >>>> faster) code: >>>> >>>> is: aSymbol >>>> >>>> ^#(Morph MySpecializedMorph FooMorph BarMorph) pointsTo: aSymbol >>>> >>> >>> >>> wow. thanks for the pointer, I wasn't aware of this one :) >>> >>> Stef >> >> It's also less readable. If you replace #pointsTo: with #includes: I know >> right away what it means. If you use this low-level optimization I have to >> think twice which object points where. > > #includes: is a lot slower of course, that's why #pointsTo: is used in > MethodDictionary >> #includesKey:. We also have #identityIncludes: which is > not so fast, but could be overridden in SequenceableCollection for better > performance. > {#[1] pointsTo: 1. #[1] identityIncludes: 1} -> #(false true) Not that i care much but... Nicolas > > In Cuis #is: could be implemented only in Object as something like > > #is: aSymbol > "#pointsTo: is used here for better performance" > > ^self implementedProtocols pointsTo: aSymbol > > and #implementedProtocols could just return a literal Array, though it's has > an extra message send. > > > Levente > >> >> - Bert - >> >> >> > > > > |
In reply to this post by Andreas.Raab
>> suppose I need test selectors like isMorph, isBorderedMorph, isMyMorph >> and isMySpecializedMorph > > Here is what you'd do: > > . > . > . > . > . > . > > Nothing. All that you're describing is already there. To wit: > > Morph new is: #Morph => true. > BorderedMorph new is: #Morph => true. > BorderedMorph new is: #BorderedMorph => true. > Array new is: #Morph => false oh, that's because you start from your #isKindOf; based implementation. ok, then, point taken. > > We need to find a middle ground here and the #is: protocol helps with that. > sure. just maybe call it #isA: like suggested elsewhere, so that its intent gets clearer (IMHO of course) cheers, Stef |
In reply to this post by Igor Stasenko
> I think this is a bad example. > #isAbstract used for different purpose, not what we're discussing > here, i.e. it doesn't tells what kind of protocol an object may > support, but rather used to test the state of object (in this case > object is a class being abstract or not). that's a thin line here. whether something is a protocol or a a query on the (static) state of an object is a matter of point of view, internal representation of the software, and eventually, taste :) regards, Stef |
In reply to this post by Juan Vuletich-4
On 3/4/2010 12:33 PM, Juan Vuletich wrote:
> I believe #isKindOf: is really bad. Reasons for this are given in > http://userweb.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf . This was > also discussed here, you can google for the name of the pdf in the > archives. > > In the Cuis implementation of Object>>#is: there is no call to > #isKindOf:. The idea is to ask for a protocol, not for inheritance. But inheritance implies protocol. There is nothing wrong with asking for protocol conformance based on inheritance; it is the same as implementing isNumber in class Number for the purpose of having subclasses inherit that. The implementation that I've proposed is making that point. Thus (42 is: #Number) returns true, since 42 conforms to the Number protocol. If you had some other class that conforms to the number protocol without subclassing it, it is free to implement, e.g., ComplexNumericRepresentative>>is: aSymbol "I conform to the number protocol" ^aSymbol == #Number or:[super is: aSymbol] As a consequence, the #is: test is not an inheritance test at all. Cheers, - Andreas |
Andreas Raab wrote:
> On 3/4/2010 12:33 PM, Juan Vuletich wrote: >> I believe #isKindOf: is really bad. Reasons for this are given in >> http://userweb.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf . This was >> also discussed here, you can google for the name of the pdf in the >> archives. >> >> In the Cuis implementation of Object>>#is: there is no call to >> #isKindOf:. The idea is to ask for a protocol, not for inheritance. > > But inheritance implies protocol. There is nothing wrong with asking > for protocol conformance based on inheritance; it is the same as > implementing isNumber in class Number for the purpose of having > subclasses inherit that. > > The implementation that I've proposed is making that point. Thus (42 > is: #Number) returns true, since 42 conforms to the Number protocol. > If you had some other class that conforms to the number protocol > without subclassing it, it is free to implement, e.g., > > ComplexNumericRepresentative>>is: aSymbol > "I conform to the number protocol" > ^aSymbol == #Number or:[super is: aSymbol] > > As a consequence, the #is: test is not an inheritance test at all. > > Cheers, > - Andreas What you say is right. The reasons for me not doing it that way are perhaps subtle and aesthetic. I prefer making it as clear as possible that this is not about inheritance but protocol. I also think that my approach is easier to explain and understand. Besides I don't like it looking like there are "special" or "privileged" classes or hierarchies. Perhaps more important, I prefer not having "implicit" protocol conformance without anybody declaring (for example) that #BorderedMorph is now considered a protocol. In addition, I believe that this should be used only when really needed. In general, a better design might make all these queries unneeded. So, forcing people to declare their protocols might discourage abuse. Anyway, I think both solutions are acceptable and it comes down to taste. Cheers, Juan Vuletich |
On 5 March 2010 01:05, Juan Vuletich <[hidden email]> wrote:
> Andreas Raab wrote: >> >> On 3/4/2010 12:33 PM, Juan Vuletich wrote: >>> >>> I believe #isKindOf: is really bad. Reasons for this are given in >>> http://userweb.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf . This was >>> also discussed here, you can google for the name of the pdf in the >>> archives. >>> >>> In the Cuis implementation of Object>>#is: there is no call to >>> #isKindOf:. The idea is to ask for a protocol, not for inheritance. >> >> But inheritance implies protocol. There is nothing wrong with asking for >> protocol conformance based on inheritance; it is the same as implementing >> isNumber in class Number for the purpose of having subclasses inherit that. >> >> The implementation that I've proposed is making that point. Thus (42 is: >> #Number) returns true, since 42 conforms to the Number protocol. If you had >> some other class that conforms to the number protocol without subclassing >> it, it is free to implement, e.g., >> >> ComplexNumericRepresentative>>is: aSymbol >> "I conform to the number protocol" >> ^aSymbol == #Number or:[super is: aSymbol] >> >> As a consequence, the #is: test is not an inheritance test at all. >> >> Cheers, >> - Andreas > > What you say is right. The reasons for me not doing it that way are perhaps > subtle and aesthetic. I prefer making it as clear as possible that this is > not about inheritance but protocol. I also think that my approach is easier > to explain and understand. Besides I don't like it looking like there are > "special" or "privileged" classes or hierarchies. Perhaps more important, I > prefer not having "implicit" protocol conformance without anybody declaring > (for example) that #BorderedMorph is now considered a protocol. In addition, > I believe that this should be used only when really needed. In general, a > better design might make all these queries unneeded. So, forcing people to > declare their protocols might discourage abuse. > > Anyway, I think both solutions are acceptable and it comes down to taste. > a) Object>>is: aSymbol ^ false b) Object>>is: aSymbol self class environment at: aSymbol ifPresent:[:aClass| ^self isKindOf: aClass]. ^false both methods should have an appropriate comment, explaining how and when to use it. I just skipped it here. My vote is for a). Initially i proposed a little different implementation: is: anObject ^ self = anObject (note that i'm using 'anObject' argument name , not just symbol) but now, i agree with Juan that more not always better. A method , which answers just false (as in (a) case) looking a bit obscure, but if we take into account that it comes with definitive giude about how and when it should be used, then its not. > Cheers, > Juan Vuletich > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Juan Vuletich-4
On Fri, Mar 5, 2010 at 9:33 AM, Juan Vuletich <[hidden email]> wrote:
> Andreas Raab wrote: >> >> For discussion, this is what I'm suggesting: >> >> Object>>is: aSymbol >> >> "A generic membership test. Should be used to avoid the proliferation >> of isXXX >> methods where appropriate. Use it like here: >> >> FooBar>>is: aSymbol >> ^aSymbol == #Foo or:[aSymbol == #Bar or:[super is: aSymbol]] >> >> This implementation can also be used with class names to replace the >> usage >> of aMorph isKindOf: SketchEditorMorph with, e.g., aMorph is: >> #SketchEditorMorph >> to avoid unnecessary dependencies on classes" >> >> "Check to see if aSymbol is a class name in the receiver's environment" >> self class environment >> at: aSymbol >> ifPresent:[:aClass| ^self isKindOf: aClass]. >> >> ^false > > I believe #isKindOf: is really bad. Reasons for this are given in > http://userweb.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf . This was also > discussed here, you can google for the name of the pdf in the archives. > > In the Cuis implementation of Object>>#is: there is no call to #isKindOf:. > The idea is to ask for a protocol, not for inheritance. It sounds like Java-style Interfaces should be implemented. (anObject implements: AnInterface) ifTrue: [ ... ] Gulik. -- http://gulik.pbwiki.com/ |
In reply to this post by Stéphane Rollandin
On 2010-03-04, at 1:18 PM, Stéphane Rollandin wrote: > I got it; see my answer to Juan. I guess I'm just programming in bad style: I do indeed consider that Object is part of my packages (or, more accurately, that Object is not a forbidden place for my package to go in). Hear hear. I've been wondering why people are so enthusiastic about #is: - good to see I'm not the only one. I think #isA: is fine, as an easy way to do #isKindOf: without a direct class reference. Being able to avoid class references makes it easier to avoid dependencies, which makes it easier to have a modular system. Juan's implementation of #is: puzzles me though. It replaces polymorphic dispatch with boolean logic. Good OO design generally goes in the opposite direction. Furthermore, Juan's version of #is: makes it more difficult to modularize the system. If I write a package that needs to add the concept of "greenness" to the system, I can add #isGreen extension methods wherever I want, without breaking any existing code. Somebody else can add #isPurple methods without breaking my code. But if we both need to override #is:, we have a gratuitous incompatibility. Note that #is: may work well in Cuis, but that's because Cuis is *not* a modular system. Finally, I also want to point out that "simpler" and "fewer methods" are not the same thing. Methods that answer booleans are dead simple to understand, no matter how many of them there are. A single #is: method increases incomplexity as the number of tests it encompasses increases. So, consider this moral support for Stéphane, since he seems to be beset on all sides. Also, +0 for #isA: -1 for #is: Colin |
On 5 March 2010 06:37, Colin Putney <[hidden email]> wrote:
> > On 2010-03-04, at 1:18 PM, Stéphane Rollandin wrote: > >> I got it; see my answer to Juan. I guess I'm just programming in bad style: I do indeed consider that Object is part of my packages (or, more accurately, that Object is not a forbidden place for my package to go in). > > Hear hear. I've been wondering why people are so enthusiastic about #is: - good to see I'm not the only one. > > I think #isA: is fine, as an easy way to do #isKindOf: without a direct class reference. Being able to avoid class references makes it easier to avoid dependencies, which makes it easier to have a modular system. > > Juan's implementation of #is: puzzles me though. It replaces polymorphic dispatch with boolean logic. Good OO design generally goes in the opposite direction. > Agreed. But then expect an Object class to have thousands of isXXXX methods, since we having way many things which we can imagine and may want to model them. Then the Object class will become a flat space of system-wide methods. Is this what can be called good OO design which using polymorphic dispatch? > Furthermore, Juan's version of #is: makes it more difficult to modularize the system. If I write a package that needs to add the concept of "greenness" to the system, I can add #isGreen extension methods wherever I want, without breaking any existing code. Somebody else can add #isPurple methods without breaking my code. But if we both need to override #is:, we have a gratuitous incompatibility. > But you are still free to do that, so what the problem? But in 90% of cases, i think you can use #is: method , without the need of adding extensions anywhere, because the only reason why you adding it is to be overridden in subclass, which belongs to your package. > Note that #is: may work well in Cuis, but that's because Cuis is *not* a modular system. > > Finally, I also want to point out that "simpler" and "fewer methods" are not the same thing. Methods that answer booleans are dead simple to understand, no matter how many of them there are. A single #is: method increases incomplexity as the number of tests it encompasses increases. > I disagree. Adding a new protocols and corresponding way to test a conformance to it - this is what increases system complexity in a first place. The #is: method by itself puts zero weight into it, if you not using it. > So, consider this moral support for Stéphane, since he seems to be beset on all sides. Also, > > +0 for #isA: > -1 for #is: > > Colin > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Colin Putney
2010/3/5 Colin Putney <[hidden email]>:
> > On 2010-03-04, at 1:18 PM, Stéphane Rollandin wrote: > >> I got it; see my answer to Juan. I guess I'm just programming in bad style: I do indeed consider that Object is part of my packages (or, more accurately, that Object is not a forbidden place for my package to go in). > > Hear hear. I've been wondering why people are so enthusiastic about #is: - good to see I'm not the only one. > > I think #isA: is fine, as an easy way to do #isKindOf: without a direct class reference. Being able to avoid class references makes it easier to avoid dependencies, which makes it easier to have a modular system. > > Juan's implementation of #is: puzzles me though. It replaces polymorphic dispatch with boolean logic. Good OO design generally goes in the opposite direction. > > Furthermore, Juan's version of #is: makes it more difficult to modularize the system. If I write a package that needs to add the concept of "greenness" to the system, I can add #isGreen extension methods wherever I want, without breaking any existing code. Somebody else can add #isPurple methods without breaking my code. But if we both need to override #is:, we have a gratuitous incompatibility. > Exactly, the good argument of Stephane. YOU SHALL NOT USE #is: FOR EXTENDING A CLASS WHICH IS NOT IN YOUR PACKAGE. So, yes, this is more a isA: Nicolas > Note that #is: may work well in Cuis, but that's because Cuis is *not* a modular system. > > Finally, I also want to point out that "simpler" and "fewer methods" are not the same thing. Methods that answer booleans are dead simple to understand, no matter how many of them there are. A single #is: method increases incomplexity as the number of tests it encompasses increases. > > So, consider this moral support for Stéphane, since he seems to be beset on all sides. Also, > > +0 for #isA: > -1 for #is: > > Colin > |
On 5 March 2010 11:17, Nicolas Cellier
<[hidden email]> wrote: > 2010/3/5 Colin Putney <[hidden email]>: >> >> On 2010-03-04, at 1:18 PM, Stéphane Rollandin wrote: >> >>> I got it; see my answer to Juan. I guess I'm just programming in bad style: I do indeed consider that Object is part of my packages (or, more accurately, that Object is not a forbidden place for my package to go in). >> >> Hear hear. I've been wondering why people are so enthusiastic about #is: - good to see I'm not the only one. >> >> I think #isA: is fine, as an easy way to do #isKindOf: without a direct class reference. Being able to avoid class references makes it easier to avoid dependencies, which makes it easier to have a modular system. >> >> Juan's implementation of #is: puzzles me though. It replaces polymorphic dispatch with boolean logic. Good OO design generally goes in the opposite direction. >> >> Furthermore, Juan's version of #is: makes it more difficult to modularize the system. If I write a package that needs to add the concept of "greenness" to the system, I can add #isGreen extension methods wherever I want, without breaking any existing code. Somebody else can add #isPurple methods without breaking my code. But if we both need to override #is:, we have a gratuitous incompatibility. >> > > Exactly, the good argument of Stephane. > > YOU SHALL NOT USE #is: FOR EXTENDING A CLASS WHICH IS NOT IN YOUR PACKAGE. > Right. But this was exactly an intent from very starting. One is free to override #is: in own package class , but should not replace/patch it in external package. > So, yes, this is more a isA: > > Nicolas > >> Note that #is: may work well in Cuis, but that's because Cuis is *not* a modular system. >> >> Finally, I also want to point out that "simpler" and "fewer methods" are not the same thing. Methods that answer booleans are dead simple to understand, no matter how many of them there are. A single #is: method increases incomplexity as the number of tests it encompasses increases. >> >> So, consider this moral support for Stéphane, since he seems to be beset on all sides. Also, >> >> +0 for #isA: >> -1 for #is: >> >> Colin >> > > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Colin Putney
Colin Putney wrote:
(snipped parts that were answered by Nicolas and Igor) > ... > Note that #is: may work well in Cuis, but that's because Cuis is *not* a modular system. > Of course it is not. Anyway, it is much closer to being modular than Squeak. At least there is a lot less dependencies in the kernel upon the applications. The removal of lots of #isXXX methods in Object is just a small part of that. Cheers, Juan Vuletich |
In reply to this post by Colin Putney
>> I got it; see my answer to Juan. I guess I'm just programming in
>> bad style: I do indeed consider that Object is part of my packages >> (or, more accurately, that Object is not a forbidden place for my >> package to go in). > > Hear hear. I've been wondering why people are so enthusiastic about > #is: - good to see I'm not the only one. > > I think #isA: is fine, as an easy way to do #isKindOf: without a > direct class reference. Being able to avoid class references makes > it easier to avoid dependencies, which makes it easier to have a > modular system. > > Juan's implementation of #is: puzzles me though. It replaces > polymorphic dispatch with boolean logic. Good OO design generally > goes in the opposite direction. > > Furthermore, Juan's version of #is: makes it more difficult to > modularize the system. If I write a package that needs to add the > concept of "greenness" to the system, I can add #isGreen extension > methods wherever I want, without breaking any existing code. > Somebody else can add #isPurple methods without breaking my code. > But if we both need to override #is:, we have a gratuitous > incompatibility. > > Note that #is: may work well in Cuis, but that's because Cuis is > *not* a modular system. > > Finally, I also want to point out that "simpler" and "fewer methods" > are not the same thing. Methods that answer booleans are dead simple > to understand, no matter how many of them there are. A single #is: > method increases incomplexity as the number of tests it encompasses > increases. > > So, consider this moral support for Stéphane, since he seems to be > beset on all sides. Also, > > +0 for #isA: > -1 for #is: > > Colin the askFor: version does support modularity. Users can askFor: #isGreen. Suppliers can implement #isGreen, and you get your tagging as well. Smalltalk askFor: #isSqueak regards Keith |
Free forum by Nabble | Edit this page |