Почему в Presenter First метод SubscribeSomeEvent в интерфейсе предпочтительнее простых старых событий?
Недавно я узнал о Presenter First и прочитал их технические документы, блоги и т. Д.
В большинстве примеров, которые я нашел, события объявляются не непосредственно в интерфейсе, а как метод для него. Например,
public interface IPuzzleView
{
void SubscribeMoveRequest(PointDelegate listener);
// vs
event PointDelegate MoveRequest;
}
Я не совсем понимаю, почему. Я думал, что где-то видел статью / статью / блог, где объясняются причины этого, но я больше не могу его найти. В указанном тексте также содержались фрагменты кода модульного тестирования - я знаю это, потому что помню, как говорил себе, что один из модульных тестов был неверным.
ОБНОВИТЬ:
Ниже приведен пример для сравнения:
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 ответ
Короткий ответ таков: Presenter First изначально развивался во времена.NET 1.1 и VS2003, и события C# могли быть проблематичными.
Тогдашние инструменты тестирования / проверки не поддерживали нашу необходимость инкапсулировать подписку и рассылку событий. Со временем мы почувствовали, что разоблачение специфической природы событий вне их излучающих классов обременяет клиентский код слишком большим знанием реализации, что затрудняет рефакторинг.
В опубликованных примерах мы хотели не связывать метод Presenter First с языковой функцией. (Например, Java не имеет эквивалента C# событий или делегатов, но это не значит, что вы не можете использовать шаблон Observer.)
Я вижу, что события, анонимные делегаты и насмешливые инструменты прошли долгий путь за последние несколько лет. В следующий раз, когда я возьму проект на C#, я пересмотрю все свои предположения о "наилучшем способе" обработки подписки и отправки событий. Приведенные выше примеры интригуют.
Подводя итог нашим оригинальным, возможно, датированным причинам скрытия нашего использования событий C#: - подписка на поддельные события была невозможна в модульных тестах - иногда мы использовали другой внутренний механизм для обработки подписки / отправки событий. Это привело к несогласованности между интерфейсами. - Несколько раз мы рассматривали возможность отказа от событий C# даже внутри компании, поскольку они вели себя по-разному, когда не было подписчиков. Разоблачение событий извне усложнило бы повторную реализацию.
Когда Джихо Хан связал меня с этим вопросом, он также спросил о привязке данных и более конкретном примере PF, на который я ответил, опубликовав новый, более полный пример Presenter First и подробно остановившись на адаптерах.