Re: Looking for Design Input



On Mar 7, 9:50 am, "Malbs" <ssefl...@xxxxxxxxxxxxx> wrote:
I have a probelm I'm trying to solve. I was trying to thing of the same
problem in a different domain to discover if maybe there is some sort of
pattern I can apply... I was struggling to come up with the same design
problem in a different domain when it hit me. The common mailing list.

think of a simple mailing list system design. Sorry to make people think in
text, but here we go.

MailingList
addMember: aMember - adds a member
removeMember: aMember - removes a member
includesMember: aMember - tests for membership.
selectMembers: aBlock

MailingList class
repository
^Repository ifNil: [ Repository := OrderedCollection new ]

Member
username - gets and sets username ivar
password - gets and sets password ivar
emailAddress - gets and sets password ivar
subscriptions - returns a list of all the subscribed mailing lists.
^MailingList repository select: [ :ea | ea includesMember: self ]

The design problem is, that for each subscription a Member may have
different preferences. In one mailing list they may want a digest mode,
however in another mailing list they may prefer a threaded or per-message
mode.

So I started thinking.. is it a decorator pattern I wanted to use. Wrap up
the Member object in a new object which also contains the Options for the
member, and delegated all of the Member protocols to its internal Member
object... I didn't really feel like that was the correct pattern to apply
here.. so this is what I came up with and I'm wondering what other people
think of it from an OO/Smalltalk/Eww Yuck point of view

Created a new class:

MailingListOptions
initializeWithMember: aMember mailinglist: aMailingList - Private, sets
the two ivars
member - returns the member this is for
mailinglist - returns the mailing list its for
beDigest
beStandard
isDigest
isStandard

then we modify the add and remove methods of MailingList

addMember: aMember
(self includesMember: aMember) ifTrue: [ ^aMember ]
memberOptions at: aMember put: (MailingListOptions member: aMember
mailinglist: self)
members add: aMember.

removeMember: aMember
(self includesMember: aMember) ifFalse: [ ^aMember ]
memberOptions removeKey: aMember.
members remove: aMember.

and introduce a new method to get the options:

optionsForMember: aMember
^memberOptions at: aMember

so now a person can go to their subscription of PHP-Dev, and:

(mailinglist optionsForMember: me) beDigest.

then when it comes time to generate the digest email:

mailinglist selectMembers: [ :ea | (mailinglist optionsForMember: ea)
isDigest ].

gets me a list of members who have set their preference to digest mode.

Now I realise this doesn't cover such things as tracking when digest mode
was turned on, so as to not send messages the user has already received in
standard mode, but thats beyond the scope of this :P

So what I'm interested in?

Has anyone else had to implement a similar design summarised with:

A Member can belong to many MailingLists, and that person may have different
MailingListOptions for each MailingList.

And how did you do it? Am I on the right track, wrong track? I don't know
any Smalltalkers IRL that I can talk to about this. Hell I don't know anyone
who really knows OO that I can talk to about this. Everyone I work with uses
classes as a way to have c code with namespaces.

This seems a lot of work to only records member options: Why not:

MailingList
ivar
memberOptions a Dictionary
key - member
value - #digest || #normal

Appropiate methods to set and retrieve the member state would need to
be added.

I would make the Repository a class even if you only need a singleton.

To further elaboration the design you need to consider how you handle
the message forwarding operations.

--


.



Relevant Pages