[Seaside] Smalltalk design advice - how toimplement genericbi-directional pointers?

Aaron Rosenzweig aaron at cocoanutstech.com
Sun Dec 23 19:21:19 UTC 2007


I'd like to thank Sophie and Christoph for asking an excellent  
question. And thanks to Ramon, Colin, David, Amos, Sebastian and  
others for lending a hand.

This thread strikes a real chord with me. I believe that if you model  
the domain effectively then the application feels like it can write  
itself. That is, spend time developing your critical domain objects  
and behavior before you start writing your app. If you find that in  
your app you are writing a lot of code, you are probably doing  
something wrong at which time you should revise your domain model.

What Sophie, Christoph, and myself are really asking is, "How should  
I go about developing my domain model". And more specifically "I have  
an idea of how to do this from my past experience, but given the new  
world of Squeak and Smalltalk, what's the best practice?"

Ramon mentioned "Class Responsibility Collaborator" models, or just  
"CRC cards" for short. That terminology is new to me and the idea is  
pretty cool. For the uninitiated, here's a few links:

General Definition:
===============
http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card

Extended example:
===============
http://www.agilemodeling.com/artifacts/crcModel.htm

Bitmap scans of the actual handwritten CRC cards used in the creation  
of "HotDraw":
===============
http://c2.com/doc/crc/draw.html

Review of "Ecode", a CRC card design tool for Squeak:
===============
http://coweb.cc.gatech.edu/cs2340/3372

So I installed "Ecode" from SqueakMap into my 3.9 image taken from  
the Seaside one-click-experience. After running Ecode I could no  
longer "yellow" click on the desktop or other areas without getting  
an exception thrown... so I guess it is not compatible with the  
current Squeak. The idea of Ecode sounds pretty stellar and basically  
the kind of tool I want to use. Does anyone have suggestions about  
alternatives?

I've grown accustomed to having a visual tool where all I concentrate  
on is the domain objects, what their responsibilities are, and how  
they collaborate.

Let's talk again about the "Car" and "Tire" objects. I agree with  
Ramon that generally a Car needs to know about the Tire objects but  
the inverse is not important. A Tire can be placed on a different car  
and it shouldn't care. But what about a luxury car? Is that any  
different? Could be. The Tire might want to tell the car when its air  
pressure is low. For this it seems plausible that the tire might want  
to know that it is attached to the Car, that way it can send a  
message to the Car when it's time to replenish the air. You could  
still argue that the Car could "ping" the Tire every five minutes to  
find out the air pressure, or perhaps once each time you turn on the  
ignition, so it all depends.

I think Sophie was looking for some pattern along the lines of:

| car tire1 |
	car := Car new.
	tire1 := Tire new.
	car add: tire1 toBothSidesOfRelationshipWithKey: 'tires'.

The message "add: object toBothSidesOfRelationshipWithKey: string"  
would attach the tire to the car and, if you had modeled the inverse,  
it would tell the tire what car it was placed on. So the 'tires'  
relationship and the optional inverse 'car' relationship would have  
to be modeled somehow. Like maybe Tsunami or maybe Magritte but I  
don't know what I'm talking about here because I haven't cracked open  
those two Squeak frameworks yet.

Ramon, maybe you can clarify. You mentioned your Tsunami framework  
but in the same breadth alluded that we shouldn't use it? Or I  
misunderstand. In what situations *should* we use Tsunami or is it  
that you once felt it was necessary but later learned it isn't? In  
the Tsunami framework it mentions inspiration from the book  
"Streamlined Object Modeling" which has examples for both Java and  
Squeak. Would you say this is an excellent book for us new guys to read?

Thanks for listening,
-- Aaron


On Dec 23, 2007, at 2:40 AM, Ramon Leon wrote:

>> Let's say I have employees and projects where each employee
>> might work on many projects and each project has many
>> employees working on it. Now in a RDB I would have three
>> tables one for each projects/employees and a linking table
>> for the m:n relationship, possibly containing details of the
>> association.
>
> If you're trying to think in objects, the first thing you need to  
> stop doing
> is starting by thinking about how you'd do it in a relational  
> database.
> Relational database are meant to store data in such a manner that  
> it'll work
> for any model in any application, all data and no behavior.  That  
> isn't OO
> and that's not what you need to think about.
>
>> Users of my application would expect to be able to search for
>> all the employees working on a given project and vice versa.
>> Trying to find an OO model to represent this, I end up with
>> three Classes that correspond to the three tables mentioned
>> above ( maybe this is wrong already??).
>
> Why?  Seriously, you're still thinking relationally, you're talking  
> about
> nothing but data and searching.
>
>> I would be very thankful if anybody could point me into a
>> better direction, ( or recommend some books to read )
>>
>> Regards, Christoph
>
> First, stop thinking about the data, programs aren't about data,  
> they're
> about behavior.  You have to ask yourself what is this program  
> going to do,
> what is its purpose, what does it accomplish for the user.  Is the  
> program
> about projects, or users, and which one is it going to be centered  
> around?
> What objects are you going to need most?  Modeling a program is  
> about making
> choices, picking a direction, and going for it.  Trying to keep
> bidirectional links everywhere is just a way to avoid making a  
> decision.  An
> object model isn't a relational schema, it's not supposed to be  
> agnostic,
> it's supposed to be opinionated.
>
> Trying to make a model that works for all cases (relational db's)  
> just leads
> to a model that doesn't work well for any case.  Pick your most  
> important
> use cases and make the model work well for them, and make sure to  
> let the
> programs actual behavior dictate which solution is best.  Don't sit  
> down and
> design your object model like a relational schema where you name  
> all the
> attributes and try and normalize the data, rather, use CRC cards  
> and figure
> out how your objects collaborate, behaviorally.  Don't bother  
> listing the
> attributes, that doesn't matter, you can figure that out at  
> implementation
> time.
>
> If you think hard enough, and find that your app really is just  
> data with
> little if any behavior, then you really just stop thinking about  
> trying to
> make a *good object model* and just dump the data to the screen in the
> easiest manner possible, be it sql queries or an active record, it  
> won't
> really matter.  Object models are best suited for behaviorally complex
> applications.
>
> Ramon Leon
> http://onsmalltalk.com
>


More information about the seaside mailing list