Грамотное ООП: организация надёжной бизнес-логики / Дмитрий Елисеев (ElisDN)
HTML-код
- Опубликовано: 16 июл 2020
- Приглашаем на конференцию Saint HighLoad++ 2024, которая пройдет 24 и 25 июня в Санкт-Петербурге!
Программа, подробности и билеты по ссылке: vk.cc/cuyIqx
--------
--------
Презентация и тезисы:
phprussia.ru/2019/abstracts/5114
Все мы читали про объектно-ориентированное программирование и проектирование абстрактных типов данных, но мало кто из нас использует их по назначению. И бизнес-логику проектировать и тестировать получается не у всех. Почему-то вместо красивого кода образуется переплетение вызовов, и загромождаются контроллеры.
Вместе мы научимся раскладывать весь этот код по местам. Потренируемся в объектно-ориентированной декомпозиции для грамотного проектирования сущностей по обязанностям. Научимся сочинять ко всему этому быстрые, удобные и надёжные юнит-тесты.
Как производить отделение UI от бизнес-логики, чтобы не было протечек слоёв в MVC. Научимся создавать агрегаты для сущностей предметной области для соблюдения инварианта. Какие проверки поместить в сущность, а какие - в сервисный слой. Как производить валидацию и использовать исключения.
--------
Нашли ошибку в видео? Пишите нам на support@ontico.ru
Наверно самая короткая лекция Дмитрия =)
Ага, но качество тоже что и всегда.
Ахахаха 🤣
Если кого не устраивает, Дмитрий может вернуть деньги)))
Пояснение: Это он так на своих занятиях говорил, когда по PHP показывал Pascal, а народ начал возмущаться))
Лучший доклад, что я видел, про архитектуру, огромное спасибо, Дмитрий!
Мне не оч нравится такая архитектура с Entity Manager. Если у меня сложный объект, у которого много полей one to many, то изменение одного простого поля повлечёт за собой сложные запросы в БД с сохранением всех остальных полей, включая запросы в другие таблицы для сохранения one to many полей.
При чтении лота из БД нужно заполнить поле isDraft, а в его коде это поле невозможно передать в конструктор. Как тогда создать объект для лота из существующего в БД?
Для команд с незначительными изменениями в полях лота будут скачиваться все его one to many поля, даже если они не будут использоваться.
Короче это какой-то хайп вокруг DDD, который требует использования entity manager. Убрать Entity Manager и добавить в классы с бизнес-логикой зависимость на Repository и будет норм
Hexagonal architecture посмотри, или clean architecture
@@MrAmmid нет ни какого хайпа, это стандарты из программной инженерии. Стандарт потому что многие про это знают и многие это используют. Соответственно когда приходишь на новое место работы, и если прошлый разработчик писал код по этим стандартам, то понять и сопровождать, такой код будет намного легче. А вот если прошлый разработчик писал код исходя из своих субъективных предпочтений, типа "нравится/не нравится", то вероятнее всего, такой код будет трудно понять новому разработчику, и соответственно сопровождать, так как он не знает субъективных предпочтений прошлого автора.
@@user-qx1jc9qv6h а где вы в докладе "стандарт" увидели ?
@@MrAmmid абсолютно верно, но как для джуна ты задаешь слишком много вопросов )) ты должен пускать слюни и восхищаться докладом
Наконец то доклад, в котором есть код. Практичный доклад
такая короткая лекция, что я думал тизер
Жаль что раздел с вопросами вырезали из видео
Грамотное ООП: организация надёжной бизнес-логики / Дмитрий Елисеев (ElisDN)
00:00 Введение
• Дмитрий Елисеев рассказывает о своем опыте программирования и о том, как он изучает лучшие практики и пытается привить их другим людям.
• Он также объясняет, что такое объектно-ориентированное программирование (ООП) и как оно отличается от классово-ориентированного программирования.
02:37 Контроллеры и фреймворки
• Дмитрий обсуждает, как контроллеры и фреймворки используются для разделения кода и его удобного распределения.
• Он также объясняет, как контроллеры могут быть использованы для обработки запросов и команд, а также для создания и сохранения пользователей.
06:22 Примеры кода
• Дмитрий приводит примеры кода, который может быть использован для создания контроллеров и обработки различных ситуаций.
• Он также обсуждает, как можно использовать контроллеры для обработки ошибок валидации и отправки писем с подтверждением регистрации.
09:09 Консольный режим
• Дмитрий объясняет, что консольный режим может быть использован для выполнения административных задач, таких как активация пользователей или выполнение других действий.
• Он также подчеркивает, что консольный режим использует другие стандартные переменные и файл, который отличается от файла, используемого в приложении.
10:09 Создание консольных команд
• В видео обсуждается создание консольных команд в Symfony, которые могут быть использованы для выполнения различных задач.
• В примере создается команда для регистрации пользователя, которая принимает импут и опыт и запускает код для выполнения задачи.
11:09 Использование очередей и микросервисов
• Помимо консольных команд, в Symfony также можно использовать очереди и микросервисы для выполнения задач.
• В этом случае, команды или микросервисы могут быть вызваны из очереди, и их выполнение будет контролироваться специальным классом, который будет обрабатывать запросы и отправлять их на выполнение.
12:09 Создание общего класса для обработки команд
• Для удобства, можно создать общий класс, который будет обрабатывать все команды, и вызывать его из разных контроллеров.
• Этот класс будет принимать зависимости, такие как репозитории, хешер пароля, токенизатор и отправитель, и выполнять необходимые действия.
15:09 Обработка ошибок и логирование
• В случае возникновения ошибок, можно использовать специальный класс для обработки ошибок и логирования.
• Это позволит упростить код и избежать дублирования кода в разных контроллерах.
16:24 Структура кода и фреймворки
• В видео обсуждается структура кода и фреймворки для работы с веб-приложениями.
• Упоминается, что каждый сервер может иметь свой собственный фреймворк, что позволяет выбирать между различными вариантами.
18:12 Взаимодействие с пользователем и контроллеры
• В видео объясняется, что контроллеры взаимодействуют с пользователем, обрабатывают запросы, принимают и отправляют ответы, а также рендеринг.
• Обсуждается, что контроллеры могут содержать только пи-код или консольный код, а также взаимодействие с сущностями и юзерами.
23:12 Логика и сущности
• В видео говорится о том, что логика из контроллеров должна быть вынесена в юс-кейсы, чтобы избежать путаницы и обеспечить разделение обязанностей.
• Обсуждается использование инкапсуляции и принципов ООП для улучшения кода.
25:12 Создание сущностей и использование конструкторов
• В видео демонстрируется создание сущностей с использованием конструкторов и фабрик для создания объектов.
• Обсуждаются преимущества использования конструкторов для создания объектов и их использования в объектно-ориентированном мире.
27:59 Создание конструктора для лота аукциона
• Обсуждение использования простых активных записей вместо сложных конструкторов для упрощения работы с данными.
• Создание конструктора для лота аукциона, который принимает параметры и проверяет их на корректность.
30:59 Тестирование конструктора лота аукциона
• Создание тестов для проверки корректности работы конструктора лота аукциона.
• Тестирование работы конструктора с различными параметрами и проверка на ошибки.
34:54 Создание методов для работы с лотом аукциона
• Создание методов для редактирования контента и цены лота аукциона.
• Разделение методов на простые и сложные в зависимости от их функциональности.
38:47 Создание статического метода для создания лота аукциона
• Создание статического метода для создания лота аукциона, который упрощает процесс создания и тестирования.
• Проверка корректности работы статического метода и его взаимодействия с другими методами.
39:47 Создание иммутабельных методов в билдере
• В докладе обсуждается создание иммутабельных методов в билдере, которые позволяют передавать контент без его изменения.
• Методы проверяют, что контент является черновиком, и если это не так, то выбрасывают исключение.
43:34 Реализация иммутабельных методов в доктрине
• В докладе объясняется, как реализовать иммутабельные методы в доктрине, используя аннотации и типы.
• Упоминается, что доктрина автоматически создает вложенные объекты и связи между ними.
45:34 Создание вложенных объектов и связей
• В докладе обсуждаются способы создания вложенных объектов и связей между ними, включая использование аннотаций и типов.
• Упоминается, что доктрина автоматически обрабатывает вложенные объекты и связи, сохраняя их вместе.
2:02 а инстанс не прямая реализация объекта со свойствами, состояниями и т.д.?
Моя база
Я не совсем понимаю. Метод build LotBuilder принимает некий Member $member, который не видно чтоб использовался. И в тестах потом вызывается просто ->build().
Дмитрий, большое спасибо за доклад! Очень было интересно. Хорошо, что там у ставки три состояния, еще можно как то в методах ифами поведение разрулить. Но что будет, если это сущность "заказ" с 5-ю (условно) состояниями, с таким подходом будет сложно в каждом методе ставить ифы по состоянию + еще может состояние появиться и придется в каждом методе еще и его учитывать. Очень интересно познакомиться с Вашим виденьем по реализации "паттерна State с Doctine2" и Доменных событий. Спасибо!
Да, можно замутить State и сделать для него StateType.
Спасибо, Дмитрий!
Спасибо за доклад. Все как всегда на высшем уровне.
Спасибо за труд!
35:47 isDraft почему бы не сделать его тру фалс вместо двух методов isActive. Что я пропустил?
на этом моменте выключил 🤝
15:50 а что собственно мешает вызов команды в индексе убрать в try catch и выводить нормально отренжеренную красивую 500 ?
46:30 Эванс и другие эту пачку)) называют агрегатом.
Получается, Дмитрий! Спасибо за то, что Вы делаете!
32:40 однотипные тесты даже копипастить не нужно, красивее сделать параметрические тесты
Крутая лекция!
47:30 Цыклические ссылки делать не обязательно. Ребята из Doctrine даже сами говорили не создавать циклические ссылки без необходимости.
14:30 Зачем флашер? Почему бы сохранение в репозитории не реализовать. типо repositoy->save($user) или update, и абстрагироваться от Doctrine
Абстракция транзакции
Или можно делать флюч по ивентам. onTerminate и т.д.
@@wcode404 , не знал о таком подходе.
Это удобно когда ты работаешь с одним объектом. А как быть если тебе нужно работать с большим объёмом лотов например. Каждый лот как объект и в нем мелкие объекты из которого состоит лот. Это увеличивает объем данных в памяти. Например если нужно обработать 50-60 тыс.
Даже если использовать массив, то хранить в памяти десятки тысяч элементов так себе идея. Нужно дробить на чанки. А вообще да, ради оптимизации часто приходиться жертвовать красотой кода.
lazyload для внутренних объектов и возвращать генератор из em/репозитория
48:00 Вместо сурогатного ключа + уникального индекса, я обычно делаю составной праймери ключ из lot_id и member_id
Связь winnerBid тогда будет сделать трудно. А так да, можно двум связям проставить @Id.
Дмитрий как всегда крут
Фрейморки кроме котролеров и роутинга , предоставляют еще кучу функционала , различные ORM ,хелперы, валидаторы итд. Думаю для +95% проектов неоправдано изолировать слой бизнес логики от фремворка .
Кроме того, в большинстве случаев трудозатраты не окупаются. Например ORM накладывает свои ограничения на модели (даже Doctrine) и попытка отделить модели от ORM сделает использование ORM бессмысленным, а код persistent слоя монструозным.
В большинстве случаев трудозатраты окупаются. Если вы посмотрите в других языках можно использовать ORM и настроить автоматический мапинг на конвенциях(которые в случае чего можно настроить), с минимальными ограничениями на модели(иногда и вовсе без ограничений). В коде нужно сказать только "дай мне агрегат класса X", и все, а в мидлваре перед завершением запроса написать что-то вроде "если что-то изменилось сохрани". Кроме этого кода, кода использующего ORM в проекте вообще не будет, разве что мапинги в трудных местах ручками написать, но таких мест парочка на проект в 1кк LOC. А вот эти все "фреймворки дают много фишек" это булщит который не нужен в 95% проектах не на уровне инфраструктуры, а пихать их всюду, так во фронтенд идите, там такой код выкидывают каждый день тоннами. А потом возникают вопросы что дешевле найти разработчика который поправит одно поле в форме на каком нибудь мертвом фреймворке и на лайвскрипте или переписать на реакт =)
очень много туфты в докладе - наброс для джуна(не более). Вывод вообще ппц - типа спрятали изменения состояний в методах-командах ))) но состояния сами себя не меняют, поэтому в любом случае нужно будет реализовать не публичные методы для работы с состояниями. А обращение к паттерну Информационный эксперт это "грамотное ООП" ? ой блин не хочется токсичить , но ребят , берите информацию из разных источников и думайте своей головой. А за доклад спасибо - он и нужен чтобы его обсуждать, спорить и расти дальше.
по фотке сразу видно, программист
Первая половина - вообще банальщина
Пока что смотрю только начало и слегка недоумеваю, как можно совать логику в контроллеры? Если далее автор доклада перевернет все так, что все это не там, а в доменных моделях нужно делать, то все ок, в ином случае будет минимум странно.
Далее уже смешались люди и кони. Инфраструктура и домены в одной слое. Мда. Пока что человек создает впечатление начинающего миддла. Посмотрим что дальше. Может дальше уже вывернет таким образом, мол, не так должно быть.
помоему Дима говорит о Laravel без уважения !
А с чего должно быть уважение? Когда Laravel не поощряет такого стиля написания, там связь Controller и Model и все можно вызывать где угодно
Laravel - редкостная гадость: магические методы, куча наследования, трейты без интерфесов, фасады и т.д.
@@c3tv3r -_-
потому он адепт божественного yii
@@c3tv3r "Laravel - редкостная гадость: магические методы, куча наследования, трейты без интерфесов, фасады и т.д."
)) привет Дима!
Супер конечно нудный чел. Больше позвать некого?
на скорости 2 норм смотреть