Страница 1 из 1

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

Добавлено: 2018.07.14, 00:17
Maxim Glushko
Интересует мнение, насколько идея бредовая.

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

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

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]);
}

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

Добавлено: 2018.07.14, 08:21
maleks
да, два числа конечно лучше.
Константу можете и в самом классе Article определить

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

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

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

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

Добавлено: 2018.07.14, 11:37
BalykhinAS
А че связь по двум полям быстрее или лучше?

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

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

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

Добавлено: 2018.07.14, 12:02
skynin
Нормальная идея, если нужно.

на одном проекте я реализовал так всю доменную область.
так что динамически даже 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, то есть которая будет кастомизироваться не вами, и неизвестно заранее для каких бизнес-задач

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

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

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

Добавлено: 2018.07.14, 12:13
skynin
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 - почти одно и тоже будет.

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

индекс может и не ускорить ничего, а вот замедлить другие операции - запросто :)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

если у вас приложение просто CRUD формы - то конечно на кой они нужны :)

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

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

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

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

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

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

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

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

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