[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: ActiveRecord в боевом применении.
Страницы: 1, 2, 3, 4, 5, 6
Oyeme
то что бросилось в глаза сразу.

promoution > promotion
Analitics > Analytics
viziters > visitors (visits)
last_vizit > last_visit
twin
Вот спасибо! Исправлено. smile.gif

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Продолжим.
А теперь ответ на второй вопрос - как сущности будут взимодействовать. Для этого нужно организовать связи. Это уже начало бизнес-логики.
Первый этап - что. Сейчас организованы те свойства, которые необходимы для хранения состояния (информации).
Второй - как. Для этого нужно прописать свойства со связями - своего рода ссылки на те объекты, от которых нужно получить информацию, либо кому может потребоваться информация.

Логика покупки товара очень проста.
1. Если посетитель выбрал твар и положил его в корзину, он переходит из статуса "посетитель" в статус "покупатель". Соответственно для него инициируется объект класса Buyer. Так, как на сайте не предусмотрена регистрация, идентификация покупателя будет производиться по уникальному кукису.
2. На выбранный товар создается объект заказа Order
3. Одновременно создается объект корзины. Это временный объект, имеет срок жизни. Служит для того, чтобы покупатель мог посмотреть и подредактировать заказ.
4. В заказе сохраняются текущее положение дел. Цена на момент покупки (она может измениться в товаре) и действующая на момент оформления акция.

Допустим покупатель выбрал товар и положил его в корзину. По сути - начал оформлять заказ. Соответственно должен появиться объект заказа, принадлежащий покупателю. Добавляем в класс Order атрибут buyer_id, что бы идентифицировать принадлежность. Заказ (Order) соответственно должен распологать информацией, что именно заказали. Делаем связь с товаром - помещаем в класс атрибут product_id. Еще нам нужно знать, действовала ли на момент оформления заказа какая-либо акция (promotion_id). Ну и последнее, проверяем, действует ли для текущего заказа корзина (basket_id).

У покупателя должна быть связь с корзиной. Если есть открытая, то выбираем заказы которые принадлежат ей. Соответственно классу Buyer нужна связь basket_id

Товар должен знать, какая акция действует на него в текущий момент. Значит делаем связь Product -> promotion_id

Для отчетности связи не нужны, это по сути логи.

Так что теперь сущности со связями будут такими:

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Я тут отсутствовал несколько дней, люблю путешествовать smile.gif

Так что ничего не закончилось, продолжим.

На прошлом этапе я определил сущности, которые будут участвовать в процессах. Другими славами - возможности храниь состояния.

Теперь самое интересное - процесс моделирования, сиречь проектирование поведений.

Вот тут, на мой взгляд, существует некоторая путаница, если не сказать больше - противоречие. В большинстве популярных фрймворках моделями принято называть отдельные классы. Но модель зачастую должна содержать внутри себя несколько объектов разных взимодействующих классов. Так что моделью будем считать всю предметную область, участвующую в каком то отдельном, но атомарном действии. Допустим моделируем процесс покупки товара.

Оперируя терминологией DDD, сначала нужно определить (ограничить) контексты. Тогда будет проще понимать, что с чем и как должно взаимодействовать.

При ознакомлении с ассортиментом товаров, важными составляющими являются сам покупатель, витрина (каталог) и товар. Можно представить себе это в виде одного контекста, где составляющие являются необходимыми и достаточными. Нельзя выбрать товар, если его нет. Некому это сделать, если нет покупателя. Покупатель и товар не встреятся в этой жизни, если их не свести друг с другом посредством витрины. Но они вполне могут обойтись на данном этапе без корзины, заказа и уж тем более отчетов.

С другой стороны, цена на продукт может (но не обязательно) зависеть от промоушена, а отчет по покупателям хочет знать, сколько и когда было посетителей. Так что тут нужно очень тщательно продумать контексты и их взаимодействия, чтобы не смешать все в кучу, и грамотно распределить ответственности по агрегатам.

Свернутый текст
То, что сейчас делается, делается не совсем верно. По хорошему так "мельчить" нельзя, по сути должно быть три контекста - магазин, администрирование и отчеты. Но это будет не совсем наглядно.


_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Ну а теперь попробуем спроектировать агрегаты.

Агрегат, это набор объектов, учавствующих в каком то определенном действии. Он может состоять из сущностей, объект-значений, служб (сервисов) и корня - объекта, объединяющего все это в одну систему, и предоставляющего интерфейс. Всё общение с агрегатом должно производиться через этот корень. У агрегата должен быть собственный идентификатор.

Если посмотреть внимательно на предыдущую схему, можно увидеть, что фактически там все уже разложено по агрегатам (контексты чудесным образом с ними совпали), нужно только обозначить внешние связи. Ну и службы убрать, они не должны хранить состояний, а значит к агрегатам не относятся. Хотя сами агрегаты могут в процессе своей работы использовать (агрегировать) сервисы.

Единственное, что пока не имеет корня - агрегат статистики. Добавим.

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Тут важно вот что. Агрегат не может просто ссылаться на другой объект, только на корень другого агрегата. Так что пришлось немного изменить связи. И хотя это нерационально, все должно быть по-врослому. smile.gif

Я намеренно не упминал ничего ни о конструкторах, ни о вьюшках, ни вообще о фреймворке. Хочется сделать доменную модель доменной моделью. Не покидая её пределов. smile.gif

Однако пора потихонку приступать и к кодингу. Сначала сделаю модели анемичными, все равно ничего работать наружу не будет. Потом добавл что нужно.

Свернутый текст
Если кому интересно повторить на практике, фреймворк здесь, вопросы по нему в личку.


_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
twin
Долго ждал замечаний от гуру, но видимо всё идеально делаю. :D Ну и ладно тогда.

Первые буковки кода. Каталог.

Класс Product пока совсем пустой, нужен только чтобы организовать доступ к СУБД, все же Active Record, не хухры мухры:
<?php 

namespace App\Models\Catalogue;

use ABC\Core\ActiveRecord\Model;

/**
* Catalogue
*
*/

class Product extends Model
{

}


Долго думал, как лучше сделать, решил, что нафиг не нужна дополнительная служба, можно напрямую заюзать сервис пагинатора. Структура странная получается, но вобщем то объяснимо.
<?php 

namespace App\Models\Catalogue;

use ABC\Core\ActiveRecord\Model;
use App\Models\Catalogue\Product;

/**
* Catalogue
*
*/

class Buyer extends Model
{

protected $pageMenu;

/**
* Получаем список продуктов в постраничном режиме
*
*
@return array
*/

public function getProduct()
{
$config = \ABC::getConfig('catalogue');
$pageNum = GET('num');

$paginator = \ABC::newService(\ABC::PAGINATOR);
$paginator->setNums($pageNum, $config['num_rows'], $config['num_collumns']);
$cnt = Product::countAll();
$lmt = $paginator->getLimit();
$ofs = $paginator->getOffset($cnt);
$this->pageMenu = $paginator->createMenu();

return Product::find()->asObject()
->
limit($lmt)
->
offset($ofs)
->
all();
}
}



Метод называется getProduct(), потому что такой синтаксис у AR, дабы задействовать магию. Получается, что покупатель взял продукт, хотя по сути он ничего не брал, а пока только смотрит. Но с другой стороны, чтобы посмотреть, нужно взять и вытащить на страницу. Я к такой логике не привык, может это всё неверно. Но с другой стороны, добавлять методов ради привычек... Или нужно, кто как считает?

Зато, с другой стороны, вызывается двумя строчками, и бизнес-логика вроде в модели, не где попало
        $buyer = Buyer::findById(1);
$products = $buyer->product;

Покупатель пока не идентифицируется, поэтому он один, с соответстующим случаю, ID.

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.