MVP и пакетный цикл между представителем и докладчиком

Я только что пришел на проект, где они используют дизайн GWT и MVP. Они используют следующую структуру:

client.mvp.presenter (contains interfaces)
client.mvp.presenter.impl
client.mvp.view (contains interfaces)
client.mvp.view.impl

В коде Presenter знает свое представление, но представление также знает своего Presenter, поэтому я нашел циклы в пакете между Presenter.impl и View.impl.

Думая об этом снова, я спросил себя, почему impl связаны между собой, вместо того, чтобы ссылаться только на интерфейсы и, таким образом, избегая цикла.

Но я также думаю, "почему представление должно знать своего предъявителя?" и, глядя на какой-то сайт, говорящий о MVP, не очень понятно, должны ли зрители и докладчики знать друг друга.

Что будет лучше?

  • Попросить их использовать интерфейсы для удаления цикла?
  • Попросить удалить presenter и позволяет ли ведущий непосредственно взаимодействовать с пользователем?
  • Ничего не делать, обычно цикл между этими пакетами в MVP

Спасибо!

2 ответа

Решение

С MVP докладчик и представление должны знать интерфейсы партнера:

  • Ведущий обычно должен обновить представление
  • Представление вызывает методы презентатора, когда происходят события (например, ValueChangeEvents).

Попросить их использовать интерфейсы для удаления цикла?

Да.

Попросить убрать докладчика с поля зрения и позволить докладчику непосредственно взаимодействовать с пользователем?

Нет, это не будет MVP.

Ничего не делать, обычно цикл между этими пакетами в MVP

Цикл, который обязательно остается, - это цикл создания: вы не можете использовать как презентатора в качестве параметра конструктора представления, так и представления в качестве конструктора параметра презентатора. Это становится особенно очевидным при использовании Dependency Injection на основе конструктора и теоретически неизбежно в Java. Но вы можете выбрать либо использовать установщик (по крайней мере на одной стороне), либо использовать фабрику / провайдера с внедрением конструктора.

На самом деле, в то время как презентатор impl [1] теперь нуждается в представлении (интерфейсе), интерфейс презентатора вообще не нужен.

Типичная картина:

interface FooPresenter {
   // methods called by the view (generally in response to user interaction)
   void doSomething(String foo);
}

interface FooView {
   /** Tells the view which presenter instance to call back. */
   void setPresenter(FooPresenter presenter);

   // methods called by the presenter to control the view
   void showSomething(String foo);
}

class FooPresenterImpl implements FooPresenter {
    private final FooView view;

    FooPresenterImpl(FooView view, /* other dependencies here */) {
       this.view = view;
    }

    // could also be the start() method of com.google.gwt.activity.shared.Activity
    public void init() {
       view.setPresenter(this);
    }

    // optional; could be called from onStop() and onCancel() if using Activity
    public void dispose() {
       view.setPresenter(null);
    }
}

На самом деле, я обычно объявляю интерфейс презентатора, вложенный в интерфейс представления:

interface FooView extends IsWidget {

    interface Presenter {
       // ...
    }

    void setPresenter(Presenter presenter);

    // ...
}

class FooPresenter extends AbstractActivity implements FooView.Presenter {
   // ...
}

Что касается знания, подразумевается, что наиболее важно то, что презентатор не ссылается на представление, так как это (как правило) предотвратит юнит-тестирование без GWTTestCase (издевается над видом). Обратное - меньше проблем, но тогда вам не нужен интерфейс презентатора по сравнению с Impl, верно?

[1] технически это может быть подразумеваемое представление, но, как правило, все наоборот, так что представление может пережить презентатора (презентаторы, как правило, легковесны, в отличие от представлений, которые могут иметь немалое время создания из-за манипуляций с DOM)

Другие вопросы по тегам