Принципы проектирования, рекомендации и шаблоны проектирования для C (или процедурного программирования в целом)?

Существуют ли какие-либо известные принципы проектирования, лучшие практики и шаблоны проектирования, которые можно использовать при разработке проекта C? Или полезные принципы проектирования для процедурного (императивного) программирования в целом?

(Я являюсь дочерним по отношению к "объектно-ориентированному поколению" и должен проектировать большой проект C в первый раз)

Ответ 1

Сокрытие информации - как Parnas (Основы программного обеспечения).

Тщательное управление заголовками и видимостью:

  • Все в исходном файле, которое может быть скрыто от внешнего мира, должно быть; должен быть открыт только документированный внешний интерфейс.
  • Все, что выставлено, объявлено в заголовке.
  • Этот заголовок используется там, где необходима функциональность (и где она определена).
  • Заголовок самодостаточен - когда вам это нужно, вы его используете, и вам не нужно беспокоиться о том, "что другие заголовки я также должен включить", потому что заголовок гарантирует, что он работает, включая все, что нужно для его создания Работа.
  • Заголовок самозащищен, поэтому не имеет значения, включен ли он несколько раз.

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
    
  • Проектируйте наборы функций для работы с "объектами" (обычно структурами) - и используйте эти функции вместо того, чтобы разбираться с внутренностями структуры в коде, который ее использует. Думайте об этом как о добровольной инкапсуляции.

Ответ 2

Существует бесплатная, бесплатная онлайн-книга под названием Объектно-ориентированное программирование с ANSI-C, которое охватывает тему написания объектно- ориентированный код в C. A google search для "объектно-ориентированного C" также дает ряд других хороших примеров и ресурсов.

Если ваш проект критически важен, MISRA-C - это хороший набор правил. Он предназначен в основном для встроенных c, но может быть полезен и в других областях.

Я считаю себя OO-кодером, и я много работаю со встроенным C. Лучший совет, который я могу дать, особенно для крупных проектов, - это не переусердствовать. Создание полной OO-структуры поверх ANSI C может быть очень заманчивым, но для его исправления требуется много времени и усилий. Чем больше у вас собеседника, тем больше времени вы потратите на отладку своей инфраструктуры вместо работы над реальным проектом. Подходите к задаче с четкой головой и хорошим, надежным пониманием YAGNI. Удачи!

Ответ 3

Мои три совета:

  • Напишите юнит-тесты. Они помогут вам сосредоточиться на дизайне, который подходит для вашей проблемы по мере продвижения вперед. Намного лучше, чем полагаться (исключительно) на размышление перед медитацией.
  • Имейте детектор утечки памяти (есть все виды библиотек там), установленный и работающий с первого дня. Пусть эта библиотека распечатает все утечки, как только программа/тесты завершатся. Это позволит вам обнаружить утечку, как только вы ее введете, что сделает ее устранение гораздо менее болезненным.
  • Написать код ООП на C. Не так сложно. Хотя можно эмулировать переопределение методов, я предлагаю начать с эмуляции простых объектов. Даже этот простой механизм может дать вам большой пробег.

Вот пример:

typedef struct Vector {
  int size;
  int limit;
  int* ints; 
} Vector;

Vector* Vector_new() {
  Vector* res = (Vector*) malloc(sizeof(Vector));
  res->limit = 10;
  res->size = 0;
  res->ints = (int*) malloc(sizeof(int) * res.limit);

  return res;
}


void Vector_destroy(Vector* v) {
  free(v->ints);
  free(v);
}

void Vector_add(Vector* v, int n) {
  if(v->size == v->limit) {
    v->limit = v->limit * 2 + 10;
    v->ints = realloc(v->ints, v->limit);     
  }

  v->ints[v->size] = n;
  ++v->size;
}

int Vector_get(Vector* v, int index) {
  if(index >= 0 && index < v->size)
    return v->ints[index];

  assert false;
}

Ответ 4

ООП - это методология, а не технология. Поэтому мой первый совет - перестать думать об этом как процедурное программирование.

В точку e.James вы не хотите пытаться воссоздать объектно-ориентированный язык или притворяться, что у вас есть возможности. Вы все еще можете делать все правильно, цепляясь за несколько простых принципов:

  • Проверить все.
  • Найдите, что меняется и инкапсулирует его.
  • Дизайн для интерфейсов.