<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">
Thank you Ramon for your well thought out explanation. It helps a lot. Your "Tsunami" package sounds exactly what Sophie and I *thought* we wanted, but now after gaining your insights, it's probably not the way to go. Still, it sounds like Tsunami is a great technical achievement and could be used in other ways in the future. As an aside, you might want to copy some of your previous reply and paste it into the general description of Tsunami on SqueakSource so that the casual passer-by can weigh the pros and cons of the technique.<div><br class="webkit-block-placeholder"></div><div>I have to ask this next question, let's reconsider the code snippet you offered:</div><div><br><div><div>On Dec 24, 2007, at 2:39 AM, Ramon Leon wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica">name</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica"><span class="Apple-converted-space">    </span>^name</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"><br></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica">name: aName</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica"><span class="Apple-converted-space">    </span>self testName: aName.</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica"><span class="Apple-converted-space">    </span>set doSetName: aName.</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"><br></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica">testName: aName</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica"><span class="Apple-converted-space">    </span>"throw exceptions for business rule violations"</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"><br></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica">doSetName: aName</font></p> <p style="margin: 0.0px 0.0px 0.0px 0.0px"><font face="Helvetica" size="3" style="font: 12.0px Helvetica"><span class="Apple-converted-space">    </span>name := aName</font></p> </blockquote></div><br></div><div>I get it. You separate the concerns of "testing" and "setting" into methods that can be overridden. You also don't want to allow the general "setter" to save invalid data, so you construct it in a clever way to call the other two methods. Even though this all makes sense, it begs a question... "Maybe data validation happens too soon?"</div><div><br class="webkit-block-placeholder"></div><div>Imagine "name" was bound up to a text field on an HTML web form. Let's say that the testing code required the first letter of the name to be in upper case to pass. So I type my last name into the field like so "rosenzweig" and click "submit". Because an exception gets thrown, we can imagine that we capture it and will display an error dialog to the user upon page reload. The error message could be quite verbose, even blurting out "you typed 'rosenzweig' but should have typed 'Rosenzweig'". However, the actual "name" value is still nil and you won't see "rosenzweig" in the text field, you'll see emptiness.</div><div><br class="webkit-block-placeholder"></div><div>I would offer a slight variation. I would write your snippet like so:</div><div><br class="webkit-block-placeholder"></div><div><div>name</div><div>    ^name</div><div><br class="webkit-block-placeholder"></div><div>name: aName</div><div>    name := aName</div><div><br class="webkit-block-placeholder"></div><div>validateName</div><div>    "Massage _name_ to pass validation if possible, otherwise</div><div>    throw exceptions for business rule violations. If an </div><div>    exception is not thrown, set the corrected </div><div>    (or unmodified) value"</div><div><br class="webkit-block-placeholder"></div><div><br class="webkit-block-placeholder"></div><div>The idea here is that "name" will always get set, regardless of what is typed, but it might not be saved to your persistence layer (object database - Magma, or relational database - GLORP). When you type in "rosenzweig" and hit "submit", one of the following could occur:</div><div><br class="webkit-block-placeholder"></div><div>1) An exception will be thrown. A descriptive error dialog will appear on page refresh. The value of "name" will still show "rosenzweig" in the text field. The user sees what they typed but realize it didn't validate and can offer a slight modification then resubmit.</div><div><br class="webkit-block-placeholder"></div><div>2) The method "validateName" is clever enough to realize that it can silently coerce (massage) "rosenzweig" into "Rosenzweig" on the user's behalf. The corrected value gets committed to the persistence layer and the user is taken to the next page.</div><div><br class="webkit-block-placeholder"></div><div>This technique hinges on something knowing when and how to call "validate" methods on attributes. Perhaps the persistence layer will call "validateForSave" on each object before it actually does a commit. "validateForSave" would then, in turn, look over all of its attributes and call the "validateObject" method for each one, if it is defined.</div><div><br class="webkit-block-placeholder"></div><div>-- Aaron</div></div></body></html>