В моей компании есть код, который принимает следующую форму:
class ObjectA {
public:
ObjectA(ObjectB &objectB): objectB(objectB) { }
void Initialize() { ... }
private:
ObjectB &objectB;
};
class ObjectB {
public:
ObjectB(ObjectA &objectA): objectA(objectA) { }
void Initialize() { ... }
private:
ObjectA &objectA;
};
По сути, два класса имеют взаимозависимость друг от друга.
Само по себе это не то, что беспокоитменя, (хотя это не лучший дизайн IMO) , это то, что взаимные зависимости передаются через конструктор по ссылке в обеих ситуациях .
Итак, единственный способфактически построить эту пару объектов (они оба требуются в приложении) означает передать неполную ссылку в качестве зависимости.Чтобы учесть это, отдельные Initialize
методы добавляются как конструктор 2-го этапа, который затем вызывается после создания обоих объектов.Следовательно, конструкторы часто ничего не делают, кроме как присваивают параметры конструктора внутренним объектам и инициализируют все в методе * 1015. *
Хотя код может быть действительным, я склоняюсь к тому, что это в корне невернодизайн по следующим причинам:
- Состояние зависимого объекта не может быть гарантировано в конструкторе
- Требуется, чтобы разработчики сделали дополнительный вызов к
Initialize
- Это исключает использование предупреждений компилятора, которые проверяют, были ли инициализированы переменные-члены
- Ничто не мешает многократному вызову
Initialize
, что может привести к странным, трудно отслеживаемым ошибкам
Мои коллеги говорят мне, что наличие отдельного метода инициализации упрощает конструирование объекта, поскольку разработчику не нужно беспокоиться о том, какие объекты заказа объявлены в корне приложения.Они могут быть объявлены и построены в совершенно произвольном порядке, поскольку все гарантированно будет действительным после вызова Initialize.
Я выступал за то, чтобы конструкция объекта следовала тому же порядку графа зависимостей, и что эти объекты должныбыть переработан, чтобы устранить взаимную зависимость, но я хотел посмотреть, что гуру SO должен сказать по этому поводу.Неужели я ошибаюсь, считая, что это плохая практика?
Редактировать:
Способ, которым эти классы на самом деле создаются, - через фабричный класс, как показано ниже:
Factory {
public:
Factory():
objectA(objectB),
objectB(objectA) {
}
private:
ObjectA objectA;
ObjectB objectB;
};