Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Обсуждаем, как правильно строить приложения
Ответить
Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

STI не подразумевает смены типа(состояния) из одного в другой?
по примеру

если я уберу из beforeSave
$this->type = self::TYPE;
и создам метод

Код: Выделить всё

public function goNext() 
{
    $this->type = self::NEXT_TYPE;
}
Это будет уже не STI?

Ну а по шаблону State, как мне фиксировать смену состояния в бд?
По примеру из википедии(первый пример php5)
Если у меня состояние Client хранится в базе в поле type, как сохранять и восстанавливать состояние?

Аватара пользователя
samdark
Администратор
Сообщения: 9262
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение samdark »

Тип — это не состояние. Состояние — это status. Вообще не очень понятно, решения какой проблемы вы хотите добиться при помощи данного паттерна и при чём тут база данных...

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

samdark писал(а):
2017.03.23, 00:13
Тип — это не состояние. Состояние — это status. Вообще не очень понятно, решения какой проблемы вы хотите добиться при помощи данного паттерна и при чём тут база данных...
Есть товары. Есть категории товаров(новый, оформление, подготовка, продано и т.п.). Категории в строгой последовательности, перепрыгивать через одно нельзя. Во время перехода из одной категории в другую проверяются различные условия(свое отдельное условие для каждой категории). Категорий может быть где то штук 15.
Вот я и пытался рассматривать категории, как состояния товаров. Но я не могу понять как сохранять и восстанавливать из базы определенное состояние.

Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Ale}{ »

Krash писал(а):
2017.03.23, 05:07
samdark писал(а):
2017.03.23, 00:13
Тип — это не состояние. Состояние — это status. Вообще не очень понятно, решения какой проблемы вы хотите добиться при помощи данного паттерна и при чём тут база данных...
Есть товары. Есть категории товаров(новый, оформление, подготовка, продано и т.п.). Категории в строгой последовательности, перепрыгивать через одно нельзя. Во время перехода из одной категории в другую проверяются различные условия(свое отдельное условие для каждой категории). Категорий может быть где то штук 15.
Вот я и пытался рассматривать категории, как состояния товаров. Но я не могу понять как сохранять и восстанавливать из базы определенное состояние.
А вы точно про категории товаров говорите? у вас производство?
Просто все это похоже на статусы заказов

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

Ale}{ писал(а):
2017.03.23, 05:51
А вы точно про категории товаров говорите? у вас производство?
Просто все это похоже на статусы заказов
Ну да, возможно, я не совсем удачно слова подбираю.

Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Ale}{ »

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

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

Вот так правильно?

Код: Выделить всё

<?php

use yii\db\ActiveRecord;

class Order extends ActiveRecord
{
    const STATE_A = 1;
    const STATE_B = 2;
    const STATE_C = 3;

    public function rules()
    {
        return [
        	...
            [['state'], 'integer'],
            	...
        ];
    }

    /**
     * @inheritdoc
     */
    public function afterFind()
    {
        switch ($this->state) {
            case self::STATE_A:
                $this->state = new StateA($this);
                break;
            case self::STATE_B:
                $this->state = new StateB($this);
                break;
            case self::STATE_C:
                $this->state = new StateC($this);
                break;
        }
        parent::afterFind();
    }
    
    public function setState(AState $state)
    {
        if ($state instanceof StateA) {
            $this->state = self::STATE_A;
        } elseif ($state instanceof StateB) {
            $this->state = self::STATE_B;
        } elseif ($state instanceof StateC) {
            $this->state = self::STATE_C;
        }
        $this->save();
    }
    ...
}

Код: Выделить всё

abstract class AState 
{
    /**
     * @var Order храним ссылку на контекст для удобного переключения состояний
     */
    protected $context;

    public function __construct($context)
    {
        $this->context = $context;
    }

    /**
     * Переход в предыдущее состояние.
     */
    public function movePrev()
    {
        throw new \Exception('Реализуем в наследниках');
    }
    /**
     * Переход в следующее состояние.
     */
    public function moveNext()
    {
        throw new \Exception('Реализуем в наследниках');
    }

    public function setState(AState $state)
    {
        $this->context->setState($state);
    }
}

Код: Выделить всё

class StateA extends AState
{
    public function movePrev()
    {
        throw new \Exception('Запрещено!');
    }
    public function moveNext()
    {
        $this->setState(new StateB($this->context));
    }
}

Код: Выделить всё

class StateB extends AState
{
    public function movePrev()
    {
        $this->setState(new StateA($this->context));
    }
    public function moveNext()
    {
        $this->setState(new StateC($this->context));
    }
}

Код: Выделить всё

class StateC extends AState
{
    public function movePrev()
    {
        $this->setState(new StateB($this->context));
    }
    public function moveNext()
    {
        throw new \Exception('Запрещено!');
    }
}
Последний раз редактировалось Krash 2017.03.23, 14:55, всего редактировалось 3 раза.

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

Вместо этого
Krash писал(а):
2017.03.23, 08:57

Код: Выделить всё

   
    public function setState(AState $state)
    {
        if ($state instanceof StateA) {
            $this->state = self::STATE_A;
        } elseif ($state instanceof StateB) {
            $this->state = self::STATE_B;
        } elseif ($state instanceof StateC) {
            $this->state = self::STATE_C;
        }
        $this->save();
    }

Это:

Код: Выделить всё

public function setState(AState $state)
    {
           $this->state = $state;
    }
    
public function beforeSave($insert)
    {
        if ($this->state instanceof StateA) {
            $this->state = self::STATE_A;
        } elseif ($this->state instanceof StateB) {
            $this->state = self::STATE_B;
        } elseif ($this->state instanceof StateC) {
            $this->state = self::STATE_C;
        }
        parent::beforeSave($insert);
    }
Последний раз редактировалось Krash 2017.03.23, 14:50, всего редактировалось 2 раза.

Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Ale}{ »

Посмотрел бегло код (за сам код ничего не говорю - сам начинаю приходить к тому, что необходимо учиться DDD, SOLID. Пока сам пишу на AR но вот хочу отвязаться от них).
Сразу вопрос в ЛОБ - сейчас у вас 3 Состояния (или статуса все-таки?) - и каждый описан в отдельном классе - а что будет если их станет 10, 15?
Переход в другое состояние - это вообще что - просто смена одного поля - или что-то еще?
Вот пример - Есть документ -Заказ клиента. - у него есть статусы: На согласовании, К выполнению, В заказе, Поступил в магазин, К отгрузке.

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

То есть по сути можно сказать -что статус - это стадия, на которой находиться объект. И на каждой стадии меняется ответственное лицо которое производит необходимые действия и меняет статус - получается конвейер.

У вас такая ситуация?

Если совсем просто - то пример из 1C. Объект -Документ- имеет метод -провести. Так вот в конце. если все проводки (а их может быть очень много) прошли успешно- документ имеет статус "Проведен".

Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Ale}{ »

Krash писал(а):
2017.03.22, 21:31
STI не подразумевает смены типа(состояния) из одного в другой?
по примеру

если я уберу из beforeSave
$this->type = self::TYPE;
и создам метод

Код: Выделить всё

public function goNext() 
{
    $this->type = self::NEXT_TYPE;
}
Это будет уже не STI?

Ну а по шаблону State, как мне фиксировать смену состояния в бд?
По примеру из википедии(первый пример php5)
Если у меня состояние Client хранится в базе в поле type, как сохранять и восстанавливать состояние?
по примеру- это вообще из другой оперы.
Это реализация наследования ООП в РСУБД- и кстати не единственный способ.

К примеру - имеем номенклатуру- у всех есть атрибуты:id, наименование.
И есть виды номенклатуры - автозапчасти(добавляем как минимум Производитель, артикл), Круглый лес(добавляем в атрибуты как минимум Порода, длина, диаметр, сорт).

Но все объекты у вас будут лежать в одной таблице.

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

Ale}{ писал(а):
2017.03.23, 09:44
Сразу вопрос в ЛОБ - сейчас у вас 3 Состояния (или статуса все-таки?) - и каждый описан в отдельном классе - а что будет если их станет 10, 15?
их и есть 15 штук примерно.
Переход в другое состояние - это вообще что - просто смена одного поля - или что-то еще?
Что то еще. Для каждого состояния своя собственная проверка на возможность перейти на след. состояние. Плюс поведение самих состояний может отличаться
Так вот логика такая - само действие Смена статуса - может быть какое угодно в том плане. что На согласовании-> К выполнению->К отгрузке (товар есть на складе). ТО есть мы перепрыгнули - и это нормально.
А вот при выполнения какого либо действия с заказом - как раз и проверятся статус . К примеру - Мы не можем создать заказы поставщикам на основании заказ клиента, если он находится в статусе На согласовании. А вот сама смена статуса На согласовании->К выполнению -и дает основание менеджеру по закупу приступить к обработке заказа и сделать заказ(ы) поставщику(ам).
Да, примерно то. Действия с заказом зависят от статуса(состояния).
То есть по сути можно сказать -что статус - это стадия, на которой находиться объект. И на каждой стадии меняется ответственное лицо которое производит необходимые действия и меняет статус - получается конвейер
конвейер - это паттерн Chain of Responsibility?
У меня статусы могут менять не только в одном направлении. Заказ может вернуться и назад. Например, по вашим стадиям, заказ на стадии "К выполнению", но мы вспомнили, что нужно согласовать еще что то(забыли) - и возвращаем назад, делаем что надо и двигаемся дальше.

Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Ale}{ »

конвейер - это паттерн Chain of Responsibility?

Забудьте пока про паттерны. Вам нада для начала языке бизнеса поставить задачу с описанием всех возможных нюансов. На сколько я понимаю DDD - начинать нада с определения предметной области, обозначить ее границы, ввести понятия и определения - чтоб понимал Заказчик и ВЫ (чтоб забор был забором а не штакетником лежащим на земле в кучке). И все это необходимо определить в рамках вашего проекта. А судя по вашему вопросу - вы и сами не совсем понимаете или не можете изложить то что вам нужно (хорошо если я ошибаюсь).

Исходя из вышесказанного я делаю вывод - что первичны действия над объектом и если они прошли успешно - то меняется статус. При этом перед выполнением действия делаем проверку статуса а также дополнительные проверки. К примеру у Заказа стоит статус к отгрузке (на языке бизнеса это значит что для отгрузки нет преград). Но вот начали создавать отгрузку - все равно проверяем наличие на складах доступных остатков (это не совсем реальные остатки - учитывают резервы по другим заказам) .

Вопрос в том куда писать действия - это методы объекта - или отдельные классы (1 действие -1 Класс) И здесь я вам не совсем помощник - так как у себя делал реализацию - и все делал по аналогии с 1С -методы в объекте. Но сейчас смотрю на форуме что используют Сервисы - и сам не до конца понимаю, какой метод оставить в объекте а какой выносить и почему? какие критерии есть для выбора правильного (в том смысле чтоб можно было вести поддержку кода) пути... Сам хочу посмотреть что на это ответят.

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

Ale}{ писал(а):
2017.03.23, 10:50
Забудьте пока про паттерны. На сколько я понимаю DDD - начинать нада с определения предметной области, обозначить ее границы, ввести понятия и определения
DDD тут ни при чем.

Из книги "Приемы объекто-ориентривонного программирования. Паттерны проектирования." :

Применимость:
  • когда поведение объекта зависит от его состояния и должно изменяться во
    время выполнения;
  • когда в коде операций встречаются состоящие из многих ветвей условные
    операторы, в которых выбор ветви зависит от состояния. Обычно в таком
    случае состояние представлено перечисляемыми константами. Часто одна
    и та же структура условного оператора повторяется в нескольких операци-
    ях. Паттерн состояние предлагает поместить каждую ветвь в отдельный
    класс. Это позволяет трактовать состояние объекта как самостоятельный
    объект, который может изменяться независимо от других.
Не моя ситуация?

Ale}{
Сообщения: 46
Зарегистрирован: 2015.03.11, 09:47

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Ale}{ »

Krash писал(а):
2017.03.23, 11:32
Ale}{ писал(а):
2017.03.23, 10:50
Забудьте пока про паттерны. На сколько я понимаю DDD - начинать нада с определения предметной области, обозначить ее границы, ввести понятия и определения
DDD тут ни при чем.

Из книги "Приемы объекто-ориентривонного программирования. Паттерны проектирования." :

Применимость:
  • когда поведение объекта зависит от его состояния и должно изменяться во
    время выполнения;
  • когда в коде операций встречаются состоящие из многих ветвей условные
    операторы, в которых выбор ветви зависит от состояния. Обычно в таком
    случае состояние представлено перечисляемыми константами. Часто одна
    и та же структура условного оператора повторяется в нескольких операци-
    ях. Паттерн состояние предлагает поместить каждую ветвь в отдельный
    класс. Это позволяет трактовать состояние объекта как самостоятельный
    объект, который может изменяться независимо от других.
Не моя ситуация?
Честно не в курсе, потому как не увидел в ваших сообщениях подробного описания конкретной ситуации (бизнес-логики) того, что вам нада реализовать, обычным человеческим языком без ссылок на паттерны проектирования.

Сейчас почитал про указанный вами паттерн. Я его понял так - у объекта есть метод (может даже и не один) реализация которого не постоянна а зависит от условий (от внутреннего состояния объекта) И чтобы не плодить if/case внутри метода объекта - применяем данные паттерн.

Минимальный пример моего понимания паттерна
Возьмем автомобиль - его состояние - "Зажигание включено", "Зажигание выключено". Есть метод -ДавимНаПедальГаза.
В методе идет проверка на состояние - если Зажигание включено - то вызываем другие методы (поехал автомобиль) , если нет - то ничего не происходит.

Аватара пользователя
samdark
Администратор
Сообщения: 9262
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение samdark »

Задачу обрисуйте словами не привязываясь к реализации детально, тогда можно будет что-то подсказать...

anton_z
Сообщения: 464
Зарегистрирован: 2017.01.15, 15:01

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение anton_z »

Вы выбрали правильный паттерн - состояние. У вас workflow система. Sti это другой паттерн и про него пока забудьте. В бд состояние будет сохраняться в виде поля типа int. Если AR, то в afterFind на основе этого значения создаете соответствующий объект состояния, в beforeS ave обратное преобразование. Переходы между состояниями можно реализовать в методах классов состояний. На пальцах пример разобран в книге "Паттерны проектирования" Фрименов. См главу про паттерн "Состояние"

Krash
Сообщения: 29
Зарегистрирован: 2016.04.19, 12:43

Re: Вопрос по шаблонам Состояние и STI(Single Table Inheritance)

Сообщение Krash »

anton_z писал(а):
2017.03.24, 15:04
Вы выбрали правильный паттерн - состояние. У вас workflow система. Sti это другой паттерн и про него пока забудьте. В бд состояние будет сохраняться в виде поля типа int. Если AR, то в afterFind на основе этого значения создаете соответствующий объект состояния, в beforeS ave обратное преобразование. Переходы между состояниями можно реализовать в методах классов состояний. На пальцах пример разобран в книге "Паттерны проектирования" Фрименов. См главу про паттерн "Состояние"
Спасибо большое:)

Ответить