GWT MVP architecture advantages

2020-05-16 06:59发布

问题:

I am learning GWT and i have read at multiple places that using MVP architecture is best suitable to develop a GWT Application

I have also read that its easy to do testing using the MVP ARCH.Can somebody explain me why its easy to do testing using the MVP architecture.

Also i am working on a project using MVP and i find it very tedious to make the view connect to the data base.I mean i have to update my presenter,service,serviceAsync,servicImpl,Facades in order to make connection to database.

So can somebody provide me the essence of MVP for GWT?i would appreciate a couple of examples.

回答1:

Separation between the presenter (which contains logic) and view (a dumb wrapper around UI controls) allows you to:

  • write unit tests for the presenters that can run without needing the corresponding environment (desktop, browser, GWT widgets)
  • reuse front-end logic without being tied to a particular set of widgets/UI framework

The latter use case is rare, so let's focus on the MVP model's suitability for automated, programmatic testing. With a team of developers this often takes the form of a continuous build/test cycle using Hudson (or similar) on a headless server, where it's not practical to open a web browser, create controls, etc. every time a test is run.

Typical usage of MVP+GWT is that views implement an interface provided by the presenter, and often this interface is defined in terms of other generic interfaces. Here's a very simple presenter that increments a numeric label when a button is clicked - note that instead of exposing the TextBox and Button directly, the view returns generic HasText and HasClickHandlers instances:

public class ButtonClickPresenter {
    public interface View {
        HasText currentValue();
        HasClickHandlers incrementButton();
    }

    private final View myView;
    private int currentValue = 0;

    public ButtonClickPresenter(View myView) {
        this.myView = myView;
        this.myView.currentValue().setText("0");

        this.bind(); // for the sake of demonstration
    }

    public void bind() {
        this.myView.incrementButton.addClickHandler(
            @Override
            new ClickHandler() {
                void onClick(ClickEvent event) {
                    currentValue ++;
                    myView.currentValue().setText(
                        Integer.toString(currentValue));
                }
            });
    }
}

The "real" view returns UI widgets (created via UiBinder in this example):

public class ButtonClickView implements ButtonClickPresenter.View {
    // ... skipped UiBinder initialisation ...

    @UiField Label currentValueLabel;
    @UiField Button incrementButton;

    @Override
    public HasText currentValue() {
        return currentValueLabel;
    }

    @Override
    public HasClickHandlers incrementButton() {
        return incrementButton;
    }

    // ... etc ...
}

whereas unit tests create a dummy implementation (or use Mockito, EasyMock, etc.) and thus don't require any UI components:

public class ButtonClickPresenterTest {
    ButtonClickPresenter presenter;
    ClickHandler currentHandler;
    String currentText;

    @Before
    public void setUp() {
        presenter = new ButtonClickPresenter(
            // dummy view - just stores label text in a String and
            // keeps track of the Presenter's click handler
            new ButtonClickPresenter.View() {
                @Override
                public HasText currentValue() {
                    return new HasText() {
                        @Override public String getText() { return currentText; }
                        @Override public void setText(String text) { currentText = text; }
                    };
                }

                @Override
                public HasClickHandlers incrementButton() {
                    return new HasClickHandlers() {
                        @Override
                        public HandlerRegistration addClickHandler(ClickHandler handler) {
                            currentHandler = handler;
                        }
                    };
                }
            });
    }

    @Test
    public void testIncrement() {
        // initial value
        assertEquals("0", currentText);

        // clicking the button should increment the number
        currentHandler.onClick(null);
        assertEquals("1", currentText);
    }
}

As for your next paragraph: your views shouldn't be connecting to the database at all! The presenter should request data via Service/ServiceAsync (or an abstraction such as gwt-dispatch or gwt-platform), then call methods on the view to populate the UI.

By the way, those last two links (along with gwt-presenter) are a good start if you're looking for GWT MVP code samples - combined with Google GIN they provide frameworks for tying all this stuff together.

Having said all that, I agree - the combination of GWT+MVP+Java can be hard work and extremely verbose (I'm glad I don't have to work with it much these days). The alternative, though, is even less attractive: an untestable, unmaintainable ball of spaghetti...



回答2:

You might like to have a look at the sample gwt-platform application blogged about here-> http://uptick.com.au/content/serendipity-working-gwt-platform-and-smartgwt.

Cheers Mark



标签: gwt mvp