On 23 juil, 10:20, Kwhit <kwhitting...@gmail.com> wrote:
> I think Jason has hit the nail on the head.
>
> The reason I got uncomfortable with the HasXxx's is that they expose
> the internal workings of the Viewer (Display in RR's terms). The name
> getSelectionButton() is a clue. The presenter doesn't and shouldn't
> care about how the Viewer decides how to trip an action - it might be
> by some convoluted means like a time out and then HasClickHandler
> makes no sense.

If you care about "modularization", then yes; but if you are more
pragmatic and only think about decoupling (to allow testing your
"presentation logic" separate from the actual "view"), then I don't
see a problem (much like whether your components know the "place
service" or the place service is rather an "optional module" that you
can plug in and out of your app without side effect apart from
"history management" // see above in this thread).

> The other thing that made me uncomfortable was where Display was
> defined - in the Viewer implementation.

Er, no, it's in the Presenter (slides 58 and 59).

> As a programmer I find myself being too focused on the internal view
> when I should be looking at how consumers of an interface see it.
> Guice for example sees it's core entities as injectors but I see them
> as factories. As the consumer, the Presenter is the boss here and, for
> example, a sign in Viewer only needs (g/s)etAccountName(), getPassword
> () and a 'signIn' callback. The HasXxxx expose a whole lot of other
> functionality that you don't want anybody using.

IMO, you're thinking here at a higher level.

If I have a text field (for the user name), password field and button
(to sign-in), and want the sign-in button to be automatically disabled
whenever one of the field is empty; then I need to listen for events
on the fields. This is part of the Presenter logic, because:
 - it works whether the view is implemented in GWT (HTML) or Swing
 - it works whether I use a text field or password field for the
password
 - it works whether I use a Label, HTML, Button, CustomButton or
PushButton
 - that's a behavior I that I want to be testable (this is the main
argument actually)
Here, HasValue<String> comes in very handy (instead of: getAccountName
() + addAccountNameChangeHandler(), etc.) what would be missing in GWT
is a "Enableable" interface for the button.

The point of Ray about MVP is about testability of your presentation
logic with "pure Java" JUnit tests. You still think in terms of
widgets but your don't have a dependency on the Widget class (which
has a dependency on com.google.gwt.dom.*, which uses JSNI and
therefore requires a GWTTestCase; on the other hand, DomEvent<?>, such
as ClickEvent, only use JSNI as part of the getNativeEvent(); you can
mock a ClickEvent by extending it and how it is used by other methods
such as preventDefault and stopPropagation, but the class can be
extended and the methods overriden if you really need your Presenter
to deal with them, and your MockHasClickHandlers would then pass such
a MockClickEvent to the presenter's ClickHandler).

It's just and only about how to organize your widgets code to make it
testable easily.

The goal isn't that your test be independent of the presenter's
internals (if the presenter doesn't even make use of the ClickEvent,
the mock HasClickHandlers could pass 'null' as an argument instead of
a MockClickEvent).
It isn't either that your presenter be independent of the view
"details" (if your first version didn't enable/disable the sign-in
button but instead show an alert if one of the fields were empty when
the button is clicked, you wouldn't need HasValue<String> and a
getAccountName would be enough; and the time you change your mind
about your presentation logic, you update both your presenter and view
code).

You can of course use MVP at a higher level too, but the whole point
of Ray is to not burn your event handlers inside your "view" and
instead use "abstract" interfaces

(updated with your followup mail)
> In summary
> 1/ Define your Presenter logic
> 2/ Define Viewer interface (without thinking about how the Viewer
> might be implemented)
> 3/ Unit test your Presenter implementation
> 4/ Implement and test your Viewer

I think you were right in your first mail: "define the Display/Viewer
interface" *thinking* about how you'll implement it, because your
presenter logic relies on it.

As I said, you're at a higher level here; thinking more about
modulalization/componentization and abstractions, than about
pragmatism and testability of your UI logic (don't put words in my
mouths: this is not a bad thing, just something different).

To continue the reasoning about this example: the presenter would,
when the sign-in button is clicked, make an RPC call to validate the
credentials. If I understand Ray's Command Pattern correctly, the RPC
call would be successful even if the credentials were wrong, with the
ValidateCredentialsResponse object containing the error (see slide
#62); so the SignInPresenter would have it's AsyncCallback#onSuccess
called and could handle the error by e.g. showing a message (the view
could show it next to the sign-in button for example). The generic
AsyncCallback#onFailure processing is only used for unexpected server
errors. On a successful login, then either the presenter or the
service (using a wrapping ServiceAsync implementation; but I think
this is actually useful merely for CRUD operations on data) would fire
a SignInEvent on the event bus.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to Google-Web-Toolkit@googlegroups.com
To unsubscribe from this group, send email to 
google-web-toolkit+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/Google-Web-Toolkit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to