well, as Ray Ryans talk indicates, the UiBinder and the MVP patterns work quite well together (i.e. the UiBinder doesn't leave the MVP behind). Here's the thing with making the view's .java file contain business logic: it's business logic in your view. The ui.xml is simply for layout, it's has no concept of control statements (if/else/for etc.) so *some* java code needs to back it. That java code that backs the view should really be view-centric, not business logic centric.
The first time I played with UiBinder I was quite tempted to put raw event handling in the view's .java file, however it felt wrong (especially after watching Ray Ryans GWT Best Practices talk), so that drove me to having the view dispatch events rather than control the UI's business logic. For instance: sometimes you need to pull things from the backend server based on an event from the user (choosing something from a drop down, clicking on a checkbox etc.) it just feels wrong to have a class that extends Composite handle that kind of traffic. Hence the decision to have a Presenter manage that communication. History has shown when you have a clear, distinct separation of concerns between your UI and your business logic your code is more stable, note that this isn't a clear line drawn between the UI event handling and the UI layout. :) I guess it all boils down to preference, but I do happen to have experience working on projects where business logic is embedded in display level classes and it simply isn't scalable (i.e. you can't swap out the display easily, and you can't ever re-use the business logic code unless you load your whole UI framework). just a thought, -bryce On Fri, Mar 5, 2010 at 2:13 PM, Fabio Kaminski <[email protected]> wrote: > the way i see, when UiBinder arrives it has made the Presenter/Display > design behind it.. > particularly i find a little painful to write that kind of weird coding.. > > in that way UiBinder was a blessing, cause, in my point of view the ui.xml > file its similar to display as the view tier.. > and leave the widget .java file to write only the event handling logic > similar to presenter tier in that example.. > > and the best of it.. with less code and confusion, with a new xml artefact > that could be handled by a designer focused on it if you wish so, that > does'nt need any java knowlodge or to open the source and compile every > time you need to change the view tier.. > > > > > > On Fri, Mar 5, 2010 at 5:16 PM, bryce cottam <[email protected]> wrote: >> >> indeed, that's the direction I'm going with it. I wasn't using GIN at >> first, (since everything I was doing was proof of concept) but now >> that I'm "really" coding it, GIN comes in quite handy for this. >> >> On Thu, Mar 4, 2010 at 6:30 PM, PhilBeaudoin >> <[email protected]> wrote: >> > Just a quick thought... If you wanted to make the Presenter-View >> > relationship bidirectional without having to inject it manually, >> > couldn't you have GIN inject a Provider<MyPresenter.DisplayHandlers> >> > into the view? Then you just bind MyPresenter.DisplayHandlers to >> > MyPresenter. >> > >> > On Feb 21, 11:33 am, ross <[email protected]> wrote: >> >> Hey all, >> >> >> >> I have been wrestling with this design pattern the past week or so on >> >> my application architecture. I am eagerly awaiting to hear Google's >> >> stance onUiBinder+MVPpatterns but maybe we'll have to wait for I/O >> >> to find that out :) >> >> >> >> In the meantime I really appreciated this thread and I've gone with >> >> something very much along the lines of what Bryce mentioned with >> >> having the 'Execute' interface in the Presenter. Having the 'Execute' >> >> interface defined in the View seemed too circular for me (and also the >> >> javac) :) >> >> >> >> Here's my code: >> >> >> >> --------------------------------------------- >> >> Presenter >> >> --------------------------------------------- >> >> >> >> public class MyPresenter implements Presenter { >> >> >> >> public interface DisplayHandlers { >> >> void onBackLabelClicked(); >> >> } >> >> >> >> public interface Display { >> >> void setDisplayHandlers(DisplayHandlers handlers); >> >> Widget asWidget(); >> >> } >> >> >> >> public MyPresenter(..., HandlerManager eventBus, >> >> Display display) { >> >> this.eventBus = eventBus; >> >> this.display = display; >> >> } >> >> >> >> @Override >> >> public Widget bind() { >> >> display.setDisplayHandlers(new DisplayHandlers() { >> >> >> >> @Override >> >> public void onBackLabelClicked() { >> >> // fire an event on the bus or whatever else you may fancy >> >> } >> >> >> >> }); >> >> >> >> return display.asWidget(); >> >> } >> >> >> >> } >> >> >> >> --------------------------------------------- >> >> View >> >> --------------------------------------------- >> >> >> >> public class ErrorView extends Composite implements >> >> ErrorPresenter.Display { >> >> >> >> @UiField >> >> Label backLabel; >> >> >> >> ErrorPresenter.DisplayHandlers handlers; >> >> >> >> } >> >> >> >> --------------------------------------------- >> >> >> >> hope this helps someone (only relevant code is shown) >> >> >> >> On Jan 29, 3:37 pm, bryce cottam <[email protected]> wrote: >> >> >> >> >> >> >> >> > Yes, I am using this pattern and liking it quite a bit right now. I >> >> > feel it cleans up a lot of boiler-plate code. >> >> > Here is a sample application that demonstrates some of the design >> >> > patterns I'm using (including the Command Pattern for RPC calls): >> >> >> >> >http://www.resmarksystems.com/code/GwtSample.zip >> >> >> >> > It's pretty basic, and some things could be improved (like the use of >> >> > GIN/Guice and some more reflection based RPC dispatching on the >> >> > server), but I didn't go to great lengths to include that because the >> >> > main thing I wanted to demonstrate in this code was the use of the >> >> > MVC >> >> > tweaks brought up in this thread. >> >> >> >> > I want to emphasize that it was thrown together for a friend in order >> >> > to demonstrate concepts and not as a tutorial walk through, it >> >> > includes stuff like rpc based login (which I don't suggest using). >> >> > Anyhow, I hope it helps demonstrate how I'm dispatching events. >> >> >> >> > as far as your usingUiBinder+MVPwithout any issues: I wouldn't say >> >> > your "missing" anything per se', it's just that I wanted something >> >> > cleaner than what I was seeing around the forums. I don't like >> >> > returning HasText/HasClickHandler type interfaces from my view to my >> >> > presenter 'cause I think my display can be smarter than that without >> >> > embedding any business logic in it. I like making calls like >> >> > display.getName() rather than display.getNameBox().getText(). When I >> >> > do things that way, it makes it really easy to swap out my display >> >> > instances with simple beans and I don't have to much with any testing >> >> > frameworks like easymock or anything. I've found it to be helpful. >> >> >> >> > cheers, >> >> > -bryce >> >> >> >> > On Fri, Jan 29, 2010 at 3:42 AM, Matt Read <[email protected]> wrote: >> >> > > Hi, could you possible re-cap on what problem this approach solves? >> >> > > I'm >> >> > > usingUIBinderwithmvp-presenter without inverting the dependencies >> >> > > in this >> >> > > way without any problems so I'm wondering what I'm missing. >> >> > > Thanks, >> >> > > Matt. >> >> >> >> > > 2010/1/29 István Szoboszlai <[email protected]> >> >> >> >> > >> Hello Bryce, >> >> >> >> > >> Are you using the approach you were describing in any project now >> >> > >> with >> >> > >> success? If so it would be very appreciated if you could write >> >> > >> some >> >> > >> sentences about your experiences. >> >> > >> I thing I like what you proposed, and I also think it is not a big >> >> > >> drawback that you have to inject the presenters 'execute' >> >> > >> interface int he >> >> > >> view by hand. >> >> >> >> > >> So I think I will give a chance to this approach. >> >> >> >> > >> I'll write if I have any conclusion (good, or bad). >> >> >> >> > >> Best - Istvan >> >> >> >> > >> On Wed, Dec 30, 2009 at 1:55 AM, bryce cottam <[email protected]> >> >> > >> wrote: >> >> >> >> > >>> very similar, but I think I either wanted to keep the Execute >> >> > >>> interface on the Presenter (since the View is already dependent >> >> > >>> on a >> >> > >>> nested interface from the Presenter) or having it on a top level >> >> > >>> package. Come to think of it I think I tried to define the >> >> > >>> Execute >> >> > >>> interface inside the Presenter and the compiler didn't like that, >> >> > >>> so I >> >> > >>> wound up just making it a top level api Interface. I think this >> >> > >>> is >> >> > >>> more decoupled than the interface being nested in the View >> >> > >>> implementation, (since the Presenter is only dealing with >> >> > >>> interfaces >> >> > >>> defined either in it's self, or in a top level package) >> >> >> >> > >>> You are correct on the constructor injection though, you wouldn't >> >> > >>> be >> >> > >>> able to inject both via constructor arguments, however, in the >> >> > >>> Presenter constructor you could simply inject it's self into a >> >> > >>> setter >> >> > >>> on the Display: >> >> >> >> > >>> public MyPresenter(MyDisplay display) { >> >> > >>> display.setExecute(this); >> >> > >>> } >> >> >> >> > >>> I'm used to Spring-style injection, which usually leverages some >> >> > >>> kind >> >> > >>> of setter post-construction anyhow. You could even have some >> >> > >>> other >> >> > >>> class implement the Executer api that just had a reference to the >> >> > >>> Presenter instance, but that's a few levels of indirection for >> >> > >>> delegating method calls :) >> >> >> >> > >>> I guess it's a small trade off for me to self-inject in my >> >> > >>> constructor >> >> > >>> rather than having Guice inject me if I can reduce boiler plate >> >> > >>> code. >> >> >> >> > >>> I'm glad to hear you were at least considering my approach, it's >> >> > >>> nice >> >> > >>> to know i'm not way off in left field. >> >> >> >> > >>> -bryce >> >> >> >> > >>> On Tue, Dec 29, 2009 at 4:53 PM, FKereki <[email protected]> >> >> > >>> wrote: >> >> > >>> > I also gave a thought to your method, but in the end opted >> >> > >>> > out... but >> >> > >>> > I guess it's where you are heading. >> >> >> >> > >>> > In the same way that the View implements Display, an interface >> >> > >>> > defined >> >> > >>> > in the Presenter class, Presenter could implement Execute, an >> >> > >>> > interface defined in the View class. >> >> >> >> > >>> > The View should have a method allowing injection of the Execute >> >> > >>> > object; the Presenter would this "self injection" in its >> >> > >>> > constructor. >> >> >> >> > >>> > Then, whenever any event happened, the View handler would do >> >> > >>> > getExecute >> >> > >>> > ( ).someMethod( ). >> >> >> >> > >>> > You would do away with all anonymous classes, and each class >> >> > >>> > (View, >> >> > >>> > Presenter) would implement an interface defined in the other >> >> > >>> > class. >> >> >> >> > >>> > The symmetry breaks down a bit because you cannot inject each >> >> > >>> > object >> >> > >>> > in the other through their constructors (obviously!) >> >> >> >> > >>> > Is this along the lines you were thinking? >> >> >> >> > >>> > -- >> >> >> >> > >>> > You received this message because you are subscribed to the >> >> > >>> > Google >> >> > >>> > Groups "Google Web Toolkit" group. >> >> > >>> > To post to this group, send email to >> >> > >>> > [email protected]. >> >> > >>> > To unsubscribe from this group, send email to >> >> > >>> > [email protected]. >> >> > >>> > For more options, visit this group at >> >> > >>> >http://groups.google.com/group/google-web-toolkit?hl=en. >> >> >> >> > >>> -- >> >> >> >> > >>> You received this message because you are subscribed to the >> >> > >>> Google Groups >> >> > >>> "Google Web Toolkit" group. >> >> > >>> To post to this group, send email to >> >> > >>> [email protected]. >> >> > >>> To unsubscribe from this group, send email to >> >> > >>> [email protected]. >> >> > >>> For more options, visit this group at >> >> > >>>http://groups.google.com/group/google-web-toolkit?hl=en. >> >> >> >> > >> -- >> >> > >> Best Regards >> >> > >> - István Szoboszlai >> >> > >> [email protected] | +36 30 432 8533 | inepex.com >> >> >> >> > >> -- >> >> > >> You received this message because you are subscribed to the Google >> >> > >> Groups >> >> > >> "Google Web Toolkit" group. >> >> > >> To post to this group, send email to >> >> > >> [email protected]. >> >> > >> To unsubscribe from this group, send email to >> >> > >> [email protected]. >> >> > >> For more options, visit this group at >> >> > >>http://groups.google.com/group/google-web-toolkit?hl=en. >> >> >> >> > > -- >> >> > > You received this message because you are subscribed to the Google >> >> > > Groups >> >> > > "Google Web Toolkit" group. >> >> > > To post to this group, send email to >> >> > > [email protected]. >> >> > > To unsubscribe from this group, send email to >> >> > > [email protected]. >> >> > > For more options, visit this group at >> >> > >http://groups.google.com/group/google-web-toolkit?hl=en. >> > >> > -- >> > You received this message because you are subscribed to the Google >> > Groups "Google Web Toolkit" group. >> > To post to this group, send email to >> > [email protected]. >> > To unsubscribe from this group, send email to >> > [email protected]. >> > For more options, visit this group at >> > http://groups.google.com/group/google-web-toolkit?hl=en. >> > >> > >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Google Web Toolkit" group. >> To post to this group, send email to [email protected]. >> To unsubscribe from this group, send email to >> [email protected]. >> For more options, visit this group at >> http://groups.google.com/group/google-web-toolkit?hl=en. >> > > -- > You received this message because you are subscribed to the Google Groups > "Google Web Toolkit" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/google-web-toolkit?hl=en. > -- You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.
