Quando separare un progetto in più sottoprogetti


30

Vorrei sapere se ha senso dividere il progetto a cui sto lavorando in due repository anziché in uno.

Da quello che posso dire:

  • Il frontend verrà scritto in html + js
  • Backend in .net
  • Il backend non dipende dal frontend e il frontend non dipende dal backend
  • Il frontend utilizzerà un API riposante implementato nel backend.
  • Il frontend potrebbe essere ospitato su qualsiasi server http statico.

A partire da ora, il repository ha questa struttura:

radice:

  • fine frontale/*
  • backend / *

Penso che sia un errore mantenere entrambi i progetti nello stesso repository. Poiché entrambi i progetti non hanno dipendenze tra di loro, dovrebbero appartenere a singoli repository e, se necessario, a un repository padre con sottomoduli.

Mi è stato detto che è inutile e che non trarremo alcun vantaggio dal farlo.

Ecco alcuni dei miei argomenti:

  • Abbiamo due moduli che non dipendono l'uno dall'altro.
  • Avere la cronologia di origine di entrambi i progetti a lungo termine può complicare le cose (prova a cercare nella storia qualcosa nel frontend mentre hai metà dei commit completamente estranei al bug che stai cercando)
  • Conflitto e fusione (Questo non dovrebbe accadere ma avere qualcuno che spinge verso il back-end costringerà gli altri sviluppatori a tirare le modifiche del back-end per spingere le modifiche del front-end).
  • Uno sviluppatore potrebbe funzionare solo sul backend ma dovrà sempre tirare il frontend o viceversa.
  • A lungo termine, quando sarà il momento di implementare. In qualche modo, il frontend potrebbe essere distribuito su più server statici pur avendo un server back-end. In ogni caso, le persone saranno costrette a clonare l'intero backend con esso o a creare uno script personalizzato per inviare a tutti i server solo il frontend o per rimuovere il backend. È più semplice spingere / tirare solo il frontend o il backend di entrambi se ne è necessario solo uno.
  • Contro argomento (una persona potrebbe lavorare su entrambi i progetti), creare un terzo repository con sottomodulo e svilupparlo con esso. La cronologia viene mantenuta separata nei singoli moduli e puoi sempre creare tag in cui la versione di backend / frontend funziona davvero in sincronia. Avere entrambi frontend / backend insieme in un repository non significa che lavoreranno insieme. Sta solo fondendo entrambi la storia in un unico grande repository.
  • Avere frontend / backend come sottomoduli renderà le cose più facili se si desidera aggiungere un libero professionista al progetto. In alcuni casi, non vuoi davvero dare pieno accesso alla base di codice. Avere un grande modulo renderà le cose più difficili se vuoi limitare ciò che gli "estranei" possono vedere / modificare.
  • Introduzione e correzione di bug, ho inserito un nuovo bug nel frontend. Quindi qualcuno corregge un bug nel backend. Con un repository, il rollback prima del nuovo bug eseguirà anche il rollback del backend, il che potrebbe rendere difficile la correzione. Dovrei clonare il back-end in una cartella diversa per far funzionare il back-end mentre corregge il bug nel frontend ... quindi provare a rimettere insieme le cose ... Avere due repository sarà indolore perché lo spostamento della TESTA di un repository ha vinto non cambiare l'altro. E i test con versioni diverse del backend saranno indolori.

Qualcuno può darmi più argomenti per convincerli o almeno dirmi perché è inutile (più complicato) dividere il progetto in due sottomoduli. Il progetto è nuovo e la base di codice ha un paio di giorni, quindi non è troppo presto per essere risolto.

Risposte:


23

Nella mia azienda, utilizziamo un repository SVN separato per ogni componente del sistema. Posso dirti che diventa estremamente frustrante. Il nostro processo di costruzione ha così tanti strati di astrazione.

Lo facciamo con Java, quindi abbiamo un pesante processo di compilazione con compilation javac, compilation di binding JibX, validazione XML, ecc.

Per il tuo sito, potrebbe non essere un grosso problema se non lo "costruisci" (come PHP vanilla).

Lati negativi alla suddivisione di un prodotto in più repository

  1. Gestione della build - Non posso semplicemente fare il checkout del codice, eseguire uno script di build autonomo e avere un prodotto eseguibile / installabile / distribuibile. Ho bisogno di un sistema di build esterno che esca su più repository, esegua più script di build interni, quindi assembla gli artefatti.
  2. Rilevamento delle modifiche: vedere chi ha cambiato cosa, quando e perché. Se una correzione di bug nel frontend richiede una modifica del backend, ora ci sono 2 percorsi divergenti a cui fare riferimento in seguito.
  3. Amministrazione: vuoi davvero raddoppiare il numero di account utente, criteri password, ecc. Che devono essere gestiti?
  4. Unione: le nuove funzionalità potrebbero cambiare molto codice. Suddividendo il progetto in più repository, si moltiplica il numero di fusioni necessarie.
  5. Creazione di un ramo - Lo stesso affare con la ramificazione, per creare un ramo, ora è necessario creare un ramo in ciascun repository.
  6. Tagging: dopo un test riuscito del codice, si desidera taggare una versione per il rilascio. Ora hai più tag da creare, uno in ciascun repository.
  7. Difficile trovare qualcosa - Forse frontend / backend è semplice, ma diventa una pendenza scivolosa. Se divisi in abbastanza moduli, gli sviluppatori potrebbero dover indagare su dove risiede un pezzo di codice nel controllo del codice sorgente.

Il mio caso è un po 'estremo in quanto il nostro prodotto è suddiviso in 14 repository diversi e ciascun repository viene quindi suddiviso in 4-8 moduli. Se ricordo, abbiamo da qualche parte circa 80 o alcuni "pacchetti" che devono essere controllati singolarmente e poi assemblati.

Il tuo caso con solo backend / frontend potrebbe essere meno complicato, ma ancora sconsiglio.

Esempi estremi possono essere argomenti convincenti a favore o contro praticamente qualsiasi cosa :)

Criteri che vorrei usare per decidere

Vorrei prendere in considerazione la suddivisione di un prodotto in più repository di codice sorgente dopo aver considerato i seguenti fattori:

  1. Costruisci: i risultati della creazione di ciascun componente si uniscono per formare un prodotto? Come combinare file .class da un gruppo di componenti in una serie di file .jar o .war.
  2. Distribuzione: finisci con i componenti che vengono distribuiti insieme come un'unità o unità diverse che vanno su server diversi? Ad esempio, gli script del database vanno al tuo server DB, mentre javascript va al tuo server web.
  3. Co-change - Tendono a cambiare frequentemente o insieme? Nel tuo caso, possono cambiare separatamente, ma comunque frequentemente.
  4. Frequenza di ramificazione / fusione: se tutti effettuano il check-in nel trunk e le filiali sono rare, potresti riuscire a cavartela. Se spesso ti ramifichi e ti unisci, questo potrebbe trasformarsi in un incubo.
  5. Agilità: se è necessario sviluppare, testare, rilasciare e distribuire una modifica in un momento (probabilmente con SaaS), è possibile farlo senza perdere tempo prezioso a destreggiarsi tra filiali e repository?

I tuoi argomenti

Inoltre, non sono d'accordo con la maggior parte dei tuoi argomenti per questa scissione. Non li disputerò tutti perché questa lunga risposta diventerà ancora più lunga, ma alcuni che si distinguono:

Abbiamo due moduli che non dipendono l'uno dall'altro.

Senza senso. Se porti via il tuo backend, funzionerà il tuo frontend? È quello che pensavo.

Avere la cronologia di origine di entrambi i progetti a lungo termine può complicare le cose (prova a cercare nella storia qualcosa nel frontend mentre hai metà dei commit completamente estranei al bug che stai cercando)

Se la radice del progetto è suddivisa in frontend / e backend /, è possibile esaminare la cronologia di tali gerarchie in modo indipendente.

Conflitto e fusione (Questo non dovrebbe accadere ma avere qualcuno che spinge verso il back-end costringerà gli altri sviluppatori a tirare le modifiche del back-end per spingere le modifiche del front-end.) Uno sviluppatore potrebbe lavorare solo sul back-end ma dovrà sempre tirare il back-end o in altro modo in giro.

Dividere il tuo progetto in diversi repository non risolve questo problema. Un conflitto frontend e un conflitto backend ti lasciano ancora con 2 conflitti, che si tratti di 1 repository volte 2 conflitti o 2 repository volte 1 conflitto. Qualcuno deve ancora risolverli.

Se il problema è che 2 repository indicano che uno sviluppatore frontend può unire il codice frontend mentre uno sviluppatore backend unisce il codice backend, è ancora possibile farlo con un singolo repository utilizzando SVN. SVN può unire a qualsiasi livello. Forse è una limitazione gur o mercuriale (hai taggato entrambi, quindi non sei sicuro di quale SCM usi)?

D'altro canto

Detto questo, ho visto casi in cui funziona la suddivisione di un progetto in più moduli o repository. L'ho persino sostenuto una volta per un particolare progetto in cui abbiamo integrato Solr nel nostro prodotto. Solr ovviamente funziona su server separati, cambia solo quando un changeset è legato alla ricerca (il nostro prodotto fa molto più della ricerca), ha un processo di compilazione separato e non ci sono artefatti di codice o artefatti di build condivisi.


Moderazione in tutte le cose, come diceva mia madre ...
William Payne,

Al momento della mia scrittura, sto scrivendo il frontend senza backend. Emulo il backend con i file json e probabilmente potrei anche emularlo completamente con indexedDB nel browser. Quindi sì, il backend è solo un server che serve json. Potrebbe essere sostituito da qualsiasi cosa purché i dati ricevuti siano conformi all'API. Entrambi i progetti utilizzano un sistema di build diverso. In breve, è praticamente come avere un sito Web e un'app Android mobile. Aggiunta dell'applicazione mobile all'interno del repository webserver.
Loïc Faure-Lacroix

Inoltre, se non fosse chiaro, il backend e il frontend non sono interfacce utente / amministratore. Ma frontend è solo un'interfaccia Ajax e il backend serve json. Utenti e ruoli vengono gestiti in modo diverso e l'interfaccia di amministrazione sarà nel frontend. L'idea è di mantenere entrambe le parti isolate e impedire all'html generato da JavaScript di caricare l'html generato dal server. Il server dovrebbe servire solo json o xml.
Loïc Faure-Lacroix

1
Quindi non hai problemi di compilazione o distribuzione, quindi potrebbe essere ok. Ma ancora una volta, se apporti una modifica importante, potrebbe essere necessario modificare l'API, che influisce sia sul frontend che sul backend e quindi ti ramificherai due volte, unendo due volte, tag due volte, ecc. Ma purché rimanga solo due volte e non lo faccia non si trasforma in 3 ... 4 ... 12 ... 20, probabilmente non è una cattiva idea.
Brandon,

Anche se l'API cambia, con il controllo delle versioni corretto, potrebbe essere possibile creare versioni di diramazione per ciascun frontend che supporta una versione dell'API. Il back-end dovrebbe avere una certa compatibilità "arretrata" e far funzionare l'API precedente il più a lungo possibile.
Loïc Faure-Lacroix

3

Alcuni dei tuoi argomenti sono validi e altri no.

Abbiamo due moduli che non dipendono l'uno dall'altro.

Questo in realtà non è del tutto vero. Per poter comunicare, sia il front-end che il back-end devono avere un'interfaccia comune (descrizione). Ciò lo rende un argomento debole a favore di avere entrambi in un repository comune. Ma solo un argomento debole in quanto non fa molta differenza.

Avere la cronologia di origine di entrambi i progetti a lungo termine può complicare le cose (prova a cercare nella storia qualcosa nel frontend mentre hai metà dei commit completamente estranei al bug che stai cercando)

Questo è un argomento falso. Se vuoi cercare come è stato risolto un determinato bug, cerca nel bug-tracker il commit che contiene la correzione. E se vuoi sapere come si è evoluto un particolare pezzo di codice, guardi la storia di un singolo file (o al massimo una manciata). In entrambi i casi, avere altri file, eventualmente da altri moduli, nel repository non dovrebbe complicare le cose in alcun modo.

Conflitto e fusione (Questo non dovrebbe accadere ma avere qualcuno che spinge verso il back-end costringerà gli altri sviluppatori a tirare le modifiche del back-end per spingere le modifiche del front-end).

Questo è un argomento falso. Non sono a conoscenza di alcun VCS (metà decente) in cui è necessario sincronizzare l'intero repository prima di poter eseguire il commit / push delle modifiche. Al massimo è necessario sincronizzare le cartelle che contengono i file modificati (e spesso solo i file stessi).

Uno sviluppatore potrebbe funzionare solo sul back-end, ma dovrà sempre tirare il back-end o viceversa.

Questo è lo stesso argomento fasullo del precedente.

A lungo termine, quando sarà il momento di implementare. In qualche modo, il frontend potrebbe essere distribuito su più server statici pur avendo un server back-end. In ogni caso, le persone saranno costrette a clonare l'intero backend con esso o a creare uno script personalizzato per inviare a tutti i server solo il frontend o per rimuovere il backend. È più semplice spingere / tirare solo il frontend o il backend di entrambi se ne è necessario solo uno.

A seconda di come le persone prevedono che lo schieramento sarà fatto, questo può essere un argomento valido. Se la distribuzione verrà eseguita decomprimendo un file zip / tarbal sul server, non importa come sono organizzati i repository. Se la distribuzione verrà eseguita estraendo (parte di) un repository sul server, allora può essere una buona idea utilizzare repository separati per i moduli che vengono distribuiti separatamente.

Contro argomento (una persona potrebbe lavorare su entrambi i progetti), creare un terzo repository con sottomodulo e svilupparlo con esso. La cronologia viene mantenuta separata nei singoli moduli e puoi sempre creare tag in cui la versione di backend / frontend funziona davvero in sincronia. Avere entrambi frontend / backend insieme in un repository non significa che lavoreranno insieme. Sta solo fondendo entrambi la storia in un unico grande repository.

Questo è un argomento valido, ma non è così forte.

Avere frontend / backend come sottomoduli renderà le cose più facili se si desidera aggiungere un libero professionista al progetto. In alcuni casi, non vuoi davvero dare pieno accesso alla base di codice. Avere un grande modulo renderà le cose più difficili se vuoi limitare ciò che gli "estranei" possono vedere / modificare.

Questo è un argomento valido.

Introduzione e correzione di bug, ho inserito un nuovo bug nel frontend. Quindi qualcuno corregge un bug nel backend. Con un repository, il rollback prima del nuovo bug eseguirà anche il rollback del backend, il che potrebbe rendere difficile la correzione.

Questo è un argomento falso, perché significherebbe che dopo due correzioni di bug in un modulo, non si sarebbe in grado di ripristinare il primo. Qualsiasi VCS decente ti consentirà di eseguire il rollback di quasi tutti i vecchi commit (anche se spesso significherà che esegui un nuovo commit che inverte tali modifiche, a volte anche per la parte superiore di HEAD).

Dovrei clonare il back-end in una cartella diversa per far funzionare il back-end mentre corregge il bug nel frontend ... quindi provare a rimettere insieme le cose ... Avere due repository sarà indolore perché lo spostamento della TESTA di un repository ha vinto non cambiare l'altro. E i test con versioni diverse del backend saranno indolori.

Questa è in realtà una buona argomentazione. Avere due repository semplifica il test degli scenari in cui i front-end e i back-end distribuiti potrebbero diventare (leggermente) fuori sincrono.


Ad essere onesti, la maggior parte degli argomenti fasulli possono essere risolti con i rami. Branch per frontend e branch per backend. Master per la sincronizzazione. Ma in qualche modo, gestire un ramo del genere rende le cose più complicate che avere due repository.
Loïc Faure-Lacroix,

1
@Sybiam: In realtà, sono argomenti fasulli, perché non evidenziano un problema che potrebbe esistere con l'utilizzo di un singolo repository, anche se tutte le modifiche vengono apportate solo a trunk / main.
Bart van Ingen Schenau,

Penso che le tue critiche siano valide. Non penso proprio che fosse questo il punto della domanda.
sylvanaar,

2

Questo post è un po 'vecchio ma vorrei contribuire. Mentre il tuo back-end non conosce davvero il front-end, il front-end deve avere richieste corrispondenti all'API del back-end. Se si considera il back-end come un'API REST, è possibile definire un file di interfaccia come un'interfaccia YAML spavaldo. Ora ci sono davvero 3 progetti, che puoi dividere individualmente in diversi repository come ritieni opportuno:

  • Definizione API
  • Back-end
  • Fine frontale

La definizione dell'API è una dipendenza negli altri due progetti, supponiamo che tu stia usando Maven come strumento di iniezione delle dipendenze. Quindi dipende da quanto rigorosamente si desidera eseguire il controllo delle versioni. Puoi aumentare la versione del progetto di definizione dell'API ogni volta che apporti una modifica per assicurarti che i progetti siano sempre in uno stato compatibile ma richiedano un maggior sovraccarico, oppure puoi usare qualcosa come SNAPSHOTS in Maven e fare il controllo delle versioni solo una volta che sei soddisfatto dell'interfaccia che è meno sovraccarica ma potresti avere incompatibilità. Ma finché imporrete la definizione API nel vostro front-end e back-end, andrete bene a suddividere i progetti in diversi repository.

Questi problemi riguardano maggiormente la gestione delle dipendenze. Anche se i progetti non sono suddivisi e si trovano nello stesso repository, è abbastanza facile mettere il sito Web in uno stato in cui front-end e back-end non sono sincronizzati. L'unico modo per fermare questo è in realtà definire il contratto tra i due, ma si desidera farlo in un modo che non accoppi le implementazioni del front-end e del back-end, proprio come se si codificasse invece un'interfaccia di un'implementazione nella programmazione OO.

Anche per gestire preventivamente le critiche che ciò crea un sovraccarico nel mantenimento di questo file di interfaccia, ad esempio Swagger può persino produrre stub di codice per diversi linguaggi di programmazione e framework come JAX-RS. Quindi puoi produrre un'interfaccia nella tecnologia prescelta e quindi implementare questa interfaccia. Aggiunge inoltre una documentazione molto bella al back-end, rendendo più semplice per gli sviluppatori front-end svolgere il proprio lavoro.

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.