Meriti relativi del repository monolitico su più piccoli

0

Mi è stato assegnato il compito di implementare uno stack di rete. Il software è autonomo senza dipendenze esterne: ha solo bisogno della libreria standard C ++ 14 e di una piattaforma POSIX.

A mio parere non c'è nulla che impedisca di implementarlo con successo in un singolo repository poiché la separazione logica (livelli, classi, ecc.) può ancora essere presentata in modo pulito senza la necessità di manifestare come separazione fisica (una directory di progetto separata -with-a-Makefile per classe, ad esempio). Tuttavia, i miei superiori hanno insistito per suddividere il progetto in più repository minori e ho difficoltà a valutare la loro logica.

Uno dei loro argomenti è che "nel 2003 abbiamo provato a scrivere progetti in singoli repository e non funzionava, ci voleva una settimana per compilare!". Questo non mi convince.

In che modo la suddivisione del progetto in più sottoprogetti può essere d'aiuto in questo scenario? Se hai un progetto di 50k linee, devi compilare 50k linee. Se hai dieci progetti di linee 5k devi ancora compilare 50k linee, ma ora non puoi lasciare che il sistema di costruzione sfrutti le dipendenze tra entità per compilare in parallelo perché hai serializzato la build (prima build pacchetto A, quindi pacchetto B, quindi pacchetto C, ecc.).

Inoltre, non puoi semplicemente avere class A avere membro B* e, allo stesso tempo, avere class B avere un membro A* senza averli nello stesso progetto (per consentire al compilatore di vedere loro intestazioni), o creando ancora un altro pacchetto contenente solo le intestazioni per tali classi. Ma questa è follia! Invece di avere un progetto ora ne hai tre ... per ragioni. (Come nota a margine, forse questo è causato dal fatto che io e il mio team siamo costretti a stipare tutto nei pacchetti Maven? Non vedo come questo ci aiuti esattamente per il problema " A* - B* " dichiarato sopra.).

Inoltre, mettere tutto nei pacchetti memorizzati su un server centrale (di nuovo, siamo costretti a usare Maven) ha lo sfortunato effetto di altri sviluppatori che influenzano il mio lavoro nei momenti meno attesi. Quando corro un bug mi aspetto che il mio ambiente rimanga costante, ma quando costruisco un progetto e il sistema di costruzione recupera automaticamente le nuove versioni di tutte le sue dipendenze, l'ambiente cambia e un bug che il mio collega ha appena introdotto è quello di ombre Ci sto lavorando perché succede prima nel percorso di esecuzione ... e ora sto perdendo tempo perché devo sistemare il mio ambiente locale. Non vedo come ci possa aiutare.

Ancora una volta, questo problema può essere facilmente risolto eseguendo solo build offline senza raggiungere il repository online, ma poi devo andare manualmente in ogni directory del progetto ed eseguire la build per rendere i pacchetti disponibili nel repository locale sul computer di sempre di uno sviluppatore .
Tuttavia, questo ha chiari svantaggi in linguaggi come C ++ perché devo ricordare in quale ordine devono essere costruiti i pacchetti - altrimenti, la dimensione degli oggetti prodotti da una libreria potrebbe essere diversa da quella del consumatore di la biblioteca si aspetta (è l'esempio più semplice di cosa può andare storto: costruisco il pacchetto A con una vecchia versione del pacchetto B , quindi compro il pacchetto B ma la classe che contiene ora ha un membro int aggiuntivo ... e oops, siamo fuori sincrono e andiamo direttamente al terreno SIGSEGV); se mi fosse permesso di realizzare il progetto in un monorepo, anche un semplice Makefile avrebbe distribuito correttamente le dipendenze.

D'altra parte, un singolo progetto ha chiari vantaggi (secondo me):

  • Posso dire al team di test "L'ultima versione nota è 0f52ab27199ffc , usala per i test perché potremmo avere da allora X non funzionante, non sono ancora sicuro, ma si comporta in modo strano dopo aver fatto Y."
  • Posso bloccare il mio ambiente per il tempo necessario a correggere un bug (semplicemente derivando dal ramo principale).
  • Posso utilizzare pienamente gli strumenti disponibili per velocizzare le build (ad esempio invocare make -j N per avviare N jobs in parallelo).
  • Posso lasciare il compilatore libero sulla base di codice con -O3 e lasciare che ottimizzi il binario risultante senza ostacoli sul suo modo (ad esempio è molto più facile incorporare una funzione disponibile come sorgente, rispetto a una disponibile come simbolo in alcuni .so ).
  • Posso facilmente eseguire il debug del programma - no "Oh, ho dimenticato di aggiungere -g a project foo ." o " Make breakpoint pending on future shared library load? " in GDB.

I miei argomenti sono validi, o sono fuorviato e dividere un progetto in un gruppo di .so s è davvero la strada da percorrere ("perché è così che lo facciamo nei nostri progetti Java")?

    
posta Mael 27.02.2018 - 08:53
fonte

1 risposta

3

Ci sono due domande nel tuo post e dovrebbero essere fornite a IMHO separatamente. Presupposto si creerà un sistema software "grande" utilizzando C ++,

  • si dovrebbero creare diversi progetti C ++ (sotto) fisicamente separati, ognuno con un proprio makefile, versioni separate, test separati? O la separazione logica è sufficiente?

  • nel caso in cui si utilizzino progetti separati fisicamente, si dovrebbero usare anche diversi repository per questo?

Dalla mia esperienza, la risposta alla prima domanda è "per sistemi di una certa dimensione, vale la pena dividerli" . Altrimenti, i tempi di costruzione e collegamento uccideranno il tuo progetto. Soprattutto i link time della maggior parte dei linker C ++ tendono a comportarsi almeno in quadratura, quindi aspettatevi che il tempo di collegamento per 10 progetti con 5kLOC sia molto più piccolo rispetto a un progetto enorme con 50kLOC. Non esiste una build parallela che ti impedisca di farlo. Non posso dirti esattamente cosa significherà "certa dimensione" nel tuo caso, ma raccomando vivamente Il libro di Lakos per avere più informazioni di base su questo argomento, l'intero argomento è troppo ampio per essere spiegato qui in uno o due paragrafi.

Ovviamente, per dividere un grande progetto in più piccoli si dovranno investire alcune considerazioni sulla gestione automatica delle dipendenze e su come incorporare diversi makefile. Ma sono sicuro che ci sono soluzioni disponibili per ogni ambiente di compilazione C ++, Google e CMake saranno tuoi amici.

La seconda domanda è stata già posta più volte su questo sito, ed è IMHO più dipendente dal VCS che si sta utilizzando, dal modo di lavorare del team e meno dal linguaggio di programmazione. Vedi questa vecchia domanda , è etichettato con "Java", ma gli argomenti non sono molto diversi per C ++.

La mia opinione personale su questo è, se il software, come hai scritto, "è autonomo senza dipendenze esterne", utilizzando diversi repository e uno strumento come Maven è eccessivo, abbastanza inutile e aggiunge un sovraccarico di gestione inutile a esso. Tuttavia, se il tuo team o la società per cui lavori ha un criterio "uno (sotto) progetto - un repository" e ha già una soluzione per gestire il sovraccarico di gestione aggiuntivo con più repository, allora potresti stare meglio con attenersi a tale politica.

    
risposta data 27.02.2018 - 11:45
fonte

Leggi altre domande sui tag