Как создать слабую связь между частями проекта?

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

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

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 ++ с различными частями, очень зависимыми друг от друга, не становясь при этом проблемой? Я прочитал ТАК ответ на интерфейсы но я не уверен, как применить это к этой проблеме — это даже путь сюда? Существует ли шаблон проектирования (не обязательно объектно-ориентированный), который подходит для таких проектов, как этот?

1

Решение

Нет, для таких проектов не существует шаблона проектирования.

Шаблоны дизайна не являются целью.

Итак, позвольте мне сформулировать несколько догадок:

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

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

  • объявлять классы в отдельных заголовках
  • использовать forward определяет для уменьшения связи заголовка
  • переместить реализации в соответствующие исходные файлы
  • храните нежелательные зависимости реализации от файла заголовка. При желании здесь можно использовать идиому 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 любым способом, который статически компилируется. «Ограничением» является то, что внедрение зависимостей должен быть статически определен / напечатан. Преимущество заключается в максимальной гибкости и отсутствии накладных расходов: например, у вас не могло быть шаблонов виртуальных функций-членов, но вы можете использовать это как 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>;
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]