I've been looking at MetaObjects's [1] decade old implementation of the
vm in Cocoa. It has a class called SqueakInterpreter.h that defines a protocol that is used in SqView. The selectors are listed in SqueakInterpreter.h but implemented in SqView.m. I believe this kind of thing is now called a category in Objective-C-ese. And I was wondering why somebody would do this? We don't separate the protocols from the classes in Smalltalk. And I think the reason is we use abstract superclasses. And we have deep user developed hierarchies. Then it occurred to me that Objective-C doesn't have any user hierarchies of any depth. There are framework hierarchies of great depth. But the programmer in Objective-C from the start is supposed to go straight to composition and only produce very shallow hierarchies. I've got a book where a designer of Objective-C says inheritance is superfluous.[2] OK. Composition good. Inheritance bad. And it explains why there is no decent hierarchy browser in Xcode 4. There was one in Xcode 3 and they tossed it. And following these protocols from where they are defined to where they are implemented and where all developer hierarchies are two classes deep feels sort of like walking around a basement where the ceiling is too low with a flashlight looking for a crate. And so I'm guessing that this idea of splitting a protocol from its class has bled into Squeak from Objective-C in the form of Traits. Casimiro must have a reason for using them that he likes. But they do seem like a workaround as a result of a shallow hierarchy. I think I'd rather create my own abstract superclass to define an interface. Chris [1] http://www.metaobject.com/downloads/Squeak/ [2] "Masterminds Of Programming" (2009) O'Reilly, pg. 258-260. Brad Cox quotes: "Inheritance just isn't all that important. Encapsulation is OOP's lasting contribution." "Smalltalk didn't have anything like protocol in those days and that was added by Steve Naroff, who is now in charge of the Objective-C at Apple." "At first I used inheritance heavily, experimenting to find its bounds. Then I realized that encapsulation was the real contribution of OOP and that it could be used manually to do almost everything I'd been using inheritance for, but more cleanly." |
On 12 October 2012 17:21, Chris Cunnington
<[hidden email]> wrote: > I've been looking at MetaObjects's [1] decade old implementation of the vm > in Cocoa. It has a class called SqueakInterpreter.h that defines a protocol > that is used in SqView. The selectors are listed in SqueakInterpreter.h but > implemented in SqView.m. I believe this kind of thing is now called a > category in Objective-C-ese. And I was wondering why somebody would do this? > We don't separate the protocols from the classes in Smalltalk. And I think > the reason is we use abstract superclasses. And we have deep user developed > hierarchies. Protocols allow you to say "these messages, unrelated by inheritance, nevertheless both understand these sets of messages". That's very handy, because sometimes you can't or don't want an inheritance relationship between the two classes. Perhaps the classes both come from 3rd party libraries, and you're writing something that should be able to operate on both, and want to express that in THIS LIMITED way, the classes are similar. frank > Chris |
On 12-10-12 12:26 PM, Frank Shearar wrote:
> On 12 October 2012 17:21, Chris Cunnington > <[hidden email]> wrote: >> I've been looking at MetaObjects's [1] decade old implementation of the vm >> in Cocoa. It has a class called SqueakInterpreter.h that defines a protocol >> that is used in SqView. The selectors are listed in SqueakInterpreter.h but >> implemented in SqView.m. I believe this kind of thing is now called a >> category in Objective-C-ese. And I was wondering why somebody would do this? >> We don't separate the protocols from the classes in Smalltalk. And I think >> the reason is we use abstract superclasses. And we have deep user developed >> hierarchies. > Protocols allow you to say "these messages, unrelated by inheritance, > nevertheless both understand these sets of messages". understand messages. Objects do. "These objects, unrelated by inheritance, nevertheless both understand these sets of messages." Perhaps? > That's very > handy, because sometimes you can't or don't want an inheritance > relationship between the two classes. > > Perhaps the classes both come from 3rd party libraries, and you're > writing something that should be able to operate on both, and want to > express that in THIS LIMITED way, the classes are similar. > Yea, that makes sense. And it's illustrated by the vm source I've been looking at. SqueakInterpreter.h is going to be the same no matter the platform. The implementation in the view class will depend on the operating system. I think there's a lot of that going on in SqueakPureObjc.xcodeproj vm code with categories like: sqSqueakOSXApplication+imageReadWrite.m sqSqueakOSXApplication+events.m sqSqueakOSXApplication+attributes.m sqSqueakOSXApplication+cursor.m That makes your point, I think. So what we're talking about is scale. "Few people" using a code base as opposed to "many people". Now that you say it, I suppose Cincom address this because they make an enterprise Smalltalk. And I guess namespaces come into this domain of many users. Chris |
In reply to this post by Chris Cunnington
On Fri, Oct 12, 2012 at 9:21 AM, Chris Cunnington
<[hidden email]> wrote: > And so I'm guessing that this idea of splitting a protocol from its class > has bled into Squeak from Objective-C in the form of Traits. Casimiro must > have a reason for using them that he likes. But they do seem like a > workaround as a result of a shallow hierarchy. I think I'd rather create my > own abstract superclass to define an interface. You might find this interesting: http://www.jot.fm/issues/issue_2002_05/article1/ It's a paper about SmallInterfaces, which created first-class interfaces (in Java parlance) for Smalltalk. There was a Squeak port that ran in Squeak 3.2 IIRC. I find it much more fruitful to think about protocols rather than classes when designing or analyzing OO systems. This fits in nicely with what you said about composition being better than inheritance. But there are a few issues with a protocol-centric view in Smalltalk: One is that we don't really need formal protocols the way Java or Objective-C do, because of the flexibility of Smalltalk. Objective-C uses protocols to allow classes to be extended even when you don't have the source code to the object that you're extending. Java uses interfaces to allow polymorphism between classes that aren't related by inheritance. In both cases, formalized protocols work around a problem caused by the mechanics of the language or it's tools. In Smalltalk, doing everything in-image, we don't have those problems. Given that protocol-oriented programming is so good, it would be nice to have better support for that mode of thinking. I bet, for example, that there's a latent "Map" protocol in the image, which is a subset of the methods that Dictionary implements. It's #at: and #at:put: plus a few other supporting methods, but *not* the whole protocol implemented by Dictionary and certainly not all the stuff it inherits from Collection. I'd love to see a tool that would let us discover these latent protocols, name them, and then view and manipulate the system based on them. Colin |
In reply to this post by Chris Cunnington
On 12 October 2012 17:42, Chris Cunnington
<[hidden email]> wrote: > On 12-10-12 12:26 PM, Frank Shearar wrote: >> >> On 12 October 2012 17:21, Chris Cunnington >> <[hidden email]> wrote: >>> >>> I've been looking at MetaObjects's [1] decade old implementation of the >>> vm >>> in Cocoa. It has a class called SqueakInterpreter.h that defines a >>> protocol >>> that is used in SqView. The selectors are listed in SqueakInterpreter.h >>> but >>> implemented in SqView.m. I believe this kind of thing is now called a >>> category in Objective-C-ese. And I was wondering why somebody would do >>> this? >>> We don't separate the protocols from the classes in Smalltalk. And I >>> think >>> the reason is we use abstract superclasses. And we have deep user >>> developed >>> hierarchies. >> >> Protocols allow you to say "these messages, unrelated by inheritance, >> nevertheless both understand these sets of messages". > > There's something dicey about this wording, I feel. Messages don't > understand messages. Objects do. "These objects, unrelated by inheritance, > nevertheless both understand these sets of messages." Perhaps? Er yes, that's what I had _meant_ to type. (But of course Message instances are objects, and understand messages :) ) frank |
On Fri, Oct 12, 2012 at 2:27 PM, Frank Shearar <[hidden email]> wrote: Absolutely. I knew there was a wrinkle I wasn't seeing. :)On 12 October 2012 17:42, Chris Cunnington Chris |
In reply to this post by Colin Putney-3
On 12-10-12 1:37 PM, Colin Putney wrote:
> On Fri, Oct 12, 2012 at 9:21 AM, Chris Cunnington > <[hidden email]> wrote: > >> And so I'm guessing that this idea of splitting a protocol from its class >> has bled into Squeak from Objective-C in the form of Traits. Casimiro must >> have a reason for using them that he likes. But they do seem like a >> workaround as a result of a shallow hierarchy. I think I'd rather create my >> own abstract superclass to define an interface. > You might find this interesting: > > http://www.jot.fm/issues/issue_2002_05/article1/ > > It's a paper about SmallInterfaces, which created first-class > interfaces (in Java parlance) for Smalltalk. There was a Squeak port > that ran in Squeak 3.2 IIRC. again in a few days to get a better idea. > > I find it much more fruitful to think about protocols rather than > classes when designing or analyzing OO systems. Hmm. That's interesting. > This fits in nicely > with what you said about composition being better than inheritance. > But there are a few issues with a protocol-centric view in Smalltalk: > > One is that we don't really need formal protocols the way Java or > Objective-C do, because of the flexibility of Smalltalk. Objective-C > uses protocols to allow classes to be extended even when you don't > have the source code to the object that you're extending. That's a good point. They are a bit more restricted. > Java uses > interfaces to allow polymorphism between classes that aren't related > by inheritance. In both cases, formalized protocols work around a > problem caused by the mechanics of the language or it's tools. In > Smalltalk, doing everything in-image, we don't have those problems. > > Given that protocol-oriented programming is so good, it would be nice > to have better support for that mode of thinking. I bet, for example, > that there's a latent "Map" protocol in the image, which is a subset > of the methods that Dictionary implements. It's #at: and #at:put: plus > a few other supporting methods, but *not* the whole protocol > implemented by Dictionary and certainly not all the stuff it inherits > from Collection. I'd love to see a tool that would let us discover > these latent protocols, name them, and then view and manipulate the > system based on them. to that is studying old images (i.e. 2.7) and comparing them to today. What kind of criteria would such a tool use? <Spock>Fascinating.</Spock> Chris |
On Fri, Oct 12, 2012 at 1:02 PM, Chris Cunnington
<[hidden email]> wrote: >> I'd love to see a tool that would let us discover >> these latent protocols, name them, and then view and manipulate the >> system based on them. > > An automated code archaeologist? The only thing I can think of similar to > that is studying old images (i.e. 2.7) and comparing them to today. What > kind of criteria would such a tool use? <Spock>Fascinating.</Spock> Well, I'm imagining something a bit like a type inference tool. But instead of figuring out what the concrete classes of receivers are, it would just collect a list of messages that get sent to it. So imagine that we pick a class at (pseudo) random, say ChangeSet, and focus on one of its variables, say 'structures'. If we look at all the methods of ChangeSet, we can see what messages get sent to 'structures'. Here's the list methods that use 'structures': ChangeSet >> noteClassForgotten: ChangeSet >> noteClassStructure: ChangeSet >> structures ChangeSet >> askAddedInstVars: ChangeSet >> askRenames:addTo:using: ChangeSet >> askRemovedInstVars: ChangeSet >> checkForConversionMethods ChangeSet >> absorbStructureOfClass:from: #noteClassForgotten: sends the following messages to 'structures': #ifNil: #includesKey: #removeKey:ifAbsent: #noteClassStructure sends these messages: #ifNil: #includesKey: #at:put: So we've got a little histogram of messages: #ifNil: - 2 #includesKey: - 2 #removeKey:ifAbsent: - 1 #at:put: - 1 And we can continue on down the list of ChangeSet's methods building up our statistical database. We could do the same thing with temporary variables, and even expressions that never get stored into a variable, but do get sent messages. A type inference tool would compare the sets of messages that an object receives to the actual classes in the image and try to figure out which classes it could be an instance of. What this protocol tool would do differently is ignore the actual classes in the image, and instead try to find patterns in the message sends, and try to shed light on programmer intent. So we might ask, what other messages are associated with #includesKey:, and how strong is the association? What's the largest set of methods that are sent to at least 95% of objects that receive #includesKey:? What objects fall into the other 5%? There would probably be a lot of noise in the data - #ifNil:, for example, might confuse things a bit. But I bet there's a lot of signal as well, and with a bit of direction from the user, that sort of tool might be able point out, for example, a class that almost implements the Magnitude protocol, but is missing a couple of methods. Anyway, thanks for bringing up this topic. It's interesting stuff. Colin |
On 12 October 2012 23:09, Colin Putney <[hidden email]> wrote:
> On Fri, Oct 12, 2012 at 1:02 PM, Chris Cunnington > <[hidden email]> wrote: >>> I'd love to see a tool that would let us discover >>> these latent protocols, name them, and then view and manipulate the >>> system based on them. >> >> An automated code archaeologist? The only thing I can think of similar to >> that is studying old images (i.e. 2.7) and comparing them to today. What >> kind of criteria would such a tool use? <Spock>Fascinating.</Spock> > > Well, I'm imagining something a bit like a type inference tool. But > instead of figuring out what the concrete classes of receivers are, it > would just collect a list of messages that get sent to it. > > So imagine that we pick a class at (pseudo) random, say ChangeSet, and > focus on one of its variables, say 'structures'. If we look at all the > methods of ChangeSet, we can see what messages get sent to > 'structures'. Here's the list methods that use 'structures': > > ChangeSet >> noteClassForgotten: > ChangeSet >> noteClassStructure: > ChangeSet >> structures > ChangeSet >> askAddedInstVars: > ChangeSet >> askRenames:addTo:using: > ChangeSet >> askRemovedInstVars: > ChangeSet >> checkForConversionMethods > ChangeSet >> absorbStructureOfClass:from: > > #noteClassForgotten: sends the following messages to 'structures': > > #ifNil: > #includesKey: > #removeKey:ifAbsent: > > #noteClassStructure sends these messages: > > #ifNil: > #includesKey: > #at:put: > > So we've got a little histogram of messages: > > #ifNil: - 2 > #includesKey: - 2 > #removeKey:ifAbsent: - 1 > #at:put: - 1 > > And we can continue on down the list of ChangeSet's methods building > up our statistical database. We could do the same thing with temporary > variables, and even expressions that never get stored into a variable, > but do get sent messages. > > A type inference tool would compare the sets of messages that an > object receives to the actual classes in the image and try to figure > out which classes it could be an instance of. http://www.squeaksource.com/SqueakCheck does exactly this: given a Theory (an arity 1 method on a TheoryTestCase marked with the <theory> pragma), it finds all messages sent to the Theory's argument (call it foo), and to foo class. It then finds all possible Class types that match that protocol, and uses those classes as seeds for generating random data to throw at the Theory. > What this protocol tool > would do differently is ignore the actual classes in the image, and > instead try to find patterns in the message sends, and try to shed > light on programmer intent. So we might ask, what other messages are > associated with #includesKey:, and how strong is the association? > What's the largest set of methods that are sent to at least 95% of > objects that receive #includesKey:? What objects fall into the other > 5%? This is a much more complicated/difficult problem than what SqueakCheck tries to do. > There would probably be a lot of noise in the data - #ifNil:, for > example, might confuse things a bit. But I bet there's a lot of signal > as well, and with a bit of direction from the user, that sort of tool > might be able point out, for example, a class that almost implements > the Magnitude protocol, but is missing a couple of methods. I wonder if some of the natural language tools can't help here: I'm thinking things like bigram/trigram models and the like. My brain's just melted from being up too late. There's another probabilistic tool that can divide up high dimensional spaces to maximise differences in data points. If I remember the name I'll mention it :/ frank > Anyway, thanks for bringing up this topic. It's interesting stuff. > > Colin > |
In reply to this post by Colin Putney-3
On 12 October 2012 19:37, Colin Putney <[hidden email]> wrote:
> On Fri, Oct 12, 2012 at 9:21 AM, Chris Cunnington > <[hidden email]> wrote: > >> And so I'm guessing that this idea of splitting a protocol from its class >> has bled into Squeak from Objective-C in the form of Traits. Casimiro must >> have a reason for using them that he likes. But they do seem like a >> workaround as a result of a shallow hierarchy. I think I'd rather create my >> own abstract superclass to define an interface. > > You might find this interesting: > > http://www.jot.fm/issues/issue_2002_05/article1/ > > It's a paper about SmallInterfaces, which created first-class > interfaces (in Java parlance) for Smalltalk. There was a Squeak port > that ran in Squeak 3.2 IIRC. > > I find it much more fruitful to think about protocols rather than > classes when designing or analyzing OO systems. Same here. I think i even have class or two who serving just for documentation purposes, i.e. having no much sense to be inherited from, but just indicate what protocol(s) should be used for interacting with such kind of objects. Today, i base my design on protocols and roles. By role i mean any object at some certain place, and that place (method argument, instance variable etc), defines what protocol(s) a given role should conform to. The inheritance is relevant only when you need polymorphism and to reuse (inherit) large amount of common code, which every subclass should (or can) use. -- Best regards, Igor Stasenko. |
Free forum by Nabble | Edit this page |