Должен ли я попытаться исправить возможно плохое дизайнерское решение в сторонней библиотеке? - PullRequest
0 голосов
/ 01 сентября 2009

Мой проект включает в себя Qt plus и неназванную стороннюю библиотеку симуляторов физики. Работа библиотеки физики заключается в том, что физические тела не могут создавать самих себя; «Мир» должен создавать их экземпляры, чтобы они могли быть немедленно добавлены в мир.

Мой проект создает оболочку вокруг этих физических тел, чтобы добавить дополнительную функциональность, но, поскольку он хранит эти физические тела, он также не может быть создан. Первый вопрос: имеет ли смысл позволить этим органам стоять самостоятельно? Часть, которую я нахожу неудобной, заключается в том, что я должен передать объекту ссылку на мир, чтобы он мог быть создан, когда, для меня, имеет больше смысла передавать объект в мир.

Чтобы исправить это, я могу отложить создание стороннего тела, пока оно не будет добавлено в мою оболочку мира. Но это означает, что моя мировая оболочка отвечает за правильную инициализацию тела. Это также означает, что я не могу получить доступ к каким-либо свойствам объекта до тех пор, пока он не будет добавлен в мир, потому что все они зависят от инициализации тела третьей стороны ... если я не продублирую все эти данные и не передам их в библиотеку, когда она будет добавлена.

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

Я упомянул Qt, потому что графическая структура Qt работает так, что вы можете создавать QGraphicsItems в любое время, и они будут стоять самостоятельно, но они просто не будут видны, пока вы не добавите их в сцену. Аналогия здесь заключается в том, что GraphicsItem == Body, а Scene == World.

Ответы [ 3 ]

2 голосов
/ 01 сентября 2009

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

код sudo:

Rock rock = new Rock(100); //simple data container for now.

PhysicsFacade f = new PhysicsFacade(); //internally creates world.

f.DoSomething(rock); //internally rock's data used by world to create an equivalent    object which is attached to the rock data container for future use.
1 голос
/ 01 сентября 2009

все мои геттеры и сеттеры в основном должны проверять "тело инициализировано?"

Если вы используете Qt, я полагаю, вы используете C ++.

Я не знаю Qt и не знаю, почему вы хотите изменить существующий механизм, но в любом случае: одна вещь, которую вы можете сделать в C ++, которая может быть вам полезна, это перегрузить оператор -> для получить доступ к вашим объектам. Когда кто-то вызывает оператор ->, оператор может также создать объект точно в срок, если он еще не был создан, что-то вроде:

World& getWorld();

class Body;

class MyWrapper
{
  Body* m_body;

public:

  MyWrapper() : m_body(0) {}

  Body* operator->()
  {
    if (!m_body)
    {
      m_body = new Body(getWorld());
    }
    return m_body;
  }

  ... etc ...
};

Редактировать

Что вы имеете в виду, «изменить существующий механизм»? Тот, который выложил физическая библиотека? Я думаю, что упомянул свои причины.

Да.

С вашим решением ... что делает getWorld ()? Это глобальная функция? Если мир плавает в глобальном пространстве, то проблемы на самом деле нет, я могу просто создать экземпляр тела в то же время, когда создается экземпляр MyWrapper.

Да, он возвращает ссылку на Мир, который вам нужен для создания тела в библиотеке физики. Это пример, я не знаю, откуда вы взяли ссылку на ваш Мир, и когда.

Но что, если мир все еще не существует в тот момент, когда используется оператор ->? Я не совсем уверен, что это что-то решает. Не говоря уже о том, что так или иначе, вы все еще передаете мир телу

Может быть, getWorld сгенерирует исключение, если оно вызывается слишком рано. В любом случае, то, что это должно было вас купить, было:

  • Возможность создания MyWrapper экземпляров без ссылки на Мир и, возможно, до создания мира.

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

Оператор -> - это то, что клиенты использовали бы, чтобы получить физическое тело, которое вы упаковываете: как «умный указатель».

Возможно, будет проще понять и / или предложить решения для вашей проблемы, если вы проиллюстрируете свою проблему с помощью некоторого псевдокода.

Не говоря уже о том, что так или иначе, вы все еще передаете мир телу

Вы сказали, что это требование базовой библиотеки. Когда вы сказали: «Должен ли я попытаться исправить», я подумал, что вы имеете в виду «Должен ли я реализовать другой API в моей оболочке и скрыть существующий API в моей частной реализации?» Мне не пришло в голову, что вы можете попытаться изменить (а не просто обернуть) существующую реализацию.

0 голосов
/ 02 сентября 2009

Прежде чем я поделюсь своим ответом, позвольте мне переименовать несколько вещей. «Объект» - это то, что содержит «физическое тело». «Мир» - это то, что держит «мир физики». Опять же, только «физический мир» может создать «физическое тело» (его конструктор является личным).

Вот что я сделал. Объект просто содержит указатель на физическое тело. Таким образом, вы можете создавать Объект в любое время и играть со всеми его данными, даже не нуждаясь в мире ... вы просто не можете прикоснуться к свойствам, непосредственно связанным с физическим телом (я собираюсь УКАЗАТЬ это).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...