Strategia di ramificazione e controllo delle versioni per le librerie condivise

12

Questi posts sembrano correlati, ma il mio cervello sta iniziando a sciogliersi, provando a pensare a questo: P

Il mio datore di lavoro ha appena iniziato a utilizzare il controllo del codice sorgente, principalmente perché prima di assumere altri sviluppatori, il "repository" era il disco fisso del dev del solo, che lavora principalmente da casa. Tutto il codice .NET che ha scritto è stato controllato in in massa e c'è molta funzionalità duplicata (leggi: copia-incolla). In questo momento, il nostro sistema SCM è un backup glorificato.

Mi piacerebbe inserire parte del codice duplicato in librerie condivise. Lascerò da solo il repository originale in modo da non rompere nulla: possiamo spostare e / o rifattorizzare il codice esistente come e quando necessario. Quindi ho creato un repository solo per il nuovo codice, incluse le librerie.

Il mio problema ruota attorno al versionare le librerie senza mirarci in un processo eccessivo: avendo riconosciuto che abbiamo bisogno di un approccio più coerente, con più sviluppatori che scrivono codice molto simile, la gestione e gli altri sviluppatori sono aperti a riorganizzare le cose, ma probabilmente non andrà giù bene se la soluzione inizia a influenzare la produttività.

La soluzione ideale nella mia mente ossessiva è quella di costruire le librerie separatamente, con ogni progetto dipendente costruito contro versioni deliberatamente scelte e compatibili di loro. In questo modo, sappiamo esattamente quali client hanno quali versioni di quali librerie, possono riprodurre in modo più affidabile i bug, mantenere rami di rilascio indipendenti per prodotti e librerie e non rompere i rispettivi progetti quando cambiano il codice condiviso.

Questo rende l'aggiornamento delle biblioteche ingombrante, in particolare per gli sviluppatori che lavorano da casa. Mi aspetto che le librerie cambino rapidamente, almeno inizialmente quando (finalmente) tiriamo insieme i bit comuni. È abbastanza probabile che io stia completamente pensando troppo a questo e staremmo bene solo costruendo tutto contro i commit più recenti della biblioteca, ma mi piacerebbe almeno essere preparato per il giorno in cui decidiamo che alcuni i componenti devono essere versionati e distribuiti in modo indipendente. Il fatto che alcune librerie debbano essere installate nel GAC rende la versionazione particolarmente importante.

Quindi la mia domanda è: cosa mi manca? Mi sento come se avessi fissato una soluzione e ora sto provando a trovare variazioni su di essa che renderanno i cambiamenti più fluidi. Che tipo di strategie hai usato per risolvere questo tipo di problema prima? Mi rendo conto che questa domanda è dappertutto; Farò del mio meglio per ripulire e chiarire qualsiasi punto di incertezza.

E per quanto mi piacerebbe usare Mercurial, abbiamo già speso denaro in un SCM commerciale centralizzato (Vault) e il passaggio non è un'opzione. Inoltre, penso che il problema qui sia più profondo della scelta dello strumento di controllo della versione.

    
posta shambulator 02.04.2011 - 00:44
fonte

6 risposte

1

Raccomando la tua iniziativa. Ciò dovrebbe comportare una serie di vantaggi per l'organizzazione man mano che si implementa questo. Sposterei il codice piuttosto che copiarlo. Avere copie probabilmente porterà a cambiamenti incompatibili che dovranno essere risolti.

Ci sarà un po 'di dolore quando le librerie saranno sviluppate e stabilizzate. Una volta fatto, i benefici arriveranno. Ricorda che le interfacce alla libreria sono essenzialmente un contratto con i progetti che lavorano con il contratto. Potresti avere il vantaggio di rimuovere le vecchie interfacce in quanto potresti essere in grado di determinare se sono utilizzate.

Mentre le librerie si stanno stabilizzando, l'acquisizione di nuove librerie dovrebbe probabilmente far parte del processo di aggiornamento del codice. Si consiglia di pianificare i commit delle modifiche alle librerie. Annunciando che il codice viene spostato può aiutare a ridurre le modifiche in conflitto.

Le biblioteche dovrebbero essere trattate come progetti separati e stabilizzate il prima possibile. Una volta che sono stabilizzati (in particolare le interfacce), dovrebbe essere più facile integrare le modifiche con altri progetti. Le nuove librerie dovrebbero funzionare con il vecchio codice. Tagga le versioni di librerie stabili con il loro id di rilascio. Prova a trattare le librerie come faresti con le librerie di terze parti.

    
risposta data 02.04.2011 - 02:57
fonte
6

Il codice condiviso tra i progetti deve essere considerato come progetto su se stesso. Devono essere trattati con la stessa accuratezza delle librerie di terze parti. Non c'è altro modo.

Se non riesci a far adottare al tuo gruppo una strategia per il codice condiviso, puoi adottarne uno tu stesso con l'aiuto di moderni strumenti di gestione del codice sorgente come Mercurial o GIT, anche se nessuno dei due è l'SCM che la tua azienda utilizzerà ufficialmente. Con un po 'di attenzione, due SCM possono usare la stessa directory di lavoro semplicemente dicendo a uno di ignorare i file interni dell'altro. Dovresti utilizzare un SCM per gestire il quotidiano e l'azienda da integrare.

In ogni caso, devi essere responsabile di quando aggiornare la tua directory di lavoro con le modifiche che altri progetti hanno apportato al codice condiviso. Questi dovrebbero accadere solo quando sei pronto per affrontare le incompatibilità che possono sorgere; altrimenti, il tuo lavoro potrebbe diventare instabile oltre il possibile.

    
risposta data 02.04.2011 - 02:08
fonte
4

Se hai la possibilità di suddividerli in progetti "modulo" separati, prenderei questo approccio. Una cosa di cui preoccuparsi è l'accoppiamento del codice. Crei una separazione delle preoccupazioni suddividendola, che è una buona pratica.

Alcuni vantaggi:

  1. Semplificazione del debug di ciascun modulo.
  2. Cicli di costruzione più rapidi (nessuna ricostruzione di librerie che non sono state modificate)
  3. Una volta che qualcosa funziona, hai meno probabilità di romperlo cambiando un'altra area al di fuori di quel modulo (non al 100%, ma riduci le possibilità).
  4. Più facile interrompere i compiti di lavoro se non è un grande disordine interdipendente.
  5. Distribuzione più rapida di pezzi più piccoli quando si aggiusta una libreria (una grande ragione per cui si hanno file .dll / .so).

Ho una domanda su questa parte:

"The ideal solution in my obsessive mind is to build the libraries separately, with each dependent project built against deliberately chosen, compatible versions of them."

Link statico all'intero progetto? In tal caso ciò porterebbe a: 6. Riduzione del numero inutile di codice.

Alcuni negativi:

  1. Se il progetto è di piccole dimensioni, stai solo aggiungendo complessità laddove non è necessario.
  2. La ramificazione di molti moduli può trasformarsi in un problema di manutenzione per progetti davvero grandi. Non conosco "Vault", quindi non sono sicuro che le loro operazioni di ramificazione siano buone o cattive.
risposta data 02.04.2011 - 01:15
fonte
1

Al momento, sembra che tu abbia creato una base di codice tutta in una volta in un bersaglio. Probabilmente non hai più di cinque sviluppatori. Non vedo davvero l'utilità di separare troppo le librerie. Dovresti cambiare il tuo flusso di lavoro dal codice - > compila - > corri al codice - > compila - > copia DLL - > compila - > eseguire ... ick.

Alcune aziende (Google e Amazon) hanno un'infrastruttura sufficiente per lo sviluppo che è abbastanza semplice avere un sacco di librerie separate costruite separatamente. L'infrastruttura per renderlo indolore implica un modo per specificare le versioni della libreria che risiedono nel tuo SCM (che probabilmente hai), un modo per specificare le versioni delle dipendenze che vivono nel tuo SCM, un server di build che può dare un senso e compilare tutto correttamente e un modo per afferrare gli artefatti di build appropriati dal tuo server di build e dallo spazio di lavoro locale. Dubito che tu abbia quello.

Senza questa infrastruttura, separerei il progetto quando si applica una delle seguenti condizioni:

  • Hai più prodotti o applicazioni distinte a seconda di questa libreria
  • Lavori esclusivamente su queste librerie per diversi giorni alla volta
  • Le funzionalità della libreria sono estremamente diverse da qualsiasi attività commerciale (ad esempio, i wrapper attorno alle API specifiche della piattaforma)
  • I tempi di costruzione per il progetto combinato diventano troppo grandi

Mi preoccuperei di creare quell'infrastruttura quando hai molti progetti e alcuni hanno sviluppatori dedicati e cicli di rilascio indipendenti.

Ciò che può e dovrebbe fare ora è configurare un server di build per build affidabili e ripetibili e assicurarsi di poter trovare la revisione sorgente da un determinato eseguibile. Sembra che tu stia usando .NET; è abbastanza semplice configurare CruiseControl.NET per inserire una stringa di versione, incluso il numero di revisione.

Una volta creato un server di build, la suddivisione di una libreria sarà praticamente una questione di spostamento in Vault, aggiunta di un'altra destinazione in CC.NET e copia della DLL risultante nella cartella della libreria del progetto principale e in cui viene eseguita. Più facile sul lato SCM rispetto allo sviluppo giorno per giorno.

    
risposta data 02.04.2011 - 04:15
fonte
1

Mercurial ha una funzione chiamata sottorepository. Di recente ho letto questo blog dal forno spiegando come funzionano.

Fondamentalmente, si collega il progetto a una revisione specifica di un repository di libreria. È possibile aggiornare la libreria quanto si desidera senza interrompere i progetti dipendenti. Quando sei pronto, puoi inserire le nuove funzionalità della libreria nel tuo progetto e gestire eventuali rotture. Diversi progetti possono collegarsi a diverse revisioni della libreria, quindi non tutti devono essere sincronizzati e utilizzare la stessa revisione della libreria.

Forse Vault ha una funzionalità simile.

    
risposta data 02.04.2011 - 06:11
fonte
1

Abbiamo aggiunto un file di metadati a ciascun modulo in SC che indica il nome di tutti gli altri moduli da cui dipende. Un prodotto avrà un secondo file di metadati che indica quale versione di ciascun modulo dipendente è richiesta per il prodotto. In cima a questo c'è uno strumento per analizzare i file dei metadati, controllare tutti i moduli richiesti e generare un progetto per il nostro IDE.

Ciò garantisce che le nostre build siano sempre riproducibili e che i file di intestazione corretti siano sempre condivisi tra i componenti. Un'altra complessità può essere stratificata a seconda dell'esigenza. Abbiamo strumenti che ora possono generare report sulle differenze tra due build di un prodotto, specificando i file di origine che sono stati modificati, i commenti di check-in, i commenti di versione, gli autori, su tutti i moduli indipendenti in SC. Otteniamo una quantità fenomenale di riutilizzo dalla nostra base di codici.

    
risposta data 02.04.2011 - 15:14
fonte