Вот буквально каждый раз, когда достаётся на поддержку чей-нибудь проект, волосы дыбом встают (а они у меня длинные — это ж какую силу надо их так поднять). Очень бывает непросто поднять проект, зарядить все зависимости, наполнить демо-данными, понять, что там к чему, где что валяется и почему. Порой до того доходит, что охота бросить всё и написать всё заново в духе заправского красноглазого пионера. Хотя ведь именно в случае разработки на Django так просто и удобно содержать проект в порядке. Особенно удивляет то, что порой бардак в проекте присутствует и у опытных разработчиков, а не только у новичков. Попробую с этим бардаком побороться словами.
1) Репозиторий — это хорошо и правильно.
Порой приходит задача и присылают код, запакованный в архив. В принципе можно и так работать, но неудобно же! А бывает, что несколько разработчиков ведут работу над проектом, обмениваясь архивами. Диковато, правда.
Сейчас же, в текущем проекте, заказчик просил исправить мелкую мелочь, но, глядя в код, было не понять, откуда что берётся. Развернув проект у себя, понимаю, что части кода просто нет. Почти день ушёл на то, чтобы выяснить, что другой разработчик правил непосредственно на сервере и просто коммит не сделал. Пишите у себя, и заведите правило — каждое логически завершённое изменение надо коммитить.
2) PEP8 — это не просто чудачество.
Регулярно приходит код, где отступы то 2 пробелами, то табами. Про всякие пустые строки между классами и функциями уже вообще не говорю. Именование классов, функций, переменных — кто в лес, кто по дрова. Это жесть. Есть ведь правила. Открывая код на питоне, ожидаешь, что он соответствовать будет этим правилам. Получаешь ошибку из-за неправильного отступа — тратишь на неё внимание и время. А ведь можно было обойтись без такого. Имя класса в змеиной нотации — wtf? Методы класса сплошняком, не отбитые пустыми строками — их можно не заметить, когда ожидаешь отбивку эту увидеть. Всё это снижает скорость работы, отвлекает внимание на всякую хрень.
3) Зависимости нужно прописывать.
Вот почему-то вообще редко-редко кто удосуживается прописывать зависимости в проекте. А потом подключаться новому участнику. Создать виртуальное окружение и … и что дальше? Что туда устанавливать?
Заведите привычку: устанавливать через файл зависимостей. В корне проекта создать файл requirements.txt, в него записывать имя и версию приложения, а затем делать pip install -r requirements.txt. Версию, кстати, обязательно. Некоторые приложения обратно несовместимы и от версии к версии меняются настолько, что с другой версией этого же приложения проект может и не завестись.
4) А вот класть виртуальное окружение в репозиторий не надо.
Разные разработчики могут работать на разных ОС. И бинарник под винду на маке будет только мусором лежать.
5) Пути должны быть относительно корня проекта.
Клонирую проект, а там MEDIA_ROOT = '/home/maks/django-projects/zapchast/media/'. Приходится колдовать, прописывая персонально для себя другие пути в local_settings. Но что мешало сразу предположить, что у другого разработчика абсолютный путь скорее всего будет другим? Пишите сразу так:
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
6) Следует использовать локальные настройки.
Допустим, те же пути можно и в самом деле сделать относительными и забыть об этом. Но например база данных. Реквизиты доступа к БД могут быть у каждого свои. А на боевом сервере и вовсе они могут быть совсем другими. Да и светить пароли-явки в общедоступных репозиториях — дурная практика. А ещё на локальном может быть отправка почты в консоль, а на боевом — smtp-сервер.
В общем, стоит делать рядом с settings.py файл local_settings.py с настройками, специфичными именно для этой машины, под контроль версий его не класть, а в конце settings.py подключать его:
try:
from .local_settings import *
except ImportError:
pass
А в репо можно положить образец, что-то типа local_settings.py.tpl, где будет показано, какие настройки там должны быть прописаны.
7) Не надо всё-всё-всё умещать в один файл.
Проект большой? Да, бывает. Значит, скорее всего, его удобно разбить на слабосвязанные приложения. Но даже если какую-то большую часть не получается разбить на приложения, в рамках одного приложения тоже стоит код делить на небольшие части. Например, в файле models.py на 10к строк, содержащем с полсотни моделей, ориентироваться затруднительно. Но ведь можно сделать каталог models, в котором разные файлы содержат разные классы.
8) А ещё давайте не изобретать велосипеды.
Если у вас возникла какая-либо задача, подумайте: наверняка эта задача возникала уже у кого-то до вас. И скорее всего красивое и удобное решение есть непосредственно на уровне фреймворка.
Извините, коллеги. Наболело. Опять пришёл проект, в котором присутствует беда по всем из этих пунктов. Но может я где-то преувеличиваю? А может наоборот, кто-то сталкивается с проблемами, здесь не описанными? А может моя неправда, а всё описанное — на самом деле норма?