On Wed, 30 Apr 2003 at 18:07 GMT, Dave Thomas wrote:
> Is a Contact that you return as the result of a search(say) the same 
> type of thing that you use to create or edit a new entry?

Yes.

> You assumption is that they are (basically) the same thing, but perhaps 
> you might want to rethink that. They don't seem to share the same 
> methods. Maybe you need two classes: Contact and MutableContact. Regular 
> Contact classes have methods that let them be examined but not altered. 
> MutableContacts allow change.  If needed by your application, class 
> Contact could include a #to_matuable method that returned a MutableContact.

Hmmm. I never thought about that, mainly because it requires creating
two types of contacts that will hold _exactly_ the same data. I will
take it into consideration.


Simon

PS: When I have complex problems like this one, I have a habit of
writing them out as a post to clarify my thinking. I often let it simmer
a while and rewrite it before I post. This time however I inadvertently
posted the message before I got a chance to rewrite it :>. (I canceled
the post immediately but it seems it did get to ruby-talk.)

For those of you who are interested: this is what I *was* going to post
before I got Dave's reply:


<snip>

_Goal:_ An Addressbook class that can be reused. 


_Initial Design and shortcomings:_

The way I see it, an addressbook is merely a (smart) container for
contacts. It is responsible for loading, storing, managing (adding,
deleting) and saving the contacts. Thus, the interface could be
something like:

Addressbook
  |- open(filename)
  |- addContact(contact) 
  |- getContact(name)
  `- removeContact(name) 

Contact
  |-setName
  |-getName
  |-setAge
  |-getAge
  |-...

This approach provides a lot of flexibility - you can change a
contact with a one-liner: 

 myAddressbook.getContact('Simon Vandemoortele').setAge(25).

However, it leaves the content of addressbook (the contacts) freely
editable by everyone. I hope we all agree to the fact that this is a
serious limitation to the interface. Because someone can change a
contact without the addressbook noticing, the addressbook cannot enforce
any invariant that depends on it's contacts content. i.e.: it can't
enforce a no-two-entries-with-the-same-name policy. Nor can we decide to
implement the addressbook as a sorted Array anymore.


_Alternative designs:_

I am told by learned colleagues that the OO take on this kind of
problems is to introduce *immutability*. 

[1] The classical way to do this is by making the interface immutable
(no writer methods). So 'setAge' would not change the contact's name but
instead create a copy of the instance with an updated age attribute:

  myContact = myAddressbook.getContact('Simon Vandemoortele')
  myContact = myContact.setAge(25)
  myAddressbook.updateContact(myContact)

This can be quite cumbersome. 

[2] In Ruby there might be a different way to do it: require that all
contacts submitted to the addressbook be frozen.  That way you can
enforce immutability without losing the convenience of attribute writers
on Contact. The drawback I see is that the immutability is not really
enforced in the interface: a client can still *try* to change a frozen
contact, something that is impossible in [1].


_Questions:_

Am I right in going the immutable way here ? (I've thought of 2 other
solution to the shortcomings of the first design: having the contacts
cooperate with the addressbook or using deepcopy when adding and
deleting contacts.)

If so, which implementation would you chose ?





-- 
There are 10 types of people in the world... 
those who understand binary and those who don't.