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 |
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 |
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. > > ... 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 |
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 |
> ...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 |
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 |
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 |
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... |
>... 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 |
Free forum by Nabble | Edit this page |