L'article répondra à la question qui a causé la perte de temps pour de nombreux programmeurs: quelle structure de répertoire doit être utilisée pour un projet futur ou existant? Quelle structure sera la plus optimale non seulement pour la conception actuelle du projet, mais ne sera pas aussi douloureuse à l'avenir en termes d'extension du projet ou de division en parties?
Racine
Et donc nous avons commencé le projet. Que ce soit le projet le plus simple de myapp. Nous créons un répertoire pour cela dans le dossier principal pour le développement (j'ai ce Devel).
mkdir myapp cd myapp
À l'avenir, toutes les actions seront à l'intérieur du catalogue du projet principal
Git
Initialiser un référentiel vide
git init
.gitignore
# *.pyc *.pyo **/__pycache__/ # **/config/ # **/data/ **/logs/ # ( ) **/bin/
Lisez moi
L'étape suivante consiste à créer le fichier README requis. Ce fichier contient la description principale et clé de notre futur projet. Certains créent un fichier texte / simple appelé README.txt. Sur les grands portails, les référentiels sont acceptés pour la norme Markdown sous le nom README.md. Je préfère le HTML, car il est plus pratique pour moi de faire des sélections de couleurs, d'intégrer des liens, des images et d'autres éléments multimédias, d'ouvrir dans un navigateur, d'intégrer des morceaux de code dans les balises <pre> et <code>, d'utiliser des cadres prêts à l'emploi comme Bootstrap pour la décoration et d'autres éléments magiques en dehors de Poudlard. En conséquence, le nom README.html
touch README.html
Si le projet est mené par plusieurs équipes, je recommande à chaque équipe d'avoir son propre fichier README à l'intérieur de chaque module, composant, bibliothèque, etc. développé de manière indépendante.
App
Je nomme le répertoire principal de l'application de la même manière que le répertoire du projet. Dans le cas de cet article, myapp
mkdir myapp touch myapp/__init__.py
Modules et composants
Dans le répertoire de l'application, __init__.py est créé par défaut, contenant le code d'initialisation de l'application et connectant toutes les parties nécessaires à l'application. En particulier, il s'agit de Blueprints pour des URL à branche unique ou un espace de noms pour la logique d'un service distinct, mais avec des URL différentes (un exemple simple consiste à créer un espace de noms pour un service d'articles de blog, où il existe clairement des chemins d'accès différents du formulaire / pages et / page / ID)
mkdir myapp/bp_component touch myapp/bp_component/__init__.py
ou
mkdir myapp/ns_component touch myapp/ns_component/__init__.py
Modèle DB
Le modèle de base de données contient le code d'initialisation de la base de données ainsi que les connexions. Et, bien sûr, la structure des tables et des relations. Il est également souhaitable de sélectionner des tables dans des fichiers séparés en fonction de la logique métier de l'application. La description de plusieurs classes de tables et de liens dans un fichier séparé est pratique car vous pouvez facilement réutiliser le code en copiant le fichier souhaité vers un autre projet ou utiliser des liens symboliques vers le fichier de la bibliothèque partagée pour différents projets.
mkdir myapp/models touch myapp/models/__init__.py touch myapp/models/page.py
Modèles pour le moteur de modèles
Certaines applications (principalement des applications Web) se caractérisent par l'utilisation de modèles pour générer des pages feuilles. Étant donné que l'objectif principal est de séparer le code exécutable de la présentation des données, cette étape aidera l'équipe à économiser beaucoup de temps, d'efforts et d'argent en offrant la possibilité d'un travail parallèle des programmeurs et des concepteurs.
mkdir myapp/templates mkdir myapp/templates/html mkdir myapp/templates/js mkdir myapp/templates/css
Je note que dans ce cas, les sous-répertoires js et css ne sont pas destinés au stockage de bibliothèques JavaScript statiques ou de styles CSS, mais au code modifiable, au code de paramètres ou au code intégré. Par exemple, s'il existe un composant de rendu de calendrier avec des fonctionnalités supplémentaires connectées aux boutons, il sera beaucoup plus pratique de placer le composant de calendrier dans js et d'activer le composant dans des fichiers html, mais avec les paramètres nécessaires. Peut-être que cela ressemblera à une sorte de merde pour quelqu'un, mais c'est beaucoup mieux que de créer une bibliothèque de calendrier statique prête à l'emploi, et après six mois ou un an pour comprendre que vous devez ajouter quelques trois propriétés et méthodes au composant (par exemple, faire datepicker non seulement sous la forme d'un mois, mais et ajouter la possibilité de le transformer en calendrier pendant un an), et quel genre de magie était à l'intérieur, personne ne s'en souviendrait. Les inserts donneront plus de transparence.
Statique
Ici, tous les styles principaux qui ne changent jamais (ou changent extrêmement rarement) sont les styles, les images, les sons, les bibliothèques JS et les frameworks.
mkdir myapp/static mkdir myapp/static/css mkdir myapp/static/js mkdir myapp/static/images
Bibliothèque de fonctions
La facilité de connexion des bibliothèques dépend principalement du langage et du framework au cœur de l'application. Il n'y a PAS de bibliothèques connectées à partir de référentiels et prises en charge par des développeurs indépendants. Voici vos propres fonctions d'assistance. Par exemple, j'ai quelques fonctions de décoration lors du traitement d'un itinéraire, mais avant d'appeler la fonction principale.
mkdir myapp/lib touch myapp/lib/__init__.py
Paramètres et configuration
Comment stocker les paramètres qui définissent les paramètres d'application globaux? Combien de combats étaient à cet égard et ne comptaient pas. Sans détails, comment je le fais: je le stocke en tant que module Python dans un répertoire séparé. Fichiers internes pour différents modes de lancement.
mkdir config echo "CONFIG = 'config.devel'" > config/__init__.py touch config/devel.py touch config/prod.py
Pourquoi py? Oui, car l'analyse syntaxique de XML, YAML, INI et autres non-sens, quand il est assez facile de créer des variables du formulaire à portée de main, n'est passée à personne:
import os DEBUG = True TITLE = 'SpecialistOff.NET' DIR_BASE = '/'.join(os.path.dirname(os.path.abspath(__file__)).split('/')[:-1]) DIR_DATA = DIR_BASE + '/data' DIR_FILES = DIR_DATA + '/files' MIMETYPES = { 'gif': 'image/gif', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png', 'txt': 'text/plain' } SERVERS = [ {'name': 'server1', 'IP': '8.8.8.8', 'port': '80'} ]
Les données
Les fichiers, journaux et autres données chargés pendant l'opération sont stockés dans un répertoire de données séparé
mkdir data mkdir data/files
Test
Modules et accessoires de test
mkdir tests mkdir tests/fixture touch tests/__init__.py touch test.py chmod +x test.py
La documentation
Toute la documentation du projet doit être conservée séparément. J'utilise le répertoire doc pour cela et le stocke sous forme de pages Web statiques avec un point d'entrée index.html. C'est pratique car je peux partager un répertoire de documentation séparé via n'importe quel serveur Web. Ou naviguez directement à partir du répertoire avec n'importe quel navigateur Web (y compris ceux de la console comme lynx, elinks).
mkdir doc touch doc/index.html
Déploiement
Tout dépend des tâches. Et dans les commentaires (à mon humble avis) n'est pas particulièrement nécessaire.
mkdir deploy touch deploy/requirements.txt touch deploy/build.sh mkdir deploy/config touch deploy/config/__init__.py touch deploy/config/demo.py mkdir deploy/cron touch deploy/cron/myapp mkdir deploy/docker touch deploy/docker/Dockerfile touch deploy/docker/docker-compose.yml mkdir deploy/nginx touch deploy/nginx/myapp.conf mkdir deploy/uwsgi touch deploy/uwsgi/conf.ini mkdir deploy/uwsgi/conf.d touch deploy/uwsgi/conf.d/myapp.conf
Journalisation
Ici, vous pouvez ajouter des journaux pour les lancements de tests ou les conclusions de l'application elle-même.
mkdir logs
Scripts et utilitaires d'assistance
mkdir utils touch utils/useradd.py chmod +x utils/useradd.py
Au lieu d'une conclusion
En principe, c'est tout. Pourquoi suis-je si laconique? Parce que le code parlera pour moi mieux que moi. Le reste de mes commentaires peut soit embrouiller, soit susciter la controverse sur l'approche qui sera meilleure / pire.