У нас есть многоуровневое приложение, или, по крайней мере, он находится в процессе перехода к одному, разбитому следующим образом:
- Интерфейс (пользовательский интерфейс или интерфейс приложения, т. Е. Веб-сервис и т. Д.)
- Бизнес логика
- Доступ к данным
Чтобы сделать остальную часть этого вопроса более конкретной, я опишу конкретный случай.
У нас есть пользовательский интерфейс, за которым находится объект контроллера (уровень бизнес-логики). Этот контроллер взаимодействует с базой данных через другой объект (уровень доступа к данным).
В данном контексте пользовательский интерфейс позволяет пользователю выбрать сотрудника, чтобы связать выполняемую операцию. Поскольку существуют правила, касающиеся того, какие сотрудники пользователь может выбирать (ну, на самом деле, любой мир за пределами контроллера), контроллер предоставляет для этого две вещи:
- читаемое свойство, содержащее список доступных сотрудников на выбор
- свойство для чтения / записи, содержащее выбранного сотрудника
Пользовательский интерфейс может прочитать список и использовать его для заполнения поля со списком.
В версии 1 этого приложения комбинированный список содержит идентификационный номер сотрудника + имя сотрудника.
Все хорошо ...
... до версии 1.1 исправление. Пользователь жалуется, что не может выбирать между Джимми Олсоном и Джимми Олсоном , потому что приложение не позволяет ему достаточно легко узнать, что есть что. Он знает, что в отделе продаж есть один Джимми, а в отделе разработки - другой, поэтому исправление для этой версии 1.1 состоит в том, чтобы просто коситься косой черты + названия отдела в выпадающем списке. В версии 2 мы бы предпочли заменить комбинированный список комбобоксом с поддержкой столбцов, удалив косую черту, но в 1.1 это то, что выбрано для минимизации риска дальнейших ошибок.
Другими словами, комбинированный список будет содержать:
- 1 - Джимми Олсон / Продажи
- 2 - Джимми Олсон / Девелопмент
Однако код пользовательского интерфейса не имеет кода SQL или какого-либо другого способа получить доступ к этому отделу, и поэтому мы должны пойти к контроллеру и посмотреть там код. Контролеру не нужен отдел, и, честно говоря, ему даже не нужно имя сотрудника, достаточно идентификационного номера, поэтому в контроллере нет ничего, что запрашивает или делает что-либо с отделом. Поэтому нам нужно перейти на уровень доступа к данным и изменить там SQL.
Это решение довольно откровенно пахнет.
Если к этому контроллеру имеется несколько интерфейсов с различными требованиями, у нас есть три возможных решения:
- Изменение уровня доступа к данным для удовлетворения (растущих / разнородных) потребностей нескольких интерфейсов (на расстоянии 2 уровня), что означает, что все интерфейсы, возможно, получат все необходимые данные, но они также получат все данные требуется для любого из других интерфейсов
- Добавьте что-то, что позволит пользовательскому интерфейсу сообщать слою доступа к данным (еще 2 слоя), что ему нужно
- Каким-то образом заставить уровень пользовательского интерфейса получить необходимые данные, не меняя ни контроллер, ни уровень доступа, это звучит так, как будто нам нужно больше кода доступа к данным где-то.
Ни одно из вышеперечисленных решений не чувствует себя хорошо.
Что мне интересно, мы совершенно не в курсе? Как бы вы это сделали? Есть ли четвертое и пятое решение ниже 3 выше?
На этот вопрос: Разделение проблем , принятый ответ содержит эту цитату:
Разделение задач позволяет хранить код для каждой из этих задач отдельно. Изменение интерфейса не должно требовать изменения кода бизнес-логики, и наоборот.
Означает ли это, что все, что должен предоставить нам уровень доступа к контроллеру / данным, - это все, что ему нужно для выполнения своей работы (т. Е. Идентифицирующее число сотрудников), а затем пользовательский интерфейс должен обратиться к базе данных и спросить Для получения дополнительной информации о этих конкретных сотрудников ?