GWT MVP architecture advantages

前端 未结 2 994
天命终不由人
天命终不由人 2021-01-31 12:28

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 testi

2条回答
  •  伪装坚强ぢ
    2021-01-31 13:08

    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...

提交回复
热议问题