Грамотное ООП: организация надёжной бизнес-логики / Дмитрий Елисеев (ElisDN)
ฝัง
- เผยแพร่เมื่อ 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 абсолютно верно, но как для джуна ты задаешь слишком много вопросов )) ты должен пускать слюни и восхищаться докладом
Наконец то доклад, в котором есть код. Практичный доклад
такая короткая лекция, что я думал тизер
Жаль что раздел с вопросами вырезали из видео
Моя база
Спасибо за доклад. Все как всегда на высшем уровне.
Спасибо, Дмитрий!
Я не совсем понимаю. Метод build LotBuilder принимает некий Member $member, который не видно чтоб использовался. И в тестах потом вызывается просто ->build().
32:40 однотипные тесты даже копипастить не нужно, красивее сделать параметрические тесты
Дмитрий, большое спасибо за доклад! Очень было интересно. Хорошо, что там у ставки три состояния, еще можно как то в методах ифами поведение разрулить. Но что будет, если это сущность "заказ" с 5-ю (условно) состояниями, с таким подходом будет сложно в каждом методе ставить ифы по состоянию + еще может состояние появиться и придется в каждом методе еще и его учитывать. Очень интересно познакомиться с Вашим виденьем по реализации "паттерна State с Doctine2" и Доменных событий. Спасибо!
Да, можно замутить State и сделать для него StateType.
Спасибо за труд!
Крутая лекция!
47:30 Цыклические ссылки делать не обязательно. Ребята из Doctrine даже сами говорили не создавать циклические ссылки без необходимости.
Получается, Дмитрий! Спасибо за то, что Вы делаете!
46:30 Эванс и другие эту пачку)) называют агрегатом.
35:47 isDraft почему бы не сделать его тру фалс вместо двух методов isActive. Что я пропустил?
на этом моменте выключил 🤝
Это удобно когда ты работаешь с одним объектом. А как быть если тебе нужно работать с большим объёмом лотов например. Каждый лот как объект и в нем мелкие объекты из которого состоит лот. Это увеличивает объем данных в памяти. Например если нужно обработать 50-60 тыс.
Даже если использовать массив, то хранить в памяти десятки тысяч элементов так себе идея. Нужно дробить на чанки. А вообще да, ради оптимизации часто приходиться жертвовать красотой кода.
lazyload для внутренних объектов и возвращать генератор из em/репозитория
15:50 а что собственно мешает вызов команды в индексе убрать в try catch и выводить нормально отренжеренную красивую 500 ?
2:02 а инстанс не прямая реализация объекта со свойствами, состояниями и т.д.?
48:00 Вместо сурогатного ключа + уникального индекса, я обычно делаю составной праймери ключ из lot_id и member_id
Связь winnerBid тогда будет сделать трудно. А так да, можно двум связям проставить @Id.
14:30 Зачем флашер? Почему бы сохранение в репозитории не реализовать. типо repositoy->save($user) или update, и абстрагироваться от Doctrine
Абстракция транзакции
Или можно делать флюч по ивентам. onTerminate и т.д.
@@wcode404 , не знал о таком подходе.
Грамотное ООП: организация надёжной бизнес-логики / Дмитрий Елисеев (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 Создание вложенных объектов и связей
• В докладе обсуждаются способы создания вложенных объектов и связей между ними, включая использование аннотаций и типов.
• Упоминается, что доктрина автоматически обрабатывает вложенные объекты и связи, сохраняя их вместе.
Дмитрий как всегда крут
Фрейморки кроме котролеров и роутинга , предоставляют еще кучу функционала , различные ORM ,хелперы, валидаторы итд. Думаю для +95% проектов неоправдано изолировать слой бизнес логики от фремворка .
Кроме того, в большинстве случаев трудозатраты не окупаются. Например ORM накладывает свои ограничения на модели (даже Doctrine) и попытка отделить модели от ORM сделает использование ORM бессмысленным, а код persistent слоя монструозным.
В большинстве случаев трудозатраты окупаются. Если вы посмотрите в других языках можно использовать ORM и настроить автоматический мапинг на конвенциях(которые в случае чего можно настроить), с минимальными ограничениями на модели(иногда и вовсе без ограничений). В коде нужно сказать только "дай мне агрегат класса X", и все, а в мидлваре перед завершением запроса написать что-то вроде "если что-то изменилось сохрани". Кроме этого кода, кода использующего ORM в проекте вообще не будет, разве что мапинги в трудных местах ручками написать, но таких мест парочка на проект в 1кк LOC. А вот эти все "фреймворки дают много фишек" это булщит который не нужен в 95% проектах не на уровне инфраструктуры, а пихать их всюду, так во фронтенд идите, там такой код выкидывают каждый день тоннами. А потом возникают вопросы что дешевле найти разработчика который поправит одно поле в форме на каком нибудь мертвом фреймворке и на лайвскрипте или переписать на реакт =)
Первая половина - вообще банальщина
по фотке сразу видно, программист
очень много туфты в докладе - наброс для джуна(не более). Вывод вообще ппц - типа спрятали изменения состояний в методах-командах ))) но состояния сами себя не меняют, поэтому в любом случае нужно будет реализовать не публичные методы для работы с состояниями. А обращение к паттерну Информационный эксперт это "грамотное ООП" ? ой блин не хочется токсичить , но ребят , берите информацию из разных источников и думайте своей головой. А за доклад спасибо - он и нужен чтобы его обсуждать, спорить и расти дальше.
помоему Дима говорит о Laravel без уважения !
А с чего должно быть уважение? Когда Laravel не поощряет такого стиля написания, там связь Controller и Model и все можно вызывать где угодно
Laravel - редкостная гадость: магические методы, куча наследования, трейты без интерфесов, фасады и т.д.
@@c3tv3r -_-
потому он адепт божественного yii
@@c3tv3r "Laravel - редкостная гадость: магические методы, куча наследования, трейты без интерфесов, фасады и т.д."
)) привет Дима!
Пока что смотрю только начало и слегка недоумеваю, как можно совать логику в контроллеры? Если далее автор доклада перевернет все так, что все это не там, а в доменных моделях нужно делать, то все ок, в ином случае будет минимум странно.
Далее уже смешались люди и кони. Инфраструктура и домены в одной слое. Мда. Пока что человек создает впечатление начинающего миддла. Посмотрим что дальше. Может дальше уже вывернет таким образом, мол, не так должно быть.
Супер конечно нудный чел. Больше позвать некого?
на скорости 2 норм смотреть