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


91

Чи є відомі принципи проектування, найкращі практики та шаблони проектування, яким можна керуватися під час проектування проекту С? Або корисні принципи проектування процедурного (імперативного) програмування загалом?

(Я дитина "об'єктно-орієнтованого покоління", і мені вперше доводиться розробляти великий проект C)


1
Ви можете бути зацікавлені в anwsers на це питання: stackoverflow.com/questions/661307 / ...
mouviciel

7
До того, як я опублікував своє запитання, я провів кілька досліджень в Інтернеті та університетській бібліотеці, і я точно не був завалений книгами про дизайн програмного забезпечення для C. Я прошу вас про улюблену (не кажу про загальні книги C, не кажу про правила кодування, як значуща змінна імена, але про вищу абстракцію, рівень архітектури програмного забезпечення). Крім того, я не погоджуюсь на ваш докір "покладатися на інших людей". Ви маєте на увазі, що кожен програміст повинен сам дізнатись про найкращі практики та гарні схеми дизайну? Це, безумовно, питання, на якому повинен бути використаний досвід інших людей.
Дімі

2
Вибачте, Дімі, це стосувалося не особливо вас, і я не був дуже зрозумілим. Колись ці речі передавались усною традицією так само, як і будь-яким іншим способом: не було номінального набору офіційних «Шаблонів», відповідь Джонатана була тим, що ви знайдете в книгах, але всі знали про приховування інформації. Здається, усна традиція втрачається, і багато молодих програмістів вважають, що ООП винайшов інкапсуляцію та розділення. Здається, ця спільнота має менше почуття власної історії, ніж я хотів би бачити. Таким чином, моє визнання того, що я перебуваю на сварливій території старого.
dmckee --- екс-модератор кошеня

1
Я не можу поділитися вашим ретроспективним поглядом, оскільки просто знаходжу ноги в полі, але я приймаю вашу пропозицію. Дякуємо, що ви висловилися чіткіше, завжди дуже важливо, щоб прочитати думку досвідченої людини. Я дуже ціную ваш внесок.
Дімі

Стандарт кодування 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;
}

Дякую, Ітей. Я дотримуватимусь ваших порад.
Дімі

1
4. Не кидайте результат malloc.
SS Anne

22

Існує хороша, безкоштовна, онлайн-книга під назвою « Об’єктно-орієнтоване програмування за допомогою ANSI-C» , яка охоплює тему написання об’єктно-орієнтованого коду на мові C. Пошук у Google для «об’єктно-орієнтованого коду » також дає ряд інших корисних даних приклади та ресурси.

Якщо ваш проект є критично важливим для безпеки, MISRA-C - це хороший набір правил. Він призначений здебільшого для вбудованого c, але може бути корисним і в інших областях.

Я вважаю себе кодером ОО і роблю багато роботи з embedded-C. Найкраща порада, яку я можу дати, особливо для великих проектів, - не перестаратися. Створення повного OO-фреймворку поверх ANSI C може бути дуже спокусливим, але для його правильного використання потрібно багато часу та зусиль. Що більше любителів, тим більше часу ви витратите на налагодження вашого фреймворку, замість того, щоб працювати над реальним проектом. Підходьте до завдання з ясною головою і добре, міцно обіймаючи ЯГНІ . Удачі!


Дякую, е. Джеймс. Я не хочу створювати об'єктно-орієнтовану структуру поверх ANSI C, але шукаю спеціальні та відповідні принципи дизайну процедурного програмування. Підказка MISRA-C дуже корисна, особливо тому, що насправді це вбудований проект. Я збираюся поглянути на нього ближче.
Дімі

Ах, радості вбудованого C. Не забувайте, що ви повинні оголосити свої змінні у верхній частині вашої функції (або у верхній частині будь-якого { }блоку). Цей мене завжди кусає один-два рази:)
Джеймс

7

ООП - це методологія, а не технологія. Тож моя перша порада - перестати думати про це як про процедурне програмування.

На думку Дж. Джеймса, ви не хочете намагатися відтворити об’єктно-орієнтовану мову або робити вигляд, що у вас є її можливості. Ви все ще можете робити все правильно, дотримуючись кількох простих принципів:

  1. Тест-драйв всього.
  2. Знайдіть, що варіюється, та інкапсулюйте це.
  3. Дизайн інтерфейсів.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.