At 05:41 PM 10/12/2005 -0700, John Anderson wrote:
Phillip J. Eby wrote:
At 02:04 PM 10/12/2005 -0700, John Anderson wrote:
Phillip J. Eby wrote:
My point is that - at least as I understand it - CPIA doesn't allow you
to encapsulate a tree of blocks as a *new kind of block*, or to treat
them as a template for a tree of widgets, or allow treating widget
properties as pluggable items, or any other composability mechanism that
would make UI upgrades relatively simple, and not require any copying.
I still think that there is some confusion here. I don't see why you'd
want to make a "tree of blocks" a new kind of block. That seems like
mixing apples and oranges. Trees of blocks make a corresponding tree of
widgets when they are visible on the screen, and the persistent attributes
of the widget is all a block really is. Widget properties don't persist,
and tend to be framework specfic, so we try to map them to block
attributes in a way that makes them less framework specific.
CPIA conflates the views (specifying widget properties, event interactions,
etc.) with the interaction model (the current application state being
viewed and edited) in blocks. These two things have no essential
similarity or connection, as a simple counterexample can show. Consider
.xrc files, for example. They specify a tree of widgets, but not the state
of the contents. Putting both the model and the view into the same Block
is like having Chandler save its data by writing out .xrc
files! (Confusing the view and the model, in other words.)
Thus, even if you want to use the repository persistence to save the
rendering parameters and event hookups of a set of widgets, there's no
reason to store that data in the same object that holds the model
state. Those rendering parameters are code, not state, because they come
with the application or parcel, and they do not change.
(Note, by the way, that adding tools to allow end-users to customize the
application is entirely orthogonal to this issue, so the fact that we'd
like to allow customization doesn't influence the design here, although
good separation between model and view would likely make customization
*easier*.)
Many people who use Excel will copy a spreadsheet and change the numbers,
then use their desk calculator to fill in the totals. That's what we're
doing today with CPIA, at least as I understand it, because CPIA doesn't
let you create the equivalent of "formulas". We can't turn a tree of
blocks into a new class of block, we still have to create the individual
blocks. If you could do that, there would be no need to copy anything,
and the UI upgrade problem would then be identical to all other schema
upgrade problems.
Sometimes you need new spreadsheets, sometimes you need new formulas, both
make sense. CPIA is the same, sometime you need a new tree of blocks,
sometimes you need to change the attribute on the block that controls the
display, or the data that is displayed. CPIA's strength is that it can
build a whole bunch of different UIs out of different trees of blocks and
the attributes on them. Doing this without writing new code, or definining
new kinds of blocks makes contstructing/changing the UI simpler. Of course
that doesn't preclude new kinds of blocks, it's just a more difficult task.
Translating our positions into an analogy, here's where we stand so
far. I've said, "CPIA currently uses square pegs. I think there is a
possibility that we have some round holes here, and in 0.7 we should
consider perhaps using round pegs, or maybe sanding the corners of the
square pegs, or something like that."
I'm reading your reply here as, "But square pegs can be made to fit almost
anywhere if you pound them hard enough." I certainly don't disagree with
that, but it also has no bearing on whether round pegs might work better in
certain cases, and whether that is the case here.
The only things there should be instances of are user-configurable
components, that need an independent persistent state, such as the main
views themselves. But their persistent state should consist only of the
user's settings, not the independent state of an abritrary collection of
blocks, that may or may not be the same blocks when upgraded.
The position of a scrollbar should persist and isn't user-configurable.
The position of a scrollbar is a function of a model value - namely the
currently selected item in the view the scrollbar is scrolling. Storing it
as though it were the state of the scrollbar is confusing the model and
view. More to the point, though, it's duplicating data, which means it's
wasteful and can get out of sync. Since you have to have code that makes
it match the model, but we're also storing it on disk when we already have
the model data stored, it's wasteful of performance and makes upgrading
much more difficult than it needs to be.
All of this is more complex and error-prone than an MVC or MVP approach
would be, both in the code that already exists, and the code that will need
to exist in the future, and in what parcel developers have to do to create
a basic parcel.
The selection, and sort of a table on a collection also needs to persist
and is on a collection displayed in a block
What are the user-configurable attributes of a Label? Labels don't change,
do they? Even if they do, it's in response to some *model* change. What
about buttons? They don't change either. What are we persisting for a
button or a label? We're persisting their *design*, which is the view
definition, which is application-delivered code.
If you don't think Label or Button are fair examples, just look at
Block. It defines 14 persistent attributes, but as far as I can tell it
seems to me that maybe only 'contents' and 'isShown' might be abusable to
store model state mixed in with the view definition.
Despite being "higher level" than widgets, most of the block classes I've
seen are essentially just view definitions, whose duplicated persistence of
occasional bits of model data adds little besides complexity and overhead.
Meanwhile, the blocks defining the layout have no particular reason for
being persistent themselves, at least not until/unless we have a UI
builder. But even then, there's nothing that requires those objects to
be defined by the repository persistence scheme, vs. say a pickle in a
blob in the repository. And even then, there's nothing that says
(architecturally) that you have to have an instance of each one for every
widget the block defines, any more than you have to have a class for
every object.
I think you might be confusing UI widgets and blocks. Having a way to
persist the state of UI is what blocks do.
What they mostly persist is the *design* of the UI, not its
state. Separating this from the *state* of the UI would make CPIA much
easier to learn and use by decoupling view rendering from state management,
and improve its performance by decoupling rendering from the
repository. It would also make it more practical to backend CPIA to
different widget frameworks, because decoupling the interaction models from
their views means the models don't have to change.
It's not just a matter of making it easier to keep state in an upgrade, in
other words, but rather an issue that's fairly global to the project. As I
mentioned before, however, I didn't want to try to get into this issue
while we're wrapping up 0.6, because it does have so many ramifications. I
only mentioned it in the current context because Bryan brought up the issue
of UI upgrades. CPIA's model-view merging does have an impact there, just
as it also has performance impacts, but it affects more than just those two
things. It needs to be evaluated with respect to our platform goals for
0.7 and beyond.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "Dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/dev