Strategia di branching e versioning per librerie condivise


12

Questi post sembrano correlati, ma il mio cervello sta iniziando a sciogliersi, provando a riflettere su questo: P

Il mio datore di lavoro ha appena iniziato a utilizzare il controllo del codice sorgente, principalmente perché prima che assumessero più sviluppatori, il "repository" era il disco rigido dello sviluppatore solitario, che lavora principalmente da casa. Tutto il codice .NET che aveva scritto è stato verificato in massa , e ci sono molte funzionalità duplicate (leggi: copia-incolla). In questo momento, il nostro sistema SCM è un backup glorificato.

Vorrei inserire parte del codice duplicato nelle librerie condivise. Lascio da solo il repository originale in modo da non rompere nulla: possiamo spostare e / o refactificare il codice esistente come e quando necessario. Quindi ho creato un repository solo per il nuovo codice, comprese le librerie.

Il mio problema ruota attorno al controllo delle versioni delle librerie senza farci mirare in un processo eccessivo: avendo riconosciuto che abbiamo bisogno di un approccio più coerente, con più sviluppatori che scrivono tutti codice molto simile, la gestione e gli altri sviluppatori sono aperti a riorganizzare le cose, ma probabilmente non lo farà andare bene se la soluzione inizia a influire sulla 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. In questo modo, sappiamo esattamente quali client dispongono di quali versioni di quali librerie, possono riprodurre in modo più affidabile i bug, mantenere rami di rilascio indipendenti per prodotti e librerie e non interrompere i progetti reciproci quando cambiano il codice condiviso.

Questo rende comunque complicato l'aggiornamento delle librerie, in particolare per lo sviluppatore che lavora da casa. Mi aspetto che le librerie cambino rapidamente, almeno inizialmente mentre (finalmente) mettiamo insieme i bit comuni. È del tutto possibile che stia pensando troppo a tutto ciò e staremmo bene solo costruendo tutto contro gli impegni della libreria più recenti, ma mi piacerebbe almeno essere preparato per il giorno in cui decidiamo che alcuni componenti devono essere sottoposti a versione indipendente e distribuito. Il fatto che alcune librerie debbano essere installate nel GAC rende il controllo delle versioni particolarmente importante.

Quindi la mia domanda è: cosa mi sto perdendo? Mi sento come se avessi risolto una soluzione e ora sto cercando di trovare variazioni che rendano le modifiche più fluide. Che tipo di strategie hai usato per risolvere questo tipo di problema prima? Mi rendo conto che questa domanda è ovunque; Farò del mio meglio per ripulire e chiarire eventuali punti di incertezza.

E per quanto mi piacerebbe usare Mercurial, abbiamo già speso soldi per 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.


il costo fisso viene affondato
alternativa l'

Risposte:


1

Mi congratulo con la tua iniziativa. Ciò dovrebbe comportare una serie di vantaggi per l'organizzazione durante l'implementazione. Sposterei il codice piuttosto che copiarlo. Avere copie comporterà probabilmente modifiche incompatibili che dovranno essere risolte.

Ci sarà un po 'di dolore mentre le librerie vengono sviluppate e stabilizzate. Una volta fatto ciò, i benefici arriveranno. Ricorda che le interfacce per la biblioteca 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 vengono utilizzate.

Mentre le librerie si stanno stabilizzando, probabilmente ottenere nuove librerie dovrebbe far parte del processo di aggiornamento del codice. È possibile che si desideri pianificare il commit delle modifiche alla libreria. L'annuncio del trasferimento del codice può aiutare a ridurre le modifiche in conflitto.

Le biblioteche dovrebbero essere trattate come progetti separati e stabilizzate al più presto. Una volta stabilizzati (in particolare le interfacce) dovrebbe essere più facile integrare i cambiamenti con altri progetti. Le nuove librerie dovrebbero funzionare con il vecchio codice. Contrassegna le versioni di librerie stabili con il proprio ID di rilascio. Prova a trattare le librerie come faresti con le librerie di terze parti.


6

Il codice condiviso tra progetti deve essere trattato come un progetto su se stesso. Devono essere trattati con la stessa accuratezza delle biblioteche 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 dei moderni strumenti di gestione del codice sorgente come Mercurial o GIT, anche se nessuno dei due SCM utilizzerà ufficialmente la tua azienda. Con un po 'di attenzione, due SCM possono utilizzare la stessa directory di lavoro semplicemente dicendo a uno di ignorare i file interni dell'altro. Utilizzeresti uno SCM per gestire il quotidiano e quello aziendale da integrare.

Ad ogni modo, 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 ad affrontare le incompatibilità che possono sorgere; altrimenti, il tuo lavoro potrebbe diventare instabile oltre il possibile.


4

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

Alcuni vantaggi:

  1. Debug più semplice di ciascun modulo.
  2. Cicli di generazione più rapidi (nessuna ricostruzione delle librerie che non sono state modificate)
  3. Una volta che qualcosa funziona, avrai 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 gli incarichi di lavoro se non è un gran casino interdipendente.
  5. Distribuzione più rapida di pezzi più piccoli quando si corregge una libreria (un grande motivo per cui si hanno file .dll / .so).

Ho una domanda su questa parte:

"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 esse."

Colleghi staticamente l'intero progetto? In tal caso, ciò comporterebbe: 6. Riduzione del codice inutile.

Alcuni aspetti negativi:

  1. Se il progetto è piccolo, allora stai solo aggiungendo complessità dove non è necessario.
  2. La ramificazione di molti moduli può trasformarsi in un problema di manutenzione per progetti di grandi dimensioni. Non conosco "Vault", quindi non sono sicuro che le loro operazioni di diramazione siano buone o cattive.

È il codice C #, quindi è un "no" al collegamento statico nel suo significato abituale. Vault è come Subversion, pre-1.5: PI ha aspettato con tanta impazienza di unire il tracking in svn, pensando che ero in paradiso quando finalmente è arrivato. Poi ho trovato DVCS.
shambulator

1

In questo momento, sembra che tu abbia un codebase tutto in una volta in un unico target. Probabilmente non hai più di cinque sviluppatori. Non vedo davvero l'utilità di separare troppo le librerie. Cambieresti il ​​tuo flusso di lavoro da codice -> compila -> esegui a codice -> compila -> copia DLL -> compila -> esegui ... ick.

Alcune aziende (Google e Amazon) hanno infrastrutture sufficienti per lo sviluppo che è abbastanza indolore avere molte librerie separate costruite separatamente. L'infrastruttura per renderlo indolore implica un modo per specificare le versioni della libreria che vivono 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 acquisire gli artefatti di compilazione appropriati dal server di compilazione e dall'area di lavoro locale. Dubito che tu l'abbia.

Senza tale 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
  • La funzionalità della libreria è estremamente separata da qualsiasi cosa relativa alle attività commerciali (ad esempio, wrapper attorno alle API specifiche della piattaforma)
  • I tempi di costruzione per il progetto combinato diventano troppo grandi

Mi preoccuperei di costruire quella infrastruttura quando hai molti progetti e alcuni hanno sviluppatori dedicati e cicli di rilascio indipendenti.

Quello che puoi e dovresti fare ora è impostare un server di build per build affidabili e ripetibili e assicurarti di poter trovare la revisione del sorgente da un determinato eseguibile. Sembra che tu stia usando .NET; è abbastanza semplice impostare CruiseControl.NET per inserire una stringa di versione, incluso il numero di revisione.

Una volta che hai un server di compilazione, dividere una libreria sarà praticamente una questione di spostarla in Vault, aggiungere un'altra destinazione in CC.NET e copiare la DLL risultante nella cartella della libreria del progetto principale e commetterla. Più facile dal lato SCM rispetto allo sviluppo quotidiano.


1

Mercurial ha una funzione chiamata sottorepository. Di recente ho letto questo blog di Kiln che spiega come funzionano.

In sostanza, si collega il progetto a una revisione specifica di un repository di librerie. Puoi aggiornare la libreria quanto vuoi senza interrompere i progetti dipendenti. Quando sei pronto, puoi inserire le nuove funzionalità della libreria nel tuo progetto e affrontare qualsiasi rottura. Diversi progetti possono collegarsi a diverse revisioni della libreria, quindi non devono essere tutti sincronizzati e utilizzare la stessa revisione della libreria.

Forse Vault ha una funzione simile.


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. Inoltre, è uno strumento per analizzare i file di 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. Altre complessità possono essere stratificate man mano che si sviluppa la necessità. Disponiamo di 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 sulla versione, gli autori, in tutti i moduli indipendenti in SC. Riceviamo un fenomenale riutilizzo dalla nostra base di codice.

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.