Comment dois-je organiser mon arbre source?


89

Je suis un développeur individuel travaillant principalement sur des projets Web (W / LAMP) et, parfois, sur des projets C / C ++ (non GUI) de taille moyenne.

J'ai souvent du mal à structurer mon arbre de code source. En fait, en général, je ne termine pas un projet sans vider l’arbre en entier et réarranger les pièces trois à quatre fois, ce qui demande beaucoup d’efforts et de plus, le résultat final semble être un compromis.

Parfois, je me retrouve avec une classification excessive de la source - une très longue arborescence de dossiers et de sous-dossiers. À d'autres moments, je finis simplement par concentrer tous les fichiers dans un dossier particulier en fonction de l'objectif plus large qu'ils servent, ce qui conduit à des dossiers "chaotiques" dans la source.

Je voudrais demander:

  • Existe-t-il des principes / logique / meilleures pratiques qui peuvent m'aider à mieux structurer mon arbre source?
  • Existe-t-il des techniques graphiques / schématiques (par exemple: DFD en cas de flux de données) qui puissent m'aider à visualiser mon arbre source au préalable en fonction de l'analyse du projet?
  • Quelle stratégie adopter pour structurer l’arborescence de fichiers multimédia associée au projet?

À propos de la prime : j'apprécie les réponses existantes avec les membres partageant leurs propres pratiques, cependant, j'aimerais encourager des réponses plus générales et instructives (ou des ressources) et davantage de réponses des membres.


8
Je n'ai pas le temps de faire un essai pour le moment, mais "donnez des noms à ce qu'ils sont", "placez les choses à leur place", "gardez les choses semblables les unes à côté des autres" et, enfin, "ne vous inquiétez pas , vous espérez avoir un IDE qui vous aidera à naviguer rapidement entre les morceaux de code ".
John Saunders

@ John, je ne suis pas très bon avec IDE (s), je tire généralement un Notepad ++ ou vi en fonction du système d'exploitation. Cela rend les choses un peu plus difficiles. Le reste des points est utile, mais encore une fois, il s’agit de prendre des décisions difficiles, telles que les fonctions de journalisation (journaux d’erreurs, etc.) plus proches de la logique d’application, du DAL ou de la gestion du cache ou des gestionnaires de vues. Les erreurs ont presque la même probabilité de se produire.
check123

3
Peut-être qu'une fois que vous aurez eu ce genre de question, il est temps de laisser certains outils faire le travail pour vous. Et la journalisation est clairement une préoccupation interfonctionnelle, utilisée par toutes les parties de l'application (si vous utilisez le type de code qui nécessite la journalisation). Un autre petit dicton est "placez le code au-dessus du code qui l’utilise", la journalisation devrait donc être proche du début, peut-être dans \ utilities.
John Saunders

@ John: très apprécié. Peut-être que je devrais commencer à chercher un IDE. Eclipse semble prometteur.
check123

1
@ check123 "... réarrangez les pièces trois à quatre fois ..." Pratique courante: «La question de la gestion n'est donc pas de savoir s'il faut construire un système pilote et le jeter à la poubelle. Tu vas faire ça. La seule question qui se pose est de savoir s'il faut planifier à l'avance la construction de la jetée ou promettre de la livrer à ses clients. ”- Frederick P. Brooks Jr., The Mythical Man-Month: Essais sur le génie logiciel
shawnhcorey

Réponses:


25

La disposition de l’arbre source doit refléter l’architecture; corollairement, une architecture bien structurée peut conduire à une structure d'arborescence source bien structurée. Je suggère de lire le motif POSA1 Layers en essayant d’intégrer votre architecture dans une structure en couches, puis en nommant chacune des couches résultantes et en s’en servant comme base pour la hiérarchie de votre source. En prenant comme référence une architecture à trois niveaux commune :

  • presentation / webService (présente une interface de service Web à notre logique métier)
  • logic / * (les modules de logique métier vont ici)
  • storage / sql (ici, les API de stockage back-end utilisent une interface SQL pour stocker dans une base de données)
  • util / * (code utilitaire - utilisable par toutes les autres couches, mais qui ne fait pas référence à l'extérieur de util, va ici)

Notez que les couches ne contiennent pas de code directement, mais sont strictement utilisées pour organiser les modules.

Dans un module, j'utilise le type de mise en page suivant:

  • <module> (chemin d'accès direct au module; définit l'interface modulaire)
  • <module>/impl/<implName> (une implémentation spécifique de l'interface modulaire)
  • <module>/doc (Documentation pour utiliser le module)
  • <module>/tb (code de test unitaire du module)

où le <module>est situé dans le référentiel en fonction de la couche à laquelle il appartient.


5
+1: La disposition de l'arborescence source doit refléter l'architecture - une chose évidente que je vis sur.
check123

Comment gérez-vous les fichiers sécurisés - des fichiers auxquels seuls les utilisateurs autorisés peuvent accéder après la connexion?
check123

@ check123 Je ne suis pas sûr de comprendre la question. Je me suis concentré sur l'organisation des modules source, plutôt que sur les fichiers de support du projet, et le code source est généralement destiné à être accessible à tous. (Il y a des exceptions, et j'utilise un répertoire dist / au-dessus de tout code contenant des restrictions d'utilisation / de modification non standard.)
Aidan Cully

48

Je ne peux pas vraiment vous donner beaucoup de conseils sur les projets Web, mais voici comment je structure mon arbre dans un projet de programmation (principalement du point de vue du C / C ++):

  • /
    • src - Fichiers sources écrits par moi-même
    • ext - contient les bibliothèques tierces
      • libname-1.2.8
        • include - En-têtes
        • lib - Fichiers lib compilés
        • Donwload.txt - Contient un lien pour télécharger la version utilisée
    • ide - Je stocke les fichiers de projet ici
      • vc10 - J'organise les fichiers de projet en fonction de l'EDI
    • bin - exe compilé va ici
    • build - Les fichiers de compilation du compilateur
    • doc - Documentation de tout genre
    • LISEZMOI
    • INSTALLER
    • COPIER

Quelques notes:

  1. Si j'écris une bibliothèque (et que j'utilise C / C ++), je vais organiser mes fichiers sources d'abord dans deux dossiers appelés "include" et "src", puis par module. Si c'est une application, je vais les organiser simplement par module (les en-têtes et les sources iront dans le même dossier).

  2. Les fichiers et les répertoires que j'ai énumérés ci-dessus en italique ne seront pas ajoutés au référentiel de code.


Quelle est la différence entre ide et build ?
M. Dudley

3
ideest juste où je stocke les fichiers de projet eux-mêmes. buildcontient les fichiers objets générés par le compilateur. Différents IDE peuvent utiliser le même compilateur, c'est pourquoi je garde les fichiers de projet IDE séparés des fichiers objets générés par le compilateur.
Paul

so build == obj (terme utilisé par de nombreux autres systèmes)
gbjbaanb

@ gbjbaanb Ouais, je suppose. Cela n'a pas vraiment d'importance puisque ce répertoire n'est pas poussé dans le référentiel. :) Je l'ai appelé 'build' car c'est ce que l'EDI que j'utilisais att appelait cela (Visual Studio).
Paul

Que faire si votre exe a besoin de dll à exécuter? Est-ce que vous copiez tous les fichiers dll dans le même répertoire que exe? Utilisez-vous des événements post-build?
Wakan Tanka

14

Bien que Maven Standard Directory Layout soit spécifique à Java, il peut également servir de base pour d’autres types de projets.

Voici la structure de base (vous pouvez remplacer les répertoires "java" par "php", "cpp", etc.):

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 structure se décompose essentiellement en 'src / main' et 'src / test' puis groupés par type.


5

Je ne connais pas vraiment les conventions, mais tous mes projets principaux sont réalisés à l'aide de Symfony Framework et je me suis habitué à une arborescence de la manière suivante:

racine/

  • applications
  • nom de l'application
    • config (fichiers de configuration spécifiques à l'application)
    • lib (fichiers php spécifiques à l'application)
    • modules (distribution modulaire de fonctionnalités)
      • nom_module
        • modèles (html)
        • actions (code php)
  • confing (fichiers de configuration de projet)
  • lib (code php pouvant être utilisé dans un projet de trou)
  • modèle (classes qui représentent les informations du projet)
    • base
  • forme (fichiers php qui gèrent les formes, cela pourrait être assez difficile à réaliser sans symfony)
    • base (classes de formulaire de base)
  • la toile
  • css
    • images
    • fichier.css
  • js
  • log (fichiers journaux pouvant être générés)
  • données (informations spécifiques aux données, telles que des correctifs SQL, ou autre)
  • sql
  • plugins (bibliothèques utilisées pouvant être fusionnées avec n'importe quelle application du projet)

Si vous êtes intéressé, veuillez lire la documentation de symfony à ce sujet pour plus d'informations ( MVC et Code Organization sur Symfony ).


Votre dossier CSS est-il centralisé? Je veux dire que tous vos CSS (à travers le projet) sont dans le même répertoire?
check123

Pas nécessairement, vous pouvez le diviser, mais comme la plupart de mes projets ont tendance à ne comporter que deux applications (frontend et backend), il n’ya pas beaucoup de fichiers css (les plugins ont toujours leur propre dossier Web pour l’abstraction)
guiman

5

Dans l’idéal, l’organisation dispose d’un référentiel unique, dont la structure est destinée à accroître l’engagement entre l’ingénierie et les entreprises et à promouvoir la réutilisation.

...\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\

des produits

Un dossier par produit; aide à communiquer comment le logiciel soutient l'entreprise.

Idéalement, chaque "produit" est un peu plus qu'un fichier de configuration indiquant les systèmes à appeler et leur configuration. Le sous-dossier doc peut contenir le dossier de haut niveau \ spec & tout matériel promotionnel, etc.

En séparant les produits et les systèmes, nous communiquons le potentiel de réutilisation au côté de l'entreprise axé sur le client et décomposons les silos par produit. (Cela contraste avec l'approche "gamme de produits" du même problème)

systèmes

Un dossier par système; aide à communiquer les principales capacités et opportunités / valeur du contenu du référentiel.

  1. Fichiers "Gestion de la configuration" spécifiant les environnements de construction et de déploiement.
  2. Configuration de test au niveau du système (peut être une quantité significative).
  3. Logique et fonctionnalité de haut niveau; les tâches les plus lourdes sont effectuées par les bibliothèques

bibliothèque

Composants réutilisables invoqués par différents systèmes. La plupart des activités de développement sont organisées autour de la production de bibliothèques plutôt que de systèmes. La réutilisation est donc «intégrée» au processus de développement.

devops

Construction, intégration continue et autres fonctionnalités d'automatisation du développement.

Conclusion

L'arbre source est un élément clé de la documentation et détermine l'approche, la structure et la psychologie de la relation de l'entreprise avec sa technologie brevetée.

Les facteurs de cette approche sont expliqués un peu plus en profondeur dans ma réponse à cette question: https://softwareengineering.stackexchange.com/questions/43733/who-organizes-your-matlab-code/59637#59637


Remarque: Il peut être utile de nommer les dossiers de manière compatible avec le type de hiérarchie de produits décrit dans le manuel d’ingénierie des systèmes INCOSE.
William Payne

3

Ce que j'essaie de faire pour chaque projet ressemble à ceci:

  • src - fichiers source, un dossier pour chaque espace de noms / package permettant de récupérer facilement des fichiers (même des fichiers d'en-tête pour C / C ++)
  • ext - pour les bibliothèques externes / tierces, il est simple d'ajouter des externes (telles que des référentiels SVN). À l'intérieur, un dossier pour chaque bibliothèque (fichiers binaires et fichiers inclus)
  • bin - pour les binaires construits, peut être rapidement exporté pour publication
    • inc - pour le fichier d'en-têtes C / C ++ (copié par IDE / makefile / etc ...)
  • out - pour tous les fichiers générés temporairement (.class, .obj etc ...) et peut être ignoré (par exemple par SVN)
  • doc - pour toute documentation, généralement générée avec Doxygen
  • res - en plaçant des ressources ici, il est possible de séparer les fichiers source texte des ressources binaires utilisées par le programme. Je n'ai pas vraiment de hiérarchie spécifique à l'intérieur.
    • config - pour certains fichiers de configuration
    • drawable - pour certaines images ou icônes

Tous les fichiers ou makefiles de l'EDI sont enregistrés directement à la racine si vous n'en utilisez qu'un.


2

Je fais quelque chose comme ça. Fonctionne bien pour un jeu multi-plateformes que je fais dans mon temps libre. Malheureusement au travail, les choses sont beaucoup moins organisées ...

Output                      <-- Build outputs
Docs
External
   <libname>
      Include
      Lib
Data
<ProjectName>.xcodeproj
<ProjectName>VS2010
Source
Temp                        <-- Intermediate stuff from builds and other tools
Tools

2

Pour mes équipes, nous essayons de mettre en place une structure standard pour tous les projets afin de faciliter la recherche d'éléments dès que l'équipe change de contexte et d'éviter de devoir réapprendre à chaque fois. Tous les projets n’ayant pas besoin de tous les systèmes, nous commençons par le jeu minimal.

/ Source / Composant / Langue

/ Source / Composant / 3ème partie /

/ Documentation / Conditions requises

/ Documentation / Design

/ Tests / Automatisé / Unité

/ Tests / Automated / ToolName

/ Tests / Manuel

Il en résulte une certaine duplication, en particulier sous le code et les bibliothèques tiers, mais au moins nous n'oublions jamais la réponse à quelque chose comme "Qu'est-ce qui utilise l'éditeur RogueWave?"


1
Les composants de chemin capitalisés me paraissent vraiment stupides et inutiles. Pourquoi beaucoup tout en minuscule? C'est tellement plus facile à taper pour les humains (alors que les outils ne tiennent pas, y compris les gestionnaires de fichiers WIMP ), et lit tout aussi bien grâce aux séparateurs de chemins. Une victoire définitive pour moi.
ulidtko

2

J'aime les idées présentées dans cette page www.javapractices.com/topic/TopicAction.do?Id=205 . En gros, il est recommandé d'organiser votre projet en fonctionnalités (ou modules, composants). En plus des raisons présentées ici:

  1. Moins de charge cognitive lorsque vous réfléchissez à la portée du code sur lequel vous travaillez car vous avez la garantie que tout code de la fonctionnalité sur laquelle vous travaillez est "privé de fonctionnalité".
  2. Il existe un sentiment de sécurité supplémentaire lorsque vous avez la garantie que vous ne modifiez le code que pour une fonctionnalité donnée. Par exemple, vous ne cassez rien d'autre que la fonctionnalité sur laquelle vous travaillez. Encore une fois, cela est dû au "feature-private".
  3. Moins de charge cognitive simple car il y a moins de fichiers que vous pouvez voir pour un paquet donné. Je suis sûr que tout le monde a vu un paquet contenant plus de 15 fichiers.

Notez que cela concerne les packages Java (aussi appelés espaces de noms). Pour les grands projets, je recommande, pour les mêmes raisons, de diviser le projet en plusieurs projets (comme dans plusieurs projets maven) qui représentent une fonctionnalité métier. Pour les projets Maven, je recommande cette lecture .

Jusqu'à présent, les projets auxquels je participais / que je suis ne les suivent pas. Il y a beaucoup de raisons, mais en voici quelques unes:

  1. Incompréhension du modificateur d'accès par défaut de Java (modificateur d'accès le plus incompris selon ce livre )
  2. "Argumentum ad populum": culture prédominante de paquet par couche (probablement causée par la raison 1)

Je pense qu'il existe une opportunité manquée d'éviter la complexité si l'organisation de la source du projet n'est pas prise au sérieux au début du projet, comme l'a dit l'architecte Alexander:

"Comme tout concepteur vous le dira, ce sont les premières étapes d'un processus de conception qui comptent pour la plupart. Les premiers traits, qui créent la forme, portent en eux le destin du reste." - Christopher Alexander

Selon la taille et la complexité d'un projet, l'opportunité manquée de réduire les coûts ou le retour sur investissement peut être très lourde. (Je suis intéressé de voir une étude pour voir les chiffres exacts pour cela)


2

Ma recommandation est de télécharger une variété de cadres ou de moteurs et de voir comment d’énormes équipes de développement gèrent la disposition de leurs dossiers.

Il y a tellement de façons d'organiser les fichiers qu'il vaut mieux en choisir un et essayer de s'y tenir à chaque projet. S'en tenir à une convention particulière jusqu'à l'achèvement ou la réorganisation pour éviter les bugs et perdre du temps inutile.

Vous pouvez télécharger les frameworks Laravel, Symphony ou Codeigniter pour des projets Web afin d’obtenir une disposition de dossiers instantanée qui fonctionne.

Je vais donc essayer de transmettre une mise en page de dossiers commune à tout développement:

MVC (Model View Controller) donne un bon paradigme d'organisation.

Le code source racine peut être src (C ++) ou application (développement Web)

Une structure de fichier qui n'a pas d'objectif clair pour les classes qu'elle regroupe va certainement créer de la confusion. Ce n'est pas seulement pour organiser le code, il peut également supporter des chargeurs automatiques, une fabrique de classes, un stockage local, un stockage distant et un espacement de noms.

Cette structure de dossiers est dérivée et simplifiée de Laravel Framework . Ma préférence pour ce post est un nom au pluriel mais j'utilise des mots singuliers dans mes projets.


src / storage (implémentations modèles / stockage de fichiers / api / mysql / sql-lite / memcached / redis)

src / repositories (encapsuleur d '' implémentations de stockage 'avec une logique de stockage, une interface commune et une convention de résultat renvoyée.)

src / services | la logique | entités (logique de bussiness App)

src / contrôleurs (Utilisé sur le développement Web pour les demandes de serveur d'itinéraire à vos services)

src / modules | systèmes ( systèmes modulaires qui étendent les fonctionnalités générales de votre infrastructure. Les services peuvent utiliser des modules, mais pas l'inverse)

src / helpers (classes helper ou wrapper telles que, par exemple, la manipulation de chaînes. Cela peut souvent arriver sur libs | vendor quand un tiers)

src / types (énumérations nommées)

public | construire | sortie (web ou c ++)

config (fichiers d'installation. YAML devient populaire pour les fichiers de configuration multiplates-formes)

cache

les journaux

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

bootstrap (Démarre le framework et l'application)

docs (documentation écrite au format markdown .md)

tests ( tests unitaires)

base de données / migrations (Créer une structure de base de données à partir de zéro)

database / seed (Remplit votre base de données avec des données factices à tester)

libs | fournisseur (tous les logiciels tiers. "libs" sur C ++ et "vendeur" habituellement sur php)

atouts | ressources (images / sons / scripts / json / tout support)


1

Avec les langages orientés objet, vous avez la possibilité de créer des espaces de noms. Cette décomposition logique utilisée pour séparer des parties de l'application afin d'éviter le couplage est la principale source de décomposition d'emplacement de fichier logique. Utiliser le couplage pour dissocier les espaces de noms constitue un bon point de départ pour http://en.wikipedia.org/wiki/Software_package_metrics .

D'autres ont parlé de la mise en place du projet par rapport à la construction, mais une fois que vous entrez dans la source elle-même, il s'agit de déterminer ce qui a du sens - utilisez simplement la façon dont vous séparez logiquement le code.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.