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 avviareN
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 projectfoo
." 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")?