Возможно, на самом деле это не ответ на ваш вопрос, но, тем не менее, есть над чем подумать.
Я не согласен с тем, куда вы помещаете доступ к данным в иерархию компонентов.Я бы не поставил его между двумя функциональными уровнями домена.Даже не «над» классами модели одного домена.Доступ к данным или их постоянство не имеют значения для любого класса домена.Это должно быть только то, что можно сделать с ними, а не то, что они делают.
Хотя я начал кодировать такие вещи, как TClient.Save
и TClient.Load
, я пришел к выводу, что это неКлиент, который решает, что он должен быть сохранен, но пользовательские взаимодействия, которые определяют, когда нужны данные экземпляра домена и, следовательно, должны быть загружены, и когда данные клиента должны быть сохранены, если вообще.Поэтому я теперь сторонник кодирования (в GUI, точнее, контроллера в GUI) таких вещей, как DataStore.Load(ClientInstance)
и DataStore.Save(ClientInstance)
.Затем это зависит от уровня доступа к данным, чтобы выяснить, как это сделать.Он может использовать отражение в C # или новый RTTI в Delphi для итерации по всем свойствам клиента, чтобы он мог отправлять их в базу данных.
В то время как многоуровневое использование - это очень хорошая концепция, чтобы отделить проблемы и не дать вам поставитьПовсюду, просто придерживаясь «Вы можете звонить, но не звонить», это не так помогает при решении таких вопросов, как ведение журнала, обработка исключений, уведомления и все другие интересные сквозные проблемы, которые нужны каждому другому компоненту / слою.
Кроме того, общий слой, поскольку он является служебным слоем, должен быть действительно доступен для всех остальных слоев.
Чтобы поместить все это в изображение (где я сохранил различие между вамисделайте между простыми классами доменов, вашей моделью и межклассовыми бизнес-правилами, вашим BAL):
+---+ +-------------+
| C |<--| Data Access |<--------------------------+
| o | +-------------+ |
| m | | |
| m | | |
| o | v |
| n | +-------------+ +----------------+ +-----+
| |<--| Model +<--| Cross class |<--| GUI |
| | +-------------+ | business rules | | |
| | | | | |
| |<--------------------| | | |
| | +----------------+ | |
| | | |
| |<-----------------------------------------| |
+---+ +-----+
Реализация INotify, которая обращается к базе данных, в настоящее время находится в модели, которая на рисунке выше не делаетвызов самого уровня доступа к данным, он только вызывается, или, вернее, intдопущено уровнем доступа к данным.
Вопрос на самом деле в том, должен ли INotify входить в «модель», часть уровня домена, или это должен быть общий интерфейс и должен быть отдельный ».Уровень уведомления / компонент, доступный из домена и графического интерфейса.Этот новый компонент может касаться не только уведомлений, но и многих других сквозных задач, например ведения журнала.У него есть доступ к общим (конечно) и компонентам доступа к данным, а также к графическому интерфейсу, по крайней мере, в некотором роде обратного вызова.
На рисунке ниже я попытался визуализировать это, но я неочень хорош в визуализации и всегда имеет проблемы с этими надоедливыми поперечными резцами.Вот почему нет стрелок вызова от уровня домена к сквозным задачам, хотя, конечно, уровень домена должен иметь доступ, например, к интерфейсу «Logger».Может быть, я стараюсь провести различие между общими и сквозными компонентами, и можно привести аргумент для их объединения и визуализации их в виде отдельных блоков в слое / компоненте «Утилиты».
+--------------------------------------------+
+-----| Cross cutting concerns |
| +--------------------------------------------+
v v^ ^
+---+ +-------------+ |
| C |<--| Data Access |<--------------------------+ |
| o | +-------------+ | |
| m | | | |
| m | | | |
| o | v | v
| n | +-------------+ +----------------+ +-----+
| |<--| Model +<--| Cross class |<--| GUI |
| | +-------------+ | business rules | | |
| | | | | |
| |<--------------------| | | |
| | +----------------+ | |
| | | |
| |<-----------------------------------------| |
+---+ +-----+