#.net #design-patterns #multi-tier
#.net #шаблоны проектирования #многоуровневый
Вопрос:
Я нахожусь на начальной стадии нового проекта. Поскольку я всегда хочу совершенствоваться и пытаюсь избежать ошибок из прошлого (у каждого есть некоторый багаж), я посмотрел на образец многоуровневой архитектуры для .NET. Глядя на данные и бизнес-логику, я заметил, что уровень данных на самом деле имеет ссылку на ExpenseSample.Бизнес.Объекты собраны, поэтому уровень данных знает, что существует бизнес-уровень. Это выглядит и ощущается довольно неловко.
Конечно, это экономит время на сопоставлении DataObject с BusinessEntities, но разве это не «опасный» подход?
С нетерпением жду некоторого обсуждения и, возможно, каких-то лучших решений.
ОБНОВЛЕНИЕ: Спасибо за информацию. Теперь я использую
MyApp.Data.Contracts.*
MyApp.Data.Access.* /* has the classes to access the DB and maps it to
the Data.Contracts */
MyApp.Business.Entities.*
MyApp.Business.Components.* /* accesses the classes from Data.Access,
maps the Contracts to the Business.Entities and
provides the components to access them */
Таким образом, я могу убедиться, что внутренние изменения в представлении моих данных не влияют на внешние уровни.
Ответ №1:
Я не согласен, к некоторым объектам должны быть доступны все уровни, я делаю это следующим образом:
-----------
| DAL | E |
------- N |
| BAL | T |
------- I |
| G | T |
| U | I |
| I | E |
| | S |
-----------
DAL обычно подключается к службе WCF и скрывает от остальной части приложения информацию об этом (поэтому ее можно изменить через несколько лет, когда WCF устареет).
BAL в основном специфичен для приложения (хотя может быть повторно использован в другом приложении), но сущности созданы специально для приложения, крайне маловероятно, что я когда-либо использовал бы их где-то еще.
Конечно, это для достаточно небольшого приложения, его можно расширить другими библиотеками DLL (модулями сторонних производителей и т.д.) И сделать намного более сложным, но в этом и заключается идея.
Я думаю, что я пытаюсь сказать, что сущности и BAL — это две разные вещи, не путайте их 😉
Ответ №2:
Общее правило заключается в том, что нижний уровень не должен знать о верхних слоях. Пример некорректен, поскольку бизнес-сущности являются частью BAL, а не DAL. Следовательно, сопоставление должен выполнять бизнес-уровень, а не уровень данных.
Сопоставление на самом деле не требует времени, просто используйте что-то вроде ValueInjecter
Отказ от ответственности: я не просматривал связанный образец. Просто даю свои два цента за многоуровневость в целом.
Ответ №3:
… таким образом, уровень данных осознает, что существует бизнес-уровень
Не совсем корректно, просто известно, что существует пространство имен с именем Business.Entities
, но эти сущности, безусловно, являются листами в архитектуре. Они не зависят ни от чего другого, кроме .Net framework. В сущности, в них нет никакой логики (кроме toString()), поэтому они просто действуют как контракты данных во всей архитектуре. Также в них нет ссылок на какие-либо другие проекты. Единственное, что не делает их POCOs, это то, что они поддерживают сериализацию.
Как упоминал Бабуин, такой подход возможен, и я уверен, что есть примеры, где это работает очень хорошо. И если вы посмотрите на проект и код, все это выглядит так мило и уютно, что я просто хочу влюбиться в это.
И это будет хорошо и упорядоченно до тех пор, пока вы тщательно планируете каждое дополнение ко всей вашей архитектуре, просматриваете каждое изменение и поддерживаете тесную связь с разработчиками. Но как только ваша архитектура, ваша база данных и ваши бизнес-процессы будут развиваться более быстрыми темпами, вам придется значительно расширить возможности моделирования данных для всех этих уровней с использованием общих объектов. Есть несколько примеров, которые, на мой взгляд, говорят в пользу контрактов с данными для конкретного уровня. Среди них то, что однажды программист пользовательского интерфейса захочет иметь уведомители PropertyChanged в ваших объектах для своего уровня пользовательского интерфейса. Hrmpf! Вы не можете сделать это, не затронув также ваш BAL и DAL. В другой раз вы сталкиваетесь со случаем, когда вы хотите, чтобы в объектах хранились свойства, доступные только для GUI (например, цвет отображения, положение на экране, состояния выбора и т.д.). При чем здесь база данных? И если вы внимательно посмотрели, вы заметили, что у сущностей уже есть обработки, зависящие от уровня. Вы видели виртуальные ключевые слова в свойствах навигации? Они существуют для того, чтобы EF мог подклассифицировать их и предоставить вам прокси-классы с поддержкой отложенной загрузки… которые, в свою очередь, вероятно, не предназначены для передачи через службу.
Альтернативой является использование сопоставления объектов (вручную, с помощью шаблонов или библиотек, таких как AutoMapper). Это решение, безусловно, менее чистое, менее удобное, поскольку имеет место дублирование кода и бесконечные строки кода сопоставления. Но все это позволяет вам разделять данные в ваших слоях и моделировать их в соответствии с конкретными потребностями каждого уровня.
Комментарии:
1. DTO и POCOs не зависят ни от чего другого. Сущности являются представлением бизнес-логики этих DTO, POCOs. Сущности обладают логикой, проверкой, настойчивостью, осведомлены о бизнесе.
2. Если вы загружаете образец многоуровневой архитектуры для . Сеть, о которой говорил OP, вы можете видеть, что сущности не зависят ни от чего, кроме .Net. Является ли это хорошим образцом для многоуровневых архитектур или нет, спорно . Тем не менее, я думаю, что логика не должна быть частью сущностей. Вы бы создали продукт, у которого есть метод getPrice () или, скорее, какой-нибудь класс PriceCalculator, который берет продукт и выдает вам цену? Первый подход нарушил бы разделение задач.
3. Я предпочитаю метод fist. И нет, это не нарушает разделение интересов, если я считаю, что цена является свойством моего продукта. Этот первый метод быстрее, качественнее и проще, поэтому его легче поддерживать.
4. Ладно, разные мнения… Я не собираюсь обсуждать концепции, поскольку для некоторых продуктов при определенных обстоятельствах это действительно может рассматриваться как свойство без каких-либо проблем. Тем не менее, я не понимаю причину снижения. Вы говорите об общих концепциях, и я процитировал и сослался на образец, упомянутый в OP.
Ответ №4:
Я бы сказал одну вещь: если вы собираетесь разрешить DAL доступ к бизнес-объектам, то вы также можете создать один проект и разделить BAL и DAL на отдельные каталоги и пространства имен внутри этого проекта. По крайней мере, вы не обманываете себя по поводу многоуровневости.
В большинстве проектов, над которыми я работал, было мало пользы в разделении BAL и DAL на отдельные сборки. Если ваше решение для базы данных, вероятно, изменится, и вы хотите быть уверенным в будущем, используйте вместо этого ORM, подобный NHibernate.