![]() |
|
Модераторы: skyboy, MoLeX, Aliance, ksnk |
![]()
|
|
| BuShaRt |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1391 Регистрация: 29.6.2006 Репутация: 4 Всего: 6 |
На работе пробуем начать программировать на правильном ООП (использовать SOLID и т.п.). Возникают вопросы. Вот один из них.
У нас есть класс User (мы называем такие классы Entity - он описывает все элементарные свойства объекта + имеет набор сеттеров и геттеров + какие-то методы, производяшие подсчеты, на которые влияют только данные уже имеющиеся в объекте). Вообще мы используем Doctrine 2, если кто работал с ней, тем будет сразу ясно о чем речь. Примерно так User - id - name + getId + setName + getName + getStamp { retuen name + id } А теперь у нас есть задача, получить набор статусов этого пользователя, но для подсчетов используется сложная логика, затрагивающая несолько таблиц в БД и соотвественно несолько объектов (для нагялдности представим, что эта логика состоит из лапши из циклов и SQL-запросов). Если мы поместим эту логику в наш класс User, то мы автоматически нарушим принцип SOLID, как минимум тем, что этот объект сам по себе не может обращаться к базе, что говорить о том, что он станет в курсе того какие еще объекты есть в системе. Конечно в голову приходят варианты решения задачи, на пример следующие: - Сделать отдельные объекты - процессоры, которые будет на входе получать объект user, а на выходе отдавать значение одного из статусов. - Сделать объект SuperUser, который принимает на входе объект User и при инициализации производит все необходимые подсчеты (хотя, мне кажется тут тоже нарушается принцип SOLID) - Еще такая идея пришла, пока писал пост. Каким нибудь образом добавить необходимые статусы в класс User, но поместить в них не значения, а объекты типа процессоров описанных в первом пункте (наверно в данном контексте это будет похоже на паттерн прокси). Вот... Расскажите, как вы поступаете в таких ситуациях? |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
на это можно взглянуть иначе: мы имеем не запрос, а функцию, возвращающую значение. не вникая в подробности реализации можно её просто использовать. Нужно ответить на вопрос: чем является информация (в БД), на основе которой считаются статусы, по отношению к пользователю. Тогда станет понятно а) это свойство пользователя или операция над ним б) как лучше абстрагировать слой БД, что бы User или функция расчета оперировали терминами задачи, а не таблицами ЗЫ. Отвлеченный вопрос. Предполагается, что юзер может быть переименован (я про setName)? Добавлено через 1 минуту и 36 секунд Прежде поиска технических решений надо с концепцией определиться |
|||
|
||||
| BuShaRt |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1391 Регистрация: 29.6.2006 Репутация: 4 Всего: 6 |
А можно я приведу более подробное описание, а вы ответите сами на эти вопросы? Просто я не уверен, что точно их понял, а на вашем примере мне будет проще сооринтироваться. Имеем следующие статусы 1. Стутус частоты заказов. 1.1 = 2, если пользователь за последние 14 дней заказывал не менее двух товаров в день как минимум 10 раз (дней) 1.2 = 1, если пользователь за последние 14 дней заказывал не менее одного товара в день как минимум 5 раз (дней) 1.3 = 0 во всех други случаях 2. Статус прогресса заказов 1.1 = 2, если пользователь за последние 5 дней заказал больше, чем за предыдушие 5 дней 1.2 = 1, если пользователь за последние 5 дней заказал товара меньше, чем за предыдушие 5 дней, но не более чем на 20% (меньше) 1.3 = 0 во всех других случаях
Это просто пример. Реально у нас есть поле identity, которое нельзя менять, а name менять можно т.к. он информационное. Это сообщение отредактировал(а) BuShaRt - 20.9.2013, 12:19 |
||||
|
|||||
| georgiy11 |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 29.9.2008 Репутация: нет Всего: нет |
Здесь не проблема в чистом или не чистом ООП. Проблема в том как модель User будет себя позиционировать в системе: включать бизнес логику (AR) и это как раз определение выше сказанных условий или будет обычным шлюзом к таблице в БД.
Обычно, если бизнес логика не велика (то есть при добавлении модель не будет раздута до небес), это вмещается и в AR, например я бы сделал так (это очень удобно) 1. Стутус частоты заказов. 1.1 = 2, если пользователь за последние 14 дней заказывал не менее двух товаров в день как минимум 10 раз (дней) $user->isOrderedLeastTwoItems($period = 14, $countOrders = 10); 1.2 = 1, если пользователь за последние 14 дней заказывал не менее одного товара в день как минимум 5 раз (дней) $user->isOrderedLeastOneItems($period = 14, $countOrders = 5); 1.3 = 0 во всех други случаях Что дают такие методы: избавляемся от статусов и инкапсулируем бизнес логику в методах (бизнес логика имеет структуру но настраиваема, хотя лучше конечно полностью инкапсулировать) Тфжёлое в этом подобрать имена методам |
|||
|
||||
| BuShaRt |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1391 Регистрация: 29.6.2006 Репутация: 4 Всего: 6 |
georgiy11, Я Вас чуть-чуть обманул. Я только сейчас узнал, что в Doctrine 1 использовался AR-паттерн, а в Doctrine 2 используется Data Mapper. Я написал, что мы работаем с Doctrine, но не уточнил с какой именно, видимо этим введя вас в заблуждение. Так вот мы работаем с Doctrine 2 и наши объекты не являються не AR, не шлюзами - они являются просто объектами, без бизнес логики, манипалирование которыми берет на себя Data Mapper. Но Data Mapper умеет манипулировать только элементарными данными этих объектов + явно выраженными связями. Т.е. он может заполнить объекты проксями к другим объектам или самими данным, но вот производить вычисление на базе данных он не умеет, да и не должен уметь судя по тому, как я понял его концепцию.
Это сообщение отредактировал(а) BuShaRt - 20.9.2013, 14:05 |
|||
|
||||
| georgiy11 |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 29.9.2008 Репутация: нет Всего: нет |
Тогда это прослойка из стратегий, хорошо вписывается в архитектуру. Стратегии могут и должны содержать бизнес логику, и могут оперировать множеством сущностей.
То есть, фактически, стратегия будет инкапсулировать какой то объём бизнес логики с различными мапперами и их связями. Ещё более чистый ООП, подразумеваем инкапсулирование мапперов в сущностях Entites и соответственно связи производится будут между entity<->entity, в которых инкапсулированы данные от мапперов. Но мне кажется это слишком не нужный подход. Решение стратегий довольно гибкое для средних проектов (имею ввиду с более менее сложной бизнес логикой). Где отлично работает архитектура с сущностями и в них маппер, так это высоконагруженная бизнес-логика например игра браузерная. Это лично моё мнение |
|||
|
||||
| baldina |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
BuShaRt, значит имеем три связанные сущности - пользователь (User), его заказы (Orders) и его статусы (Status).
Класс Orders умеет получать информацию о заказах конкретного пользователя (посредством обращения к хранилищу - БД) Класс Status умеет рассчитывать значение статуса на основании определенной статистики (заказов) Класс User пользуется и тем и другим, связывая их и предоставляя интерфейс доступа к значению статусов. Итого примерно такая схемка (вместо классов с одной функцией для краткости использую функции):
где функции статуса могут быть например такие
Добавлено через 7 минут и 35 секунд ужос)))) Это сообщение отредактировал(а) baldina - 20.9.2013, 17:13 |
||||
|
|||||
| georgiy11 |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 29.9.2008 Репутация: нет Всего: нет |
http://design-pattern.ru/patterns/data-mapper.html В чём то есть правильность подхода. Кстати, а можно ли наследовать маппер и делать дочерний класс AR. |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
как техническое решение - да, есть такое. есть и множество других. только ООП тут непричем ООП это подход, его то и не хватает, а вы углубляетесь в частности не определив общее решение. Добавлено через 10 минут и 39 секунд BuShaRt, у вас уже были хорошие решения - 1 и 3 из первого поста. Какое выбрать зависит от вкусовых пристрастий и необходимости дальнейшего расширения проекта. 1й простой и расширяемый, но требует часть концепции в голове держать. 3й это модный DI (при злоупотреблении вносящий больше путаницы чем пользы). Идите по пути ослабления связей между классами, это всегда оставляет возможность для изменений без переписывания всего. |
|||
|
||||
| georgiy11 |
|
||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 92 Регистрация: 29.9.2008 Репутация: нет Всего: нет |
[B]baldina[/B
Есть решение принять функциональный подход к задаче Есть решение ООП подход, Есть решение совмешённый ООАП, ООП, функциональный, процедурный ....
Сори, датамапер ни к какой парадигме не подойдёт как к ООП, если ВЫ конечно не оспорите
Вкусовые пристрастия .... ну ну .... Это сообщение отредактировал(а) georgiy11 - 22.9.2013, 01:23 |
||||||
|
|||||||
| baldina |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 26 Всего: 101 |
вы заблуждаетесь. точнее, если вы так смотрите на ООП, то многое теряете, практически ничего не приобретая. ООП - парадигма, подход, методология.
писать так
или вам известен Единственно Верный Путь? |
||||||
|
|||||||
![]()
|
| Правила форума "PHP" | |
|
|
Новичкам:
Важно:
Внимание:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | PHP: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |