[squeak-dev] The Trunk: Environments-cmm.38.mcz

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Mon Dec 23 09:10:13 UTC 2013


2013/12/23 Levente Uzonyi <leves at elte.hu>

> On Sun, 22 Dec 2013, Chris Muller wrote:
>
>  So here is another correct example of CPM when more than one variable
>> needs initialized.
>>
>> Your home-brew version of CPM does the same thing, but it 1) violates
>> the rule to say things once and only once, 2) has #initialize getting
>> called from any of half-a-dozen places rather than the ONE place, 3)
>> doesn't factor the behavior of simply *constructing* a _well-formed
>> object_ from the behavior of fully initializing it (i.e.., building up
>> a large cache).
>>
>
> If you follow this pattern, then #initialize will become a lie, because
> it's not initializing anything. You do the actual initialization in the
> #set* methods.
> Also your third point applies to this CPM method (or what) too, because
> #new will not create a _well-formed object_, the #set* methods will do
> that. (Yes, there are cases when an object without being initialized _with
> a parameter_ is not a well-formed object).
>
> You're thinking more into #initialize than what it actually is. It's
> nothing more than a hook, which is usually called when an object is
> created, but there are no guarantees. I may override #new whenever I want,
> or I might call #basicNew. I'm sure there are plenty of classes in the
> current Trunk, which don't use #initialize at all.
>
>
An example is Point. Point x: 4 y: 5 will send basicNew, not new.
Point does not define an initialize method. Well it could initialize
x:=y:=0; but it doesn't.
Indeed, why would a point initialize x:=y:=0 to immediately change the
values?
Initializing twice would just be a useless slowdown and is considered as an
anti-pattern.
So Chris, please let us the freedom to not use set, and let instances be
initialized by a single method, not a useless two phases
(new->initialize)setThis:andThat:

Nicolas


>
> Levente
>
> P.S.: AFAIK #initialize is a "new concept", which was not part of ST-80.
> P.P.S.: Just because someone (Kent Beck in this case) is doing something
> differently than you, it doesn't mean it's better than what you do.
> P.P.P.S.: Most Smalltalkers dislike the #set* methods for some reason.
>
>
>>  1) each class that declares instance variables has exactly one
>>>>> initialization method
>>>>>
>>>>
>>>> Well then you can't have more than one constructor type then.  Not all
>>>> objects can follow a path down to a single constructor on the
>>>> class-side that ends up calling #initializeWtih:...
>>>>
>>>
>>> Why not? I've never found this to be an issue.
>>>
>>>
>>>> In several cases,
>>>> you'll need #initializeWithThis: and #initializeWithThat:.  And, in
>>>> both cases, you want to call #initialize from the top of them.  That's
>>>> repeating yourself and unconventional.
>>>>
>>>
>>> Right. That's why the rule is one initializer.
>>>
>>
>> What is an "initializer?"  Is that an #initialize method or an
>> #initializeWith... method?  If the former, it makes no sense to say
>> it's a rule to only have one because that's all you COULD have.  If
>> the latter, you're contradicting yourself in the above paragraph.
>>
>>  2) each initialization method must leave the instance in a valid state
>>>>>
>>>>
>>>> Of course, as does any initialization method like CPM methods.
>>>>
>>>
>>> Not so. If your class has ivars 'foo' and 'bar' and it needs both of
>>> them to
>>> have values for the object to be valid, then neither #setFoo: nor
>>> #setBar:
>>> leave the object in a valid state. You have to call both of them to get a
>>> fully-initialized object. But #initializeWithFoo:bar: leaves the object
>>> in a
>>> valid state.
>>>
>>
>> The above makes it very clear you haven't read CPM.
>>
>> That's why I've committed this change, as second example of CPM
>> showing it does the same thing, but without repeating itself and
>> without the other issues associated with the home-brew version.
>>
>>  3) each initialization method is named verbosely starting with
>>>>> 'initializeWith' and describes its parameters
>>>>>
>>>>
>>>> The ONLY reason you call it "initializeWithThis:that:other:thing:"
>>>> instead of "setThis:that:other:thing:" is because you want to repeat
>>>> yourself by calling #initalize at the top of each method.
>>>>
>>>
>>> The reason to call it #initializeWithThis:that: is that it initializes
>>> the
>>> object with this and that. If you like consider this an instance of
>>> "intention-revealing selector".
>>>
>>
>> But what if I ONLY want a minimally well-formed instance, (e.g.,
>> minimum number of inst-vars set to make a well-formed instance, but
>> not, say, 'cache' variables which are derived from the minimum vars --
>> CPM does the minimum, initializeWith:... implies to build the cache as
>> well).
>>
>>  6) there is one or more class-side constructors which send #basicNew and
>>>>> the
>>>>> initialization message
>>>>>
>>>>
>>>> Why basicNew instead of new?  Honestly, there's no good reason for
>>>> that and it forces you to repeat yourself in all of your
>>>> #initializeWith: methods.
>>>>
>>>
>>> Because #new calls #initialize. When following this pattern, #initialize
>>> still gets called, but by a subclass initializer, not by the
>>> constructor. We
>>> want to avoid calling #initialize twice.
>>>
>>
>> Exactly.  You've articulated one of the problems with your home-brew
>> CPM.  You're doing this unnecessary dance with calling #basicNew and
>> #initialize yourself when all you need to say is, simply, #new.
>> That's a definite regression of CPM.
>>
>> On Sun, Dec 22, 2013 at 11:23 AM,  <commits at source.squeak.org> wrote:
>>
>>> Chris Muller uploaded a new version of Environments to project The Trunk:
>>> http://source.squeak.org/trunk/Environments-cmm.38.mcz
>>>
>>> ==================== Summary ====================
>>>
>>> Name: Environments-cmm.38
>>> Author: cmm
>>> Time: 22 December 2013, 11:23:45.064 am
>>> UUID: bcae5b17-4e55-4b16-be84-90fc1e283ae4
>>> Ancestors: Environments-cmm.37
>>>
>>> Use proper implementation of Constructor Parameter Method.
>>>
>>> =============== Diff against Environments-cmm.37 ===============
>>>
>>> Item was changed:
>>>   ----- Method: EnvironmentInfo class>>name:organization:packages: (in
>>> category 'as yet unclassified') -----
>>>   name: aString organization: aSystemOrganizer packages:
>>> aPackageOrganizer
>>> +       ^ self new
>>> +               setName: aString
>>> -       ^ self basicNew
>>> -               initializeWithName: aString
>>>                 organization: aSystemOrganizer
>>>                 packages: aPackageOrganizer!
>>>
>>> Item was removed:
>>> - ----- Method: EnvironmentInfo>>initializeWithName:organization:packages:
>>> (in category 'as yet unclassified') -----
>>> - initializeWithName: aString organization: aSystemOrganizer packages:
>>> aPackageOrganizer
>>> -       self initialize.
>>> -       name := aString.
>>> -       organization := aSystemOrganizer.
>>> -       packages := aPackageOrganizer.
>>> -       !
>>>
>>> Item was changed:
>>> + ----- Method: EnvironmentInfo>>name (in category 'access') -----
>>> - ----- Method: EnvironmentInfo>>name (in category 'as yet
>>> unclassified') -----
>>>   name
>>>         ^ name!
>>>
>>> Item was changed:
>>> + ----- Method: EnvironmentInfo>>organization (in category 'access')
>>> -----
>>> - ----- Method: EnvironmentInfo>>organization (in category 'as yet
>>> unclassified') -----
>>>   organization
>>>         ^ organization!
>>>
>>> Item was changed:
>>> + ----- Method: EnvironmentInfo>>packages (in category 'access') -----
>>> - ----- Method: EnvironmentInfo>>packages (in category 'as yet
>>> unclassified') -----
>>>   packages
>>>         ^ packages!
>>>
>>> Item was changed:
>>> + ----- Method: EnvironmentInfo>>printOn: (in category 'printing') -----
>>> - ----- Method: EnvironmentInfo>>printOn: (in category 'as yet
>>> unclassified') -----
>>>   printOn: aStream
>>>         aStream nextPutAll: name.
>>>         aStream nextPutAll: 'Info'!
>>>
>>> Item was added:
>>> + ----- Method: EnvironmentInfo>>setName:organization:packages: (in
>>> category 'initialize-release') -----
>>> + setName: aString organization: aSystemOrganizer packages:
>>> aPackageOrganizer
>>> +       name := aString.
>>> +       organization := aSystemOrganizer.
>>> +       packages := aPackageOrganizer!
>>>
>>>
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20131223/c4010b12/attachment.htm


More information about the Squeak-dev mailing list