On Dec 28, 2009, at 12:39 , Igor Stasenko wrote:
2009/12/28 Stéphane Ducasse <stephane.ducasse@inria.fr>:
Package Classes Methods Traits 59 873 Traits-Kernel 22 343 Traits-Kernel-Traits 17 215 Traits-Composition 7 127 NanoTraits-Kernel 9 190 NanoTraits-Tests 9 122
Haha. This table is nonsense: - The package "Traits" includes "Traits-Kernel", "Traits-Composition" etc. so it is counting the same classes and methods twice - The numbers are from an older implementation of Traits. In Pharo there is a refactored version with less traits that is easier to understand. Squeak has an old version. - Methods defined in the traits ("Traits-Kernel-Traits") are also used by Behavior, ClassDescription, etc. hence making these classes smaller in turn (but the table does not show this fact) - The requires algorithm is not directly related to Traits (as I pointed out in a recent mail) In a Pharo 1.0 image I get Package Classes Methods Traits-Kernel 11 343 Traits-Kernel-Traits 6 215 Traits-Composition 7 122 [...]
Igor please rephrase your thoughts! :) amount of complexity !!! not amount of code!!! Come on number of classes is not a decent measure in presence of late binding!
hehe.. i hope that Andreas writing short methods, not a fat ones which trying to do everything at once :)
Not sure about this. I browsed through the NanoTraits code for 2 minutes, and one thing that puzzled me was this method: !ClassDescription methodsFor: '*NanoTraits-Extensions' stamp: 'ar 12/20/2009 13:38'! installTraitsFrom: aTraitComposition "Install the traits from the given composition" | allTraits methods oldMethod removals oldCategories | (aTraitComposition isKindOf: NanoTraitComposition) ifFalse:[self error: 'Invalid composition']. (self traitComposition isEmpty and: [aTraitComposition isEmpty]) ifTrue: [^self]. "Check for cycles" allTraits := aTraitComposition gather: [:t | t allTraits copyWith: t]. (allTraits includes: self) ifTrue:[^self error: 'Cyclic trait definition detected']. "XXXX: addUser/removeUser should be part of setter, but subclass override prevents it until we've got rid of Traits mess." self traitComposition removeTraitUser: self. self traitComposition: aTraitComposition. aTraitComposition addTraitUser: self. "Assemble the methods in a new dictionary first. Uses a Dictionary instead of a MethodDictionary for speed (MDs grow by #become:)" methods := Dictionary new. "Stick in the local methods first, since this avoids generating conflict methods unnecessarily" self selectorsAndMethodsDo:[:sel :newMethod| (self isLocalMethod: newMethod) ifTrue:[methods at: sel put:newMethod]]. "Now assemble the traits methods" aTraitComposition do:[:trait| trait selectorsAndMethodsDo:[:sel :newMethod| oldMethod := methods at: sel ifAbsentPut:[newMethod]. newMethod == oldMethod ifFalse:["a conflict" (self isLocalMethod: oldMethod) ifFalse:[ methods at: sel put: (self resolveTraitsConflict: sel from: oldMethod to: newMethod). ]. ]. ]. ]. "Apply the changes. We first add the new or changed methods." oldCategories := Set new. methods keysAndValuesDo:[:sel :newMethod| oldMethod := self compiledMethodAt: sel ifAbsent:[nil]. oldMethod == newMethod ifFalse:[ self traitAddSelector: sel withMethod: newMethod. (self organization categoryOfElement: sel) ifNotNil:[:cat| oldCategories add: cat]. self organization classify: sel under: (newMethod methodHome organization categoryOfElement: newMethod selector). ]]. "Now remove the old or obsoleted ones" removals := OrderedCollection new. self selectorsDo:[:sel| (methods includesKey: sel) ifFalse:[removals add: sel]]. removals do:[:sel| self traitRemoveSelector: sel]. "Clean out empty categories" oldCategories do:[:cat| (self organization isEmptyCategoryNamed: cat) ifTrue:[self organization removeCategory: cat]]. self isMeta ifFalse:[self class updateTraitsFrom: aTraitComposition].! ! Not that it bothers me... Andreas is free to do what he likes in his Squeak ;) Cheers, Adrian