Re: Про бизнес-объекты: для сохранения, для API, для внутреннего
От: vmpire Россия  
Дата: 10.10.17 19:13
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Практически в каждом проекте эти данные используются для 4-5 вещей:


S>1. Для внутреннего потребления, т.е. вы некие классы передаете/принимаете в своих методах и что-то с ними делаете.

S>2. Для сохранения. Как правило ORM позволяет сохранять сами эти структуры данных. Но так просто не получается -- их нужно либо наделить атрибутами либо кодогенерацией (ну или XML-описанием).
S>3. Эти же структуры данных иногда приходится сохранять на диск в неком формате без ORM. К примеру для сохранения в xlsx-файл.
S>4. Эти же структуры вам нужно отдавать через REST/SOAP-API внешним пользователям.
S>5. Эти же структуры вам нужно получать из внешнего API, от которого уже вы зависите.

S>Главное неудобство вижу в том, что по стуи очень похожие структуры в каждом из этих 5 случаев нужно копировать одну в другую. Потому что они хотя и похожи, порой на 90%, но все же отличаются. К примеру в одном случае требуется обязательное наличие set-еров, иначе библиотека отказывается работать с данными (к примеру, стандартная XML-сериализация требует чтобы у списка был set-ер). Но наличие set-еров противоречит внутренней парадигме.


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

Краткий ответ на этот вопрос такой:
— Если приложение небольшое (скажем, до 100000 строк) и с небольшим временем жизни (год-два) — делайте комбинированный класс для всех целей сразу, отключая ненужное в каждом случае при сериализациях.
Потому что зачем повторять одно и то же в нескольких местах?
В одном объекте можно атрибутами задать и правида сериализации в XML (ну, по крайней мере, до тех пор, пока такой формат только один) и мэппинг на базу и всё что там ещё нужно.

— Если приложение среднее или большое или планируется к долгой жизни — не поленитесь создать отдельные классы.
Потому, что экономия на одном классе вместо пяти в масштабе проекта будет мизерной, а вот проблемы от того, что нужно, например, изменить использование класса во внешнием API, а структура прибита гвоздями и к базе и к JavaScript (где почти никогда нет дотошных тестов, проверяющих все варианты использования всех полей) — будут вполне реальными.
Плюс постоянно будут скрытые ошибки или просто потеря скорости из-за того, что где-то что-то лишнее сериализовалось, либо сериализовалось не в тот тип...
У меня такие случаи со старым кодом встречются регулярно.
Вот как раз совсем недавно был свежий пример: понадобилось изменить тип поля с DateTime на DateTimeOffset для внешнего API, оставив DateTime в остальных случаях.
И как хорошо, что у меня где-то на 80% эти классы уже были выделены.
Иначе бы развалилось довольно много.

Для второго случая нужно заранее продумать схему преобразований. Если она оказывается "все ко всем" — то где-то есть архитектурная проблема.
Обычно получается что-то типа звезды: в центре — бизнес-сущность "для внутреннего потребления", а от неё двунаправленные конвертации в базу, в DTO и т.д.
И нужно понимать, что отдельный формат представлений — это не всегда отдельный класс созданный вручную. Например, для уравня DataAccess этим представлением может быть маппинг для ORM.

То есть, наример, между слоями приложения ходит формат "для внутреннего потребления"
Для сохранения в слой DataAccess приходит та же "для внутреннего потребления". Как DataAccess её сохранит — это его внутреннее дело. Может через мэппинг (если он не прописан в самой основной сущности), а может и созданием промежуточного класса, который будет жить только в DataAccess
Для внешних сервисов и для передачи в браузер создаётся специализированный DTO, который живёт в слое доступа к этим сервисам лио в выделенном service agent, если таковой есть. А приходит в этот service agent вё та же сущность "для внутреннего потребления"
Re[5]: Вижу: DRY, копипаста
От: vmpire Россия  
Дата: 11.10.17 15:02
Оценка:
Здравствуйте, Shmj, Вы писали:

S>1. Выделяете слой сервисов, реализация которых не зависит от GUI.

...
S>3. Web-приложение и десктоп-приложение работают не с сервисом OrderService, а с контрактами IOrderService. Конкретную реализацию подключаете с помощью IoC (есть готовые либы типа Unity и пр.).
А зачем нужны несколько реализаций для разных GUI, если реализация не зависит от GUI?
Re[6]: Вижу: DRY, копипаста
От: Shmj Ниоткуда  
Дата: 11.10.17 18:49
Оценка:
Здравствуйте, vmpire, Вы писали:

S>>3. Web-приложение и десктоп-приложение работают не с сервисом OrderService, а с контрактами IOrderService. Конкретную реализацию подключаете с помощью IoC (есть готовые либы типа Unity и пр.).

V>А зачем нужны несколько реализаций для разных GUI, если реализация не зависит от GUI?

Для тестирования.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.