Как построить структуру классов, когда члены также структурированы иерархически?
Я создаю веб-приложение на PHP, которое должно предоставить пользователю возможность заказать "установку"/ настройку (ConnectDirect или File Transfer Gateway) соединения между ним и другим человеком / организацией.
(Технические особенности реализации соединений не важны - в приложении речь идет только о соединениях как о продукте, которые можно заказать и управлять.)
Иерархия классов для ее уровня модели должна представлять следующую реальную инфраструктуру:
- Есть соединения, которые можно заказать.
- Соединение может быть соединением IBM Connect:Direct или соединением IBM File Transfer Gateway.
- Подключение CD напрямую от A (источник) к B (цель).
- Соединение FTGW физически состоит из двух соединений: A (источник) с сервером FTGW и от сервера FTGW до B (цель), но логически (для пользователя, заказывающего заказ) это также одно соединение.
- (Существует также случай соединения FTGW, в котором Connect: Direct используется в качестве протоколла.)
- Каждая конечная точка является либо источником, либо целью.
Поэтому я вижу следующие логические элементы: логическое соединение, физическое соединение, роль (источник и цель), тип соединения, порядок, конечная точка, тип конечной точки (CD и FTGW).
Структура, которую я сейчас имею, выглядит так:
Но есть некоторые проблемы с этим:
Существует два дерева иерархии, где каждый элемент одного содержит элементы определенного подмножества другого (каждое соединение CD состоит из конечных точек CD; каждое соединение FTGW состоит из двух конечных точек FTGW, или, более правильно: каждое логическое соединение FTGW состоит из два физических соединения FTGW - и каждое из них состоит из конечной точки FTGW и сервера FTGW в качестве второй конечной точки).
Альтернативой может стать замена отношений между
Endpoint
а такжеPsysicalConnection
двумя отношениями:EndpointCD-PsysicalConnectionCD
а такжеEndpointFTGW-PsysicalConnectionFTGW
,
Pro: более последовательный; устраняет логическую неточность (или, возможно, даже ошибку) ложной возможности построить каждое соединение (тип) из пары любых конечных точек. Против: На самом деле требование содержать две конечные точки является характеристикой каждой физической связи - с этой точки зрения правильное место для этого является самым основным PsysicalConnection
учебный класс.
Каждая конечная точка может быть как исходной, так и целевой, и содержит не только общие свойства конечной точки, но также свойства источника и назначения. Это означает, что в зависимости от текущей роли конечной точки некоторые свойства являются ненужными. И это также будет влиять на структуру базы данных (столбцы, которые иногда должны быть установлены, а иногда
NULL
).Альтернативой является расширение иерархии...
а.... по классам вроде
EndpointSource
а такжеEndpoitTarget
наследование непосредственно отEndpoint
и наследуется классамиEndpointCD
а такжеEndpointFTGW
(это означает: два идентичных поддерева - подEndpointSource
и подEndpointTarget
);б.... по классам вроде
EndpointCDSource
а такжеEndpointCDTarget
(наследование от классаEndpointCD
) а такжеEndpointFTGWSource
а такжеEndpointFTGWTarget
(наследование от классаEndpointFTGW
) наследуется каждым конкретным классом конечных точек CD или FTGW (что означает: два два идентичных поддерева);с.... по классам вроде
MyConcreteEndpoint***Source
а такжеMyConcreteEndpoint***Target
наследование от конкретных классов конечных точек (это означает, что каждыйMyConcreteEndpoint
класс становится абстрактным и получает два подкласса -MyConcreteEndpoint***Source
а такжеMyConcreteEndpoint***Target
например,EndpointCDLinux
теперь является абстрактным и наследуетсяEndpointCDLinuxSource
а такжеEndpointCDLinuxTarget
).Pro: устраняет свойства отходов. Против: A (более) сложная иерархия классов.
Ну, речь идет об архитектуре программного обеспечения и должна (и, конечно, будет) моим дизайнерским решением. Но было бы неплохо услышать / прочитать некоторые экспертные (или не экспертные) мысли о том, как справиться с таким делом. Как правильно организовать логические элементы для инфраструктуры, как я описал?
1 ответ
Может быть, я обдумываю, но я предлагаю вам использовать немного другую модель для отражения вашей бизнес-логики.
Следующее может быть полным недоразумением, но я попробую.
Так:
Основываясь на том, что на самом деле является любой связью, вот концепция:
- Каждое соединение представляет собой набор узлов, через которые должны проходить данные, чтобы достичь пункта назначения.
- Каждый узел может соединяться со следующим узлом, используя особый протокол, который специфичен только для прямого соединения между двумя конкретными узлами.
- Протокол имеет свои собственные свойства, общие для исходного и целевого узлов.
Исходя из этого, я предлагаю следующую модель построения, управления и хранения конфигурации продукта:
Вот:
LogicalConnection - это ссылка на встроенную композицию реальных классов Connection, Node и Protocol.
Соединение содержит двусвязный список узлов, которые составляются по порядку как потоки данных. т.е.: 1-й элемент - это исходный узел, 2-й - его цель и т. д.
Конкретный узел содержит конкретную конфигурацию платформы, ссылку на цель (*Node), исходный узел (* Node) и конкретный протокол (*Protocol)
Протокол содержит свою конкретную конфигурацию для источника и цели. Экземпляры узла могут ссылаться на экземпляр протокола для извлечения требуемой конфигурации.
Целевые и исходные узлы "видят" друг друга и конфигурацию исходного-целевого протокола через двойную структуру списка.
Конфигурации \* Реализации ConfigBuilder управляют процессом принятия данных из пользовательского интерфейса и преобразования их в фактическую композицию соединения, узла и протокола в зависимости от случая.
Пространства имен IBM\ConnectDirect\ и IBM\FTGW\ содержат конкретные реализации для протокола и * узла (например, WindowsNode, UnixNode)
Если по-прежнему необходимо, чтобы узел или протокол содержали атрибуты, связанные как с исходным, так и с целевым объектами, и часть из них все еще может иметь значение NULL в некоторых конфигурациях - я предлагаю использовать модель хранения EAV для БД, если есть какие-либо опасения по поводу неиспользуемых столбцов и т.
Используя предложенные модели соединений, которые вы описали в вопросе, можно представить следующим образом:
Connection:IBM_CD {
nodes:[
{//LinuxNode
target:*nextElement,
protocol:{//IBM.ConnectDirect.Protocol
..target attributes..
..source attributes..
}
..platform specific attributes..
},
{//WindowsShareNode
target:*nil,
protocol:{
//IBM.ConnectDirect.Protocol(same instance or null)
}
..platform specific attributes..
},
]
}
Connection:IBM_FTGW {
nodes:[
{//LinuxNode
target:*nextElement,
source:*nil,
protocol:{//IBM.FTGW.Protocol
..target attributes..
..source attributes..
}
..platform specific attributes..
},
{//IntermediateServerLinuxNode
target:*nextElement,
source:*prevElement,
protocol:{//IBM.FTGW.Protocol
..target attributes..
..source attributes..
},
..platform specific attributes
},
{//WindowsShareNode
target:*nil,
source:*prevElement,
protocol:*nil,
..platform specific attributes..
}
]
}