Stile di programmazione in applicazioni C ++ su larga scala

6

Recentemente ho esplorato il codice sorgente di applicazioni di grandi dimensioni scritte in C ++ per imparare un po ', ma non ho potuto fare a meno di notare che la maggior parte, se non tutte, utilizza un sacco di IFDEF e funzioni senza classi (dove avrebbero potuto essere membri / metodi della classe).

Un esempio è il codice sorgente IDE di Qt Creator:

link

Se si nota, ha un sacco di funzioni attorno alla funzione main (); uno di questi, ad esempio, è:

static inline void toHtml(QString &t)

il metodo di cui sopra è definito al di fuori mentre penso che potrebbe essere stato parte di qualche classe di utilità forse.

Inoltre, penso che gli IFDEF rendano i programmi disordinati (di nuovo la mia opinione).

La mia domanda è : è solo una pratica accettata nel mondo C ++ per mescolare codice procedurale e OO del genere?

    
posta Software Guy 13.05.2013 - 18:15
fonte

5 risposte

14

È una domanda piuttosto soggettiva: ci sono molte scuole di pratica per scrivere il codice C ++.

C ++ ti offre la possibilità di scegliere e scegliere i paradigmi che vuoi utilizzare per scrivere il tuo codice. Il linguaggio consente di utilizzare costrutti procedurali, orientati agli oggetti, generici e funzionali (in particolare con le funzionalità di C ++ 11).

Non è necessario necessariamente creare classi di utilità (diversamente da, ad esempio, in Java, dove tutto deve essere in una classe), poiché le funzioni statiche in una classe potrebbero non essere necessarie e possono essere solo funzioni libere indipendenti.

La compilazione condizionale è una necessità a causa di piattaforme disparate. Ho lavorato in difesa e ho scritto codice usando Qt, boost, librerie per videogiochi e ho lavorato su una varietà di piattaforme tra cui Linux, HP-UX, AIX, Windows, IRIX e Mac OSX - le piattaforme sono abbastanza diverse da quel codice scritto per uno non funziona necessariamente su una piattaforma diversa. Alcuni semplici esempi sono:

  • Endianess - Alcune architetture (come x86) sono little endian, ma molte altre architetture (come SPARC) sono big endian. La rete dipende anche dall'indirizzamento big endian. Quando scrivi codice tra diverse architetture, a volte devi compilare in modo condizionale un codice che supporti tali differenze endian.

  • Chiamate di libreria diverse - Windows utilizza winsock come API di rete ed è simile ai socket BSD utilizzati da Unix e dai derivati Unix. Tuttavia, è abbastanza diverso che le chiamate alle funzioni non sono simili. Inoltre, esistono chiamate di libreria che esistono in alcune versioni di Unix che non esistono in altri sapori o derivati, quindi è necessaria anche la compilazione condizionale per questo.

  • Differenze del compilatore o differenze di versione - Diverse versioni di compilatori o diversi compilatori possono supportare funzionalità / librerie che non sono supportate da altri compilatori.

Anche se usi una libreria come Qt, che mira ad essere multipiattaforma, c'è ancora una compilazione condizionale, come hai scoperto. Queste librerie multipiattaforma sono lì per ridurre le tue esigenze di compilazione condizionale.

Inoltre, gli stili e gli standard di codifica potrebbero influenzare la modalità di scrittura del codice.

  • link - Queste sono le convenzioni di codifica di Qt per sviluppatori e contributori alla libreria.

  • Convenzioni di codifica Boost - Le convenzioni della libreria Boost per i contributori.

  • Confronta con gli standard di codifica C ++ di Joint Strike Fighter - Non ho dovuto leggere questo, ma è molto diverso dalla maggior parte degli standard che ho dovuto seguire e molto severo per quanto riguarda le funzionalità di C ++ che non possono essere utilizzate e come strutturare il codice.

Solo altri aneddoti del mio passato: il C ++ può essere scritto in molti modi influenzato dagli standard interni. Ad esempio, alcune organizzazioni limitano l'uso della libreria standard C ++, in particolare per quanto riguarda l'utilizzo dei contenitori standard (come std::vector e std::list ) - ciò potrebbe essere dovuto all'ambiente in questione (come i sistemi embedded).

In definitiva, si tratta di questo: ci sono molti modi per scrivere in C ++, ed è accettabile combinare paradigmi diversi in un singolo programma C ++ e codice base, perché ci possono essere modi migliori / più semplici per esprimere qualcosa in un paradigma piuttosto che essere bloccati nell'uso di un singolo modello per un'intera base di codice.

Se vuoi vedere basi di codice C ++ di grandi dimensioni con alta qualità del codice, dirò che Boost e Qt sono tra i migliori esempi.

Convenzioni e idiomi generalmente accettati e ampiamente accettati per la programmazione in C ++ sono contenuti in libri come Effective C ++ e Più efficace C ++

    
risposta data 13.05.2013 - 19:11
fonte
3

A volte la parte "classe" di una classe di utilità non fa altro che agire come uno pseudo-namespace. Non è necessario lo stato dell'istanza, solo i parametri passati in una funzione. Ad esempio la classe Math in C #. In tal caso potresti anche avere delle funzioni libere in uno spazio dei nomi.

A volte il comportamento dovrebbe essere una proprietà dell '"ambiente" e non dell'oggetto. Ad esempio una funzione save () può essere specifica per layer / environment e dovrebbe essere una funzione libera in quel layer. L'oggetto può visitare molti livelli (fisici o logici) in cui il salvataggio potrebbe non essere pertinente.

    
risposta data 13.05.2013 - 18:36
fonte
3

Mentre concordo con gli altri sul fatto che la domanda è soggettiva, i due esempi che fornisci sono visti in modo molto diverso dalla comunità C ++:

  • #ifdef ha diffuso il codice C ++ è una cattiva pratica. Il codice dipendente dal sistema si conserva meglio isolato in file separati e gestito dal sistema di generazione. Altrimenti si ottiene il casino che hai visto nel file cpp a cui hai inviato un link.
  • Le funzioni gratuite in C ++ sono una buona cosa. Invece di dare una lunga spiegazione qui, suggerisco di leggere il classico testo di Scott Meyer sull'argomento: In che modo le funzioni non membri migliorano l'incapsulamento
risposta data 07.06.2013 - 14:31
fonte
0

È generalmente accettato in molti mondi. Ad esempio, in fxCop per C #, ti segnalerà di non rendere statici i metodi quando non usano variabili membro. L'idea è che una classe dovrebbe solo definire abbastanza un'interfaccia pubblica per proteggere i suoi invarianti; il resto è responsabilità del consumatore, che sa meglio come verrà consumata la classe.

Non sono sicuro che mi spingerei così lontano da considerarlo universalmente accettato, ma è una pratica comune .

    
risposta data 13.05.2013 - 18:33
fonte
0

Come quello che dice il birryree, questa è davvero una domanda soggettiva. Esistono molti modi per programmare un'applicazione su larga scala. Il tipo di applicazione può anche giocare un ruolo importante nel modo in cui vuoi programmare la tua applicazione.

È utile esaminare la programmazione basata su componenti se il progetto è molto grande. Questo tuttavia dovrebbe anche essere considerato caso per caso per vedere se il tuo progetto ne ha davvero bisogno.

Programmazione basata su componenti Google per ulteriori informazioni.

Ecco la pagina wiki per questo: link

    
risposta data 07.06.2013 - 10:13
fonte

Leggi altre domande sui tag