Th¡¡
El 8 sept 2019, a las 23:48, Torsten Bergmann <astares@gmx.de> escribió:
Hi,
I'm not too deep in the CDSlotNode and related - but I wonder why we need the specific #=> selector and
slotName => Definition
mapping form in the definition at all. What are the benefits of the additional "=>" style ?
To me it looks not very natural to write:
#id => InstanceVariable.
or other specific forms. The custom subclasses of class "Slot" are already inheriting the "name" iVar for the slotName. So using the additional slotName in the definition is
- disrupting the slot name from other arguments - redundant if the slot creation should have the name as well
Why not use just the plain slot object by creating it directly with a class message? We can just use custom class side instantiation methods for the slots including the name like
#named: #named:type: #named:type:default: ... or other. I mean #=> dispatches to #named: on the slot anyway.
If we define the class / slot objects like this:
Object subclass: #MyTask slots: { BOInstanceVariableSlot named: #'id'. #anotherIVar. BOTypedSlot named: #'description' type: String. BOAttributeSlot named: #'isDone' type: Boolean default: true. BOAttributeSlot named: #'created' type: Date default: [ Date today ] } classVariables: { } package: 'CustomSlots-Definitions-Examples'
is more natural than the => forms where the name is just disrupted from the other arguments. The attached file out from a Pharo 8 example demonstrates this.
Just file it in and have a look at class MyTask or inspect "MyTask new created" or "MyTask new created: 2" to see that the implemented simple slot typing and defaults are working.
Then look at the definition of #MyTask class, which looks like written above. It could be made even more readable using
Object subclass: #MyTaskEvenEasier slots: { BOAttributeSlot named: #'id'. BOAttributeSlot named: #'anotherIVar'. BOAttributeSlot named: #'description' type: String. BOAttributeSlot named: #'isDone' type: Boolean default: true. BOAttributeSlot named: #'created' type: Date default: [ Date today ] } classVariables: { } package: 'CustomSlots-Definitions-Examples'
only.
The benefits without the => indirection are: - a simple, compact and easy readable class definition even when slots are used - slot definitions are regular messages to the slot class - simply evaluate or inspect the full slot class side message - we keep the possibility to mix slots with other instance variables (here #anotherIVar in the example by using the symbol) - we keep the possibility to evaluate the full slots definition and check the array of their definition - we unify the definition with the "MyClass slots" message - as both are just return the array of slot objects - we do not rely on an additional specific definition API one has to remember
To me there is a drawback on this: even though being a message send is actually more flexible, arbitrary messages can be hard to cope with by tools. For example, if we want to validate if a slot definition is valid before loading it (e.g., if its class exists), we need to identify the slot kind/class from that message send. The same happens with the slot name. If someone defines a slot as MySlot new name: #asd. or MySlot withName: #asd. tools will just be much harder to implement Although this can be helped by strong name conventions (i.e., always a slot definition is a message send, always the receiver is a class, always the first keyword is #named: ?, all args are literal). ^^
So where is the real value in the often used additional indirection of the => message in slot definitions?
Thanks T. <CustomSlots-Definitions.st>