Stili di codifica quando si utilizzano diverse librerie diverse


9

Sto lavorando su un codice C ++ che utilizza diverse librerie, incluse alcune librerie C, che hanno tutti stili di codifica diversi. Sarà di provenienza aperta una volta raggiunta una fase utilizzabile. Quale potrebbe causare la minima confusione per un collaboratore a breve termine che controlla il codice per correggere un bug o aggiungere una funzionalità?

  • Avere uno stile di codifica coerente nell'intera applicazione, anche se occasionalmente non corrisponde allo stile di codifica tipico delle librerie utilizzate.
  • Quando una libreria viene utilizzata pesantemente in un determinato modulo, conformarsi allo stile di codifica tipico di quella libreria (ovvero lo stile di codifica utilizzato nel codice e nella documentazione della libreria) in quel modulo.

Il mio pensiero è che quest'ultimo renderà più facile per gli esperti di quella particolare biblioteca fornire contributi una tantum e faciliterà l'integrazione del codice tutorial / esempio durante lo sviluppo. Tuttavia, rende anche lo stile di codifica incoerente in tutta l'applicazione. Quali sono i pro e i contro di ogni approccio?


4
Sarebbe possibile evitare questo problema avvolgendo tutte le librerie nelle proprie astrazioni personalizzate? Il tuo codice e le tue astrazioni potrebbero quindi seguire un unico stile di codifica.
MetaFight,

Molto di ciò che sto facendo è astrarre quelle biblioteche. La domanda è quale stile di codifica usare all'interno dell'astrazione.
Karl Bielefeldt,

6
Ah. Non sono un esperto qui, ma sembra che sarebbe meglio usare la convenzione della biblioteca stessa. L'uso di una convenzione non corrispondente sembra un incubo per la manutenzione. E fintanto che lo stile della libreria è contenuto nella classe / modulo che la sottrae, presumo che sarebbe OK. Ancora una volta, non sono un professionista qui, ma questo sembra un buon equilibrio che ti garantisce una manutenzione più semplice nelle tue astrazioni e ti consente anche di avere il tuo stile nel resto dell'applicazione.
MetaFight,

1
A volte astrazioni del genere possono diventare un po 'brutte, fai del tuo meglio per mantenerlo pulito indipendentemente dalle convenzioni utilizzate, ma soprattutto assicurati solo che l'API che presenti dall'astrazione sia di qualità sufficiente che non dovrai tornare indietro nell'astrazione ingerenza e i consumatori saranno in grado di lavorare in modo coerente con le tue astrazioni facilmente per garantire che il loro codice non diventi un disastro come quello che potrebbe essere nelle tue astrazioni. Quindi in breve, non c'è una buona risposta, ma fintanto che le tue astrazioni presentano buone API almeno stai impedendo al problema di diffondersi oltre.
Jimmy Hoffa,

1
Cosa intendi esattamente con "stile di codifica" - cose semplici come using_underscores / camelCase / PascalCase e posizione del controvento, o cose più complesse come il layout di classe / metodo / funzione e stile imperativo / funzionale?
Izkata,

Risposte:


10

Penso che dipenda da quanto grande sarà il progetto complessivo.

Ad un estremo, supponiamo che tu abbia un progetto 1 Mloc. Per un progetto così vasto, è improbabile che un singolo individuo sia un "esperto" in tutte le aree interessate. Quindi, in questo caso, rimarrei con gli stili di codice esistenti per ogni componente principale. I nuovi sviluppatori sceglieranno un'area, la apprenderanno ed è improbabile che vedranno molti altri componenti che possono avere stili di codice diversi.

Se il progetto è molto più piccolo, dove è probabile che gli individui comprendano l'intera base di codice, sceglierei uno stile di codice dominante e lo rispetterei. In questo caso, penso che la coerenza nell'intero progetto abbia più senso perché i nuovi sviluppatori probabilmente lavoreranno in tutte le aree del progetto.

I progetti di medie dimensioni sono forse i più difficili da prendere per questa decisione. In questo caso, devi valutare i costi di ciascun approccio e decidere quello che ritieni sarà il più economico a lungo termine. La sfida è che i progetti di medie dimensioni sono generalmente cresciuti abbastanza da raggiungere un punto in cui un refactoring di stile completo sembra proibitivamente costoso. Potresti voler dare una seconda occhiata alla struttura ad albero del codice per vedere se le cose possono essere organizzate per raggruppare stili di codice particolari insieme.

Ad ogni modo, la decisione finale dovrebbe spettare alla squadra che stai facendo, che sta mettendo insieme questo pacchetto.


Alcuni degli outlier che potrebbero spostare il mio ragionamento dall'alto:

  • Se uno o più moduli hanno uno stile atroce, allora non ha senso tenerlo presente, anche su un progetto più ampio. Sì, lo stile è soggettivo, ma se tu e i tuoi colleghi partecipanti al progetto davvero, non vi piace davvero il modo in cui scorrono aree particolari, date una nuotata al vecchio stile e dategli uno migliore.

  • Se tutti gli stili sono ragionevolmente vicini l'uno all'altro, potrebbe essere altrettanto facile dichiarare "ecco il nuovo modo" e usarlo per tutto il nuovo codice e significativi refactoring. Questo può rendere le recensioni un po 'dolorose, ma nella mia esperienza la maggior parte delle persone sono abbastanza capaci di adattarsi a questo approccio. Fornisce anche un segnale rivelatore in cui si trova il vecchio codice.

  • A volte lo stile viene spostato in base alle nuove funzionalità aggiunte alla lingua. C ++ ha acquisito una serie di funzionalità nel corso degli anni. Può avere senso rifattorizzare secondo necessità lo stile più vecchio in uno stile più nuovo che sfrutti queste funzionalità.

  • Alcune biblioteche possono avere un approccio o uno stile particolarmente idiomatico. In tal caso, rimarrei con quello stile per quella libreria anche se potrebbe essere in conflitto con il resto del progetto. L'intento qui è di aumentare le probabilità che qualcuno che lavora frobnosticatorssu altri progetti lavorerà anche sul tuo progetto.


Alcuni dei commenti menzionano stili imperativi e orientati agli oggetti come una considerazione.

I moduli "pesanti" in uno stile particolare probabilmente dovrebbero rimanere in questo modo se il modulo è di medie dimensioni o più grande. Ho lavorato con i tre stili principali (imperativo, obiettivo e funzionale) e ho trasformato gli stili imperativi pesanti in uno stile OO. Con una quantità media o maggiore di codice, il refactoring può essere (eccezionalmente) difficile. La mia esperienza è stata confusa perché non avevo alcun supporto di strumenti per aiutare nel refactoring.

Immagino che vi sia un'alta correlazione tra i moduli dallo stile fortemente imperativo e quei moduli che sono idiomatici per particolari nicchie di sviluppo, che risale all'ultimo punto che ho sollevato con valori anomali. Quindi qualsiasi modulo che troveresti per quella funzionalità apparirà così, e vuoi che anche gli esperti di quel dominio possano facilmente lavorare sul tuo progetto. Ma se ci sono opzioni e alla tua squadra non piace lo stile di quel modulo, allora analizzerei le opzioni.

Allo stesso modo, ho lavorato con un modulo in stile OO pesante in cui i principi di OO sono stati portati troppo avanti e utilizzati in modo errato. Ad esempio, le interfacce venivano utilizzate in sostituzione dell'ereditarietà multipla. E come ci si potrebbe aspettare, è stata un'implementazione grezza. Sono stato in grado di compiere ragionevoli progressi nel refactoring di quel modulo, ma alla fine ho abbandonato quell'approccio poiché ho trovato pacchetti migliori da utilizzare.


Questo è un buon modo per dirlo. Progetti simili sono circa 300 KLOC.
Karl Bielefeldt,

3

Sembra che ci siano più livelli da considerare, almeno:

  1. Le librerie esistenti e eventuali modifiche ad esse.
  2. Nuovo codice di unit test per quelle librerie.
  3. Lo strato di astrazione.
  4. L'API presentata dal livello di astrazione.
  5. Esempio e codice di prova usando il livello di astrazione.

Suppongo che non abbia senso semplicemente rifattare tutto il codice in uno stile comune in anticipo - se così fosse non avresti fatto la domanda.

Prendendo a turno ciascuno:

  1. Per la base di codice esistente, probabilmente ti consigliamo di attenersi a quello stile.
  2. Il nuovo codice di test unitario per il codice esistente si trova in un'area grigia, in particolare a seconda di quanto è integrato con il codice precedente. Ma molto probabilmente, proverei a farlo nello "stile preferito".
  3. Il nuovo codice nel livello di astrazione. Assicurando che questo sia davvero un livello di codice separato, non dovrebbe esserci alcuna difficoltà nell'usare uno stile preferito, anche se il codice sta facendo molta interfaccia con uno o più stili legacy. La maggior parte del codice deve interfacciarsi con altri stili e non ho mai riscontrato questo problema.
  4. Ovviamente l'API stessa ha bisogno della massima attenzione e soddisfa le massime esigenze di usabilità.
  5. Qualsiasi esempio o codice di test dovrebbe anche poter essere scritto nello stile preferito. A seconda della completezza dell'astrazione (cioè se nasconde completamente gli strati inferiori), questo può essere facile o difficile. Naturalmente, assicurarsi che il codice client futuro sia leggibile sarà uno dei tuoi obiettivi chiave.

Alcune cose che ho trovato personalmente sono che con una grande base di codice legacy:

  • L'impostazione di uno stile preferito e l'applicazione delle modifiche al codice non comporta magicamente la migrazione di tutto il vecchio codice al nuovo stile.

  • La maggior parte degli ingegneri tende a preferire codificare (più o meno) lo stile esistente in una determinata libreria. Richiedere altrimenti comporta molta applicazione.

  • Richiedere uno stile preferito in una libreria legacy tende a provocare molta incoerenza nello stile in quella libreria. Quindi, per gli standard che riguardano esclusivamente la presentazione, al contrario della robustezza del codice, è difficile vedere anche molti vantaggi nel richiederli.

Come ultimo problema (leggermente fuori tema ma ritengo rilevante), la verità è che alcuni ingegneri hanno difficoltà a rispettare qualsiasi standard di stile diverso da quello che conoscono meglio. Consiglio vivamente di coinvolgere il team nelle decisioni di stile e di assicurarsi che ci sia un riscontro. Avendolo fatto, siete in una posizione molto migliore per applicare effettivamente uno standard in codice misto.


0

Concordo con @MetaFight qui nel caso in cui si stia sviluppando un progetto di grandi dimensioni con molti moduli di terze parti.

Consente di mappare il tuo problema con un vero problema di parole: " Supponi di avere uno stile di vita tranquillo nella tua casa. Ti piace che il tuo posto sia tranquillo, non parli mai più forte e non ti piace mai alcun membro della tua famiglia per farlo. Ma interagisci con molti persone diverse fuori ogni giorno per portare qualcosa per la tua casa. Non necessariamente parleranno anche con voce più bassa, in quel caso ti modellerai di conseguenza mentre gestirai tali persone. Pertanto l'interfaccia o il wrapper per queste persone è altamente flessibile solo per il gusto di il tuo lavoro da svolgere. "Esempio stupido ... lol

Ma il mio punto è creare un wrapper per tali librerie secondo il loro standard di codifica in modo tale da usare queste librerie attraverso questi wrapper mantenendo il tuo stile di codifica originale all'interno.

+1 per MetaFight.


Esattamente la soluzione giusta imo. Uso i wrapper per legare il codice che anche altre persone scrivono per i miei progetti. Definisci un'interfaccia in primo piano, quindi quando la implementano, puoi avvolgerla e testarla in black box.
Kieveli,

1
Perché questo viene ridimensionato? Penso chiaramente che sia la soluzione migliore :)
MetaFight,

0

Ciò causerebbe chiaramente la minima confusione nell'utilizzare un unico stile di codifica in tutto il progetto. Il punto fondamentale dell'utilizzo di uno stile di codifica è innanzitutto quello di rendere il codice più semplice da leggere e modificare.

Per quanto riguarda lo stile di codice utilizzato internamente in una libreria, non credo sia rilevante. Se la libreria è troppo imperativa, allora scrivere un wrapper OO va bene, ma ciò non richiede che tu usi lo stesso stile di codice degli esempi o degli interni della libreria.

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.