Come dovrei organizzare il mio albero dei sorgenti?

83

Sono uno sviluppatore individuale che lavora, in gran parte, su progetti web (W / LAMP) e, a volte, su progetti C / C ++ (non-GUI) di dimensioni medie.

Spesso faccio fatica a strutturare il mio albero del codice sorgente. In effetti, di solito, non ho completato un progetto senza scaricare l'intero albero e riorganizzare i pezzi tre-quattro volte, il che richiede davvero molto impegno e inoltre il risultato finale sembra un compromesso.

A volte, finisco con la classificazione eccessiva del sorgente - albero molto lungo di cartelle e sottocartelle. Altre volte, mi limito a concentrare tutti i file in una particolare cartella in base allo scopo più grande che servono e quindi a creare cartelle "caotiche" nella fonte.

Vorrei chiedere:

  • Esistono principi / logica / best practice che possono aiutarmi a strutturare meglio il mio albero dei sorgenti?
  • Esistono tecniche grafiche / diagrammatiche (ad esempio: DFD in caso di flusso di dati) che possono aiutarmi a visualizzare in anticipo il mio albero di origine sulla base dell'analisi del progetto?
  • Quale strategia adottare per strutturare l'albero dei file multimediali associato al progetto?

Informazioni sulla taglia : apprezzo le risposte esistenti con i membri che condividono le loro pratiche, tuttavia, vorrei incoraggiare risposte più generali e istruttive (o risorse) e più risposte dai membri.

    
posta check123 06.06.2011 - 15:33
fonte

11 risposte

22

Il layout dell'albero di origine dovrebbe riflettere l'architettura; come corollario, un'architettura ben strutturata può portare a un layout dell'albero delle sorgenti ben strutturato. Suggerisco di leggere il pattern Layer POSA1 , tentando di adattare la tua architettura a una struttura a livelli, quindi di nominare ciascuno dei livelli risultanti e utilizzandolo come base per la propria gerarchia di origine. Prendendo come base di riferimento un'architettura a tre livelli comune

  • presentation / webService (presenta un'interfaccia web-service alla nostra logica aziendale)
  • logic / * (i moduli di business logic vanno qui)
  • storage / sql (API di storage back-end qui - utilizza un'interfaccia SQL per archiviare in un database)
  • util / * (codice di utilità - utilizzabile da tutti gli altri livelli, ma che non si riferisce all'utility esterno, va qui)

Si noti che i livelli non contengono codice direttamente, ma piuttosto sono strettamente utilizzati per organizzare i moduli.

All'interno di un modulo, utilizzo il seguente tipo di layout:

  • <module> (percorso del modulo direttamente, definisce l'interfaccia modulare)
  • <module>/impl/<implName> (un'implementazione specifica dell'interfaccia modulare)
  • <module>/doc (documentazione per l'utilizzo del modulo)
  • <module>/tb (codice test unitario per il modulo)

dove <module> si trova nel repository in base al livello a cui appartiene.

    
risposta data 08.06.2011 - 22:14
fonte
41

Non posso davvero darti molti consigli relativi ai progetti web, ma ecco come strutturo il mio albero in un progetto di programmazione (principalmente da una prospettiva C / C ++):

  • /
    • src - File di origine scritti da me stesso
    • ext: contiene librerie di terze parti
      • libname-1.2.8
        • include - Intestazioni
        • lib - File lib compilati
        • Donwload.txt: contiene il link per scaricare la versione utilizzata
    • ide - Memorizzo i file di progetto qui
      • vc10 - Dispongo i file di progetto in base all'IDE
    • bin - L'exe compilato va qui
    • build - I file di compilazione del compilatore
    • doc - Documentazione di qualsiasi tipo
    • README
    • INSTALL
    • COPIA

Alcune note:

  1. Se sto scrivendo una libreria (e sto usando C / C ++) organizzerò i miei file sorgente prima in due cartelle chiamate "include" e "src" e quindi per modulo. Se si tratta di un'applicazione, le organizzerò solo in base al modulo (le intestazioni e i sorgenti verranno inseriti nella stessa cartella).

  2. File e directory che ho elencato sopra in corsivo non aggiungerò al repository del codice.

risposta data 06.06.2011 - 17:43
fonte
13

Mentre il Maven Standard Directory Layout tipo di specifico a Java, ma può anche servire come buona base per altri tipi di progetti.

Ecco la struttura di base (puoi sostituire le directory 'java' con 'php', 'cpp', ecc):

src/main/java       Application/Library sources 
src/main/resources  Application/Library resources  
src/main/filters    Resource filter files 
src/main/assembly   Assembly descriptors 
src/main/config     Configuration files 
src/main/webapp     Web application sources 
src/test/java       Test sources 
src/test/resources  Test resources 
src/test/filters    Test resource filter files 
src/site            Site 
LICENSE.txt         Project's license 
NOTICE.txt          Notices and attributions required by libraries
README.txt          Project's readme

La struttura si suddivide in base a "src / main" e "src / test", quindi raggruppati per tipo.

    
risposta data 08.06.2011 - 16:25
fonte
5

Non conosco le convenzioni ma tutti i miei progetti principali sono realizzati con Symfony Framework e mi sono abituato a una struttura ad albero come segue:

root /

  • applicazioni
  • app_name
    • config (file di configurazione specifici dell'app
    • )
    • lib (file php specifici per app)
    • moduli (distribuzione modulare della funzionalità)
      • nome_modulo
        • modelli (html)
        • azioni (codice php)
  • confing (file di configurazione del progetto)
  • lib (codice php che potrebbe essere utilizzato nel progetto hole)
  • Modello
  • (classi che rappresentano le informazioni sul progetto)
    • di base
  • form (file php che gestiscono i moduli, questo potrebbe essere abbastanza difficile da ottenere senza symfony)
    • base (classi del modulo di base)
  • web
  • css
    • immagini
    • file.css
  • js
  • log (file di registro che potrebbero essere generati)
  • dati (informazioni specifiche sui dati, come le patch sql o qualsiasi altra cosa)
  • sql
  • plugin (librerie utilizzate che potrebbero essere unite con qualsiasi app del progetto)

Se sei interessato, leggi la documentazione di symfony sull'argomento per ulteriori informazioni ( MVC e organizzazione del codice su Symfony ).

    
risposta data 06.06.2011 - 16:54
fonte
5

Idealmente, l'organizzazione ha un unico repository, la cui struttura è destinata ad aumentare il coinvolgimento tra ingegneria e ingegneria; affari e promuovere il riutilizzo.

...\products\
...\products\productName\
...\products\productName\doc\

...\systems\
...\systems\systemName\
...\systems\systemName\doc\
...\systems\systemName\res\
...\systems\systemName\build\
...\systems\systemName\test\

...\library\
...\library\libraryName\
...\library\libraryName\doc\
...\library\libraryName\build\
...\library\libraryName\test\

...\devops\

prodotti

Una cartella per prodotto; aiuta a comunicare in che modo il software supporta il business.

Idealmente, ogni "prodotto" è poco più di un file di configurazione che indica quali sistemi invocare e come devono essere configurati.    La sottocartella doc può contenere il brief di primo livello \ spec & qualsiasi materiale promozionale ecc ...

Separando prodotti e sistemi, comunichiamo il potenziale di riutilizzo al lato rivolto al cliente del business e abbattiamo i silos per prodotto.    (Questo contrasta con l'approccio "linea di prodotto" allo stesso problema)

sistemi

Una cartella per sistema; aiuta a comunicare le principali funzionalità e amp; opportunità / valore del contenuto del repository.

  1. "Gestione della configurazione" file che specificano build & ambienti di distribuzione.
  2. Configurazione di test a livello di sistema (potrebbe essere una quantità significativa).
  3. Logica e livello superiore funzionalità; il sollevamento più pesante viene eseguito dalle funzioni della libreria.

biblioteca

Componenti riutilizzabili invocati da vari sistemi.    La maggior parte delle attività di sviluppo sono organizzate attorno alla produzione di librerie, piuttosto che di sistemi, quindi il riutilizzo è "covato" nel processo di sviluppo.

DevOps

Build, Continuous Integration & altra funzionalità di automazione dello sviluppo.

Conclusione

L'albero dei sorgenti è una parte fondamentale della documentazione e modella l'approccio, la struttura e la psicologia del rapporto aziendale con la sua tecnologia proprietaria.

I driver per questo approccio sono spiegati in modo un po 'più approfondito nella mia risposta a questa domanda: link

    
risposta data 04.12.2011 - 09:10
fonte
3

Quello che sto cercando di fare per ogni progetto è simile a:

  • src - file di origine, una cartella per ogni spazio dei nomi / pacchetto per recuperare facilmente i file (anche i file di intestazione per C / C ++)
  • ext - per le librerie esterne / di terze parti, è semplice aggiungere elementi esterni (come i repository SVN). All'interno, una cartella per ogni libreria (file binari e file inclusi)
  • bin - per i binari compilati, potrebbe essere rapidamente esportato per il rilascio
    • inc - per file di intestazioni C / C ++ (copiati da IDE / makefile / etc ...)
  • out - per tutti i file generati temporaneamente (.class, .obj etc ...) e potrebbe essere ignorato (ad esempio da SVN)
  • doc - per qualsiasi documentazione, generalmente generata con Doxygen
  • res : posizionando le risorse qui, è possibile separare i file di origine del testo e le risorse binarie utilizzate dal programma. Non ho una gerarchia specifica all'interno.
    • config - per alcuni file di configurazione
    • disegnabile - per alcune immagini o icone

Tutti i file o makefile di IDE vengono salvati direttamente nella root se ne usi solo uno.

    
risposta data 10.08.2011 - 14:59
fonte
2

Faccio qualcosa di simile. Funziona bene per un gioco multipiattaforma che sto facendo nel mio tempo libero. Purtroppo nel lavoro, le cose sono molto meno organizzate ...

Output                      <-- Build outputs
Docs
External
   <libname>
      Include
      Lib
Data
<ProjectName>.xcodeproj
<ProjectName>VS2010
Source
Temp                        <-- Intermediate stuff from builds and other tools
Tools
    
risposta data 09.06.2011 - 14:23
fonte
2

Per i miei team, cerchiamo di applicare una struttura standard tra i progetti per renderli facili da trovare mentre il team cambia contesto e per evitare di dover imparare di nuovo ogni volta. Non tutti i progetti richiedono tutti i sistemi, quindi iniziamo con il set minimo.

/Source/Component/Language

/Source/Component/3rd Party/

/Documentation/Requirements

/Documentation/Design

/Tests/Automated/Unit

/Tests/Automated/ToolName

/Tests/Manual

Ne risulta una duplicazione, in particolare nel codice e nelle librerie di terze parti, ma almeno non dimentichiamo mai la risposta a qualcosa del tipo "Cosa utilizza l'editor di RogueWave?"

    
risposta data 13.06.2011 - 16:50
fonte
2

Mi piacciono le idee presentate in questa pagina www.javapractices.com/topic/TopicAction.do?Id = 205 . Fondamentalmente, la raccomandazione è di organizzare il tuo progetto in funzionalità (o moduli, componenti). Oltre alle ragioni qui presentate:

  1. Meno carichi cognitivi quando pensi all'ambito del codice su cui stai lavorando dato che hai la garanzia che qualsiasi codice nella funzione su cui stai lavorando sia "feature-private".
  2. C'è un ulteriore senso di sicurezza quando si è certi che si sta solo modificando il codice per una determinata funzione. Ad esempio, non si romperà nient'altro che la funzione su cui si sta lavorando. Di nuovo questo è dovuto alla "funzione-privato".
  3. Meno carichi cognitivi semplici perché ci sono meno file che puoi vedere per un determinato pacchetto. Sono sicuro che tutti hanno visto un pacchetto che contiene più di 15 file.

Si noti che questo è focalizzato sui pacchetti Java (noti anche come namespace). Per i grandi progetti, raccomando, per gli stessi motivi, di dividere il progetto in più progetti (come in più progetti di maven) che rappresenta una caratteristica aziendale. Per i progetti di maven, consiglio questo lettura .

Finora, i progetti a cui ero / sono coinvolto non li seguono. Ci sono molte ragioni, ma eccone alcune:

  1. L'incomprensione del modificatore di accesso predefinito Java (il modificatore di accesso più incompreso come da questo libro )
  2. "Argumentum ad populum": cultura prevalente del pacchetto per strato (probabilmente causata dal motivo n. 1)

Penso che ci sia un'occasione mancata per prevenire la complessità se l'organizzazione dell'origine del progetto non viene presa sul serio all'inizio del progetto, come ha detto l'architetto Alexander:

"As any designer will tell you, it is the first steps in a design process which count for most. The first few strokes, which create the form, carry within them the destiny of the rest." - Christopher Alexander

A seconda delle dimensioni e amp; la complessità di un progetto, l'opportunità mancata di tagliare i costi o il ROI può essere davvero grande. (Sono interessato a vedere uno studio per vedere i numeri esatti di questo)

    
risposta data 05.06.2013 - 07:00
fonte
2

La mia raccomandazione è di scaricare una varietà di framework o motori e vedere come enormi team di sviluppo hanno gestito il loro layout di cartelle.

Ci sono tanti modi per organizzare i file che è meglio sceglierne uno e provare ad attenervisi in qualsiasi progetto. Attenersi a una particolare convenzione fino al completamento o al revamping per evitare bug e perdere tempo inutile.

Puoi scaricare i framework Laravel, Symphony o Codeigniter per i progetti web per avere un layout di cartella istantaneo che funzioni.

Quindi proverò a trasmettere un layout di cartelle comune a qualsiasi sviluppo:

MVC (Model View Controller) offre un buon paradigma organizzativo.

Il codice sorgente root potrebbe essere src (C ++) o app (sviluppo web)

Una struttura di file che non ha un chiaro obiettivo per le classi che raggruppa sicuramente causerà confusione. Non è solo per organizzare il codice, ma può anche supportare gli autocaricatori, la produzione di classi, l'archiviazione locale, la memorizzazione remota e il namespace.

Questa struttura di cartelle è derivata e semplificata da Laravel Framework . La mia preferenza su questo post è la denominazione plurale, ma io uso parole singolari nei miei progetti.

src / storage (modelli / file-storage / api / mysql / sql-lite / memcached / redis implementazioni)

src / repositories (un wrapper di "implementazioni di storage" con qualche logica di archiviazione, un'interfaccia comune e una convenzione sui risultati di ritorno.)

src / services | logica | entità (logica di business dell'app)

src / controller (utilizzato sullo sviluppo web per instradare le richieste del server ai tuoi servizi)

src / modules | sistemi (sistemi modulari che estendono le funzionalità generali del framework. I servizi possono utilizzare i moduli ma non viceversa)

src / helper (classi di helper o wrapper come ad es. manipolazione di stringhe. Molte volte questo potrebbe essere su libs | vendor se di terze parti)

src / types (enumerazioni nominate)

pubblico | costruire | output (web o c ++)

config (file di installazione. YAML sta diventando popolare per i file di configurazione multipiattaforma)

La cache

log

lang (en / es / ru /...)

bootstrap (avvia il framework e l'app)

documenti (documentazione scritta in formato markdown .md)

test (test dell'unità)

database / migrazioni (Crea una struttura di database da zero)

database / semi (riempie il database con dati fittizi da testare)

libs | fornitore (tutti i software di terze parti. "libs" su C ++ e "venditore" di solito su php)

beni | risorse (immagini / suoni / script / json / qualsiasi supporto)

    
risposta data 05.05.2017 - 03:08
fonte
1

Con linguaggi orientati agli oggetti, hai la possibilità di creare spazi dei nomi. Tale suddivisione logica utilizzata per separare parti dell'applicazione per evitare l'accoppiamento è la fonte primaria di interruzione della posizione del file logico. Usare l'accoppiamento come motivo per rompere gli spazi dei nomi è un buon punto di partenza per link .

Altri hanno parlato della creazione del progetto in relazione alla costruzione, ma una volta entrati nella fonte stessa, si tratta di ciò che ha senso: basta usare il modo in cui dividi logicamente il codice in ogni caso.

    
risposta data 10.06.2011 - 01:53
fonte

Leggi altre domande sui tag