Комментарии 15
Сначала немного ворчания:
Модель пользоваеля испортируем начиная с 2013 как:
from django.contrib.auth import get_user_model
UserModel = get_user_model()
Не придумываем в бизнес слое новые методы менеджера модели, поскольку хардкод, а используем методы менеджера.
Записью в файлы/потоки/память занимаются обьекты класса Storage из django.core.files.storage, у них даже метод по генерации уникального file_name есть (generate_filename).
Проблем с замкнутым импортом тех же моделей быть не должно при позднем связывании. Имеется в виду, что вызов сервиса с выдачей "имен" вообще не должен знать о моделях Django. Сервис знает, что должен использоватся публичный метод переданного в execute объекта или класса для выполнения своей работы. Пример из статьи: Бизнес задача выдавать csv/xls список имен обьектов. Передал User получил usernames, передал Store получил Storenames.
ну и напоследок - сам сервис у тебя никак не "low in coupling and high in cohesion", а именно для сервис слоя это особенно важно. В твоем примере - методы сервиса могут быть просто функциями модуля Service Layer.
@ChasingRainbows у меня есть четкое ощущение, что я уже читал нечто подобное на medum. Это перевод?
А теперь по делу. Историю развития hexagonal архитектуры Django проекта с выносом Service Layers хорошо подали Stéphane Angel и Joachim Jablon в статье Maintaning a Django project after 10.000 commits. Я писал об их суперполезном докладе на Django Conf 2019 (подраздел Редизайн вашего проекта Django). В видео есть упоминания статей и книг, развивающих эту идею. Спасибо тебе, что озвучиваешь эту тему еще раз, вдруг кому еще зайдет.
Привет, спасибо за отзыв! Нет, не перевод. То что вы пишите имеет место быть, но статья тут скорее про совсем базовые принципы, которые были выстраданы на основе опыта поддержки и развития именно бизнес-логики, огромного и старого Django-монолита на протяжении последних пяти лет моей работы, поэтому старался максимально уйти от всяких нюансов самого фреймворка, типа менеджеров моделей, класса Storage и тп. То что сервис с выдачей "имен" вообще не должен знать о моделях Django действительно верно, но в моей парадигме это уже следующий этап развития, и движение в сторону DDD и Clean Architecture, которые, на моем опыте, подразумевают под собой больше телодвижений, дисциплины в команде, и некий порог вхождения. Может, когда нибудь выпущу статью про опыт реализации и поддержки проекта на основе Clean Architecture на питоне.
Благодарю Вас за статью. Лично для меня данный подход решает накопившуюся боль в нескольких относительно больших проектах.
Можно вопрос от начинающего использовать Django
Что можно почитать на тему правильного проектирования моделей (ну или в общем структуры в базе данных), я конечно помню что то про нормальные формы но это было давно
А так же что почитать про тесты, никогда не приходилось писать их и даже не знаю с чего начать, но понимаю что они нужны
Для представления данных в реляционных базах данных преимущественно используется реляционная модель и элементы реляционной алгебры. Реляционная модель предлагает нам думать о данных как о множествах логических высказываний (предикатов) касающихся фактов реального мира (моделируемой предметной области). То есть по сути это навороченная логика, где каждый факт описывается набором атрибутов, атрибуты группируются по смыслу в отношения (таблицы), а отношения являются аналогом переменных для использования в более сложных алгебраических выражениях (SQL запросах). Нормализация нужна для исключения логических аномалий из модели (чтобы в модели нельзя было представить данные, ведущие к логическим противоречиям). На wiki толковая статья про реляционную модель со ссылками в смежные области https://en.m.wikipedia.org/wiki/Relational_model .
А что скажете насчёт вынесения части логики в миксины? Одну группу методов можно вынести в один миксин, другую - в другой и т.д. И по названию миксина можно быстро понять, что именно он содержит.
Миксин это сущность примерно такого же порядка как функция или класс, сами по себе они никакой ценности для бизнес-логики не несут. Не совсем понимаю как вы в данном контексте себе представляете их. Но сходу могу сказать что миксины часто приводят ко множественному наследованию, которое в целом можно назвать плохой практикой - я уверен что нету программистов, которым доставляло бы удовольствие сидеть на работе и высчитывать mro, чтобы понять как пофиксить очередной баг.
Основная польза от паттерна Command это то, что команды не возвращают значения, а значит их нельзя объединять в цепочки. В больших проектах это ограничение сильно бъет по рукам разработчикам, не позволяя создавать в коде лапшу из разных сценариев, что потом сильно упрощает поддержку. С другой стороны, описывать доменную логику в таком стиле я бы не советовал. Тут напротив будет удобнее чистые функции и функциональное программирование, позволяющее легко тестировать и комбинировать между собой отдельные элементы.
Основная польза от паттерна Command это то, что команды не возвращают значения, а значит их нельзя объединять в цепочки
С чего вы взяли? Достаточно пройти в гугл с запросом "command pattern return value", чтобы быстро убедиться что это не так. В любом случае, кто и как бы не давал определения паттернам, важно помнить что они не на скрижалях высечены, и адаптировать их для своих потребностей разработчики вольны как хотят.
Спасибо за полезную статью. Интересно узнать что думаете по поводу этого пакета? https://python-dependency-injector.ets-labs.org/examples/django.html#django-example
Пример организации моего приложения на fastapi используя данный пакет: https://github.com/aliev/aioauth-fastapi
Благодарю! Пакетов таких много, как я писал в статье. Даже у гугла есть свой. Отношение к подобному я выразил выше - подумайте, нужно ли вам строить свою бизнес-логику вокруг сторонней зависимости. Библиотеки не определяют бизнес-логику, это всего лишь инструменты, которые бизнес-логика должна использовать в своих целях. К инструментам должно быть отношение как к инструментам - их сотни, каждый год выходят все более красивые и эффективные. От них не нужно зависеть - устаревшие и малоэффективные надо выбрасывать, брать более стабильные и совершенные. Сможете ли вы с легкостью выкинуть вашу библиотеку, и поменять на новую, не тронув при этом бизнес-логику? Сомневаюсь. Сложно ли это будет сделать, если ваш проект будет разрабатывать команда, скажем, из человек 10-50, а не один вы? Да, наверное. Можете ли вы однажды упереться в ограничения заложенные автором бибилиотеки? Думаю да, особенно если ваш сервис станет действительно большим и многофункциональным. Сервисный слой, это прежде всего часть философии слоистой архитектуры, в центре которой лежит домен и его бизнес-логика, а внешние библиотеки это уже дело десятое.
Большое спасибо за статью, очень полезно. Вопрос от начинающего разработчика, вот есть несколько приложений, даже допустим с подобными сервисными слоями. Как правильно связывать приложения между собой, в каком-то отдельном месте или можно использовать методы сервисного слоя одного приложения в методах другого, но тогда увеличивается связность ?
Спасибо за статью, согласен полностью с вашим подходом.
Лет 5 назад подцепил на фрилансе халтурку - думал что разово, оказалось что надолго :( Клиент платил мало, поэтому стимула делать "качественно, но дольше" не было совсем - в итоге совершил почти все ошибки, описанные в статье (и еще немного).
Например, очень толстые view, наследующиеся от одного супер-мега класса. Когда, внезапно, оказалось, что некоторые отчеты надо выполнять еще и в фоне - пришлось в celery-тасках делать фейковый Request и передавать его в, специально вызываемую для этого, view. Выглядело это все ужасно, тестов, конечно же, не было.
Python service layer: основы оформления бизнес-логики на примере Django-приложений