Обратная зависимость между слоями проблема - PullRequest
1 голос
/ 06 сентября 2010

Я строю систему управления для установки оборудования (система циркуляции воды). Я разработал его в два слоя: слой описания оборудования и уровень управления.

+----------------------------------------------+
|    Control (enables manipulation of devices) |
+----------------------------------------------+
        | uses (decorates)
        v
+---------------------------------------+  (de)serialize  +------------+
|            HW Description             |<--------------->| Files / DB |
| (stores physical layout, cabling etc) |                 +------------+
+---------------------------------------+

Уровень описания аппаратного обеспечения содержит карту аппаратного обеспечения, описывающую, как трубы подключены к теплообменникам и другому оборудованию. Данные для этого слоя настраиваются для каждой установки и будут считываться во время выполнения. Поэтому все классы в слое описания оборудования должны быть так или иначе сериализуемы (через Hibernate / сериализацию в XML или около того).

Уровень управления украсит классы слоя описания аппаратных средств интеллектом, поэтому, например, теплообменник получит связанный с ним HeatExchangerController.

В этой системе объектам на уровне управления, возможно, придется искать своих ближайших соседей по описанию оборудования, поэтому контроллер теплообмена может сделать что-то вроде

HeatExchangerController neighbour = this.getHeatExchanger().getInputPipe().getOtherSide().getHeatExchanger().getController();
neighbour.notify(highLoadAlert);

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

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

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

Спасибо.

Ответы [ 4 ]

0 голосов
/ 07 сентября 2010

Это сложное решение, которое я имел в виду. Он добавляет декоративный слой поверх слоя HW, который добавляет ссылки на управляющий слой к каждому объекту HW:

                                                                 -+
+--------------------------+               +-----------------+    | 
| HeatExchangerController  |               | PipeController  |     > Controller Layer
+--------------------------+               +-----------------+    |
            ^ 1 controller                        ^ 1 controller -+
            |                                     |
            v 1 heatExchanger                     v 1 pipe       -+
+---------------------------+  inputPipe 1 +------------------+   |
| ControlAwareHeatExchanger |--------------| ControlAwarePipe |    > Decorated HW Layer
+---------------------------+ 1 otherSide  +------------------+   |
            |                                     |              -+
            v 1 realExchanger                     v 1 realPipe   -+
+---------------------------+  inputPipe 1 +------------+         |
|      HeatExchanger        |--------------| Pipe       |          > HW Layer
+---------------------------+ 1 otherSide  +------------+         |
                                                                 -+

Декорированный слой будет содержать код вроде:

class ControlAwareHeatExchanger {
  private final HeatExchanger realExchanger;
  private final ControlAwarepipe inputPipe;

  public ControlAwareHeatExchanger(HeatExchanger decoratee) {
    realExchanger = decoratee;
    inputPipe = new ControlAwarePipe(decoratee.getInputPipe());
  }

  public ControlAwarePipe getInputPipe() {
    return inputPipe;
  }

  ...
}      

Таким образом, вы можете сделать:

ControlAwareHeatExchanger controlHE = heatExchangerController.getHeatExchanger();
ControlAwarePipe controlInputPipe = controlHE.getInputPipe();
ControlAwareHeatExchanger otherHE = controlInputPipe.getOtherSide();
HeatExchangerController otherController = otherHE.getController();

Таким образом, вы можете спуститься на декорированный слой hw, прыгнуть вокруг, а затем снова вернуться на слой контроллера, и все это без слоя hw, который знает об уровне управления.

Но, как вы можете видеть, вам нужно отразить все соединения и украсить весь слой HW, чтобы добиться этого. Многие делегации будут вовлечены. Мысли?

0 голосов
/ 06 сентября 2010

не совсем уверен, в чем ваша проблема.если вы не хотите использовать метод getController () в своем классе оборудования, вы можете хранить привязку оборудования-> контроллера в слабой хэш-карте

public class Controller

    static WeakHashMap<Hardware,Controller> map = ...

    static public Controller of(Hardware hw){ return map.get(hw); }

    Controller(Hardware hw)
    {
        map.put(hw, this);
    }

очень часто, люди любят добавлять «удобно»методы, не опасаясь сложности в зависимостях

user.getThis()
user.getThat()
user.getTheOthers()

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

0 голосов
/ 06 сентября 2010

Вы не показали нам, какую выгоду вы получите от отделения логики контроллера от описания аппаратного обеспечения. Вы уверены, что это разделение стоит усилий?

Звучит так, как будто вы строите модель анемичного домена ?

0 голосов
/ 06 сентября 2010

Используйте подход, управляемый доменом.

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

...