System.SystemEvents и FDG
От: _NN_ www.nemerleweb.com
Дата: 11.10.15 05:45
Оценка:
Не нарушает ли класс System.SystemEvents рекомендации FDG ?

Скажем если я хочу создать класс SessionEvents, делать его со статическими событиями или простым экземпляром ?
var s = new SessionEvents()
s.Logon += onLogon;

// против
SessionEvents.Logon += onLogon;
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: System.SystemEvents и FDG
От: Sinix  
Дата: 11.10.15 08:22
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Не нарушает ли класс System.SystemEvents рекомендации FDG ?


А с чего им нарушать-то?
Вполне логичный и простой способ для хоста дать доступ к глобальным событиям, кмк. Null вместо сендера легальная практика, емнип в FDG этот момент оговорен был.

Не, если у вас в одном Appdomain будут уживаться несколько сессий с разной логикой обработки этих событий — вы сами почувствуете, что что-то пошло не так.
Другое дело, что в этом случае SessionEvents будут меньшей из ваших проблем
Re: Экземпляр
От: Qbit86
Дата: 11.10.15 08:55
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Скажем если я хочу создать класс SessionEvents, делать его со статическими событиями или простым экземпляром ?

_NN>
_NN>var s = new SessionEvents()
_NN>s.Logon += onLogon;

_NN>// против
_NN>SessionEvents.Logon += onLogon;
_NN>


В качестве отправной точки лучше предпочесть нестатические методы события в статическом экземпляре (синглтон). Это упрощает анализ зависимостей и рефакторинг. Глобальный доступ к экземпляру проще переделать в локальный доступ к экземпляру (передача зависимостей в конструктор, после чего клиент ничего не знает о глобальности/синглтонности используемых сервисов). Зависимости становятся явными, и это позволяет ими манипулировать (передавать отладочные экземпляры того же класса SessionEvents, или быть может экземпляры отладочных классов DebugSessionEventsDecorator в случае иерархии).
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Экземпляр
От: Sinix  
Дата: 11.10.15 10:03
Оценка:
Здравствуйте, Qbit86, Вы писали:


Q>В качестве отправной точки лучше предпочесть нестатические методы события в статическом экземпляре (синглтон). Это упрощает анализ зависимостей и рефакторинг.


Вот это как раз то, что не следует делать по FDG: введение абстракции без _реальной_ необходимости.
Начните с сценариев использования. Несколько сессий в одном appdomain, для сессии нужно протаскивать глобальное состояние? Начинаем искать решение. Нет — сидим на попе и не дёргаемся.

Самое забавное, что если не дёргаться раньше времени, то можно прийти к куда более красивым решениям, чем унылое протаскивание зависимостей по всей цепочке, причём без отказа от статических свойств/событий. Hint: AsyncLocal<T>.
Re[3]: Экземпляр
От: Qbit86
Дата: 11.10.15 10:18
Оценка:
Здравствуйте, Sinix, Вы писали:

Q>>В качестве отправной точки лучше предпочесть нестатические методы события в статическом экземпляре (синглтон). Это упрощает анализ зависимостей и рефакторинг.


S>Вот это как раз то, что не следует делать по FDG: введение абстракции без _реальной_ необходимости.


Нет никакой новой абстракции. В простейшем сценарии для клиента использование `SomeService.Instance.Method()` от `SomeService.Method()` отличается ровно ничем. Зато в дальнейшем не запирается возможность вместо `SomeService.Instance.Method()` использовать `_someService.Method()`, где `_someService = SomeService.Instance`, или `_someService = someService`, или `_someService = _ioc.Resolve<SomeService>()`, etc.
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: Экземпляр
От: Sinix  
Дата: 11.10.15 12:25
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q> Зато в дальнейшем не запирается возможность вместо `SomeService.Instance.Method()` использовать `_someService.Method()`, где `_someService = SomeService.Instance`, или `_someService = someService`, или `_someService = _ioc.Resolve<SomeService>()`, etc.


Давайте честно: вы сами верите, что замена static-метода на вызов того же метода через синглтон как-то упрощает будущее гипотетическое внедрение DI? Серьёзно?

Я похожие штуки делал неоднократно и могу заверить: сам процесс замены даже в топ-10 проблем не попадает.

А вот проблемы из-за такого переусложнения вспоминаются на раз-два три. Самое эпичное было — порча данных при одновременном входе в систему двух пользователей. Если совсем упростить, то суть в следующем: код захватывал в лямбду аналог вашего SomeService.Instance, делегат переиспользовался для кода из другой сессии. Проблема возникла из-за классического эффекта бабочки — один человек прикрутил заготовку для DI и отрефакторил код не ччитываясь, другой — оптимизировал политику кэширования, в итоге — упс.
Re[5]: Экземпляр
От: Qbit86
Дата: 11.10.15 12:42
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Давайте честно: вы сами верите, что замена static-метода на вызов того же метода через синглтон как-то упрощает будущее гипотетическое внедрение DI? Серьёзно?


Да, конечно. Синглтон или статические методы — это единственность плюс глобальная точка доступа. Но в случае синглтона-экземпляра использующий код легко переделать так, чтобы он ни использовал глобальную точку доступа, ни закладывался на единственность. А новый код сразу писать, чтоб он как можно меньше знал о «синглтонной природе» используемого сервиса.

S>А вот проблемы из-за такого переусложнения вспоминаются на раз-два три. Самое эпичное было — порча данных при одновременном входе в систему двух пользователей. Если совсем упростить, то суть в следующем: код захватывал в лямбду аналог вашего SomeService.Instance, делегат переиспользовался для кода из другой сессии. Проблема возникла из-за классического эффекта бабочки — один человек прикрутил заготовку для DI и отрефакторил код не ччитываясь, другой — оптимизировал политику кэширования, в итоге — упс.


Это, очевидно, не «проблемы из-за такого переусложнения». Но ты можешь вообще хоть всё подряд делать глобальными статическими переменными, чтоб не было «эффектов бабочки». С тобой спорить просто лень.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Экземпляр
От: _NN_ www.nemerleweb.com
Дата: 12.10.15 06:01
Оценка: +1
Здравствуйте, Qbit86, Вы писали:

Можно сделать экзеплярный класс для проверок , а интерфейс статическим:

class SessionEventsHandler : IDisposable
{
    public event EventHandler Logon;
    ...
}

static class SessionEvents
{
  static SessionEventsHandler _instance = new SessionEventsHandler();

  public event EventHandler Logon { add { _instance.Logon += value; } remove { _instance.Logon -= value; } }


 ...
}


Вопрос тут больше в удобстве использования.
Скорее всего держать экзепляр и протаскивать его не очень удобно будет.
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.