Strategia per utilizzare il controllo versione su un sistema modulare


15

Supponiamo (per semplicità) che abbiamo un'applicazione con client e server; esiste un'idea migliore per utilizzare un repository per entrambi o una coppia di repository separati?

Mischiandoli sarà probabilmente più facile tenere traccia delle modifiche correlate e mantenere i rami correlati (ovvero l'evoluzione del protocollo), ma d'altra parte renderà lo sviluppo individuale più ingombrante ...


E cosa c'è di sbagliato nell'usare rami separati? Uno sviluppatore deve solo avere il ramo su cui sta attualmente lavorando aperto localmente, quindi non vedrà nemmeno le cose che sono solo negli altri rami. Ma, se ha bisogno di entrare nel ramo per qualche motivo, può farlo.
Spencer Rathbun,

@SpencerRathbun - L'uso di rami separati come questo è una ricetta per il disastro . Sarebbe davvero difficile condividere file tra server e client, in particolare interfacce e documentazione di sistema, ecc. Con un DVCS richiederebbe la clonazione di tutti i commit del client e del server, anche se ne volessi solo uno e non ti darebbe qualsiasi suggerimento su quali versioni client e server funzionerebbero insieme. Rispetto a un repository monolitico (singolo) o una suddivisione modulare (multipla) del repository, in realtà si ottiene il peggio di entrambi i mondi .
Mark Booth,

@MarkBooth Humm, stavo pensando alle sezioni del progetto in ogni ramo, poiché ha indicato che condivideranno il codice. Tagga ogni sezione come i rami appropriati e sei a posto. Il DVCS non consente a un file / commit di avere più tag?
Spencer Rathbun,

Risposte:


12

Se stai usando git o mercurial , allora potresti voler guardare sottomoduli o sottorepository .

Il client, il server e i loro file di interfaccia si troverebbero nei loro repository, ma sarebbero collegati insieme a livello di super repository . Ciò consentirebbe di fare un checkout al livello superiore e gito hgavrebbe controllare l'appropriato impegnarsi di ciascuno dei moduli / subrepositories.

Impegnandosi nel super repository solo quando client e server erano appropriati l'uno con l'altro, il super repository ti darebbe sempre la possibilità di verificare un sistema funzionante, quindi non proveresti mai a eseguire il nuovo client su un vecchio server o viceversa.

I sottomoduli / sottorepository offrono tutti i vantaggi dell'utilizzo di repository separati, insieme ai vantaggi di un singolo repository monolitico, a scapito di una piccola complessità aggiuntiva.

Questa risposta non ha lo scopo di sostenere gito hgsopra altri SCM, capita solo che io conosca questi SCM abbastanza bene da sapere che questa opzione esiste. Non capisco come svnfunzionano gli esterni, ad esempio.


1
Questa è una caratteristica interessante. Sarei interessato a vedere alcuni casi di studio sul suo uso, non ne avevo mai sentito parlare prima!
Ed James,

Una cosa simile nella sovversione sono le definizioni esterne: svnbook.red-bean.com/en/1.0/ch07s03.html . Tuttavia funziona in modo leggermente diverso.
liori,

1
@MarkBooth: sì, puoi. In quella pagina puoi vedere i parametri che assomigliano a -r12345 - quelli definiscono quale revisione vuoi ottenere. E poiché la proprietà svn: externals ha una versione come qualsiasi file di testo, puoi avere valori diversi per -r per ogni revisione. Inoltre, stai sfogliando la documentazione 1.0 antica. Le definizioni esterne sono state modificate in 1.5 e la versione corrente è 1.7. Vedi: svnbook.red-bean.com/en/1.7/svn.advanced.externals.html
liori

6

Separato!

In effetti, probabilmente avrei tre repository, uno per il client e le corrispondenti librerie solo client, uno per il server (e le librerie corrispondenti) e uno per le librerie condivise (che incorporano le interfacce API che espongono la funzionalità tra i due , oltre a qualsiasi altro codice condiviso). Penso che sia davvero la chiave, il codice condiviso dovrebbe andare in un repository separato. In questo modo puoi assicurarti che l'interoperabilità tra il tuo client e il server sia sempre nella stessa versione E sia isolata dal design di ciascuno dei suoi consumatori.

Ovviamente, questo non è sempre possibile, a seconda del particolare framework di comunicazione che stai utilizzando, ma è probabile che ci sia un codice condiviso che detta il formato degli oggetti di trasferimento dei dati o le fasi dell'handshake nel tuo protocollo personalizzato (o qualche altro esempio) .

Supponendo che tu abbia una discreta Integrazione continua e una configurazione di QA (un presupposto abbastanza grande, nella mia esperienza, ma ne farò comunque uno. Se non hai un dipartimento di QA dovresti almeno ottenere un CI) non dovresti non è necessario utilizzare il modello a singolo repo come difesa contro possibili errate corrispondenze del codice, o il tuo server CI segnalerà l'interoperabilità con la libreria o il tuo team di QA rileverà errori di runtime (o, meglio ancora, i test delle tue unità).

I vantaggi dei repository divisi risiedono nella possibilità di versioni separate di parti separate di un sistema. Vuoi prendere una copia del server della scorsa settimana ed eseguirlo con il client di questa settimana, per provare a bloccare la radice di un problema di prestazioni? Nessun problema.


1

In Mercurial , questo schema può essere utilizzato, usando ->per indicare una relazione di sottorepo:

product -> client -|-> (many components)
                   |->  shared component A

        -> server -|-> (many components)
                   |->  shared component A

Il prodotto ha client di sottosposizione, server. Ognuno di questi ha i propri componenti come sottosposi, possibilmente almeno un sottorepo condiviso tra i due.

La codifica dovrebbe probabilmente essere eseguita sui primi due livelli, non al di sotto di questo.

Gli commit vengono eseguiti a livello di componente, le superreposioni tengono traccia in modo efficace dei rami e delle versioni del prodotto. I rami / segnalibri nominati sono generalmente migliori dei rami clonati per usabilità (ad es. Trainabilità) e compatibilità con i sottosposi.

hg tende a supporre che le superrepos siano il prodotto e che gli commit vengano eseguiti ai massimi livelli, ma ciò non funziona particolarmente bene quando più prodotti utilizzano gli stessi componenti. :-)

Non penso che questo schema cambierà molto se trasformato in git, ma non l'ho ancora provato in git.


1

Questo è un problema di gestione della configurazione, non un problema di controllo della revisione. Come sempre, un programmatore usa un cacciavite per martellare un chiodo. Scopri come gestirai le tue configurazioni, il controllo di revisione si prenderà cura di se stesso.


1

L' approccio più semplice consiste nell'utilizzare un singolo repository, quindi a meno che non ti piaccia la complessità per motivi di complessità, quella dovrebbe essere la scelta predefinita in assenza di argomenti convincenti altrimenti.

Lo sviluppo di client e server verrà eseguito da diverse organizzazioni? Ci saranno implementazioni multiple del client (o del server)? Il client è open source e l'implementazione del server è segreta? Se la risposta a tutte queste domande è "No", è probabile che qualcosa di più complesso di un singolo repository porti solo inconvenienti senza alcun vantaggio.

Se scegli di mantenere basi di codice separate, avrai bisogno di politiche chiare su come amministrarlo, al fine di evitare incompatibilità e inferno delle dipendenze. Dopo aver esaminato i primi singhiozzi, potresti scoprire che la cosa più sicura è controllare sempre entrambi i repository, crearli insieme e distribuirli insieme ... il che ovviamente vanifica l'intero scopo di separarli!

La modularità è una proprietà piacevole da avere, ma la suddivisione dei repository non è uno strumento per raggiungere questo obiettivo. Come suggerisce il paragrafo precedente, è possibile avere componenti altamente accoppiati che sono suddivisi su più codebase (indesiderabili) e allo stesso modo è possibile avere componenti altamente modulari all'interno della stessa base di codice (desiderabile).

In più di un'occasione, ho chiesto (con successo) al mio team di unire i repository git esistenti, perché ha semplificato lo sviluppo e la distribuzione.


0

Dimentica il repository per un momento. Come organizzeresti i due progetti sulla tua macchina se non condividessi con nessuno? Come avrebbe fatto il resto della squadra? Vorresti...

  • Metti tutti i file sorgente per client e server nella stessa directory?

  • Creare una directory di progetto principale che contenga sottodirectory per il client e il server?

  • Mantenere i due progetti completamente separati?

Una volta raggiunto un consenso su questo come un team, sei pronto a controllare i progetti nel tuo repository di codice. Tutti gli strumenti di controllo delle revisioni a cui riesco a pensare sono felici di riprodurre qualsiasi struttura di directory che ti piace - a loro non importa un po 'di quale file appartiene a quale progetto. E la differenza tra avere un repository o due (o sei) di solito non è così grande, a parte piccole differenze amministrative.

Ad esempio, con Subversion, la più grande differenza tra repository separati per client e server e un singolo repository combinato è nel modo in cui cambiano i numeri di revisione. Con un repository singolo, il numero di versione aumenta ogni volta che si commette codice su client o server. Con repository separati, un commit al progetto server non cambierà il numero di revisione principale per il client.

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.