Число вместо поля класса для полиморфных связей

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
Maxim Glushko
Сообщения: 72
Зарегистрирован: 2017.04.24, 19:16
Откуда: Україна, Одеса

Число вместо поля класса для полиморфных связей

Сообщение Maxim Glushko » 2018.07.14, 00:17

Интересует мнение, насколько идея бредовая.

Вместо строки и числа для полиморфной связи использовать два числа.
Вроде как быстрее должно быть, нет?

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

class InfoModel {

	const USER = 1;
	const ARTICLE = 2;
	const SOMETHINGELSE = 3;

	public static function all() {
		return [
			static::USER => User::class,
			static::ARTICLE => Article::class,
			static::SOMETHINGELSE => SomethingElse::class,
		];
	}
}

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

// в классе Article
public function getComments()
{
	return $this->hasMany(Comment::className(), ['item_id' => 'id', 'item_type' => InfoModel::ARTICLE]);
}

Аватара пользователя
maleks
Сообщения: 1649
Зарегистрирован: 2012.12.26, 12:56

Re: Число вместо поля класса для полиморфных связей

Сообщение maleks » 2018.07.14, 08:21

да, два числа конечно лучше.
Константу можете и в самом классе Article определить

Аватара пользователя
Maxim Glushko
Сообщения: 72
Зарегистрирован: 2017.04.24, 19:16
Откуда: Україна, Одеса

Re: Число вместо поля класса для полиморфных связей

Сообщение Maxim Glushko » 2018.07.14, 09:46

Я вынес константы и массив в отдельный класс, чтобы данные обо всех моделях (используемых для полиморфных связей) были собраны в одном месте. Чтобы случайно не повторить число в каждой по отдельности модели. В какую структуру целесообразнее выносить какую-то инфу, иногда статическую, иногда вычисляемую, кроме Yii:$app->params[]?

И эти обращения к статическим свойствам или константам других классов (InfoModel::ARTICLE) насколько существенно тормозят выполнение?

Wizard
Сообщения: 157
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

Re: Число вместо поля класса для полиморфных связей

Сообщение Wizard » 2018.07.14, 11:37

А че связь по двум полям быстрее или лучше?

Аватара пользователя
Maxim Glushko
Сообщения: 72
Зарегистрирован: 2017.04.24, 19:16
Откуда: Україна, Одеса

Re: Число вместо поля класса для полиморфных связей

Сообщение Maxim Glushko » 2018.07.14, 11:42

Wizard писал(а):
2018.07.14, 11:37
А че связь по двум полям быстрее или лучше?
Полиморфные связи по одному полю-связке не построишь.
Вот объяснялка, что это такое:
https://laravel.ru/docs/v5/eloquent-relationships#pl
В yii2 не видел такого, но иногда надо. Вот об этом и тема.

skynin
Сообщения: 154
Зарегистрирован: 2017.12.12, 10:09

Re: Число вместо поля класса для полиморфных связей

Сообщение skynin » 2018.07.14, 12:02

Нормальная идея, если нужно.

на одном проекте я реализовал так всю доменную область.
так что динамически даже ActiveRecord модели создаются. В словаре типов сущностей указывался класс этой сущности.

в итоге многие универсальные паттерны стали единственными для всех сущностей.
например таблица многие-ко-многим для любых сущностей выглядит вот так:

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

CREATE TABLE `wf_m2m` (
  `id` int NOT NULL AUTO_INCREMENT,
  `e_onoff` tinyint unsigned DEFAULT '64',
  `e_id_left` int NOT NULL,
  `k_id_left` tinyint unsigned NOT NULL,
  `e_id_right` int NOT NULL,
  `k_id_right` tinyint unsigned NOT NULL,
  `e_name` varchar(250),
  `e_info` json DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `el_idx` (`e_id_left`),
  KEY `er_idx` (`e_id_right`)
) 
e - entity
k - kind of entity

или таблица расчетов (типа журнала Расчетов в 1С:Зарплата)
для какой угодно сущности, в рамках какого угодно "периода", "отдела", ..., ...

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

CREATE TABLE `wf_calc_results` (
  `id` int NOT NULL AUTO_INCREMENT,
  `e_onoff` tinyint DEFAULT '64',
  `subject_id` int NOT NULL,
  `subject_kind` tinyint unsigned NOT NULL,
  `scene_id` int NOT NULL,
  `scene_kind` tinyint unsigned NOT NULL,
  `group_id` tinyint unsigned NOT NULL COMMENT 'group of calculation',
  `group_result` int DEFAULT NULL,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `e_info` json DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `subject_idx` (`subject_id`),
  KEY `scene_idx` (`scene_id`)
)
Индексировать kind поля смысла нет. Выборки без хотя бы одного id редки, а повторяемость значений в kind поле сведет на нет индекс по нем.

Сейчас прикручиваю бух учет, но там решил что за kind будет отвечать номер счета. то есть счета будут типизированы для сущности.

По опыту работы с такой организацией могу сказать что для большинства задач - избыточная система, как и DDD :)

Хотя и удобная, все становится унифицированным и простым
Особенно упрощается работа с типичными патернами, один-ко-многим, многие-ко-многим, EAV

Нужно такое если писать какую-то систему типа Magento, то есть которая будет кастомизироваться не вами, и неизвестно заранее для каких бизнес-задач
Последний раз редактировалось skynin 2018.07.14, 12:07, всего редактировалось 1 раз.
Неврубающийся не может опознать врубающегося.

Аватара пользователя
Maxim Glushko
Сообщения: 72
Зарегистрирован: 2017.04.24, 19:16
Откуда: Україна, Одеса

Re: Число вместо поля класса для полиморфных связей

Сообщение Maxim Glushko » 2018.07.14, 12:06

skynin, т.е. вы не советуете делать объединённый индекс на двух полях?
item_id и item_type
Достаточно одного на item_id?

skynin
Сообщения: 154
Зарегистрирован: 2017.12.12, 10:09

Re: Число вместо поля класса для полиморфных связей

Сообщение skynin » 2018.07.14, 12:13

Maxim Glushko писал(а):
2018.07.14, 12:06
skynin, т.е. вы не советуете делать объединённый индекс на двух полях?
item_id и item_type
Достаточно одного на item_id?
не советую, потому что нет смысла.
а расходы на поддержку индекса - будут. особенно при вставке :)

то есть, скорость выборки
where item_id = 213213 and item_type = 12

ощутимо не просядет если будет проиндексировано только item_id
и не ускорится особо, если будет еще и индекс по item_type

когда у вас за десятки тысяч записей а у item_type только с 10ок значений - выборка
where item_type = 12
почти что фулскан :)
исключение - если такие выборки бывают очень часто.
но тогда.... лучше думать об их кешировании :)

ну а если счет на тысячи записей, то что фулскан, что с индексом по item_id - почти одно и тоже будет.

правило с индексами такое всегда
НЕ надо их тыкать бездумно, типа добавил - и все ускорилось.

индекс может и не ускорить ничего, а вот замедлить другие операции - запросто :)
Неврубающийся не может опознать врубающегося.

Wizard
Сообщения: 157
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

Re: Число вместо поля класса для полиморфных связей

Сообщение Wizard » 2018.07.14, 12:59

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

skynin
Сообщения: 154
Зарегистрирован: 2017.12.12, 10:09

Re: Число вместо поля класса для полиморфных связей

Сообщение skynin » 2018.07.14, 13:04

Wizard писал(а):
2018.07.14, 12:59
а на чем экономия, на количестве таблиц?
на коде обработки данных. он становится одинаковым.
как и вывод пользователю - тоже унифицируется, а не копипаста, пусть и сгенерированная Gii

а если этого не происходит, то да, нафик надо было заморачиваться.

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

Wizard
Сообщения: 157
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

Re: Число вместо поля класса для полиморфных связей

Сообщение Wizard » 2018.07.14, 13:05

skynin писал(а):
2018.07.14, 13:04
Wizard писал(а):
2018.07.14, 12:59
а на чем экономия, на количестве таблиц?
на коде обработки данных. он становится одинаковым.
как и вывод пользователю - тоже унифицируется, а не копипаста, пусть и сгенерированная Gii

а если этого не происходит, то да, нафик надо было заморачиваться.

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

skynin
Сообщения: 154
Зарегистрирован: 2017.12.12, 10:09

Re: Число вместо поля класса для полиморфных связей

Сообщение skynin » 2018.07.14, 13:11

Wizard писал(а):
2018.07.14, 13:05
никто не мешает повторяющийся код как минимум вынести в трейт))
но если надо цеплять к каждой модели трейт - то это прямое указание что имеем дело с наследованием :)

На примере самого фреймворка Yii - а давайте вынесем в трейт обработку событий, методы trigger и on/off?
а смысл, что это даст?

любой класс можно растащить на трейты. вопрос - с какой целью?

способов организации кода много.
а выбирать надо тот который соответствует задаче.

может и копипаста, нагенеренная Gii сгодится, без всяких там трейтов.
Wizard писал(а):
2018.07.14, 13:05
по моему эта проблема проще чем думать о производительности и прочих вытекающих такого подхода.
а какие там проблемы с производительностью?

Полиморфные связи - это следствие объектно-реляционное отображения.

если у вас приложение просто CRUD формы - то конечно на кой они нужны :)
Последний раз редактировалось skynin 2018.07.14, 13:14, всего редактировалось 1 раз.
Неврубающийся не может опознать врубающегося.

Wizard
Сообщения: 157
Зарегистрирован: 2018.02.05, 13:41
Контактная информация:

Re: Число вместо поля класса для полиморфных связей

Сообщение Wizard » 2018.07.14, 13:14

skynin писал(а):
2018.07.14, 13:11
Wizard писал(а):
2018.07.14, 13:05
никто не мешает повторяющийся код как минимум вынести в трейт))
но если надо цеплять к каждой модели трейт - то это прямое указание что имеем дело с наследованием :)

На примере самого фреймворка Yii - а давайте вынесем в трейт обработку событий, методы trigger и on/off?
а смысл, что это даст?

любой класс можно растащить на трейты. вопрос - с какой целью?

способов организации кода много.
а выбирать надо тот который соответствует задаче.

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

skynin
Сообщения: 154
Зарегистрирован: 2017.12.12, 10:09

Re: Число вместо поля класса для полиморфных связей

Сообщение skynin » 2018.07.14, 13:17

Wizard писал(а):
2018.07.14, 13:14
трейты это один из многочисленных вариантов которые куда лучше чем лепить все в одну таблицу.
трейты - это в языке PHP. какое отношение конструкции языка программирования имеют к схеме базы данных?

никакого. что с трейтами, что без - можно лепить все в одно таблицу, а можно все в разные.
Wizard писал(а):
2018.07.14, 13:14
но как по моему лучше копипаст или трейты))
от сложности предметной области проекта зависит.
Неврубающийся не может опознать врубающегося.

Ответить