Придумана ли концепция дизайна слоев? - PullRequest
3 голосов
/ 16 июня 2010

Я читаю удивительную работу Эрика Эванса «Доменно-управляемый дизайн».Тем не менее, я не могу не чувствовать, что модель «слоев» придумана.Чтобы расширить это утверждение, кажется, что оно пытается объединить различные концепции в конкретную, аккуратную модель, в которой слои взаимодействуют друг с другом.Мне кажется, что модель слоев слишком упрощена, чтобы на самом деле понять, как работает (хорошее) программное обеспечение.

Для дальнейшего расширения: Эванс говорит:

"Разделите сложную программу на слои.Разрабатывайте дизайн внутри каждого слоя, который будет единым и зависит только от нижележащих слоев. Следуйте стандартным архитектурным схемам, чтобы обеспечить слабую связь со слоями выше. "

Возможно, я неправильно понимаю, что означает" зависит ", нонасколько я могу видеть, это может означать либо a) Класс X (в пользовательском интерфейсе, например) имеет ссылку на конкретный класс Y (в основном приложении), либо b) Класс X имеет ссылку на класс Y-ишобъект, предоставляющий услуги класса Y-ish (т. е. ссылка, хранящаяся в качестве интерфейса).

Если это означает (а), то это явно плохо, так как он побеждает повторное использование пользовательского интерфейса в качестве переднегоконец некоторому другому приложению, которое обеспечивает функциональность Y-ish.Но если это означает (б), то как пользовательский интерфейс больше зависит от приложения, чем приложение от пользовательского интерфейса?Оба отделены друг от друга настолько, насколько это возможно, пока они все еще разговаривают друг с другом.

Слойная модель зависимостей Эванса, идущая в одну сторону, кажется слишком опрятной.

Во-первых, не точнее ли сказать, что каждая область проекта предоставляет модуль, который в значительной степени является островком для себя, и что в идеале вся связь осуществляется через интерфейсы в рамках контракта / ответственностипарадигма?(то есть «зависимость только от нижних уровней» придумана).Аналогично, при взаимодействии уровня домена с базой данных - уровень домена отделен от базы данных (через DAO и т. Д.), Как база данных относится к уровню домена.Ни один из них не зависит от другого, оба могут быть заменены.

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

Спасибо всем - надеемся, что ваши ответы могут прояснить мое понимание этого вопроса.Факт, который Эванс поясняет позже, что это тот случай (б), о котором он говорит: «Слои предназначены для слабой связи, с зависимостями проектирования только в одном направлении. Верхние слои могут напрямую использовать или управлять элементами нижних, вызывая их открытые интерфейсыудерживая ссылки на них ... Когда объект должен общаться вверх, нам нужен другой механизм ... такой как НАБЛЮДАТЕЛИ "

Это кажется мне полностью надуманным.Кажется, это путает зависимости дизайна только с потоком взаимодействия.UI нужна ссылка на приложение, потому что действия обычно инициируются пользователем!Для действий, которые инициируются приложением, например, какое-то внутреннее событие таймера, предупреждающее пользователя о чем-либо, приложению теперь нужна ссылка на пользовательский интерфейс, точно так же, как пользовательский интерфейс ранее нуждался в ссылке на приложение.В каком смысле один более «зависит от дизайна», чем другой?Чтобы поддержать мою точку зрения, для реализации OBSERVER, это приложение, которому понадобится список ссылок на компоненты пользовательского интерфейса.

Мне кажется, что единственная причина, по которой ссылки и дизайн SEEM переходят с верхнего уровня на нижний, заключается в том, что именно там обычно инициируются действия.Когда действие инициируется в приложении, ссылки должны идти в другом направлении.

Ответы [ 7 ]

2 голосов
/ 16 июня 2010

Я согласен с вами. Идеи в DDD звучат действительно круто, но очень сложно реализовать. Также обратите внимание, что для простого приложения CRUD с двумя или тремя формами создание слоя самого приложения может быть серьезным излишним.

Однако обратите внимание на проблему, которую пытается решить Layer Architecture в DDD.

В объектно-ориентированной программе UI, база данных и другой код поддержки часто записывается прямо в бизнес-объекты. Дополнительный бизнес логика встроена в поведение Пользовательские интерфейсы и сценарии базы данных. это происходит потому, что это самый простой способ чтобы все заработало, в краткосрочной перспективе.

Когда код домена рассеивается через такое большое количество другого кода, это становится чрезвычайно трудно увидеть и рассуждать о. Поверхностные изменения в пользовательском интерфейсе могут на самом деле изменить бизнес-логику. к изменение бизнес-правила может потребовать тщательная трассировка кода пользовательского интерфейса, код базы данных или другая программа элементы. Реализация связного, управляемые моделями объекты становятся непрактично. Автоматизированное тестирование неловко. Со всеми технологиями и логика, вовлеченная в каждое действие, программа должна быть очень простой или становится невозможным для понимания.

Обратите внимание на эту диаграмму от Microsoft, которая изображает очень хорошую реализацию многоуровневой архитектуры с использованием DDD. Обратите внимание на понятие UI Views.

alt text

2 голосов
/ 17 июня 2010

Эрик, описывающий многоуровневую архитектуру, действительно несколько сбивает с толку. Насколько я понимаю, он указал, что у хорошего приложения есть несколько слоев, и эти слои должны быть отделены. Единственный предмет слоев стоит собственной книги и не описывается далее (кроме небольшого фрагмента, который вы цитировали) в книге.

На самом деле DDD не зависит от многоуровневой архитектуры, но я уверен, что все реальные реализации DDD используют уровни в архитектуре. Лучшее (чем Эванс) объяснение при разработке решений на основе DDD - это предложение Джеффри Палермо: луковая архитектура . Палермо подробно рассказывает об обязанностях каждого слоя и о путях общения. Я лично использую этот подход с большим успехом в моих собственных проектах. Если вы хотите увидеть, как это может выглядеть на практике, взгляните на DDDSample (если вы Java-парень) или DDDSample.Net (.NET-порт DDDSample, который я имею написано)

1 голос
/ 16 июня 2010

Вы намекаете на принцип обращения зависимостей :

A. Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций. Б. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Часть A подразумевает, что ни один раздел вашего приложения не зависит напрямую от деталей реализации другого.

0 голосов
/ 16 июня 2010

Это не обязательно придумано, но на практике это очень трудно реализовать.

Учитывая ваш пример пользовательского интерфейса и уровня домена: цель объектов домена состоит только в хранении информации, относящейся к решаемой проблемеи раскрыть методы и свойства для изменения этой информации, а также уведомления о том, когда были внесены изменения.Это требует нулевой связи с верхним уровнем - пользовательским интерфейсом.

Вы отмечаете, что «это явно плохо, так как оно не позволяет повторно использовать пользовательский интерфейс в качестве внешнего интерфейса для какого-либо другого приложения, обеспечивающего функциональность Y-ish».Обобщение пользовательского интерфейса таким образом, чтобы оно могло приспосабливать множество моделей доменов с подобной функциональностью / намерением, не является целью проектирования, с которой я знаком, и я не считаю, что это также является целью проектирования в DDD.Я полагаю, что такой шаблон, как MVC, мог бы это позволить, но это просто переносит проблему на контроллер.

Это становится немного страннее, чем дальше, тем не менее.Если вы используете POXO (Plain Old [Insert Language] Objects)), тогда вашей персистентной среде в какой-то момент понадобятся зависимости как над, так и под ней. (1)

Однако большая часть кода может поддерживатьсяграфик зависимостей только для понижения, пока вы не достигнете дна.

(1) ORM знают о вашей доменной модели + DB, если вы используете DTO, тогда она знает о DTO, db и т. д.

0 голосов
/ 16 июня 2010

Я видел идею использования слоев очень эффективно, и я видел приложения там, где это было необходимо, но не использовалось.

Для примера первого случая.Я работал над проектом, где мы построили инфраструктуру и сервисы для сервис-ориентированной архитектуры.(Мы сделали это, потому что это был 1997 год, и тогда вы не могли просто скачать их)Этот пример построил один слой поверх другого.Был сетевой уровень, уровень протокола (использующий XDR для переносимости) и т. Д. В некотором смысле, это было похоже на многоуровневую передачу в TCP - обратите внимание, как отправитель добавляет к переданному блоку в обратном порядке, что получатель снимает их,Основной причиной того, что это сработало, было то, что нижние слои могли быть тщательно продемонстрированы как прочные и повторно использованные в различных местах.Большинство ошибок не возникало в этих слоях, и нам не нужно было о них беспокоиться.Это значительно сократило время отладки.

Для примера последнего - я работал над другим сетевым приложением, построенным поверх IRC.К сожалению, в этом случае не было слоев.Код очень напоминал код спагетти, который я видел в ранние годы.В этом проекте был объект User, который использовался вплоть до сетевого уровня.Это была катастрофа.Определенные ошибки в объекте User могут привести к поломке всего, вплоть до того места, куда код помещал материал в провод.Я видел случаи, когда мне приходилось выбрасывать код и начинать все сначала.Я хотел сделать это в этом случае, но политический ландшафт помешал этому.

Правильно ли наслоение для каждого приложения?Возможно нет.Но когда вы создаете приложение любой сложности, оно должно быть у вас.Это один из механизмов, который помогает нам придерживаться правила разделения интересов.

0 голосов
/ 16 июня 2010

Я не думаю, что расслоение и разделение модулей друг от друга с помощью интерфейсов являются взаимоисключающими, именно так я интерпретирую ваш пост.

В моем мире уровни совпадают как по объему функциональности, так и по зависимости компиляции / времени выполнения. Слой поверх другого слоя использует и добавляет какое-то значение (с точки зрения пользователя) к тому, что находится под ним - которое часто состоит из нескольких модулей «островного типа», которые выполняют четко определенную функцию. Я всегда скрываю реализацию за интерфейсом, облегчая боль его изменения. Это также дает мне возможность компилировать / компилировать мой код без реализации каждого уровня, что, в свою очередь, облегчает совместную работу нескольких людей.

Вот хорошая диаграмма, которая применима к большинству серьезных вещей, которые я создал:

UI/API controllers
       |
    A Facade
       |
Composite Services
       |
Isolated Services <--> External Services
       |
      DAOs
       |
  Persistance
0 голосов
/ 16 июня 2010

Я думаю, он имеет в виду, что «нижние уровни» независимы от «высших уровней» настолько, насколько они могут стоять сами по себе.

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

Аналогично для слоев Repository или DAO.

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

Но зависимость наличия нижних уровней для функционирования верхних уровней является концептуальной односторонней зависимостью.

...