Frage

MVP pattern assumes that View expose methods to Presenter. For example in View we can write:

public HasClickhandlers getButton() {
    return myBtn;
} 

and access to this method from presenter, like

view.getButton().addclickhanlder() ...

But when I build my app in this style, I have a lot unnecessary code. For example I want to create TablesView and TablesPresenter (I decide thatTablesPresenter and TablesView is minimal entity (minimal module), that can not be divided into more small presenters and views, and can not be more complex). Then, when I create TablesView, I want to put inside this view another custom component - MyCustomTable. And Inside MyCustomTable put MyCustomHeader, inside MyCustomHeader put MyCustomFilter and so on (this sequence may be much longer)... So problem is when I want to access from Presenter to entered text(by user) inside MyCustomFilter, I need to expose method on MyCustomFilter:

//inside MyCustomFilter
public String getFilterText() {
   return textBox.getText();
}

then in widget that contains MyCustomFilter - i.e. in MyCustomHeader I need to expose this method:

//inside MyCustomHeader
public String getFilterText() {
  return myCustomFilter.getFilterText();
}

after it, inside MyCustomTable I need to expose this method:

//inside MyCustomTable
public String getFilterText() {
  return myCustomHeader.getFilterText();
}

After it I need to expose getFilterText() method inside TablesView (that contains MyCustomTable) and after all this operations my presenter can access to text inside MyCustomFilter.. And sometime this sequence is more longer. So how to solve this problem? May be I not understand some things about MVP?

War es hilfreich?

Lösung

One way to solve it would be the use of interfaces. By that you could expose a view of your components without creating a tight coupling between the view and the presenter.

Something along these lines:

public interface CustomFilter {
   String getFilterText();
   // other methods that might be accessed from your presenter
}

public class MyCustomFilter implements CustomFilter {

    @Override
    public String getFilterText() {
        return textBox.getText();
    }
}

You can do the same thing for the other componenents:

CustomHeader:

public interface CustomHeader {
   CustomFilter getFilter();
   // or String getFilterText()
   // other methods that might be accessed from your presenter
}

public class MyCustomHeader implements CustomHeader {

    @Override
    public CustomFilter getFilter() {
        return myCustomFilter;
    }
}

CustomTable:

public interface CustomTable {
   CustomHeader getHeader();
   // or Sring getFilterText();
   // other methods that might be accessed from your presenter
}

public class MyCustomTable implements CustomTable {

    @Override
    public CustomHeader getHeader() {
        return myCustomHeader;
    }
}

You can decide if you only want to expose in each interface just a String or the entire client component's interface. If you expose the entire interface you might violate the law of demeter by having calls like this in your presenter:

getView().getTable().getHeader().getFilter().getFilterText(). 

Probably a better solution would be to define Strings in your interfaces which delegate the calls up the hierarchy to the your CustomFilter interface: getView().getTable().getFilterText(); or even getView().getFilterText().

The other benefits of using interfaces is that you can easily mock them for Unit testing your presenters and even view components in isolation and you can easily create an switch between different implementations of your UI components (for example one that is optimized for smartphones, etc) without changing anything in your Presenters

Andere Tipps

There's no reason your view cannot return a view on one of its components, but you have to think in terms of componentization: that'll break encapsulation, your view then exposes its internals.

Also, keep in mind that one of the most important benefit of MVP in GWT is that you can easily mock your views and unit-test your presenters without a sluggish GWTTestCase. There are trade offs to make your code easily testable/mockable.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top