Jack Unrue wrote:
On 4/10/06, Ken Tilton <kentilton@gmail.com> wrote:
Oh, if you are big on separation maybe you can confirm something I suspect, namely that Cells, by allowing different instances of the same class to have different rules for the same slot, makes OO design.
For example, one can have a game normally look like:
(make-instance 'game :speed (c? (* (^difficulty-slider) 500))...
But then for debugging a hard problem you might want to play back a log at full speed and so the replay code goes:
(make-instance 'game :speed 500...
In the first case the game /instance/ is being driven by the GUI slider widget, but the game /class/ does not know about the GUI.
Does that make sense in resolving the separation issue?
I'm going to assume a certain interpretation of your example that you might not have actually intended, so if you didn't mean that the value of (^difficulty-slider) is literally a Cells wrapper around a slider or some specific widget type, then please by all means correct me. And thus ignore the rest of this and just know that we'd be totally agreeing :-)
So at the risk of preaching to the choir...
I'm not too far out of disagreement with you, but consider a slightly different arrangement. In the above example, rename (^difficulty-slider) to something like (^difficulty-selector). What the renamed slot now indicates is that the "difficulty" value is still user input but we don't specify what UI is actually used to implement that -- it's just some mechanism for which the game logic doesn't need to know the specifics. And at the same time, change the formula associated with the difficulty-selector such that it's not directly tied anymore to any particular widget type. The game UI code is obviously responsible for translating widget events into values posted to this selector model. So, in some respects, the name change seems pedantic, but it's an important part of the abstraction.
By not pre-supposing what control is actually driving that slot, you get some freedom to make UI changes that (within reason) won't affect this game logic. For example, in version 1 the difficulty setting is a slider, but after usability testing you realize that a slider is too granular, and users are better served if it's just three radio buttons.
Exactly what I had in mind. I actually should have given: (md-value (widget-named :game-difficulty)) Then the slider is named :game-difficulty and the md-values range from 0 to 1. The rule does not have to change if :game-difficulty becomes a radio-group container widget of three radio buttons easy, average, and hard as long as the radio-group rule for md-value translates the selection to 0.33, 0.66, and 1.0 or something like that. But I am going further and saying there is not much harm in having the radio-group just take on the symbolic values 'easy, 'average, and 'hard because we can then change the code to: (make-instance 'game :difficulty (c? (ecase (md-value (widget-named :game-diificulty)) (easy 0.333)...etc ie, the ability to tailor instances with rules vs mere literal values such as 0.333, 0.555 makes decoupling less urgent. The developer just has to arrange at some point for the game difficulty to resolve to a value between zero and one. ken