Zasady projektowania, najlepsze praktyki i wzorce projektowe dla języka C (lub ogólnie programowania proceduralnego)? [Zamknięte]

91

Czy są jakieś znane zasady projektowania, najlepsze praktyki i wzorce projektowe, którymi można się kierować podczas projektowania projektu w języku C? Lub ogólnie przydatne zasady projektowania dla programowania proceduralnego (imperatywnego)?

(Jestem dzieckiem pokolenia zorientowanego obiektowo i po raz pierwszy muszę zaprojektować duży projekt w C)

Dimi
źródło
1
Możesz być zainteresowany odpowiedziami na to pytanie: stackoverflow.com/questions/661307/ ...
mouviciel
7
Zanim opublikowałem swoje pytanie, przeszukałem internet i bibliotekę uniwersytecką i zdecydowanie nie byłem przytłoczony książkami o projektowaniu oprogramowania dla C. Proszę o twoje ulubione (nie mówię o ogólnych książkach C, nie mówię o konwencjach kodowania, takich jak znacząca zmienna nazwy, ale o wyższej abstrakcji, poziomie architektury oprogramowania). Ponadto nie zgadzam się z zarzutem, że „polegasz na innych”. Masz na myśli, że każdy programista powinien sam dowiedzieć się o najlepszych praktykach i dobrych wzorcach projektowych? Jest to z pewnością pytanie, na które należy wykorzystać doświadczenie innych.
Dimi
2
Przepraszam, Dimi, to nie dotyczyło w szczególności ciebie i nie byłam zbyt jasna. Te rzeczy były przekazywane w takim samym stopniu przez tradycję ustną, jak w każdy inny sposób: nie było nominalnego zestawu oficjalnych „wzorców”, odpowiedź Jonathona była taka, jaką można znaleźć w książkach, ale wszyscy wiedzieli o ukrywaniu informacji. Wygląda na to, że tradycja ustna została utracona i wielu młodych programistów uważa, że ​​OOP wynalazł hermetyzację i separację. Wydaje się, że ta społeczność ma mniej poczucia własnej historii, niż bym chciał. Tak więc moje uznanie, że jestem na zrzędliwym terytorium starego człowieka.
dmckee --- kociak byłego moderatora
1
Nie mogę podzielić się twoimi retrospektywnymi poglądami, ponieważ po prostu znajduję swoje stopy w terenie, ale przyjmuję twoją sugestię. Dziękuję za jaśniejsze wyrażenie siebie, zawsze bardzo cenne, aby zapoznać się z poglądem doświadczonej osoby. Naprawdę doceniam twój wkład.
Dimi
SEI CERT C Coding Standard zapewnia dobry zestaw reguł i wspólnych dobrych praktyk, a także rzeczy, których należy unikać.
Rami

Odpowiedzi:

65

Ukrywanie informacji - za zgodą Parnas ( Podstawy oprogramowania ).

Staranne zarządzanie nagłówkami i widocznością:

  • Wszystko w pliku źródłowym, które można ukryć przed światem zewnętrznym, powinno być; powinien być widoczny tylko udokumentowany interfejs zewnętrzny.
  • Wszystko, co jest ujawniane, jest zadeklarowane w nagłówku.
  • Ten nagłówek jest używany tam, gdzie potrzebna jest funkcjonalność (i gdzie jest zdefiniowana).
  • Nagłówek jest samowystarczalny - kiedy go potrzebujesz, używasz go i nie musisz się martwić o to, `` jakie inne nagłówki też muszę uwzględnić '', ponieważ nagłówek zapewnia, że ​​działa, włączając wszystko, czego potrzebuje, aby to zrobić praca.
  • Nagłówek jest samozabezpieczający - więc nie ma znaczenia, czy jest dołączany wielokrotnie.

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
    
  • Zaprojektuj zestawy funkcji do pracy na „obiektach” (zwykle strukturach) - i używaj tych funkcji zamiast grzebać w wnętrzach struktury w kodzie, który jej używa. Pomyśl o tym jako o zamknięciu narzuconym przez siebie.

Jonathan Leffler
źródło
Słuszna uwaga, dziękuję, Jonathan. Abstrakcyjne typy danych to kolejny dobry przykład ukrywania informacji z czystym oddzieleniem użycia i implementacji (znany interfejs zewnętrzny i nieznana implementacja wewnętrzna).
Dimi
23

Moje trzy rady:

  • Napisz testy jednostkowe. Pomogą Ci skupić się na projekcie, który będzie odpowiadał Twojemu problemowi. O wiele lepsze niż poleganie (wyłącznie) na myśleniu z wyprzedzeniem.
  • Zainstaluj i uruchom wykrywacz wycieków pamięci (istnieją różne biblioteki) od pierwszego dnia. Niech ta biblioteka wydrukuje wszystkie wycieki zaraz po zakończeniu programu / testów. Umożliwi to wykrycie wycieku zaraz po jego wprowadzeniu, dzięki czemu jego naprawa będzie znacznie mniej bolesna.
  • Napisz kod OOP w C. Nie jest to trudne. Chociaż możliwe jest emulowanie przesłaniania metody, sugeruję zacząć od emulacji prostych obiektów. Nawet ten prosty mechanizm zapewnia duże przebiegi.

Oto przykład:

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;
}
Itay Maman
źródło
Dziękuję Itay. Postąpię zgodnie z twoimi radami.
Dimi
1
4. Nie rzucaj wyniku malloc.
SS Anne
22

Istnieje dobra, bezpłatna książka online, zatytułowana Programowanie obiektowe z ANSI-C , która porusza temat pisania kodu zorientowanego obiektowo w języku C. Wyszukiwanie w Google słowa „obiektowo zorientowane C” daje również szereg innych dobrych przykłady i zasoby.

Jeśli Twój projekt jest krytyczny dla bezpieczeństwa, MISRA-C to dobry zestaw reguł. Jest przeznaczony głównie dla osadzonego c, ale może być również przydatny w innych obszarach.

Uważam się za programistę OO i dużo pracuję z embedded-C. Najlepsza rada, jaką mogę dać, zwłaszcza w przypadku dużych projektów, to nie przesadzać. Stworzenie kompletnego frameworka obiektowego na bazie ANSI C może być bardzo kuszące, ale jego poprawne wykonanie zajmuje dużo czasu i wysiłku. Im bardziej będziesz bardziej zaawansowany, tym więcej czasu poświęcisz na debugowanie frameworka zamiast pracy nad rzeczywistym projektem. Podejdź do zadania z trzeźwą głową i dobrym, solidnym zrozumieniem YAGNI . Powodzenia!

e.James
źródło
Dziękuję, e.James. Nie chcę tworzyć frameworka zorientowanego obiektowo na podstawie ANSI C, ale szukam specjalnych i odpowiednich zasad projektowania programowania proceduralnego. Wskazówka MISRA-C jest bardzo przydatna, zwłaszcza że w rzeczywistości jest to projekt osadzony. Przyjrzę się temu bliżej.
Dimi
Ach, radości z osadzonego C. Nie zapominaj, że musisz zadeklarować swoje zmienne u góry funkcji (lub u góry dowolnego { }bloku). Ten zawsze gryzie mnie raz lub dwa:)
James
6

OOP to metodologia, a nie technologia. Więc moja pierwsza rada to przestań myśleć o tym jako o programowaniu proceduralnym.

Wracając do e.Jamesa, nie chcesz próbować odtworzyć języka zorientowanego obiektowo lub udawać, że masz takie możliwości. Nadal możesz robić wszystkie właściwe rzeczy, trzymając się kilku prostych zasad:

  1. Przetestuj wszystko.
  2. Dowiedz się, co się różni i zamknij to.
  3. Projekt do interfejsów.

źródło