2015-10-18 2 views
1

Введение: Я пришел из инженерного фона, но занял класс во встроенном программном обеспечении (на прекрасном маленьком роботе) с намерением улучшить некоторые навыки, которые у меня были в программировании. Однако класс был в значительной степени неудовлетворительным в том, чего я надеялся достичь (в основном, он преподавал основы C++ с некоторыми очень поверхностными композиционными шаблонами).Как создать свободную связь между частями проекта?

Вопрос Нам сказали, что наш код несколько ориентирован на объекты, определяя классы для различных частей кода. Поскольку все части были очень зависимы друг от друга, общая структура выглядела следующим образом (в основном, класс Drive, Sensors и WorldModel с некоторыми зависимостями и класс директора, который пытался заставить наш робот решить задачу под рукой)

class Drive{ 
    void update(); 
    Drive(Sensors & sensors); 
private: 
    Sensors & sensors 
}; 

class Sensors{ 
    void update(); 
} 

class WorldModel { 
    void update(); 
    WorldModel(Sensors & sensors, Drive & drive); 
private: 
    Sensors & sensors; 
    Drive & drive; 
}; 

class Director { 
    void update(); 
    Director(Sensors & sensors, Drive & drive, WorldModel & worldmodel); 
private: 
    Sensors & sensors; 
    Drive & drive; 
    WorldModel & worldmodel; 
}; 

Это на самом деле чрезвычайно сжатая версия. Мне кажется, однако, что это не действительно объектно-ориентированный код целых Неудобно разделить код ™. В частности, было почти невозможно сделать, например, класс Sensors получает данные из класса Drive без каких-либо ошибок в классе Director (т. е. сначала выполнить функцию в классе Drive для получения заданного значения скорости, а затем предоставить это методу update() в классе Sensors, чтобы сделать некоторый Кальман фильтрация).

Как создать проект на C++ с различными частями, которые очень зависимы друг от друга, без каких-либо проблем? Я прочитал ответ SO на interfaces, но я не уверен, как применить это к этой проблеме - это даже путь сюда? Существует ли шаблон проектирования (не обязательно объектно-ориентированный), который подходит для таких проектов, как этот?

+0

Я бы сказал, что, если вы думаете, «Объектно-ориентированный» как-то указывает на «Интерфейсы» (т.е. во время выполнения полиморфизм), то вы должны, вероятно, оставить это для C++. В областях, где C++ лучше всего подходит, я думаю, что эта модель OO редко бывает самой полезной – sehe

+0

@sehe Я не говорю, что я обязательно хочу объектно-ориентированный код - это просто, что этот код был половинчатой ​​попыткой ООП, которая была никогда не объяснял более подробно, чем «Классы». Все может быть публичным и частным. Получайте удовольствие! » – Sanchises

+0

Я думаю, что когда вы сделаете «удовольствие», вы узнаете все остальное. Либо это, либо прочитайте некоторые книги. Я не думаю, что SO - это хорошее место, чтобы сослаться на учебники, к сожалению – sehe

ответ

2

Нет, у проектов нет такого дизайна, как «это».

Дизайн шаблонов не является целью.

Итак, позвольте мне сказать несколько предположений прямо:

  • вы хотите легкий вес кода (так как в противном случае вы бы использовать Java, справа)
  • вы хотите ремонтопригодны код (потому что в противном случае, спагетти бы хорошо)
  • вы хотите идиоматического код

Вот что я хотел бы сделать:

  • объявлять классы в отдельных заголовках
  • использование вперед определяет уменьшить заголовок муфты
  • реализации перемещаются в соответствующих исходных файлах
  • держать зависимости нежелательной реализацию из заголовка файла. При желании используйте Идиому Pimpl.

    например. если вы используете библиотеку X для реализации Y::frobnicate, не включайте libX.h в свой Y.h. Вместо этого включите его только в Y.cpp.

    Если вы нашли, что вам требуется объявление члена класса, для которого в заголовке потребуется libX.h, используйте Идиома Pimpl.

Я не знаю, что еще вы могли бы хотеть здесь :)

Может быть, если вам нужно «интерфейсы» рассмотреть возможность использования композиции шаблона. Политика, стратегия, государственные модели. Например. Вместо

#include <set> 

    struct ISensors { 
     virtual int get(int id) const = 0; 
     virtual int set(int id, int newval) const = 0; 
     virtual std::set<int> sensors() const = 0; 
    }; 

    class Drive { 
     void update(); 
     Drive(ISensors &sensors); 

     private: 
     ISensors &sensors; 
    }; 

Вы могли бы рассмотреть

template <typename Sensors> 
class Drive { 
    void update(); 
    Drive(Sensors &sensors); 

    private: 
    Sensors &sensors; 
}; 

который оставляет вас свободными реализовать Sensors в любой, какой путь, который статически компилирует. «Ограничение» заключается в том, что injection of dependencies необходимо статически определить/ввести. Преимущество - это максимальная гибкость и нулевые накладные расходы: например, Вы не могли бы иметь шаблоны виртуальных функций-членов, но вы можете использовать это в качестве Sensors политики:

struct TestSensors { 
    int get(int)  { return 9; } 
    int set(int, int) { return -9; } 

    template<typename OutputIterator> 
    OutputIterator sensors(OutputIterator out) const { 
     int available[] = { 7, 8, 13, 21 }; 
     return std::copy(std::begin(available), std::end(available), out); 
    } 
}; 

using TestDrive = Drive<TestSensors>; 
+0

Спасибо за ваш обширный ответ. На самом деле нам удалось решить некоторые циклические ссылки, по сути, только # включение в исходные файлы, но я не мог решить одну проблему: ссылки должны быть инициализированы сразу, поэтому я не мог правильно инициализировать объекты, если конструкторы были «Sensor (Drive & drive)» и «Drive (Sensor & sensor)»; может ли шаблонная композиция решить эту проблему, или мне нужно ввести указатель ада? – Sanchises

+0

А, да. Я забыл о ссылках. Я бы использовал (умные) указатели, которые точно выражают семантику собственности. При желании создайте фабричную функцию, которая создает (наборы) объекты. Но на самом деле, если на Диске есть «Датчики», есть «Диск», это запах кода. Используйте разделение на основе ответственности для устранения цикла. – sehe

+0

В основном в этот момент вы можете опубликовать (сокращенную версию) свой код на [codereview.se] – sehe

Смежные вопросы