Re[8]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 01.04.16 10:43
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Теперь собственно ответ:

S>Инициализация сервиса — это ответственность IOC-фреймворка, а не конечного потребителя.

Почему инициализация не может быть частью контакта

S>Для Unity это емнип LifetimeManager + resolve with parameters.

S>также см
S>http://mikaelkoskinen.net/post/unity-passing-constructor-parameters-to-resolve

Да проблема то не в этом. Вы описали мой вариант 2: http://rsdn.ru/forum/dotnet/6402172.1
Автор: Shmj
Дата: 01.04.16


Мне хочется чтобы инициализация была частью интерфейса и чтобы была гарантия что сервис проинициализирован конкретными данными.
Re[3]: Конструктор с параметрами vs метод Init -- стоит ли использо
От: v6  
Дата: 01.04.16 10:50
Оценка:
Здравствуйте, Shmj, Вы писали:

v6>>Не уверен, что это проблема. Интерфейс определяет поведение объекта. А на момент вызова конструктора объекта еще нет. С точки зрения поведения объекта это некоторая точка сингулярности.


S>Ваша теория расходится с практикой. См. IRelatedEnd. Там и свойства и методы в одном интерфейсе.


Не вижу противоречия, можно пояснить? Свойства они все равно относятся к конкретному экземпляру объекта. Заменяем мысленно на пару методов get_Prop set_Prop и вот в интерфейсе только методы.
А что будет делать конструктор в интерфейсе объекта? Создавать _новый_ объект? Ну так пусть идет в интерфейс фабрики, тут-то он зачем нужен?

v6>>Чтобы это было непротиворечиво можно вводить какие-то статические интерфейсы, но ценность этого мне не очевидна.


S>Почему инициализация определенными параметрами не может быть частью контракта


Может быть частью контракта. Просто это другой контракт получается.
Re[7]: Конструктор с параметрами vs метод Init -- стоит ли и
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 01.04.16 10:57
Оценка:
Здравствуйте, Shmj, Вы писали:

S>А вы что для реализации IoC никакого фреймворка не используете?


А вообще не реализую IoC контейнер без необходимости. Под необходимостью я понимаю исключительно наличие динамически подгружаемых расширений.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[9]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Sinix  
Дата: 01.04.16 11:00
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Почему инициализация не может быть частью контакта


Кэп: потому что она часть другого контракта, по получению экземпляра сервиса.

Это всё равно что метод "выдай мне вот такое яблоко" считать частью контракта самого яблока


S>Мне хочется чтобы инициализация была частью интерфейса и чтобы была гарантия что сервис проинициализирован конкретными данными.

По рукам надо за такое бить. При таком дизайне чтобы огрести кучу головной боли достаточно отдать один и тот же экземпляр сервиса нескольким потребителям.
Re[10]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 01.04.16 12:22
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Кэп: потому что она часть другого контракта, по получению экземпляра сервиса.

S>Это всё равно что метод "выдай мне вот такое яблоко" считать частью контракта самого яблока

Не совсем. Это как вы покупаете новый телефон. Телефон -- это новый экземпляр.

А уже потом вы его инициализируете своим аккаунтом гугле или апппле. Причем делаете это 1 раз.

Инициализацию должен проводить пользователь. Так удобнее чем передавать в магазин данные вашего аккаунта, чтобы они сами прописали и дали уже вам готовый проинициализированный объект.

Когда в следующий раз будете покупать телефона -- вспомните мои слова. И так всю жизнь теперь будете вспоминать, особенно если сейчас будете возражать.

S>>Мне хочется чтобы инициализация была частью интерфейса и чтобы была гарантия что сервис проинициализирован конкретными данными.

S>По рукам надо за такое бить. При таком дизайне чтобы огрести кучу головной боли достаточно отдать один и тот же экземпляр сервиса нескольким потребителям.

Повторная попытка инициализации -- InvalidOperationException. Просто помнить что кто первым запросил -- тот и инициализирует.
Re[11]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Sinix  
Дата: 01.04.16 12:29
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Не совсем. Это как вы покупаете новый телефон. Телефон -- это новый экземпляр.

S>А уже потом вы его инициализируете своим аккаунтом гугле или апппле. Причем делаете это 1 раз.

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

S>>По рукам надо за такое бить. При таком дизайне чтобы огрести кучу головной боли достаточно отдать один и тот же экземпляр сервиса нескольким потребителям.

S>Повторная попытка инициализации -- InvalidOperationException. Просто помнить что кто первым запросил -- тот и инициализирует.
Здравствуй, гонки.
Re[12]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 01.04.16 12:32
Оценка:
Здравствуйте, Sinix, Вы писали:

S>>Повторная попытка инициализации -- InvalidOperationException. Просто помнить что кто первым запросил -- тот и инициализирует.

S>Здравствуй, гонки.

Ну смотрите, простое правило. Тот кто вызвал конструктор -- вызывает и Init. Никаких проблем.
Re[13]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Sinix  
Дата: 01.04.16 12:40
Оценка: +1 -1
Здравствуйте, Shmj, Вы писали:

S>>Здравствуй, гонки.

S>Ну смотрите, простое правило. Тот кто вызвал конструктор -- вызывает и Init. Никаких проблем.
Проблема в том, что вы не смотрите на реальные сценарии использования, и вместо этого предлагаете "простые правила".

Вот есть у вас две библиотеки плагинов. И ваш вариант с Init:
// assembly A:
var print = IOC.Resolve<IPintService>();
print.Init(initOptions1);

// assembly b:
var print2 = IOC.Resolve<IPintService>();
print2.Init(initOptions2);

Как между конфликт разруливать будете?
Re[14]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 01.04.16 14:08
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Вот есть у вас две библиотеки плагинов. И ваш вариант с Init:

S>
S>// assembly A:
S>var print = IOC.Resolve<IPintService>();
S>print.Init(initOptions1);

S>// assembly b:
S>var print2 = IOC.Resolve<IPintService>();
S>print2.Init(initOptions2);
S>

S>Как между конфликт разруливать будете?

А вы Unity использовали? По умолчанию (если при регистрации не укажите иное) в каждом из случаев будет создан новый объект.

Если вы нехотите чтобы создавался новый объект при каждом Resolve, то регистрируйте уже готовый объект, уже проинициализированный.
Re[15]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Sinix  
Дата: 01.04.16 14:17
Оценка:
Здравствуйте, Shmj, Вы писали:

S>А вы Unity использовали?

Вы вопрос не поняли.
Как вы собираетесь гарантировать, что такое изменение (отдавали один экземпляр -> отдаём несколько) не поломает уже существующий код?
Откуда об этом изменении узнают разработчики плагинов?
Re[3]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Strategy  
Дата: 01.04.16 15:02
Оценка:
S>Напишите как правильно.

1. Если путь загрузки не меняется на протяжении жизни службы файлов, то можно сделать интерфейс ISettingsProvider со свойством LocalFolder и передавать его в конструктор класса TestFileService.

2. Если нужно менять путь для конкретной загрузки, то лучше переделать метод загрузки в DownloadFile(FileName, LocalFolder).

3. Если нужно менять путь для конкретной загрузки, но не хочется переделывать метод загрузки, то можно использовать фабрику службы файлов, которая будет каждый раз перед загрузкой файла создавать IFileService для указанного пути или набора настроек.
Re[16]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 01.04.16 20:45
Оценка: -1
Здравствуйте, Sinix, Вы писали:

S>Как вы собираетесь гарантировать, что такое изменение (отдавали один экземпляр -> отдаём несколько) не поломает уже существующий код?

S>Откуда об этом изменении узнают разработчики плагинов?

Описать что после создания объекта его нужно единожды инициализировать
Re[15]: Конструктор с параметрами vs метод Init -- стоит ли и
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 07.04.16 18:33
Оценка: 4 (1) +1 :)
Здравствуйте, Shmj, Вы писали:

S>А вы Unity использовали? По умолчанию (если при регистрации не укажите иное) в каждом из случаев будет создан новый объект.

Некорректный подход. Идея IoC в том, чтобы избавить пользовательский код от управления временем жизни сервисов. А у вас классический набор граблей — stateful сервисы + закладывание на определённое поведение Unity, одной из фишек которой является самостоятельное управление lifetime'ом сервисов (в том числе через конфиги, ага). В данном случае (если нельзя сервис сделать stateless, но всё ещё хочется отдать его на откуп IoC) правильным решением будет регистрация в IoC фабрики + ручное управление состоянием в прикладном коде (хм...да....).
[КУ] оккупировала армия.
Re[16]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 07.04.16 19:54
Оценка:
Здравствуйте, koandrew, Вы писали:

K>В данном случае (если нельзя сервис сделать stateless, но всё ещё хочется отдать его на откуп IoC) правильным решением будет регистрация в IoC фабрики + ручное управление состоянием в прикладном коде (хм...да....).


Именно к такому решению я и пришел. Вы первый кто об этом написали.
Re[17]: Конструктор с параметрами vs метод Init -- стоит ли и
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 07.04.16 20:36
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Именно к такому решению я и пришел. Вы первый кто об этом написали.


Откровенно говоря, это решение не особенно лучше, ибо сейчас вы закладываетесь на определённое поведение фабрики (в частности, что она каждый раз будет возвращать новый экземпляр объекта). То есть вы де-факто "прибиваете" пользовательский код к конкретной реализации фабрики. Осталось сделать последний логичный шаг — вместо лукапа в контейнере по интерфейсу фабрики сделать прямой вызов фабрики. Ну или сделать лукап конкретного класса фабрики в контейнере — если сама фабрика имеет зависимости, которые резолвятся IoC. Я в последний раз использовал Юнити несколько лет назад, и тогда она умела так делать. Как сейчас — не в курсе, но не думаю, что эту фичу открутили.
То есть смысл в том, что если уж есть зависимость от конкретной имплементации, то лучше выразить эту зависимость явно в коде путём прямого референса. Так будет меньше граблей при поддержке. Из своего опыта — я пробовал обе крайности, и оптимальным с точки зрения и разработки, и дальнейшей поддержки (особенно если поддерживать будут другие люди, а не изначальная команда) оказался комбинированный подход — то есть там, где клиентский код не завязан на детали реализации сервиса, используем интерфейс, там же, где такая зависимость есть (хоть такого по идее и не должно быть, но все мы знаем, что "в теории практика не должна отличаться от теории, на практике же обычно отличается" (С)) — использовать явный референс.
[КУ] оккупировала армия.
Re[17]: Конструктор с параметрами vs метод Init -- стоит ли
От: Berill Азербайджан  
Дата: 07.04.16 21:59
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Sinix, Вы писали:


S>>Как вы собираетесь гарантировать, что такое изменение (отдавали один экземпляр -> отдаём несколько) не поломает уже существующий код?

S>>Откуда об этом изменении узнают разработчики плагинов?

S>Описать что после создания объекта его нужно единожды инициализировать

Странный у вас подход... Значит правило "после создания объекта его нужно единожды инициализировать" вы можете описать, а правило "прежде чем передать в конструктор сервиса настройки — создай их и проверь корректность" вы не можете... т.е. один тип соглашений вас устраивает, а другой нет...
Отредактировано 07.04.2016 22:00 Berill . Предыдущая версия .
Re[18]: Конструктор с параметрами vs метод Init -- стоит ли
От: Shmj Ниоткуда  
Дата: 07.04.16 23:15
Оценка:
Здравствуйте, Berill, Вы писали:

B>Странный у вас подход... Значит правило "после создания объекта его нужно единожды инициализировать" вы можете описать, а правило "прежде чем передать в конструктор сервиса настройки — создай их и проверь корректность" вы не можете... т.е. один тип соглашений вас устраивает, а другой нет...


Проблема в том что конструктор не описывается интерфейсами и х.з. что в него передавать. Нужно каждый раз описывать все параметры, которые передавать при unityContainer.Resolve

А то что нужно единожды вызвать Init после отказа от концепции конструкторов с параметрами -- это правило можно применять для всего проекта и описать/запомнить 1 раз.
Re[19]: Конструктор с параметрами vs метод Init -- стоит ли
От: Berill Азербайджан  
Дата: 08.04.16 08:23
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, Berill, Вы писали:


B>>Странный у вас подход... Значит правило "после создания объекта его нужно единожды инициализировать" вы можете описать, а правило "прежде чем передать в конструктор сервиса настройки — создай их и проверь корректность" вы не можете... т.е. один тип соглашений вас устраивает, а другой нет...


S>Проблема в том что конструктор не описывается интерфейсами и х.з. что в него передавать. Нужно каждый раз описывать все параметры, которые передавать при unityContainer.Resolve


S>А то что нужно единожды вызвать Init после отказа от концепции конструкторов с параметрами -- это правило можно применять для всего проекта и описать/запомнить 1 раз.


В самом начале этой страницы(4-ой страницы) вам описали разные варианты. Вам также предложили, и не один раз, использовать фабрики для создания вашего сервиса. В том числе и то, что вы можете в контейнере резолвить саму фабрику, если вам так уже не нравятся конструкторы с параметрами.

С другой стороны, имхо, стоит задуматься над следующим. Если каждый раз когда вам требуется объект сервиса, вы проделываете unityContainer.Resolve, то принципиально это ничем не отличается от вызова фабричного метода. В свою очередь, это намекает на то, что вы, скорее всего, протаскиваете свой объект юнити-контейнера туда, где вы его используете. Лично у меня складывается такое впечатление. И тут встает закономерный вопрос, а нужен ли этот юнити вообще?!

Если посмотреть на код метода Init (который вы приводите), то опять же, он вам не гарантирует корректность переданных настроек. Если вам еще и это надо проверять, то спросите себя: а должен ли ваш объект сервиса этим заниматься?!
Если у вас задача: создать объект сервиса с корректными настройками — то я бы разделил это на 2 подзадачи:
1. Проверка корректности настроек
2. Передача корректных настроек сервису либо при его создании (если эти же настройки используются не только для одного метода), либо в сам метод, где эти настройки используются

Все это вам описали в первом сообщении 4-ой страницы:

От: Strategy
Дата: 01.04.16 19:02
S>Напишите как правильно.

1. Если путь загрузки не меняется на протяжении жизни службы файлов, то можно сделать интерфейс ISettingsProvider со свойством LocalFolder и передавать его в конструктор класса TestFileService.

2. Если нужно менять путь для конкретной загрузки, то лучше переделать метод загрузки в DownloadFile(FileName, LocalFolder).

3. Если нужно менять путь для конкретной загрузки, но не хочется переделывать метод загрузки, то можно использовать фабрику службы файлов, которая будет каждый раз перед загрузкой файла создавать IFileService для указанного пути или набора настроек.


Определитесь с задачей сперва, и уже оттуда нужно плясать.
Re[18]: Конструктор с параметрами vs метод Init -- стоит ли и
От: Shmj Ниоткуда  
Дата: 08.04.16 08:57
Оценка:
Здравствуйте, koandrew, Вы писали:

K>Откровенно говоря, это решение не особенно лучше, ибо сейчас вы закладываетесь на определённое поведение фабрики (в частности, что она каждый раз будет возвращать новый экземпляр объекта). То есть вы де-факто "прибиваете" пользовательский код к конкретной реализации фабрики. Осталось сделать последний логичный шаг — вместо лукапа в контейнере по интерфейсу фабрики сделать прямой вызов фабрики.


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

K>То есть смысл в том, что если уж есть зависимость от конкретной имплементации, то лучше выразить эту зависимость явно в коде путём прямого референса.


К конкретной реализации фабрики не привязано. Добавил интерфейс абстрактной фабрики, котоарая имеет 2 реализации: тестовую и реальную. Тестовая используется для целей тестирования/отладки. Выбор какую использовать задается в конфигурации.
Re[20]: Конструктор с параметрами vs метод Init -- стоит ли
От: Shmj Ниоткуда  
Дата: 08.04.16 09:09
Оценка:
Здравствуйте, Berill, Вы писали:

B>В самом начале этой страницы(4-ой страницы) вам описали разные варианты. Вам также предложили, и не один раз, использовать фабрики для создания вашего сервиса. В том числе и то, что вы можете в контейнере резолвить саму фабрику, если вам так уже не нравятся конструкторы с параметрами.


Все эти варианты я описал еще на второй странице: http://rsdn.ru/forum/dotnet/6402172.1
Автор: Shmj
Дата: 01.04.16


Так что предлагали на 4 -- это громко сказано...

B>С другой стороны, имхо, стоит задуматься над следующим. Если каждый раз когда вам требуется объект сервиса, вы проделываете unityContainer.Resolve, то принципиально это ничем не отличается от вызова фабричного метода.


Разница в том что в unityContainer я регистрирую множество сервисов. Вы предлагаете передавать в конструктор сервиса по 5-6 фабричных методов? Чем это лучше?

B>В свою очередь, это намекает на то, что вы, скорее всего, протаскиваете свой объект юнити-контейнера туда, где вы его используете. Лично у меня складывается такое впечатление. И тут встает закономерный вопрос, а нужен ли этот юнити вообще?!


В моем случае реальные сервисы отрабатывают достаточно долго, по этому для целей тестирования логики используются фейковые сервисы, возвращающие набор фейковых данных. Как вы предлагаете это реализовать? Передавать к конструктор одного сервиса по 5-6 фабрик на другие сервисы, которые он использует для своей работы?

B>Если посмотреть на код метода Init (который вы приводите), то опять же, он вам не гарантирует корректность переданных настроек. Если вам еще и это надо проверять, то спросите себя: а должен ли ваш объект сервиса этим заниматься?!


Init показывает какие обазательные данные необходимы для инициализации сервиса.

B>Если у вас задача: создать объект сервиса с корректными настройками — то я бы разделил это на 2 подзадачи:

B>1. Проверка корректности настроек

Про проверку корректности вопроса не было. Вопрос в том что в интерфейсе нельзя описать параметры конструктора.

B>2. Передача корректных настроек сервису либо при его создании (если эти же настройки используются не только для одного метода), либо в сам метод, где эти настройки используются


Настройки используются для всех методов. Можно, конечно, в каждый метод их передавать в качестве первого параметра, но не хотелось бы замусоливать, ведь достаточно один раз передать в конструктор или в метод Init.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.