|
О применении SOLID
|
|||
---|---|---|---|
#18+
По мотивам закрытого топика. skyANAКак Вы предлагете использовать сборку MessageServer.dll? Тупо референс на неё добавить? И что это даст?Вы правильно заметили, что:skyANAАлексей К Тут выделена часть кода для повторного использования.Посмотрел на класс. Это действительно "часть кода для повторного использования", то есть в нём просто собранны методы, что используются в проекте более одного раза. Этакий глобальный хелпер для проекта.Речь шла о повторном использовании фрагментов логики именно внутри данного проекта (solution в терминологии VS). Повторное использование этой логики вне данного проекта не требуется. А для повторного использования внутри проекта - да, достаточно "тупо референс на неё добавить". Я не планирую использовать прикладной модуль MessageServer.dll где-то ещё кроме этого проекта. Проект разделён на прикладные модули для удобства его сопровождения. Для повторного использования в нескольких проектах (их у меня сейчас 6) предназначены 3 системных модуля SspMainXXX.dll. Здесь нет необходимости выделения прикладной логики в отдельный слой репозитариев для её отделения от слоя WCF-ных сервисов. Здесь нет необходимости в описании всего и вся интерфейсами с последующей интеграцией этого безобразия DI-контейнером. Пусть классы зависят от классов "нижних" слоёв, ничего плохого в этом не вижу. Мне непонятно почему проекты без использования IoC/DI автоматически считаются плохими по мнению некоторых. Мне кажется это не так. skyANAЭто же WCF сервис. То есть другой проект - это нечто иное Зачем писать второй WCF сервис для работы с сообщениями (message), если SvcMessage уже написан? Незачем. Зачем цеплять сборку WCF сервиса туда, где он не нужен? Тоже незачем.К SvcMessage может осуществляться доступ как удалённо через WCF, так и локально на сервере, обычным созданием этого класса оператором new или DI-контейнером, на любителя. Это обычный класс, имеющий атрибуты для работы с ним через WCF. skyANAПосмотрев остальной код проекта, прихожу к выводу, что DRY (don’t repeat yourself) у Вас и не пахнет.Перед тем как делать какие-то выводы обычно слушается мнение всех заинтересованных сторон. Укажите на места с "варварским копипастом" в этом проекте. Уверен, всему найдётся разумное объяснение. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 08:14 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей КПо мотивам закрытого топика. skyANAКак Вы предлагете использовать сборку MessageServer.dll? Тупо референс на неё добавить? И что это даст?Вы правильно заметили, что:skyANAпропущено... Посмотрел на класс. Это действительно "часть кода для повторного использования", то есть в нём просто собранны методы, что используются в проекте более одного раза. Этакий глобальный хелпер для проекта.Речь шла о повторном использовании фрагментов логики именно внутри данного проекта (solution в терминологии VS). Повторное использование этой логики вне данного проекта не требуется. А для повторного использования внутри проекта - да, достаточно "тупо референс на неё добавить". Я не планирую использовать прикладной модуль MessageServer.dll где-то ещё кроме этого проекта. Значит я был прав и Вы поспешили задать свой вопрос "Как так?":Алексей КskyANA Посмотрел на класс. Это действительно "часть кода для повторного использования" , то есть в нём просто собранны методы, что используются в проекте более одного раза. Этакий глобальный хелпер для проекта. Копипаст, кстати, тоже можно назвать повторным использованием кода, а самый распространённый случай повторного использования кода — библиотеки, что позволяют использовать одни и теже компоненты в разных проектах. Последнее - это не Ваш случай. Как так? Алексей КЗдесь нет необходимости выделения прикладной логики в отдельный слой репозитариев для её отделения от слоя WCF-ных сервисов. Здесь нет необходимости в описании всего и вся интерфейсами с последующей интеграцией этого безобразия DI-контейнером.Почему если интерфейсы, то сразу DI? К примеру у Вас там есть автосгенерированный тип message, состояние экземпляра данного типа вызывающий код может изменить как угодно, т.к. все его свойства имеют публичные сеттеры. А если так: Код: c# 1. 2. 3. 4. 5. 6. 7.
Код: c# 1. 2. 3. 4. 5. 6. 7.
То получаем инкапсуляцию на уровне модели. Алексей КskyANAЭто же WCF сервис. То есть другой проект - это нечто иное Зачем писать второй WCF сервис для работы с сообщениями (message), если SvcMessage уже написан? Незачем. Зачем цеплять сборку WCF сервиса туда, где он не нужен? Тоже незачем.К SvcMessage может осуществляться доступ как удалённо через WCF, так и локально на сервере, обычным созданием этого класса оператором new ...Вы реально так делаете? Хотя чего это я спрашиваю. Выше Вы писали, что не планируете использовать прикладной модуль MessageServer.dll где-то ещё. Алексей КskyANAПосмотрев остальной код проекта, прихожу к выводу, что DRY (don’t repeat yourself) у Вас и не пахнет.Перед тем как делать какие-то выводы обычно слушается мнение всех заинтересованных сторон.Хорошо. Вы можете своими словами описать, какие компоненты внутри проекта выделены по принципу DRY и почему этого достаточно на Ваш взгляд? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 09:12 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
skyANAПочему если интерфейсы, то сразу DI?Не всегда, но часто. :-) skyANAК примеру у Вас там есть автосгенерированный тип message, состояние экземпляра данного типа вызывающий код может изменить как угодно, т.к. все его свойства имеют публичные сеттеры. А если так: Код: c# 1. 2. 3. 4. 5. 6. 7.
Код: c# 1. 2. 3. 4. 5. 6. 7.
То получаем инкапсуляцию на уровне модели.Эта "красота" вызовет в дальнейшем необходимость описания специального DTO, что нарушает моё представление о DRY, но об этом ниже. Одним словом - оно того не стоит. skyANAАлексей Кпропущено... К SvcMessage может осуществляться доступ как удалённо через WCF, так и локально на сервере, обычным созданием этого класса оператором new ...Вы реально так делаете?Внутри проекта - да, такие случаи были, но редко. Негативных эффектов от такого использования замечено не было. skyANAАлексей Кпропущено... Перед тем как делать какие-то выводы обычно слушается мнение всех заинтересованных сторон.Хорошо. Вы можете своими словами описать, какие компоненты внутри проекта выделены по принципу DRY и почему этого достаточно на Ваш взгляд?Думаю, все. Основная цель - не писать несколько раз одно и то же. Везде где можно применяется кодогенерация. Бизнес-объекты слоя данных и логики применяются в том числе в качестве DTO, чтобы не описывать одинаковые структуры данных в нескольких местах. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 09:52 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
skyANAВы можете своими словами описать, какие компоненты внутри проекта выделены по принципу DRY и почему этого достаточно на Ваш взгляд?Или Вы хотели увидеть все компоненты, выделенные отдельно для повторного использования? Я немного не понял вопрос. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 10:07 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей КВезде где можно применяется кодогенерация. Бизнес-объекты слоя данных и логики применяются в том числе в качестве DTO, чтобы не описывать одинаковые структуры данных в нескольких местах. а можно пример? Возьму на заметочку ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 10:26 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
netivanАлексей КВезде где можно применяется кодогенерация. Бизнес-объекты слоя данных и логики применяются в том числе в качестве DTO, чтобы не описывать одинаковые структуры данных в нескольких местах. а можно пример? Возьму на заметочку Бизнес-объекты сгенерированного по БД слоя данных помечены WCF-ными атрибутами и передаются на клиента, например тут (метод GetPersonalEditByID) . Там же содержатся рукописные бизнес-объекты слоя логики (например класс PersonalView), которые так же имеют WCF-ные атрибуты и отдаются клиенту. На клиенте эти классы имеют "двойников", сгенерированных по WSDL . ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 10:44 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей КВезде где можно применяется кодогенерация Чем генерите? T4 или каким-либо платным продуктом типа CodeSmith? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:10 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Arm79Алексей КВезде где можно применяется кодогенерация Чем генерите? T4 или каким-либо платным продуктом типа CodeSmith?Запускаю из T4 Text Template. Но некоторые части кодогенератора описаны в виде сборок (assembly), скомпилированных отдельно. 1. Подробности по генерации контекста базы данных Entity Framework. 2. Подробности по генерации WCF-клиентов. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:15 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей К, авторАвтоматическое закрытие соединения из финализатора, на случай, если в прикладном коде не производится явное закрытие соединения в следствие ошибки. ??? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:24 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Где-то в степиАлексей К, авторАвтоматическое закрытие соединения из финализатора, на случай, если в прикладном коде не производится явное закрытие соединения в следствие ошибки. ???Например, SqlConnection из финализатора закрывает соединение, если до этого ему не вызвали Close или Dispose. В WCF Channel такого почему-то нет. Если явно не закрыть соединение - оно остаётся "навсегда". Поэтому добавил закрытие из финализатора навсякий. Можно ещё добавить вывод сообщения в лог. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:28 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей К, это косноязычно, и наводит на мысль что финализатор вызовется в период жизни приложения в обязательном порядке а не только при его закрытии.. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:35 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Где-то в степиАлексей К, это косноязычно, и наводит на мысль что финализатор вызовется в период жизни приложения в обязательном порядке а не только при его закрытии..Ну все же знают когда вызывается финализатор. Мне кажется тут уточнение не требуется. Впрочем, я поправил формулировку. Согласен что было "так себе". Вроде стало лучше: автор* Автоматическое закрытие соединения из финализатора на случай, если закрытие соединения не производится явно из-за ошибки в прикладном коде. зы: Недавно поймал себя на мысли, что я совершенно разучился писать по-русски. Постепенно навёрстываю упущенное. :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:43 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей К, авторНу все же знают когда вызывается финализатор ну уж вы погорячились, половина не знает или думает что только при удалении объекта коллектором, без внимания реализует ли тип IDisposable, и он в общем то может и никогда не вызваться окромя закрытия программы. У меня вопрос, а что вы носитеь с этим закрытием соединения, в чем тут сокральная изюминка, или вы используете ресурсы ядра для этого даже внедрили IDisposable, не могу уловить мысль??? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 11:50 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Где-то в степиАлексей К, авторНу все же знают когда вызывается финализатор ну уж вы погорячились, половина не знает или думает что только при удалении объекта коллектором, без внимания реализует ли тип IDisposable, и он в общем то может и никогда не вызваться окромя закрытия программы.Текст ориентирован на подготовленного читателя. :-) Где-то в степиУ меня вопрос, а что вы носитеь с этим закрытием соединения, в чем тут сокральная изюминка, или вы используете ресурсы ядра для этого даже внедрили IDisposable, не могу уловить мысль??? У меня много случаев, когда нужно дёрнуть только один метод вебсервиса. Без дополнительных костылей правильный вызов выглядит как-то так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
С костылями так: Код: c# 1. 2.
... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 12:06 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Ну и незакрытые соединения плохо влияют на WCF-сервер, поэтому добавил закрытие из финализатора. Благо, в WPF-приложении сборка мусора производится достаточно часто. :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 12:12 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Где-то в степидля этого даже внедрили IDisposable IDisposable позволяет делать так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9.
В чистом виде WCF-ный канал (и клиент) нельзя использовать с using. Там метод Dispose может генерить исключение со всеми вытекающими. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 12:19 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей К, авторплохо влияют на WCF-сервер это как? ведь в вашем случае соединение устанавливается через службу Net.TCP, ( одну на все приложения) вы кода абортируетесь или закрываете там просто исчезает ссылка на ваш поток и урл в таблице маршрутизации , внешний сокет, как был на прослушке - так и останется ( на вашем компе) а сервер хоста вообще может уйти в спячку, если его не пинать просьбами... ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 12:57 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
автор внешний сокет, как был на прослушке тут я погорячился, ну воспримем это в общих чертах ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 13:02 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Где-то в степиАлексей К, авторплохо влияют на WCF-сервер это как? ведь в вашем случае соединение устанавливается через службу Net.TCP, ( одну на все приложения) вы кода абортируетесь или закрываете там просто исчезает ссылка на ваш поток и урл в таблице маршрутизации , внешний сокет, как был на прослушке - так и останется ( на вашем компе) а сервер хоста вообще может уйти в спячку, если его не пинать просьбами...В том-то и дело, что из-за ошибки в прикладном коде клиента сетевой пакет с командой закрытия соединения на сервер может не прийти и сервер будет считать, что соединение открыто. Ну забыли на клиенте вызвать Close или Dispose, с кем не бывает. :-) Вероятно, на сервере должен быть какой-то таймоут на отсутствие активности соединения с клиента, но я более детально не изучал этот вопрос. Тем более, у нас с этим были проблемы на начальном этапе разработки. При их решении в том числе был добавлен и финализатор. В общем, с финализатором как-то спокойнее. :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 13:08 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей Кnetivanпропущено... а можно пример? Возьму на заметочку Бизнес-объекты сгенерированного по БД слоя данных помечены WCF-ными атрибутами и передаются на клиента, например тут (метод GetPersonalEditByID) . Там же содержатся рукописные бизнес-объекты слоя логики (например класс PersonalView), которые так же имеют WCF-ные атрибуты и отдаются клиенту. На клиенте эти классы имеют "двойников", сгенерированных по WSDL . вот это DTO и называется? Смотрите: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
PersonalView это же и есть ваш бизнес-объект, а в контексте БД (DbMainFactory.Scope) другой объект. Имеется разделение. А вы говорите, нет дублирования. Я как-то не так понял мысль? И поделитесь вашей proxy wcf с финализатором :) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 14:47 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей К2. Подробности по генерации WCF-клиентов. Вопрос немного не по теме (генерации), но мне показался достаточно важным Фабрика сетевых службКлиенты сетевых служб создаются с помощью фабрики, расположенной в классе WsFactory. ... Метод GetChannel содержит создание канала (Channel), используемого для взаимодействия с сервером... Каждый раз для создания канала создается фабрика, но создание фабрики вроде как дорогостоящая операция (по сравнению с созданием канала)... почему бы не закэшировать фабрику? P.S. Алексей, спасибо за Ваши труды на благо сообщества! ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 15:17 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
netivanPersonalView это же и есть ваш бизнес-объект, а в контексте БД (DbMainFactory.Scope) другой объект. Имеется разделение. А вы говорите, нет дублирования. Я как-то не так понял мысль? PersonalView - это класс, описывающий структуру данных элемента списка формы "Персонал". personal - класс, описывающий таблицу в базе данных. Это разные сущности в системе. Да, какие-то поля в них дублируются, но эти классы скорее разные чем одинаковые. Более того, я не уверен, что при добавлении полей в таблицу в базе данных я захочу увидеть автоматическое добавление полей в элемент списка формы. Поэтому было решено сделать класс PersonalView "с нуля", чем использовать при его описании класс personal. Конечно, можно сделать и так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
В каких-то случаях именно так и делается, но не в этом. netivanИ поделитесь вашей proxy wcf с финализатором :) Исходник Описание ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 15:31 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
LRАлексей К2. Подробности по генерации WCF-клиентов. Вопрос немного не по теме (генерации), но мне показался достаточно важным Фабрика сетевых службКлиенты сетевых служб создаются с помощью фабрики, расположенной в классе WsFactory. ... Метод GetChannel содержит создание канала (Channel), используемого для взаимодействия с сервером... Каждый раз для создания канала создается фабрика, но создание фабрики вроде как дорогостоящая операция (по сравнению с созданием канала)... почему бы не закэшировать фабрику?В следующих версиях WCF они обещали оптимизировать создание ChannelFactory<>, где-то была статья об этом. Вероятно в 4.5 это уже оптимизировано. Проверить это у меня сейчас нет возможности. При повторном использовании одного объекта фабрики для создания нескольких Channel-ов возникали проблемы. Какие - я сейчас точно не вспомню, надо опять делать тест и читать MSDN. Но точно помню, что проблемы были, что-то там не работало. :-) LRP.S. Алексей, спасибо за Ваши труды на благо сообщества!Пасиб. :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 15:41 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
Алексей КnetivanPersonalView это же и есть ваш бизнес-объект, а в контексте БД (DbMainFactory.Scope) другой объект. Имеется разделение. А вы говорите, нет дублирования. Я как-то не так понял мысль? PersonalView - это класс, описывающий структуру данных элемента списка формы "Персонал". personal - класс, описывающий таблицу в базе данных. Это разные сущности в системе. Да, какие-то поля в них дублируются, но эти классы скорее разные чем одинаковые. Более того, я не уверен, что при добавлении полей в таблицу в базе данных я захочу увидеть автоматическое добавление полей в элемент списка формы. Поэтому было решено сделать класс PersonalView "с нуля", чем использовать при его описании класс personal. Конечно, можно сделать и так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
В каких-то случаях именно так и делается, но не в этом. netivanИ поделитесь вашей proxy wcf с финализатором :) Исходник Описание 1. с PersonalView все ясно, я мысль не так понял 2. с каналом интересно.Только IDisposable как-то не по паттерну с МСДН, непрвычно видеть без флага) надо все исходники посмотреть. Асинхронное выполнение заинтересовало. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2013, 16:14 |
|
О применении SOLID
|
|||
---|---|---|---|
#18+
LRКаждый раз для создания канала создается фабрика, но создание фабрики вроде как дорогостоящая операция (по сравнению с созданием канала)... почему бы не закэшировать фабрику? Если закешировать, оно в принципе работает. Но тогда нет возможности изменить параметры соединения у фабрики. Она этого не позволяет после создания хотя бы одного канала с помощью неё. Чисто визуально разницы в работе приложения с кэшированием я не заметил. Из-за дополнительных ограничений для себя решил кэширование не делать. Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33.
... |
|||
:
Нравится:
Не нравится:
|
|||
26.12.2013, 07:24 |
|
|
start [/forum/topic.php?fid=20&fpage=132&tid=1403421]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
34ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
64ms |
get tp. blocked users: |
2ms |
others: | 15ms |
total: | 158ms |
0 / 0 |