Why Views use the prototype pattern?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Why Views use the prototype pattern?

Fernando Rodríguez
Hi,

It looks like each view you define is an instnace of a View clas (or
any of its subclases). Why shoudln't every view be a class?

I don't understand this design decision, I thought the prototype
pattern was for cases where creating new instances was very expensive,
but it doesn't seem to be the case...


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

Chris Uppal-3
Fernando wrote:

> It looks like each view you define is an instnace of a View clas (or
> any of its subclases). Why shoudln't every view be a class?
>
> I don't understand this design decision, I thought the prototype
> pattern was for cases where creating new instances was very expensive,
> but it doesn't seem to be the case...

More accurately, when you use the View Composer to build a "view resource" you
are assembling an instance of a compound View which contains (typically)
several sub-Views which are also instances of the various View classes.  That
instance is then converted into an STB-ed byte array and stored under the
<name, presenter class> pair in the resource registry.

As to why it's done that way.  Well, I don't speak for OA (obviously) but
here's how it seems to me:

Ultimately, the MVP framework (however it's implemented) will have to do two
things well.  One is to allow us programmers to build window and visual
component descriptions in a tool such as the VC.  The other is to create
instance of compound Views at runtime and bind them into MVP triads.  The
question is how to implement that ?  Some options are:

One: Create a special class for each kind of window/component, where the
runtime instances are built by "normal" class instantiation, which invokes
"normal" code.  This has the advantage that the code can be browsed using the
normal tools (e.g. looking for references to classes).  The downside is that
it's difficult (to say the least) to avoid it being either fragile or
inflexible.  If the programmer is "allowed" to use arbitrary code in the View
class, then that's obviously as flexible as you can get, but the chances of the
VC equivalent being able to handle hand-edited classes in this way are about
zero.  OTOH, if the programmer isn't allowed to make any (or only very small)
changes to the code, then you've lost almost all the flexibility because the
Views can only use methods and objects that the VC knows all about (or, if you
want to avoid that restriction, then you have to ensure that /all/ objects know
how to tell the VC what they are and what they can do -- I don't want to have
to write that code myself for /my/ objects...)

Two: Use a special formatted description (not arbitrary Smalltalk code) of the
view instances.  E.g. you could use fragments of XML, or maybe an
OrderedCollection of MessageSends.  At least that avoids the problem with
programmers wanting to modify the code, but it is still almost completely
inflexible.

Three: Take advantage of the fact that Dolphin has a means to save the entire
state of any object (or collection of objects) /anyway/.  Assemble the
object(s) in the VC (allowing the programmer to make any arbitrary changes to
the states of those object -- remember they are real objects and you have an
inspector to make changes to them).  Once the programmer is happy, you just
save the state and resurrect it whenever you want.  Simple!  (Actually, I don't
think it's anywhere near as easy as that in practise -- mostly because you have
to make the framework such that most Views can work without their normal Model
or Presenter in the VC -- but the Idea is simple).  This gives very nearly as
much flexibility as the "arbitrary code" approach but still allows you to have
a nice reliable View Composer.  The downside is that browsing the "definition"
of the view instances is difficult or impossible.  That also introduces some
new forms of error -- such as when you rename of redefine a View class without
taking account of any stored view resources.  Another problem (at least for me)
is that it becomes impossible for the programmer to add commentary to the view
resource.

Swings and roundabouts.  All the options have advantages and disadvantages.  OA
have chosen the third approach.  On the whole I think they made the best
choice.  (Though that's not to say that I think the implementation's perfect).

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

DiegoC
In reply to this post by Fernando Rodríguez
It should be easy to get the class from an instance, generating the code if
is that what you are needing. I felt that need some time ageo but after a
while I started to not even use the VC when I can avoid it, so now that
desire it's going.

Diego


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

Andy Bower-3
In reply to this post by Fernando Rodríguez
Fernando,

> It looks like each view you define is an instnace of a View clas (or
> any of its subclases). Why shoudln't every view be a class?
>
> I don't understand this design decision, I thought the prototype
> pattern was for cases where creating new instances was very expensive,
> but it doesn't seem to be the case...

Just to add to Chris' reply...

We normally think of a new class as adding "Behaviour" to the system.
Instances of that class are configured by setting the instance
variables in order to tailor that behaviour.

When one creates a view, say a new configuration of a ListBox (perhaps
with a specific background colour), it seemed to us to make more sense
to hold onto that as a new prototypical instance rather than create a
new class to deal with the difference between the new ListBox and the
default ListBox.

In other words, if you just change the background colour of a ListBox
and save ity as a new view, do you really think it is appropriate to
create a new class to reflect this?

In general, I think that the decision to use prototypical instances for
views is the right one. However, I no longer think our choice of
storage format (STB) is the best idea. A more appropriate format would
be as literal storage most likely held as a literal array within a
method. This way, any Symbols and classes used by the views will be
available for searching by the browsers' references command and for
refactoring.

Best regards,

Andy Bower
Dolphin Support
www.object-arts.com


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

DiegoC
Andy,

> However, I no longer think our choice of
> storage format (STB) is the best idea. A more > appropriate format
would
> be as literal storage most likely held as a >literal array within a
> method.

Can we expect that for D6?. Today I have problems because I change a
TypeConverter that were being used by many views. After that it was
imposible to save the package or open those views with VC. The problem is
that views are saved as bytes instead of objets, so that process of
serialize/deserialize is weak in some circumstances. Thank you.

Diego Coronel


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

Schwab,Wilhelm K
Diego,

> Can we expect that for D6?. Today I have problems because I change a
> TypeConverter that were being used by many views. After that it was
> imposible to save the package or open those views with VC.

Diverting attention to your immediate problem, did you change the
instance variable layout of the converter?  If so, you can probably
write a few methods and get it working again.

Incremental conversion is you best bet.  See #stbConvertFrom: and
#stbConvertFromVersion*:.  My preference (in most situations) is to use
streams over both the old and new array.

#stbConvertFrom: can be stolen from any number of places.   An example
of an incremental conversion (version 0 to 1) might be:

stbConvertFromVersion0:versionArray

                | versionStream |

        versionStream := versionArray readStream.

        ^Array writeStream
                "Suppose you had 3 ivs"
                nextPutAll:( versionStream next:3 );

                "and added a fourth with 0 as a default"
                nextPut:0;
                contents

You can do more complicated things using temporaries and indexing the
two arrays.  It helps to have lots of old STB data to use for tests.
After a while, it even starts to make sense :)

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

DiegoC
Thank you Bill. I did something like that, spending some time on it.
Nothing of this would happened if views where objets instead of static
serialized bytes. Or at least, resources should be aware of class changes
automatically.

Diego Coronel


Reply | Threaded
Open this post in threaded view
|

Re: Why Views use the prototype pattern?

Andy Bower-3
Diego

> Thank you Bill. I did something like that, spending some time on it.
> Nothing of this would happened if views where objets instead of static
> serialized bytes. Or at least, resources should be aware of class
> changes automatically.

Well, regardless, that is what you need to do. If you change the layout
of an object that is likely to be stored as STB you need to write a
conversion method for the class. Since view resources are stored as STB
you need to be aware of this.

http://www.object-arts.com/Lib/EducationCentre4/htm/convertingstbdataaft
erinstancelayoutchanges.htm


It is unlikely that the view resource format will be changed for D6.

Best regards

Andy Bower
Dolphin Support
www.object-arts.com