Почему в Presenter First метод SubscribeSomeEvent в интерфейсе предпочтительнее простых старых событий? - PullRequest
5 голосов
/ 05 октября 2009

Я недавно узнал о Presenter First и прочитал их технические документы и блоги и т. Д.

В большинстве примеров, которые я обнаружил, события объявляются не непосредственно в интерфейсе, а как метод для него. Например,

public interface IPuzzleView
{
    void SubscribeMoveRequest(PointDelegate listener);
    // vs
    event PointDelegate MoveRequest;
}

Я не совсем понимаю, почему. Я думал, что где-то видел статью / статью / блог, где объясняются причины этого, но я больше не могу его найти. В указанном тексте также содержались фрагменты кода модульного тестирования - я знаю это, потому что помню, как говорил себе, что один из модульных тестов был неверным.

UPDATE:

Ниже приведен пример для сравнения:

public class Collect
{
    public static CollectAction<T> Argument<T>(int index,
        CollectAction<T>.Collect collectDelegate)
    {
        CollectAction<T> collect = new CollectAction<T>(index, collectDelegate);
        return collect;
    }
}

public interface IApplicationView
{
    event EventHandler Load;

    // or

    void SubscribeLoad(Action action);
}

Mockery mockery = new Mockery();
IApplicationView view = mockery.NewMock<IApplicationView>();
IApplicationModel model = mockery.NewMock<IApplicationModel>();

Стиль подписки:

Action savedAction = null;
Expect.Once.On(view).Method("SubscribeLoad").Will(
    Collect.Argument<Action>(0,
    delegate(Action action) { savedAction = action; }));
Expect.Once.On(model).Method("LoadModules");
new ApplicationPresenter(view, model);
savedAction();
mockery.VerifyAllExpectationsHaveBeenMet();

против. Событие:

Expect.Once.On(view).EventAdd("Load", Is.Anything);
Expect.Once.On(model).Method("LoadModules");
new ApplicationPresenter(view, model);
Fire.Event("Load").On(view);
mockery.VerifyAllExpectationsHaveBeenMet();

К вашему сведению, описанный выше стиль событий не будет работать как есть, так как ApplicationPresenter сразу же собирает мусор, а проводка никогда не происходит.

1 Ответ

4 голосов
/ 08 января 2010

Короткий ответ таков: Presenter First изначально развивался во времена .NET 1.1 и VS2003, и события C # могли быть проблематичными.

Тогдашние инструменты тестирования / проверки не поддерживали нашу необходимость инкапсулировать подписку и рассылку событий. Со временем мы почувствовали, что разоблачение специфической природы событий вне их излучающих классов обременяет клиентский код слишком большим знанием реализации, что затрудняет рефакторинг.

Для опубликованных примеров мы хотели бы избежать ассоциирования техники Presenter First с языковой функцией. (Например, Java не имеет эквивалента C # событий или делегатов, но это не значит, что вы не можете использовать шаблон Observer.)

Я вижу, что события, анонимные делегаты и насмешные инструменты прошли долгий путь за последние несколько лет. В следующий раз, когда я возьму проект C #, я пересмотрю все свои предположения о «наилучшем способе» обработки подписки и отправки событий. Приведенные выше примеры интригуют.

Чтобы подвести итог нашим оригинальным, возможно, датированным, причинам, скрывающим наше использование событий C #: - Подписка на издевательство не была возможна в модульных тестах - Иногда мы использовали другой внутренний механизм для обработки подписки / отправки событий. Это привело к несогласованности между интерфейсами. - Несколько раз мы рассматривали возможность отказа от событий C # даже внутри компании, поскольку они вели себя по-разному, когда не было подписчиков. Разоблачение событий извне усложнило бы повторную реализацию.

Когда Джихо Хан связал меня с этим вопросом, он также спросил о привязке данных и более конкретном примере PF, на который я ответил, опубликовав более новый, более полный пример Presenter First и подробно описав адаптеры .

...