Re: EAV (Re: Object-relational impedence)

From: Dmitry A. Kazakov <mailbox_at_dmitry-kazakov.de>
Date: Sat, 29 Mar 2008 20:52:35 +0100
Message-ID: <sx63aazflvww.1r6a2614kopxw.dlg_at_40tude.net>


On Sat, 29 Mar 2008 18:54:11 GMT, Brian Selzer wrote:

> "Dmitry A. Kazakov" <mailbox_at_dmitry-kazakov.de> wrote in message
> news:1kikgag7cq3zi$.ufxkz5oaeff.dlg_at_40tude.net...

>> On Sat, 29 Mar 2008 15:37:13 GMT, Brian Selzer wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox_at_dmitry-kazakov.de> wrote in message
>>> news:e5lufueeu155.t1s8vlmxjhpt.dlg_at_40tude.net...
>>>> On Sat, 29 Mar 2008 04:47:01 GMT, Brian Selzer wrote:
>>>>
>>>>> There is a table for attributes that are common to all
>>>>> possible widgets, and a table for each set of attributes that are common
>>>>> not to all possible widgets, but rather to a subset of all possible widgets.
>>>>
>>>> It is interesting to see people reinventing the wheel (class). The set of
>>>> "all possible widgets having attributes T, U, V" is a class.
>>>
>>> That depends upon how you define what is a class.  The set of all possible
>>> widgets having attributes T, U, V, such that T and U have the same sign is a
>>> different class.  The set of all possible widgets having attributes T, U, V
>>> such that T and V have the same sign is also a different class.  Under this
>>> definition, a widget may be a member of all three classes, right?
>>
>> Is the sign of attributes itself an attribute, or it is a constraint put on
>> them? But basically, yes classes can intersect.
>>
>> ... and the point is, the problems and choices you have been discussing is
>> the good old OOA/D with relational representations as a vehicle.
>>
>>>> But that is not my point. The problem with widgets hierarchy is that 
>>>> there
>>>> are three axes of widget relations. You were discussing only one of them
>>>> attributes, which is usually directly mapped to types. This is not that
>>>> big deal. More difficult are other two:
>>>>
>>>> 2. Visual containment. Widgets can consist of / contain other widgets.
>>>
>>> If a widget consists of other widgets, then it must have attributes that are
>>> also widgets.  If a widget contains other widgets, then it either has one
>>> attribute for each contained widget or an attribute that is a set of
>>> widgets.  Visual containment can be defined in terms of attributes, so I
>>> don't understand why it is a problem.
>>
>> (I am surprised that you did not mentioned a natively relational solution.
>> I thought you would propose parent-child relation.) Anyway, an
>> attribute-based model is very weak. It is like to have only record types
>> but no arrays. There are lots of widgets which contain an unknown in
>> advance number of other widgets. Another problem why your and the
>> relational model I mentioned before would be problematic is handling all
>> sorts of ordering, layout, alignment, size constraints put on contained
>> widgets. In the traditional OO GUI design these constraints are a part of
>> the container widget behavior. For example, GTK+ table widget arranges its
>> children in columns, calculates its own size from the sizes of children
>> (that goes recursively) etc. It would be extremely tedious to expose this
>> stuff in terms of attributes for the poor user...

>
> It's a simple matter to flatten out nested relations. Also, modeling a
> 1:0..n relationship is child's play. Ordering, layout, alignment, size can
> all be represented by exposing attributes and defining functions and
> relations.

Yes, but what will happen with the nice global widget-attribute model? The problem is that the least common denominator (an OO guy would say, the root class) is practically null. This is independent on whether widgets are represented as relations of attributes or as types with properties.

> If the size of a widget depends upon the size of its children
> then it must be the result of an aggregate function. It's generally bad
> practice to record the results of an aggregate, since the value can be
> arrived at by simply computing the aggregate. Any change that might affect
> the aggregate result would then necessarily require a recomputation of the
> stored aggregate value.

In practice it is more complex, the container interacts with its children. There are quite horrific protocols of children being asked for what they want, what they could, what the user has requested (resizing), what the preferred geometry is (window manager). To bring this to one formula would be a challenge. And the problem is how would you reuse this mess? In OO it is a behavior encapsulated into the widget. In RDBMS you would have some deeply layered views of pseudo attributes. To me it is just same OO translated into some "relational code." And the mapping set value <-> behavior is as old as the world (every piece of hardware works this way).

>>>> 3. Signal handing. Handlers of widget events are composed in a certain
>>>> hierarchical way.
>>>
>>> You don't store widgets, you store snapshots of widgets.  How one widget
>>> communicates with another has no bearing on how the snapshots of each are
>>> stored.  So where is the problem?
>>
>> I don't see your point. When you hit a mouse button, that should have some
>> effect on the snapshots. Even if we ignored an application processing the
>> event, there is a delivery to it and animation. For example, a button
>> widget under the cursor gets down and up, while the sequence
>> left_mouse_press, mouse_release is translated into button_click.

>
> When you hit a mouse button, the state /may/ change. When the state
> changes, another snapshot can be taken to replace one that had already been
> recorded. Not every mouse click results in a change of state. For example,
> someone hits the "Clear" button on a screeen that has already been cleared,
> or someone double-clicks the "Clear" button, and the double-click is
> interpreted as two single-clicks. When there is no change of state, there
> is no need to record a change of state.

Normally it is the button's behavior to catch low-level events and to translate them into higher-level ones. Some events go no further. This is what I meant under composition of event handlers. An event is issued and then propagated through some dynamically managed network of handlers. It can be routed, reflected, it can signal new events etc. It is quite messy. (BTW, I don't like it. But it is the best known solution today.)

In terms of states, there exist transitional states which never become visible above some level. It seems that you consider only the states relevant for widget rendering. But this is a way different and even more complex story. Rendering states are asynchronous to the GUI and application states. The rendering engine is asynchronous to one of the widgets. Much of rendering stuff runs in the graphic accelerator or remotely. There is a sort of transaction model between the widget's engine and the rendering environment (device contexts etc).

> Bottom line: the fact that a
> left-mouse-press, left-mouse-release translates into a button_click is
> irrelevant. What has delivery and animation to do with tracking widget
> state?

Because "button pressed" is a visible state for an application if it wants to see it. Technically you cannot publish all state transitions. That would throttle most powerful hardware you'd take. And most of these states are just irrelevant to the application. Differently to DB which is largely passive and driven by applications, GUI has it own life and application just reacts on the interesting to it state transitions. It also kicks some new transitions.

This is BTW another important problem of GUI design. When an application initiates some transitions it wishes A) to be asynchronously to them and B) it often does not want to be notified about its own actions. So you need synchronization mechanisms and events filtering based on the issuer.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Received on Sat Mar 29 2008 - 20:52:35 CET

Original text of this message