Gestione di una base di codice per più client, con il proprio codice personalizzato

3

Sto lavorando su un CMS, in cui abbiamo più client che lo utilizzano, quindi il codice è memorizzato sui loro server. Ogni client ha il codice predefinito (gestore utenti, gestore pagine ecc.), Ma ogni client ha anche il proprio set di codice (temi, script, moduli personalizzati).

Sto cercando di capire come mantenere una base di codice aggiornata per tutti i client senza dover apportare ogni singola modifica al core per ogni singolo client.

Usiamo GitHub per il controllo della versione, quindi pensavo di avere tutti i client come rami diversi, ma come posso mantenere il core aggiornato con il master?

Penso che tutto questo sia sbagliato?

Quali sono le mie opzioni?

    
posta Adam 27.11.2013 - 14:02
fonte

6 risposte

4

I rami sono la soluzione sbagliata qui. I rami sono per quando il codice (temporaneamente) deve cambiare dalla base comune.

Il problema con i rami è che le modifiche apportate a un ramo rimangono su quel ramo finché non le unisci esplicitamente su un altro ramo. Questo significa in effetti che se si ha una modifica nel codice comune, è necessario applicare tale modifica a ciascun "ramo-cliente" singolarmente, che è esattamente ciò che non desidera.

Non sono completamente aggiornato con la terminologia git, ma la soluzione migliore è avere diversi repository / sotto-moduli. Quindi si crea un repository per ciascun client e un repository aggiuntivo per il codice comune. Il repository del client può quindi includere il repository comune come riferimento o sottomodulo esterno e qualsiasi modifica apportata al codice comune è immediatamente disponibile per tutti i repository dei client senza ulteriore lavoro.

    
risposta data 28.11.2013 - 08:45
fonte
1

I rami potrebbero essere ok. Quando il codice cambia, cioè le nuove caratteristiche sono scritte, i bug sono corretti, ecc, quindi vengono aggiunti al master e quindi per le nuove aree che lo ricevono devono recuperare / tirare l'ultimo master e / o rebase il loro ramo contro di esso per ottenere i nuovi cambiamenti. Possono quindi inviare il ramo aggiornato a github per assicurarsi che anche l'ultima versione di esso sia memorizzata.

Un'altra opzione è che altre aree possano biforcare il progetto. Questo è fondamentalmente un processo simile in termini di ottenere aggiornamenti (recuperare l'ultimo master e rebase su di esso).
La differenza con i fork è che non vengono automaticamente accettati nel telecomando principale, devono essere approvati dal proprietario del repository github (o da altri a cui è stato concesso tale privilegio).

    
risposta data 27.11.2013 - 14:13
fonte
1

Per drupal e wordpress abbiamo un problema simile: c'è un core che viene aggiornato da una direzione e poi alcuni file specifici del sito che provengono da un'altra direzione. La soluzione che abbiamo trovato era una combinazione di repository e sub-repository effettivamente biforcati.

Innanzitutto, per i repository ciò che facciamo è creare un progetto / sito template che incorpori il layout del progetto e gli script di configurazione e i bit con l'impostazione dell'applicazione predefinita nel nostro progetto. Questa è l'impostazione in un ramo - diciamo wp-default per wordpress - piuttosto che master. Per avviare un nuovo progetto, iniziamo un nuovo repository e tiriamo dal progetto predefinito. Quindi uniamo il ramo wp-base al repo facendo in modo che il master abbia una copia pulita della configurazione del nostro sito. In realtà non stiamo biforcando le cose perché gli aggiornamenti non torneranno mai indietro, piuttosto il progetto concreto scaricherà gli aggiornamenti di volta in volta.

Per il tuo tema e altre personalizzazioni, sarebbero semplicemente atterrati nel progetto normalmente da qui in poi. Quando c'è un aggiornamento al nucleo, si estrae le modifiche da quel progetto predefinito e quindi si uniscono nella copia di lavoro.

I sottorapodi hanno dato il via ai contenuti - abbiamo inserito i contenuti e i database dei siti in un sottorepo, principalmente perché abbiamo visto i repository di kill di contenuto, quindi vogliamo separabilità e semplifica l'aggiornamento automatico di un repository indipendente. Uno script li copia in luoghi appropriati o ripristina forzatamente le cose.

Questo funzionerà brillantemente a patto che il tema e le personalizzazioni avvengano in file separati e che le cose non siano orribilmente mescolate. Avere un end-repo completamente indipendente rende possibile fare jam in qualsiasi hack di cui si ha bisogno alla fine - abbiamo dovuto hackerare il core drupal / wordpress alcune volte per buoni e cattivi motivi.

    
risposta data 28.11.2013 - 17:21
fonte
1

Branches are the wrong solution here. Branches are for when the code (temporarily) needs to change from the common base.

Questo è fuorviante. I rami funzione (rami temporanei) sono solo uno dei tanti usi per i rami. I rami del cliente potrebbero essere rami di lunga vita, che hanno solo un antenato comune e che potrebbero beneficiare periodicamente degli aggiornamenti degli antenati.

The problem with branches is that changes made to one branch stay on that one branch until you explicitly merge them onto another branch. This effectively means that if you have a change in the common code, you need to apply that change to each 'client-branch' individually, which is exactly what you don't want.

Il suggerimento di utilizzare un sottomodulo (con codice comune) richiede anche l'aggiornamento esplicito del sottomodulo di ciascun cliente. Con lo svantaggio che quando si usano i sottomoduli non si può scegliere la ciliegina (scegliere quali modifiche si vogliono incorporare), a meno che non si decida di suddividere il sottomodulo - che sarebbe il peggiore di entrambi i mondi. Inoltre, l'uso di sottomoduli ti costringerà a mantenere tutti i codici comuni all'interno di una singola sottocartella, il che potrebbe essere un problema se devi conservare alcuni file (come HTML, ASPX, JSP, ecc.) Nella cartella principale o in una cartella specifica. Se si utilizzano i rami client, è possibile avere codice comune e codice client specifico nelle stesse cartelle (e fintanto che li si mantiene in file separati, l'unione sarà sempre banale).

Si potrebbe facilmente avere un ramo per ogni cliente, e unire i miglioramenti del prodotto in ogni ramo secondo necessità (o anche ribilanciare i rami del cliente, il che porterebbe a una cronologia più pulita, anche se ciò potrebbe portare ad alcuni stati incoerenti nella storia) . Questa risposta spiega i rami specifici del cliente. La principale sfida qui è mantenere la funzionalità principale isolata dalle personalizzazioni. Ciò potrebbe essere ottenuto usando ereditarietà, classi parziali o eventi.

Un semplice esempio: il ramo master potrebbe avere classi base, che ospiteranno la maggior parte del codice, e classi derivate quasi vuote che ospiteranno fondamentalmente le personalizzazioni. Ogni cliente avrebbe il proprio ramo e cambierebbe solo le classi derivate. Quando vengono aggiunte nuove funzionalità al ramo principale (linea di base del prodotto), è possibile unirle nelle filiali del cliente. Le estensioni del cliente potrebbero rompersi (se si utilizza un linguaggio strongmente tipizzato) a causa di modifiche del contratto sulla classe base - e ciò è positivo, è un segno che la personalizzazione dovrebbe essere rivista.

È importante isolare il codice comune dal codice specifico del cliente, in modo che le unioni siano semplici. È una buona idea tenerli in file separati, sia che si tratti di classi diverse (personalizzazione che eredita dal codice comune) sia che si tratti di classi parziali. La funzionalità di base e le personalizzazioni potrebbero anche essere classi completamente estranee, a patto che le si inserisca in qualche codice di avvio (come sottoscrizione di eventi o qualcosa del genere).

Progettando correttamente i metodi (e / o gli eventi di estensione), puoi ottenere un prodotto estensibile abbastanza solido ed evitare l'inferno di manutenzione.

    
risposta data 18.09.2016 - 00:33
fonte
0

Ci sono molti problemi quando si hanno file di codice diversi per ogni client con ogni modulo, tema, ecc. Tutto questo codice è in realtà un diverso codice base, probabilmente con una logica simile o identica a un altro codice client. A prescindere dal tempo di sviluppo iniziale, che è qualcosa che personalmente ricado in molte volte in passato, il mantenimento e il refactoring di tale codice sarà sicuramente un compito arduo. A mio parere, dovresti avere una base di codice singola con tutte le personalizzazioni del client, se non vuoi modificare ogni singolo codice client.

    
risposta data 28.11.2013 - 09:31
fonte
0

Ecco cosa ho trovato per la mia soluzione.

Per cominciare, sono l'unica persona che può usare git correttamente (ish), quindi qualsiasi argomento della linea di comando è fuori questione, le persone vogliono solo usare github per windows come "è carino".

Quindi ho il codice principale, con temi e tutto in un unico repository, stabile nel master. Quando si tratta di creare un nuovo progetto, basta copiarlo e incollarlo (dato che non è possibile eseguire il fork del proprio account) in un nuovo repository.

Per aggiornarlo, posso scaricare il master e letteralmente estrarlo dalla parte superiore, in modo che tutti i file core vengano sostituiti.

Il master ha il file di database come "_database.php", quindi non sovrascrive nulla.

Per accelerare lo sviluppo sul front-end, tutto il CSS e il JS si trovano su un CDN locale e il core lo chiama con un numero casuale alla fine per recuperare sempre una copia non in cache.

Ho scritto uno script che ottiene l'ultimo master, lo estrae e lo scarica in cima a tutti i codici che eseguono il CMS, che funziona perfettamente!

Quindi è tutto, mantiene tutto il codice aggiornato, e se un cliente vuole un sito completamente diverso può cambiare e non essere aggiornato di nuovo. Tutto il codice si trova in un repository separato in modo che possano avere i propri rami master e di sviluppo.

    
risposta data 29.11.2013 - 10:23
fonte

Leggi altre domande sui tag