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

92

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

(Я ребенок «объектно-ориентированного поколения», и мне впервые нужно разработать большой проект на C)

Дими
источник
1
Возможно, вас заинтересуют ответы на этот вопрос: stackoverflow.com/questions/661307/…
mouviciel
7
Я провел некоторое исследование в Интернете и университетской библиотеке, прежде чем опубликовать свой вопрос, и определенно не был перегружен книгами о дизайне программного обеспечения для C. Я прошу вас выбрать ваш любимый (не говоря об общих книгах по C, не говоря о соглашениях о кодировании, таких как значимая переменная имена, но о более высокой абстракции, уровне архитектуры программного обеспечения). Более того, я не согласен с вашим упреком «полагаться на других людей». Вы имеете в виду, что каждый программист должен сам узнать о лучших практиках и хороших шаблонах проектирования? Это наверняка вопрос, в котором нужно использовать чужой опыт.
Дими
2
Извини, Дими, это не касалось тебя конкретно, и я не очень понял. Раньше это передавалось устной традицией в такой же степени, как и любым другим способом: не существовало номинального набора официальных «Узоров», ответ Джонатона был тем, что вы найдете в книгах, но все знали о сокрытии информации. Кажется, что устная традиция утеряна, и многие молодые программисты думают, что ООП изобрело инкапсуляцию и разделение. Это сообщество, кажется, меньше разбирается в своей истории, чем мне хотелось бы. Таким образом, мое признание того, что я нахожусь на территории сварливого старика.
dmckee --- котенок экс-модератора
1
Я не могу разделить ваш ретроспективный взгляд, так как просто нахожусь в поле, но я принимаю ваше предложение. Спасибо за то, что вы выражаетесь более четко, всегда очень ценно, когда вы можете прочитать точку зрения опытного человека. Я очень ценю ваш вклад.
Dimi
Стандарт кодирования SEI CERT C предоставляет хороший набор правил и общепринятые передовые практики, а также вещи, которых следует избегать.
Рами

Ответы:

65

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

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

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

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

Джонатан Леффлер
источник
Хорошее замечание, спасибо, Джонатан. Абстрактные типы данных - еще один хороший пример сокрытия информации с четким разделением использования и реализации (известный внешний интерфейс и неизвестная внутренняя реализация).
Дими
23

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

  • Напишите модульные тесты. Они помогут вам сконцентрироваться на дизайне, который решает вашу проблему в дальнейшем. Намного лучше, чем полагаться (исключительно) на заранее продуманное мышление.
  • Установите и запустите детектор утечки памяти (есть все виды библиотек) с первого дня. Попросите эту библиотеку распечатать все утечки сразу после выхода из программы / тестов. Это позволит вам обнаружить утечку сразу же после ее введения, что сделает ее устранение менее болезненным.
  • Напишите код ООП на 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;
}
Итай Маман
источник
Спасибо, Итай. Я последую вашим советам.
Dimi
1
4. Не разыгрывайте результат malloc.
SS Anne
22

Существует хорошая бесплатная онлайн-книга под названием « Объектно-ориентированное программирование с помощью ANSI-C» , в которой рассматривается тема написания объектно-ориентированного кода на C. Поиск в Google «объектно-ориентированного C» также дает ряд других полезных результатов. примеры и ресурсы.

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

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

е. Джеймс
источник
Спасибо, Э. Джеймс. Я не хочу создавать объектно-ориентированную структуру поверх ANSI C, но ищу специальные и подходящие принципы проектирования процедурного программирования. Подсказка MISRA-C очень полезна, особенно потому, что на самом деле это встроенный проект. Я собираюсь рассмотреть это поближе.
Дими
Ах, радости встроенного C. Не забывайте, что вы должны объявлять свои переменные в верхней части вашей функции (или в верхней части любого { }блока). Этот всегда кусает меня один или два раза:)
Джеймс
6

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

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

  1. Тест-драйв все.
  2. Найдите то, что меняется, и инкапсулируйте это.
  3. Дизайн для интерфейсов.

источник