Der Artikel beantwortet die Frage, die bei vielen Programmierern zu Zeitverlust geführt hat: Welche Verzeichnisstruktur sollte für ein zukünftiges oder bestehendes Projekt verwendet werden? Welche Struktur ist nicht nur für die aktuelle Konzeption des Projekts am besten geeignet, sondern wird auch in Zukunft nicht so schmerzhaft sein, wenn es darum geht, das Projekt zu erweitern oder in Teile zu teilen?
Wurzel
Und so haben wir das Projekt gestartet. Lassen Sie es das einfachste Projekt von myapp sein. Wir erstellen ein Verzeichnis dafür im Hauptordner für die Entwicklung (ich habe diese Entwicklung).
mkdir myapp cd myapp
In Zukunft werden alle Aktionen im Katalog des Hauptprojekts enthalten sein
Git
Initialisieren Sie ein leeres Repository
git init
.gitignore
# *.pyc *.pyo **/__pycache__/ # **/config/ # **/data/ **/logs/ # ( ) **/bin/
Lies mich
Der nächste Schritt besteht darin, die erforderliche README-Datei zu erstellen. Diese Datei enthält die Haupt- und Schlüsselbeschreibung unseres zukünftigen Projekts. Einige erstellen eine Text- / Nur-Datei mit dem Namen README.txt. Auf großen Portalen werden Repositorys für den Markdown-Standard mit dem Namen README.md akzeptiert. Ich bevorzuge HTML, weil Für mich ist es bequemer, eine Farbauswahl zu treffen, Links, Bilder und andere Multimedia-Inhalte einzubetten, in einem Browser zu öffnen, Codeteile in <pre> - und <code> -Tags einzubetten und vorgefertigte Frameworks wie Bootstrap für die Dekoration und andere Magie außerhalb von Hogwarts zu verwenden. Dementsprechend der Name README.html
touch README.html
Wenn das Projekt von mehreren Teams durchgeführt wird, empfehle ich, dass jedes Team eine eigene README-Datei in jedem unabhängig entwickelten Modul, jeder Komponente, Bibliothek usw. hat.
App
Ich benenne das Hauptanwendungsverzeichnis genauso wie das Projektverzeichnis. Im Fall dieses Artikels, myapp
mkdir myapp touch myapp/__init__.py
Module und Komponenten
Im Anwendungsverzeichnis wird standardmäßig __init__.py erstellt, das den Initialisierungscode für die Anwendung enthält und alle erforderlichen Teile mit der Anwendung verbindet. Dies sind insbesondere Blaupausen für URLs mit einem Zweig oder Namespace für die Logik eines separaten Dienstes, jedoch mit unterschiedlichen URLs (ein einfaches Beispiel ist das Erstellen eines Namespace für einen Blog-Artikeldienst, in dem es eindeutig unterschiedliche Pfade für Form / Seiten und / Seite / ID gibt).
mkdir myapp/bp_component touch myapp/bp_component/__init__.py
oder
mkdir myapp/ns_component touch myapp/ns_component/__init__.py
DB-Modell
Das Datenbankmodell enthält Datenbankinitialisierungscode sowie Verbindungen. Und natürlich die Struktur von Tabellen und Beziehungen. Es ist auch wünschenswert, Tabellen in separaten Dateien basierend auf der Geschäftslogik der Anwendung auszuwählen. Die Beschreibung mehrerer Klassen von Tabellen und Links in einer separaten Datei ist praktisch, da Sie den Code einfach wiederverwenden können, indem Sie die gewünschte Datei in ein anderes Projekt kopieren oder symbolische Links zur Datei aus der gemeinsam genutzten Bibliothek für verschiedene Projekte verwenden.
mkdir myapp/models touch myapp/models/__init__.py touch myapp/models/page.py
Vorlagen für die Vorlagen-Engine
Einige Anwendungen (hauptsächlich Webanwendungen) zeichnen sich durch die Verwendung von Vorlagen zum Generieren von Blattseiten aus. Da das Hauptziel darin besteht, den ausführbaren Code von der Datenpräsentation zu trennen, hilft dieser Schritt dem Team, viel Zeit, Mühe und Geld zu sparen, indem die Möglichkeit der parallelen Arbeit von Programmierern und Designern bereitgestellt wird.
mkdir myapp/templates mkdir myapp/templates/html mkdir myapp/templates/js mkdir myapp/templates/css
Ich stelle fest, dass in diesem Fall das Unterverzeichnis js und css nicht zum Speichern statischer JavaScript-Bibliotheken oder CSS-Stile dient, sondern für veränderlichen Code, Parametercode oder Einbettungscode. Wenn beispielsweise eine Kalenderzeichnungskomponente mit zusätzlichen Funktionen an die Schaltflächen angeschlossen ist, ist es viel bequemer, die Kalenderkomponente in js zu platzieren und die Komponente in HTML-Dateien zu aktivieren, jedoch mit den erforderlichen Parametern. Vielleicht scheint dies für jemanden eine Art Scheiße zu sein, aber es ist viel besser als eine vorgefertigte statische Kalenderbibliothek zu erstellen und nach einem halben oder einem Jahr zu verstehen, dass Sie der Komponente ein paar weitere drei Eigenschaften und Methoden hinzufügen müssen (z. B. Datumsauswahl nicht nur in Form eines Monats, sondern auch und füge die Möglichkeit hinzu, es für ein Jahr in einen Kalender zu verwandeln), und an welche Art von Magie sich niemand erinnern würde. Einsätze sorgen für mehr Transparenz.
Statik
Hier sind alle Hauptstile, die sich nie (oder äußerst selten) ändern, Stile, Bilder, Sounds, JS-Bibliotheken und Frameworks.
mkdir myapp/static mkdir myapp/static/css mkdir myapp/static/js mkdir myapp/static/images
Funktionsbibliothek
Die einfache Verbindung von Bibliotheken hängt hauptsächlich von der Sprache und dem Framework im Kern der Anwendung ab. Es gibt KEINE Bibliotheken, die über Repositorys verbunden sind und von unabhängigen Entwicklern unterstützt werden. Hier sind Ihre eigenen Hilfsfunktionen. Zum Beispiel habe ich einige Dekorationsfunktionen beim Verarbeiten einer Route, aber bevor ich die Hauptfunktion aufrufe.
mkdir myapp/lib touch myapp/lib/__init__.py
Einstellungen und Konfiguration
Wie speichere ich Einstellungen, die globale Anwendungseinstellungen definieren? Wie viele Kämpfe gab es in dieser Hinsicht und zählte nicht. Ohne Details, wie ich es mache: Ich speichere es als Python-Modul in einem separaten Verzeichnis. Innerhalb von Dateien für verschiedene Startmodi.
mkdir config echo "CONFIG = 'config.devel'" > config/__init__.py touch config/devel.py touch config/prod.py
Warum py? Ja, da das Parsen von XML, YAML, INI und anderem Unsinn, wenn es recht einfach ist, Variablen des vorliegenden Formulars zu erstellen, an niemanden weitergegeben wurde:
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'} ]
Daten
Dateien, Protokolle und andere Daten, die während des Betriebs geladen werden, werden in einem separaten Datenverzeichnis gespeichert
mkdir data mkdir data/files
Testen
Testmodule und Vorrichtungen
mkdir tests mkdir tests/fixture touch tests/__init__.py touch test.py chmod +x test.py
Die Dokumentation
Alle Projektdokumentationen sollten getrennt aufbewahrt werden. Ich verwende dafür das doc-Verzeichnis und speichere es als statische Webseiten mit einem index.html-Einstiegspunkt. Dies ist praktisch, da ich über jeden Webserver ein separates Dokumentationsverzeichnis freigeben kann. Oder durchsuchen Sie direkt aus dem Verzeichnis mit einem beliebigen Webbrowser (einschließlich Konsolen wie lynx, elinks).
mkdir doc touch doc/index.html
Bereitstellung
Es hängt alles von den Aufgaben ab. Und in den Kommentaren (meiner bescheidenen Meinung nach) wird das nicht besonders gebraucht.
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
Protokollierung
Hier können Sie Protokolle für Teststarts oder die Schlussfolgerungen der Anwendung selbst hinzufügen.
mkdir logs
Hilfsskripte und Dienstprogramme
mkdir utils touch utils/useradd.py chmod +x utils/useradd.py
Anstelle einer Schlussfolgerung
Im Prinzip ist das alles. Warum bin ich so lakonisch? Weil der Code besser für mich spricht als ich. Der Rest meiner Kommentare kann entweder verwirren oder Kontroversen darüber auslösen, welcher Ansatz besser / schlechter sein wird.