Principi di progettazione, migliori pratiche e modelli di progettazione per C (o programmazione procedurale in generale)? [chiuso]


91

Esistono principi di progettazione, best practice e schemi di progettazione noti che è possibile seguire durante la progettazione di un progetto C? O utili principi di progettazione per la programmazione procedurale (imperativa) in generale?

(Sono figlio della 'generazione orientata agli oggetti' e devo progettare un grande progetto C per la prima volta)


1
Si può essere interessati a anwsers a questa domanda: stackoverflow.com/questions/661307/...
mouviciel

7
Ho fatto alcune ricerche su Internet e nelle biblioteche universitarie, prima di pubblicare la mia domanda, e sicuramente non sono stato sopraffatto dai libri sulla progettazione del software per C. Ti chiedo il tuo preferito (non parlando di libri generali di C, non parlando di convenzioni di codifica come la variabile significativa nomi, ma su un'astrazione più elevata, livello di architettura software). Inoltre, non sono d'accordo con il tuo rimprovero di "fare affidamento sugli altri". Vuoi dire che ogni programmatore dovrebbe scoprire da solo le migliori pratiche e buoni modelli di progettazione? Questa è sicuramente una domanda su quale esperienza dell'altro deve essere utilizzata.
Dimi

2
Scusa, Dimi, non si trattava di te in particolare, e non ero molto chiaro. Questa roba veniva tramandata tanto dalla tradizione orale quanto in qualsiasi altro modo: non c'era una serie nominale di "Schemi" ufficiali, la risposta di Jonathon era quella che avresti trovato nei libri, ma tutti sapevano dell'occultamento delle informazioni. Sembra che la tradizione orale si stia perdendo e molti giovani programmatori pensano che OOP abbia inventato l'incapsulamento e la separazione. Questa comunità sembra avere meno senso della propria storia di quanto mi piacerebbe vedere. Da qui il mio riconoscimento che sono nel territorio di un vecchio burbero.
dmckee --- gattino ex moderatore

1
Non posso condividere la tua visione retrospettiva poiché trovo i miei piedi sul campo, ma accetto il tuo suggerimento. Grazie per esserti espresso in modo più chiaro, sempre di grande valore per arrivare a leggere il punto di vista di una persona esperta. Apprezzo molto il tuo contributo.
Dimi

Lo standard di codifica SEI CERT C fornisce un buon insieme di regole e buone pratiche comuni , nonché cose che dovresti cercare di evitare di utilizzare.
Rami

Risposte:


65

Nascondere le informazioni - come proposto da Parnas ( Software Fundamentals ).

Gestione attenta di intestazioni e visibilità:

  • Tutto in un file sorgente che può essere nascosto al mondo esterno dovrebbe essere; dovrebbe essere esposta solo l'interfaccia esterna documentata.
  • Tutto ciò che è esposto viene dichiarato in un'intestazione.
  • Quell'intestazione viene utilizzata dove è necessaria la funzionalità (e dove è definita).
  • L'intestazione è autonoma: quando ne hai bisogno, la usi e non devi preoccuparti di `` quali altre intestazioni devo includere anche io '' perché l'intestazione garantisce che funzioni includendo tutto ciò di cui ha bisogno per realizzarla lavoro.
  • L'intestazione è autoprotetta, quindi non importa se viene inclusa più volte.

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
  • Progetta insiemi di funzioni per lavorare su "oggetti" (di solito strutture) - e usa quelle funzioni piuttosto che frugare all'interno della struttura nel codice che la sta usando. Consideralo come un incapsulamento autoimposto.


Buon punto, grazie, Jonathan. I tipi di dati astratti sono un altro buon esempio di informazioni nascoste con una netta separazione tra utilizzo e implementazione (interfaccia esterna nota e implementazione interna sconosciuta).
Dimi

23

I miei tre consigli:

  • Scrivi unit test. Ti aiuteranno a concentrarti su un design che si adatta al tuo problema mentre procedi. Molto meglio che affidarsi (esclusivamente) al pensiero pre-meditato.
  • Avere un rilevatore di perdite di memoria (ci sono tutti i tipi di librerie là fuori) installato e funzionante dal primo giorno. Fai in modo che questa libreria stampi tutte le perdite non appena il programma / i test sono terminati. Questo ti permetterà di catturare una perdita non appena la introduci, rendendo così la sua riparazione molto meno dolorosa.
  • Scrivi il codice OOP in C. Non è così difficile. Sebbene sia possibile emulare l'override del metodo, suggerisco di iniziare con l'emulazione di oggetti semplici. Anche questo semplice meccanismo può darti un ottimo chilometraggio.

Ecco un esempio:

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;
}

Grazie, Itay. Seguirò i tuoi consigli.
Dimi

1
4. Non lanciare il risultato di malloc.
SS Anne,

22

Esiste un buon libro online gratuito, intitolato Programmazione orientata agli oggetti con ANSI-C , che tratta l'argomento della scrittura di codice orientato agli oggetti in C. Una ricerca su Google per "C orientato agli oggetti" produce anche una serie di altri buoni esempi e risorse.

Se il tuo progetto è critico per la sicurezza, MISRA-C è un buon insieme di regole. È inteso principalmente per embedded c, ma può essere utile anche in altre aree.

Mi considero un programmatore OO e lavoro molto con embedded-C. Il miglior consiglio che posso dare, soprattutto per i grandi progetti, è di non esagerare. La creazione di un framework OO completo su ANSI C può essere molto allettante, ma richiede molto tempo e impegno per farlo bene. Più sei appassionato, più tempo passerai a eseguire il debug del framework invece di lavorare sul progetto reale . Affronta il compito con la mente lucida e una buona e solida conoscenza di YAGNI . Buona fortuna!


Grazie, e.James. Non voglio creare un framework orientato agli oggetti sopra ANSI C, ma cerco principi di progettazione di programmazione procedurale speciali e appropriati. Il suggerimento MISRA-C è molto utile, soprattutto perché in realtà è un progetto incorporato. Lo esaminerò più da vicino.
Dimi

Ah, i piaceri del C. incorporato Non dimenticare che devi dichiarare le tue variabili all'inizio della tua funzione (o all'inizio di qualsiasi { }blocco). Quello mi morde sempre una o due volte:)
James il

7

OOP è una metodologia non una tecnologia. Quindi il mio primo consiglio è smettere di pensarlo come programmazione procedurale.

Per quanto riguarda il punto di vista di James, non vuoi provare a ricreare un linguaggio orientato agli oggetti o fingere di averne le capacità. Puoi ancora fare tutte le cose giuste attenendoti ad alcuni semplici principi:

  1. Prova tutto.
  2. Trova ciò che varia e incapsulalo.
  3. Progettare per interfacce.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.