<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">2013/12/23 Levente Uzonyi <span dir="ltr"><<a href="mailto:leves@elte.hu" target="_blank">leves@elte.hu</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Sun, 22 Dec 2013, Chris Muller wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
So here is another correct example of CPM when more than one variable<br>
needs initialized.<br>
<br>
Your home-brew version of CPM does the same thing, but it 1) violates<br>
the rule to say things once and only once, 2) has #initialize getting<br>
called from any of half-a-dozen places rather than the ONE place, 3)<br>
doesn't factor the behavior of simply *constructing* a _well-formed<br>
object_ from the behavior of fully initializing it (i.e.., building up<br>
a large cache).<br>
</blockquote>
<br></div>
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.<br>
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).<br>
<br>
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.<span class="HOEnZb"><font color="#888888"><br>
<br></font></span></blockquote><div><br></div><div></div><div>An example is Point. Point x: 4 y: 5 will send basicNew, not new.<br></div><div>Point does not define an initialize method. Well it could initialize x:=y:=0; but it doesn't.<br>
</div><div>Indeed, why would a point initialize x:=y:=0 to immediately change the values?<br>Initializing twice would just be a useless slowdown and is considered as an anti-pattern.</div><div>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:<br>
</div><div><br></div><div>Nicolas<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="HOEnZb"><font color="#888888">
<br>
Levente<br>
</font></span><br>
P.S.: AFAIK #initialize is a "new concept", which was not part of ST-80.<br>
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.<br>
P.P.P.S.: Most Smalltalkers dislike the #set* methods for some reason.<div class="HOEnZb"><div class="h5"><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
1) each class that declares instance variables has exactly one<br>
initialization method<br>
</blockquote>
<br>
Well then you can't have more than one constructor type then. Not all<br>
objects can follow a path down to a single constructor on the<br>
class-side that ends up calling #initializeWtih:...<br>
</blockquote>
<br>
Why not? I've never found this to be an issue.<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
In several cases,<br>
you'll need #initializeWithThis: and #initializeWithThat:. And, in<br>
both cases, you want to call #initialize from the top of them. That's<br>
repeating yourself and unconventional.<br>
</blockquote>
<br>
Right. That's why the rule is one initializer.<br>
</blockquote>
<br>
What is an "initializer?" Is that an #initialize method or an<br>
#initializeWith... method? If the former, it makes no sense to say<br>
it's a rule to only have one because that's all you COULD have. If<br>
the latter, you're contradicting yourself in the above paragraph.<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
2) each initialization method must leave the instance in a valid state<br>
</blockquote>
<br>
Of course, as does any initialization method like CPM methods.<br>
</blockquote>
<br>
Not so. If your class has ivars 'foo' and 'bar' and it needs both of them to<br>
have values for the object to be valid, then neither #setFoo: nor #setBar:<br>
leave the object in a valid state. You have to call both of them to get a<br>
fully-initialized object. But #initializeWithFoo:bar: leaves the object in a<br>
valid state.<br>
</blockquote>
<br>
The above makes it very clear you haven't read CPM.<br>
<br>
That's why I've committed this change, as second example of CPM<br>
showing it does the same thing, but without repeating itself and<br>
without the other issues associated with the home-brew version.<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
3) each initialization method is named verbosely starting with<br>
'initializeWith' and describes its parameters<br>
</blockquote>
<br>
The ONLY reason you call it "initializeWithThis:that:<u></u>other:thing:"<br>
instead of "setThis:that:other:thing:" is because you want to repeat<br>
yourself by calling #initalize at the top of each method.<br>
</blockquote>
<br>
The reason to call it #initializeWithThis:that: is that it initializes the<br>
object with this and that. If you like consider this an instance of<br>
"intention-revealing selector".<br>
</blockquote>
<br>
But what if I ONLY want a minimally well-formed instance, (e.g.,<br>
minimum number of inst-vars set to make a well-formed instance, but<br>
not, say, 'cache' variables which are derived from the minimum vars --<br>
CPM does the minimum, initializeWith:... implies to build the cache as<br>
well).<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
6) there is one or more class-side constructors which send #basicNew and<br>
the<br>
initialization message<br>
</blockquote>
<br>
Why basicNew instead of new? Honestly, there's no good reason for<br>
that and it forces you to repeat yourself in all of your<br>
#initializeWith: methods.<br>
</blockquote>
<br>
Because #new calls #initialize. When following this pattern, #initialize<br>
still gets called, but by a subclass initializer, not by the constructor. We<br>
want to avoid calling #initialize twice.<br>
</blockquote>
<br>
Exactly. You've articulated one of the problems with your home-brew<br>
CPM. You're doing this unnecessary dance with calling #basicNew and<br>
#initialize yourself when all you need to say is, simply, #new.<br>
That's a definite regression of CPM.<br>
<br>
On Sun, Dec 22, 2013 at 11:23 AM, <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Chris Muller uploaded a new version of Environments to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Environments-cmm.38.mcz" target="_blank">http://source.squeak.org/<u></u>trunk/Environments-cmm.38.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Environments-cmm.38<br>
Author: cmm<br>
Time: 22 December 2013, 11:23:45.064 am<br>
UUID: bcae5b17-4e55-4b16-be84-<u></u>90fc1e283ae4<br>
Ancestors: Environments-cmm.37<br>
<br>
Use proper implementation of Constructor Parameter Method.<br>
<br>
=============== Diff against Environments-cmm.37 ===============<br>
<br>
Item was changed:<br>
----- Method: EnvironmentInfo class>>name:organization:<u></u>packages: (in category 'as yet unclassified') -----<br>
name: aString organization: aSystemOrganizer packages: aPackageOrganizer<br>
+ ^ self new<br>
+ setName: aString<br>
- ^ self basicNew<br>
- initializeWithName: aString<br>
organization: aSystemOrganizer<br>
packages: aPackageOrganizer!<br>
<br>
Item was removed:<br>
- ----- Method: EnvironmentInfo>><u></u>initializeWithName:<u></u>organization:packages: (in category 'as yet unclassified') -----<br>
- initializeWithName: aString organization: aSystemOrganizer packages: aPackageOrganizer<br>
- self initialize.<br>
- name := aString.<br>
- organization := aSystemOrganizer.<br>
- packages := aPackageOrganizer.<br>
- !<br>
<br>
Item was changed:<br>
+ ----- Method: EnvironmentInfo>>name (in category 'access') -----<br>
- ----- Method: EnvironmentInfo>>name (in category 'as yet unclassified') -----<br>
name<br>
^ name!<br>
<br>
Item was changed:<br>
+ ----- Method: EnvironmentInfo>>organization (in category 'access') -----<br>
- ----- Method: EnvironmentInfo>>organization (in category 'as yet unclassified') -----<br>
organization<br>
^ organization!<br>
<br>
Item was changed:<br>
+ ----- Method: EnvironmentInfo>>packages (in category 'access') -----<br>
- ----- Method: EnvironmentInfo>>packages (in category 'as yet unclassified') -----<br>
packages<br>
^ packages!<br>
<br>
Item was changed:<br>
+ ----- Method: EnvironmentInfo>>printOn: (in category 'printing') -----<br>
- ----- Method: EnvironmentInfo>>printOn: (in category 'as yet unclassified') -----<br>
printOn: aStream<br>
aStream nextPutAll: name.<br>
aStream nextPutAll: 'Info'!<br>
<br>
Item was added:<br>
+ ----- Method: EnvironmentInfo>>setName:<u></u>organization:packages: (in category 'initialize-release') -----<br>
+ setName: aString organization: aSystemOrganizer packages: aPackageOrganizer<br>
+ name := aString.<br>
+ organization := aSystemOrganizer.<br>
+ packages := aPackageOrganizer!<br>
<br>
<br>
</blockquote>
<br>
<br>
</blockquote>
<br>
</div></div></blockquote></div><br></div></div>