Some hack you just found and want to tell to others

design question

Postby duetto » 23. Dec 2009, 16:26

hi all,

looking for an "elegant" solution to a problem.

i have a list which contains objects of different types. each type has a different editor. when i double click on the item in the list i want to open the item with the correct editor.

where should the object type to editor relationship be held/resolved?

john cummings
Posts: 22
Joined: 28. Sep 2009, 02:43

Re: design question

Postby cgittinger » 23. Dec 2009, 18:13

let me give you something for discussion (some may start bashing on me...).

There are multiple ways of doing it, with increasing flexibility and possibly decreasing readability.

1) Case Switch
Let's start with the simplest, and easiest to understand (however, every "real OO-programmer" will immediately regard you as beginner, non-engineer and what else - so be careful to do this in public):

In the application, define a local translation method, which either uses nested if-then-elses, a dictionary, or self-performs to generate a mapping from model-class to editor class.
similar to:
Code: Select all
    aModel isXXX ifTrue:[ ^ XXXeditor ].
    aModel isYYY ifTrue:[ ^ YYYeditor ].
    self error:'no editor'

PLUS: local; easy to understand; easy to find; easy to modify.
MINUS: Requires change if a model class is added/renamed. Requires isXXX methods.
Big-Minus: is considered bad coding style by some religious programmers.

2) Query the Model
You will be more flexible w.r.t. added model classes, by letting the model know, which its editor is; in every model class, add a method like:

Code: Select all
    ^ XXXeditor

PLUS: easy to add new model classes in the future; without any need to touch your app.
Big-MINUS: coupling between model- and editor classes (what if another app also needs an editor class ?)

3) Visitor-pattern
add a call back via the model into an "editor-determiner-class". The visit-methods "encode" the type of model into the name of the called method. You need generic visitor-methods in your model classes:
in XXX-model:
Code: Select all
acceptVisitor: aVisitor
    ^ aVisitor visitXXX:self

and you need an EditorDeterminerClass (would be a private class of your application):
Code: Select all
    ^ XXXEditor

    ^ YYYEditor

then, to get the editor in your app, write:
Code: Select all
    editorClass := aModel  acceptVisitor:(EditorDeterminerClass new).

(actually, you probably don't need an instance of EditorDeterminerClass - you could also do it on the class side).
Also, if your models all inherit from a common AbstractModel, you would define a bunch of subclassResponsibility callers for all the visit* methods there.

PLUS: pluggable, reusable (other apps can also use it, using their own determiner instances); flexible (determiner can even look inside the model and determine the editor depending on the state or user's access rights or whatever)
MINUS: now we have a bunch of methods, spread over the system. This might be harder to understand later or by followup programmers (so, it needs some comment, somewhere). Also, during debugging, there is often quite some stepping through the system to be followed.

4) Using Reflection
Making use of some smalltalk features, we can get rid of any code in the model alltogether; as the editor should be the one to know which model-types it is able to edit, all we actually need is to choose the correct editor from the set of well-known editor classes. So, if all of your editors inherit from a common AbstractModelEditor-class, you can get that "good" one via:

in AbstractModelEditor:
Code: Select all
    ^ self allSubclasses detect:[:editorClass | editorClass isGoodFor:aModel ]

and, in some XXXEditor-subclass:
Code: Select all
    ^ aModelClass isXXX

or, you could even get independent of the name or any isXXX methods, by defining a model-type-symbol (or ID, or UUID or whatever is a constant unique identifier):
Code: Select all
    ^ aModelClass modelTypeSymbol == #xxx

we use a similar scheme in one of our apps, where the editor is either a java, smalltalk or diagram-editor. Every model defines a codeType message, which returns a symbol (or a class-singleton or a class-as-singleton).
Then a corresponding editor is searched in the set-of-known-editors.

PLUS: completely independent, easy to add models and classes later.
MINUS: might be even harder to understand and follow, as #senders and #implementors will not find much.

Hope this gives (at least) something to start a discussion with.
I am actually not sure, where the dividing line between too much coupling and over-engineering is. I guess, for small apps, which are maintained by a single person, I'd really have no problem with a switch. Often, when I get code to port, I find over-engineered flexibility, which is nowehere needed and is hard to grasp - especially, as smalltalkers tend to think, that their code is so obvious, that not a single line of comment is required anywhere - not even in the classes documentation, where such things should be mentioned.

regards & merry X-mas,
Posts: 61
Joined: 12. Nov 2008, 17:05

Re: design question

Postby duetto » 23. Dec 2009, 18:43


as usual thanks for analysis. since i have "way too much time on my hands", i will start with a switch and later experiment with the reflection approach.

Posts: 22
Joined: 28. Sep 2009, 02:43

Return to Tips and Tricks

Users browsing this forum: No registered users and 1 guest

Design by GB