2010-04-28 17 views
13

Un aspetto in cui C mostra la sua età è l'incapsulamento del codice. Molte lingue moderne hanno classi, spazi dei nomi, pacchetti ... un codice molto più conveniente per organizzare il codice di un semplice "include".Superamento dei limiti C per i progetti di grandi dimensioni

Poiché C è ancora la lingua principale per molti progetti enormi. Come si fa a superare i suoi limiti?

Suppongo che un fattore principale dovrebbe essere un sacco di disciplina. Mi piacerebbe sapere cosa fai per gestire una grande quantità di codice C, quali autori o libri puoi consigliare.

+0

Un post simile, non specifico per C, ma contenente un buon consiglio generale: http://stackoverflow.com/questions/2025733/coding-pratice-what-are-your-thoughts-on-a-1-7- million-loc-project –

risposta

18
  • Separare il codice in unità funzionali.
  • Costruire quelle unità di codice in singole librerie.
  • Utilizzare i simboli nascosti all'interno delle librerie per ridurre i conflitti nello spazio dei nomi.

Pensare al codice open source. C'è un'enorme quantità di codice C nel kernel Linux, nella libreria GNU C, nel sistema X Window e nel progetto desktop Gnome. Eppure, tutto funziona insieme. Questo perché la maggior parte del codice non vede nessun altro codice. Comunica solo tramite interfacce ben definite. Fai lo stesso in ogni grande progetto.

2

Un buon modo è possibile ottenere un po 'di incapsulamento è dichiarare metodi interni o variabili di un modulo come static

1

Come dice Andres, static è tuo amico. Ma parlando di amici ... se vuoi essere in grado di separare una libreria in due file, allora alcuni simboli da un file che devono essere visti nell'altro non possono essere static. Decisione di alcune convenzioni di denominazione: tutti i simboli non statici della libreria foo iniziano con foo_. E assicurati che vengano sempre seguiti: sono proprio i simboli per i quali sembra vincolante ("Devo chiamarlo foo_max?! Ma è solo max!") Che ci saranno scontri.

Come dice Zan, una tipica distribuzione Linux può essere vista come un enorme progetto scritto per lo più in C. Funziona. Esistono interfacce e i sottoprogetti di grandi dimensioni sono implementati come processi separati . Un'implementazione in processi separati aiuta a eseguire il debug, a testare, riutilizzare il codice e fornisce una seconda gerarchia oltre a quella esistente a livello di link. Quando il tuo progetto diventa abbastanza grande, potrebbe iniziare ad avere senso inserire alcune funzionalità in processi separati. Qualcosa già specializzato come un compilatore C viene tipicamente implementato in tre processi: pre-processore, compilatore, assemblatore.

3

Alcune persone non mi piace ma sono un sostenitore dell'organizzazione delle strutture e delle funzioni associate insieme come se fossero una classe in cui il puntatore viene passato esplicitamente. Ad esempio, combinato con una convenzione di denominazione coerente per rendere esplicito lo spazio dei nomi. Un'intestazione sarebbe qualcosa di simile:

typedef struct foo { 
    int x; 
    double y; 
} FOO_T 

FOO_T * foo_new(); 

int foo_set_x(FOO_T * self, int arg1); 

int foo_do_bar(FOO_T * self, int arg1); 

FOO_T * foo_delete(FOO_T * self); 

Nell'implementazione, tutte le funzioni "private" sarebbero statiche. Il rovescio della medaglia di questo è che non si può effettivamente far rispettare l'utente che non va a intromettersi con i membri della struct. Questa è solo la vita in c. Trovo che questo stile sia adatto a tipi C piacevolmente riutilizzabili.

+2

Nessun problema con lo stile, ma preferirei molto 'FOO_T * x; x-> x = 1; 'oltre' FOO_T * x; foo_set_x (x, 1); '. Uno è molto più chiaro per un programmatore C. (E puoi far sì che l'utente non vada e mima con i membri di una 'struct' non dandogli una definizione. Dì semplicemente" typedef struct foo FOO_T' e poi possono usare i puntatori al tuo tipo senza vedere dentro.) –

+0

Sono d'accordo con Chris: o fornite una definizione per la struttura e aspettatevi che il codice client muti i suoi membri, oppure usate il puntatore su un typedef idiom e nascondete il contenuto. –

0

Se è possibile controllare il progetto (ad esempio, in-house o si paga qualcun altro per farlo), è sufficiente impostare regole e utilizzare recensioni e strumenti per applicarle.Non è necessario che il linguaggio faccia ciò, è possibile ad esempio richiedere che tutte le funzioni utilizzabili al di fuori di un modulo (= un insieme di file, non sia necessario separarle) debbano essere contrassegnate in tal modo. In effetti, si costringerebbe gli sviluppatori a pensare alle interfacce e ad attenersi ad esse.

Se si vuole veramente fare il punto, è possibile definire macro per mostrare anche questo, ad es.

#define PUBLIC 
#define PRIVATE static 

o alcuni di questi.

Quindi hai ragione, la disciplina è la chiave qui. Si tratta di impostare le regole E assicurandosi che siano seguite.

+0

pubblico e privato nella maggior parte delle lingue OO non significa lo stesso di statico e auto. –

+0

Sono d'accordo, la disciplina è un passo importante e importante per raggiungerlo sono regole, recensioni e strumenti come accennato ma ritengo che le riscritture siano buone per esempio, quando le regole non vengono rispettate. Le revisioni anticipate (quando il codice non è stato completato) potrebbero ridurre il costo aggiuntivo sostenuto per le riscritture. La decisione di riscrittura potrebbe essere formalmente decisa da qualcuno "in alto" e sottolinea ulteriormente che le regole devono essere seguite. –

+0

Finché 'PRIVATE' non è usato in un'intestazione inclusa da più file ... :-) – paercebal

Problemi correlati