Статья ответит на вопрос, который стал причиной потери времени многих программистов: какую структуру каталогов необходимо использовать для будущего или существующего проекта? Какая структура будет наиболее оптимальной не только для текущего зачатка проекта, но и в будущем будет не такой болезненной в плане расширения проекта или его разделения на части?
И так мы взялись за проект. Пусть это будет самый простой проект myapp. Создаём для него каталог в основной папке для разработки (у меня это Devel).
В дальнейшем все действия будут внутри каталога основного проекта
Инициализируем пустой репозиторий
Следующим шагом идёт создание обязательного файла README. В этом файле хранится основное и ключевое описание нашего будущего проекта. Некоторые делают файл в виде text/plain с названием README.txt. На крупных порталах репозитариях принят за стандарт Markdown с названием README.md. Я же предпочитаю html, т.к. мне удобнее делать цветовые выделения, вставлять ссылки, картинки и другие мультимедиа, открывать в браузере, вставлять куски кода в тегах <pre> и <code>, использовать готовые фреймворки типа Bootstrap для оформления и другой магии вне Хогвардса. Соответственно и название README.html
Если проект ведётся несколькими командами, то рекомендую каждой команде иметь свой README файл внутри каждого разрабатываемого независимо модуля, компонента, библиотеки и т.д.
Основной каталог приложения называю так же, как и каталог проекта. В случае этой статьи myapp
Внутри каталога приложения стандартно создаются __init__.py, содержащий код инициализации приложения и подключения всех необходимых частей к приложению. В частности это Blueprints для одноветочных URL или namespace для логики отдельного сервиса, но с разными URL (простым примером может служить создание namespace для сервиса статей блога, где явно имеются разные пути вида /pages и /page/ID)
или
Модель базы данных содержит код инициализации базы данных, а также подключения. И, обязательно, структуру таблиц и связей. Так же желательно выделять таблицы в отдельные файлы на основе бизнес-логики приложения. Описание нескольких классов таблиц и связей в один отдельный файл удобно тем, что можно достаточно легко повторно использовать код, скопировав нужный файл в другой проект или использовать символьные ссылки на файл из общей библиотеки для разных проектов.
Для некоторых приложений (в основном веб-приложений) характерно использование шаблонов для генерации конечных страниц. Так как основной целью является отделение исполняемого кода от представления данных, то данный шаг поможет в работе команды сэкономить много времени, сил и денег, обеспечив возможность параллельной работы программистов и дизайнеров.
Замечу, что в данном случае подкаталог js и css служат не для хранения статических библиотек JavaScript или стилей CSS, а именно для изменяемого кода, кода с параметрами или кода для вставки. Например если имеется компонент прорисовки календаря с подключением допфункционала к кнопкам, то будет гораздо удобнее в js положить компонент календаря, а в html файлах делать включения компонента, но с нужными параметрами. Возможно это покажется кому-то говнокодом, но это гораздо лучше, чем создать готовую статическую библиотеку календаря, а через полгода-год понять, что требуется добавить ещё пару тройку свойств и методов к компоненту (например сделать datepicker не только в виде одного месяца, но и добавить возможность превратить в календарь на год), а какая магия была внутри никто и не вспомнит. Вставки дадут больше прозрачности.
Здесь все основные никогда не меняющиеся (или меняющиеся крайне редко) стили, картинки, звуки, JS библиотеки и фреймворки.
Удобство подключения библиотек зависит в основном от языка и фреймворка в основе приложения. Здесь НЕ лежат библиотеки, подключаемые из репозитариев и поддерживаемые независимыми разработчиками. Здесь лежат ваши собственные вспомогательные функции. Например у меня лежат некоторые функции-декораторы, при обработке маршрута, но до вызова основной функции.
Как хранить настройки, определяющие глобальные параметры приложения? Сколько на этот счет было баталий и не счесть. Без деталей как делаю я: храню в виде Python модуля отдельным каталогом. Внутри файлы для разных режимов запуска.
Почему py? Да потому, что никому не сдался парсинг XML, YAML, INI и другой чепухи, когда под рукой достаточно легко создавать переменные вида:
Подгружаемые в процессе работы файлы, логи и другие данные хранятся в отдельном каталоге data
Тестовые модули и фикстуры
Вся документация по проекту должна храниться отдельно. Я использую для этого каталог doc и храню как статические веб-страницы с входной точкой index.html. Это удобно тем, что я могу расшарить отдельный каталог документации через любой веб-сервер. Или просмотреть прямо из каталога любым веб-браузером (в том числе и консольными типа lynx, elinks).
Здесь всё зависит от задач. И в комментариях (по моему скромному мнению) не особенно нуждается.
Сюда можно складывать логи при тестовых запусках или выводы самого приложения.
В принципе, это все. Почему я так немногословен? Потому что код скажет за меня лучше, чем я сам. Остальные мои комментарии могут либо запутать, либо разжечь споры о том, какой подход будет лучше/хуже.
Корень
И так мы взялись за проект. Пусть это будет самый простой проект myapp. Создаём для него каталог в основной папке для разработки (у меня это Devel).
mkdir myapp
cd myapp
В дальнейшем все действия будут внутри каталога основного проекта
Git
Инициализируем пустой репозиторий
git init
.gitignore
# Игнорировать байткод
*.pyc
*.pyo
**/__pycache__/
# Игнорировать каталог с файлами настройки
**/config/
# Игнорировать каталог с данными и логами
**/data/
**/logs/
# Игнорировать каталог с исполнимыми файлами и модулями (если таковой имеется)
**/bin/
Прочти меня
Следующим шагом идёт создание обязательного файла README. В этом файле хранится основное и ключевое описание нашего будущего проекта. Некоторые делают файл в виде text/plain с названием README.txt. На крупных порталах репозитариях принят за стандарт Markdown с названием README.md. Я же предпочитаю html, т.к. мне удобнее делать цветовые выделения, вставлять ссылки, картинки и другие мультимедиа, открывать в браузере, вставлять куски кода в тегах <pre> и <code>, использовать готовые фреймворки типа Bootstrap для оформления и другой магии вне Хогвардса. Соответственно и название README.html
touch README.html
Если проект ведётся несколькими командами, то рекомендую каждой команде иметь свой README файл внутри каждого разрабатываемого независимо модуля, компонента, библиотеки и т.д.
Приложение
Основной каталог приложения называю так же, как и каталог проекта. В случае этой статьи myapp
mkdir myapp
touch myapp/__init__.py
Модули и компоненты
Внутри каталога приложения стандартно создаются __init__.py, содержащий код инициализации приложения и подключения всех необходимых частей к приложению. В частности это Blueprints для одноветочных URL или namespace для логики отдельного сервиса, но с разными URL (простым примером может служить создание namespace для сервиса статей блога, где явно имеются разные пути вида /pages и /page/ID)
mkdir myapp/bp_component
touch myapp/bp_component/__init__.py
или
mkdir myapp/ns_component
touch myapp/ns_component/__init__.py
Модель БД
Модель базы данных содержит код инициализации базы данных, а также подключения. И, обязательно, структуру таблиц и связей. Так же желательно выделять таблицы в отдельные файлы на основе бизнес-логики приложения. Описание нескольких классов таблиц и связей в один отдельный файл удобно тем, что можно достаточно легко повторно использовать код, скопировав нужный файл в другой проект или использовать символьные ссылки на файл из общей библиотеки для разных проектов.
mkdir myapp/models
touch myapp/models/__init__.py
touch myapp/models/page.py
Шаблоны для шаблонизатора
Для некоторых приложений (в основном веб-приложений) характерно использование шаблонов для генерации конечных страниц. Так как основной целью является отделение исполняемого кода от представления данных, то данный шаг поможет в работе команды сэкономить много времени, сил и денег, обеспечив возможность параллельной работы программистов и дизайнеров.
mkdir myapp/templates
mkdir myapp/templates/html
mkdir myapp/templates/js
mkdir myapp/templates/css
Замечу, что в данном случае подкаталог js и css служат не для хранения статических библиотек JavaScript или стилей CSS, а именно для изменяемого кода, кода с параметрами или кода для вставки. Например если имеется компонент прорисовки календаря с подключением допфункционала к кнопкам, то будет гораздо удобнее в js положить компонент календаря, а в html файлах делать включения компонента, но с нужными параметрами. Возможно это покажется кому-то говнокодом, но это гораздо лучше, чем создать готовую статическую библиотеку календаря, а через полгода-год понять, что требуется добавить ещё пару тройку свойств и методов к компоненту (например сделать datepicker не только в виде одного месяца, но и добавить возможность превратить в календарь на год), а какая магия была внутри никто и не вспомнит. Вставки дадут больше прозрачности.
Статика
Здесь все основные никогда не меняющиеся (или меняющиеся крайне редко) стили, картинки, звуки, JS библиотеки и фреймворки.
mkdir myapp/static
mkdir myapp/static/css
mkdir myapp/static/js
mkdir myapp/static/images
Библиотека функций
Удобство подключения библиотек зависит в основном от языка и фреймворка в основе приложения. Здесь НЕ лежат библиотеки, подключаемые из репозитариев и поддерживаемые независимыми разработчиками. Здесь лежат ваши собственные вспомогательные функции. Например у меня лежат некоторые функции-декораторы, при обработке маршрута, но до вызова основной функции.
mkdir myapp/lib
touch myapp/lib/__init__.py
Настройки и конфигурирование
Как хранить настройки, определяющие глобальные параметры приложения? Сколько на этот счет было баталий и не счесть. Без деталей как делаю я: храню в виде Python модуля отдельным каталогом. Внутри файлы для разных режимов запуска.
mkdir config
echo "CONFIG = 'config.devel'" > config/__init__.py
touch config/devel.py
touch config/prod.py
Почему py? Да потому, что никому не сдался парсинг XML, YAML, INI и другой чепухи, когда под рукой достаточно легко создавать переменные вида:
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'}
]
Данные
Подгружаемые в процессе работы файлы, логи и другие данные хранятся в отдельном каталоге data
mkdir data
mkdir data/files
Тестирование
Тестовые модули и фикстуры
mkdir tests
mkdir tests/fixture
touch tests/__init__.py
touch test.py
chmod +x test.py
Документация
Вся документация по проекту должна храниться отдельно. Я использую для этого каталог doc и храню как статические веб-страницы с входной точкой index.html. Это удобно тем, что я могу расшарить отдельный каталог документации через любой веб-сервер. Или просмотреть прямо из каталога любым веб-браузером (в том числе и консольными типа lynx, elinks).
mkdir doc
touch doc/index.html
Развертывание
Здесь всё зависит от задач. И в комментариях (по моему скромному мнению) не особенно нуждается.
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
Логирование
Сюда можно складывать логи при тестовых запусках или выводы самого приложения.
mkdir logs
Вспомогательные скрипты и утилиты
mkdir utils
touch utils/useradd.py
chmod +x utils/useradd.py
Вместо заключения
В принципе, это все. Почему я так немногословен? Потому что код скажет за меня лучше, чем я сам. Остальные мои комментарии могут либо запутать, либо разжечь споры о том, какой подход будет лучше/хуже.