CardContainer example please

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

CardContainer example please

acg
Hello
In a previous post re: CardContainer, there is mention of 'Lump' mode
vs 'Discrete' mode of using 'discrete MVP triad' instead of 'dropping a
Presenter.Default view onto a CardContainer...you drop a appropriate
prebuilt and self contained MVP component.'
Could someone please provide example code. I thought each presenter in
a shell had a 1:1 relationship to instance variables in a model, and
that only ONE model could be attached to a shell via #model: . I guess
I'm not sure what a 'self contained MVP' means, since ONE model suggest
'lumping'. I am trying to convert a program from ST/V which had
multiple widgets in multiple windows to one shell, with a tabs
substituting for each previous window.
It seems as if I would need one Model with all the instance variables
for each for each widgets from all the windows (tabs). As an example,
assuming I have  4 instance variables in each of 3 Model-Dispatcher
(ST/V dialect) and want to use one Presenter with 3 tabs. 'Lumping'
suggest 12 (=4*3) instance variable in one model of MVP triad.
'Discrete suggest I can maintain 3 separate Models, each with 4
instance variables, held by 3 Presenter-View pairs, within ONE shell
with 3 tabs (cardContainers). I seem to be having difficulty
understanding how to attach each instance variable to presenter other
than via lumping.

Thanks
ACG


Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

Chris Uppal-3
acg wrote:

> I thought each presenter in
> a shell had a 1:1 relationship to instance variables in a model, and
> that only ONE model could be attached to a shell via #model: .

I think you have a misconception which may be preventing you from understanding
Ian's 2002 post.  There is /NO/ relationship between presenters (or
sub-presenters) and the instance variables of a model.  Not even if you
understand "instance variables" in a broad way to mean something like "any
visible aspect".  Also there is no restriction on how many MVP triads can share
the same model.

You might be being confused by the word "model", I don't know anything about
ST/V, but in Dolphin it is strictly a /domain/ object -- not part of the
presentation layer at all (except insofar as it may "know" that it /can/ be
used in MVP because it triggers events).

So, imagine you have a Person object.  Then you could create a normal,
compound, presenter (plus its view) which displayed just some aspects of a
Person relating to their employment history -- EmploymentHistoryPresenter.  You
could create another, entirely separate, compound presenter which displayed
different things like name and address -- ContactDetailsPresenter.  And you
might create several more such presenters, FinancialDetailsPresenter,
HealthcareOptionsPresenter, and so on.  Note that there might be some overlap
between the various presenters -- they might all display the Person's #name,
for instance.

Now that you have all those written, you can point one instance of each at the
/same/ instance of Person.  You might have each in its own shell (at least for
testing).  Or you might have each as a separate area of a shared shell.  Or you
might have each one a separate tab of a card container.

Alternatively, you might take all the code you've written for all your separate
presenters and lump it together into one huge presenter, MegaPersonPresenter,
with its own, more complicated, view aggregating all the widgets you had on the
separate views before.  It's the same code, just differently arranged.

The model doesn't care at all, and shouldn't have any way to tell whether it is
being used by a group of  EmploymentHistoryPresenters,
ContactDetailsPresenters, and the like, or by a single MegaPersonPresenter, or
even by both at once.

    -- chris


acg
Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

acg
Chris Uppal wrote:

> ...So, imagine you have a Person object.  Then you could create a normal,
> compound, presenter (plus its view) which displayed just some aspects of a
> Person relating to their employment history -- EmploymentHistoryPresenter.  You
> could create another, entirely separate, compound presenter which displayed
> different things like name and address -- ContactDetailsPresenter.  And you
> might create several more such presenters, FinancialDetailsPresenter,
> HealthcareOptionsPresenter, and so on.  Note that there might be some overlap
> between the various presenters -- they might all display the Person's #name,
> for instance.
>....
> The model doesn't care at all, and shouldn't have any way to tell whether it is
> being used by a group of  EmploymentHistoryPresenters,
> ContactDetailsPresenters, and the like, or by a single MegaPersonPresenter, or
> even by both at once.
>
>    ...
Thanks Chris,
 That does shed light for me. Now as I conceive of  the model, let's
say Person object, is it preferrable to create a Person object, with
'has a' relationship with EmploymentHistory object, 'has a'
relationship with FinancialDetails' object', etc. with instance
variables for firstName, lastName, employmentHistory, financialDetails,
with appropriate accessors and initialization for each instance
variable, or preferrable to have a Person Object, with instance
variable for firstName, lastName, presentEmployer, pastEmployer,
presentBank, pastBank, a bunch of employment history and financial
details instance variables and their appropriate accessors ? I see
simplicity in a mega Person object, but a whole lot of instance
variables, and getters / setters. But I see a composite Person object,
as a 'modular / maintainable' from a object oriented standpoint, but
more difficult to hook the Presenter-View to the Person object model.
Your input is appreciated.
ACG


Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

Chris Uppal-3
acg wrote:

> Now as I conceive of  the model, let's
> say Person object, is it preferrable to create a Person object, with
> 'has a' relationship with EmploymentHistory object, 'has a'
> relationship with FinancialDetails' object', etc.

There's nothing wrong with doing that, and there may be good sound structural
reasons for setting up your objects that way (if the -- hypothetical --  GUI
separates these things then that's a good indication that the users think of
these things as separate, which in turn is a hint that maybe your code should
treat them as separate).

However, there is nothing /in MVP/ to make one or the other approach better.
MVP will work perfectly well with either a single "mega-person" object, or a
finer-grained collection of related objects.  In fact there would be almost no
differences to the code in either case.

The only way that MVP wouldn't be so happy is if you find that your objects
naturally break down along lines that are not reflected in the GUI you have
designed -- but even that is probably not a critical problem.

As an example of the possible problem, imagine that we have split up Person
along the lines you indicated.  So now we have an EmploymentHistoryPresenter
which takes an EmploymentHistory object as its model.  Nice and clean.  But now
the users tell us that it's no use looking at an employment history when you
don't know /who's/ history it is.  So our EmploymentHistoryPresenter should
display the person's name and phone number too.  Eek!  We certainly don't want
to add that kind of information to an EmploymentHistory, and even introducing a
back-link from each EmploymentHistory to its "owning" person is a bit suspect.
So what do we do ?  Actually, there's not much problem -- a Presenter isn't
constrained to show /only/ information from its model, think of a window's
caption for instance.  So we give our /presenter/ the ability to show two text
fields which are not derived from the model, and when we show a
EmploymentHistoryPresenter we (the calling code) also tell it the values
for those fields.  Or, more cleanly, we just tell it who the owning person is,
and let it set up its own "additional" fields from that information.

Of course, taken to the limit, that approach turns our
EmploymentHistoryPresenter back into a specialised kind of PersonPresenter. Its
model is a Person, but it mostly displays information related to that person's
employment history.   Which is where we came in ;-)

    -- chris


acg
Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

acg
> ...However, there is nothing /in MVP/ to make one or the other approach better.
> MVP will work perfectly well with either a single "mega-person" object, or a
> finer-grained collection of related objects.  In fact there would be almost no
> differences to the code in either case...

Thanks Chris
That's a reassurance. I was in a 'fork in the road' and could not
decide if one approach were better than the other. I will take the
finer-grained, since it echos my previous modeling of the same problem,
and try migrating from ST/V. I just realized a couple of things that
shed some light, that:

1) composite presenter with cardContainers could be named just like
TextPresenters, and instance variable for the composite presenter can
be initialized, just like other presenters in >>createComponents.

2) models for presenters can be nil,  but still view contents
accessible with user input and programmer as 'namePresenter value' or
'namePresenter value: 'joe', with out going thru a model.

3) Conceptually, MVP complexity is based on overcoming the fear of
dealing with a  potentially large number of  relationships in one's
had, realizing that are just a few relationships that make sense.

For simple example, with one Shell and one textPresenter, there are 3
objects (M,V,P) for each for 3^3 potential interactions to consider,
and even more when some interaction is 'one-way' vs 'two-way'.

But from a coding standpoint, assume a tighter relationship between a
presenter and view, and a looser association between a model and
presenter-view pair, then only 2 of the potential 9 relationships seem
relevant:
    1) 'one-way' communications, of user-interaction to view then
presenter then model aspect. (User Action -> VP ->M)
    2) 'two-way' communications, maintain the 'one-way communication'
and the communication when the model programmatically changes an aspect
which
must 'notify' view of change. (User Action -> V-P -> M) and (program
changes aspect -> M --(notification)-->VP).

Is this a good way to think about it ?
Thanks again
ACG


Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

Chris Uppal-3
acg wrote:

> 2) models for presenters can be nil,  but still view contents
> accessible with user input and programmer as 'namePresenter value' or
> 'namePresenter value: 'joe', with out going thru a model.

Minor correction.  In most cases, there /is/ still a (non-nil) model, even if
you are using basic MVP components just as raw "widgets".  But the models those
components use are not related to your /real/ (domain) model.  For instance a
ListPresenter will still have a ListModel, even if the contents of the list are
purely presentational and not related to your domain.  Or you can step through
sending #value: to a TextPresenter or NumberPresenter and see that it works by
updating the component's default model (which is a ValueHolder holding a String
or Number).


> But from a coding standpoint, assume a tighter relationship between a
> presenter and view, and a looser association between a model and
> presenter-view pair, then only 2 of the potential 9 relationships seem
> relevant:
>     1) 'one-way' communications, of user-interaction to view then
> presenter then model aspect. (User Action -> VP ->M)
>     2) 'two-way' communications, maintain the 'one-way communication'
> and the communication when the model programmatically changes an aspect
> which
> must 'notify' view of change. (User Action -> V-P -> M) and (program
> changes aspect -> M --(notification)-->VP).
>
> Is this a good way to think about it ?

Sounds pretty reasonable to me.

    -- chris


acg
Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

acg
Chris Uppal wrote:
>... Or you can step through
> sending #value: to a TextPresenter or NumberPresenter and see that it works by
> updating the component's default model (which is a ValueHolder holding a String
> or Number).
Thanks Chris

 Your comments adds reassurance that I am on the right track.
During my workspace experiments, FWIW, I found the following
interesting in terms of user input vs changing TextPresenter content
programmatically.
===============
 tp := TextPresenter show. <execute it, then type a few char in p >
 tp value: 'dog' <execute it, change content>
 tp view text: 'cat' <execute it>
 tp <inspect it, showing presenter model.value and presenter view.text
can be different>
 tp value <display it, which as expected, is 'dog'>
 a := tp view aspectValue: #alignment <execute it, to grab it>
 a value: #center <execute it, moves 'dog' to center of presenter>
===============
 Thanks again
ACG


Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

Chris Uppal-3
acg wrote:

>  tp value: 'dog' <execute it, change content>
>  tp view text: 'cat' <execute it>
>  tp <inspect it, showing presenter model.value and presenter view.text
> can be different>

Yes, I considered mentioning that, but decided it was more likely to be
confusing than helpful.

All Views can have their #text set.  Exactly what that means depends on the
view; for a ShellView it's the window caption; for a CheckBox it's the label
for the box; and so so.  Sometimes the view makes no use of its #text at all,
but the aspect is still there. Usually the #text is a purely view-ish thing and
is not related to the model, or even to the presenter unless you have coded a
relationship yourself (it's much like, say, the #backcolor in this).

But that gets a little awkward when it comes to text presenters.  In that case
the #text is the content of the text view.  So, at first glance, it seems as
though the text and the model (or the model's value to be more accurate) should
be indissolubly tied together -- changing either one should change the other.
In fact that's not how Dolphin is set up.  As far as I know the only reason for
that is a desire to avoid wasting space unnecessarily.  When a view's #text is
set, then Windows makes a copy of the string, so Dolphin's views don't save
their own copy too (they can always get it back from Windows at need).  If text
views always tied their #text and their model together, then every text view,
no matter how trivial (and remember this includes static text used as mere
labels) would have to have a full ValueModel holding a copy of the relevant
text -- even when the "MVP-ishness" of that arrangement wasn't used anywhere.

On the whole I doubt whether that optimisation really pays for itself these
days -- but memory has become a lot more readily available since OA first
designed Dolphin's version of MVP.  And even today, loading a 100 MByte file
into Scintilla is perfectly feasible[*], but you wouldn't want to be /forced/
to keep two copies of that text around.

    -- chris

[*] Or so I believe; it's not something I've tried yet...


acg
Reply | Threaded
Open this post in threaded view
|

Re: CardContainer example please

acg
>... All Views can have their #text set.  Exactly what that means depends on the
> view; for a ShellView it's the window caption; for a CheckBox it's the label
> for the box; and so so.  Sometimes the view makes no use of its #text at all,
> but the aspect is still there. Usually the #text is a purely view-ish thing and
> is not related to the model...

Thanks for sharing your insight. Sometimes doing a drill down of
presenters and subpresenters feels like an exercise of looking in a
dictionary for a good definition for 'recursion' and finding 'see
recursion'. Come to think of it, this presenter-subpresenter stuff is
sort of fractal.
ACG