Целесообразно ли упрощать разработку вариантов продукта, используя примечания вместо сложных отношений?
Я создаю приложение, в котором варианты продуктов должны обрабатываться как физические продукты, уже подготовленные и перечисленные вручную. Вместо того чтобы использовать традиционный подход со сложными отношениями между таблицами Product, Option, OptionValue и SKUValue, я пытаюсь упростить конструкцию.
💡 ERD Design:
+--------------+ +-----------------+
| Product | | ProductVariant |
+--------------+ +-----------------+
| id (PK) |<------>| id (PK) |
| name | | product_id (FK) |
| owner_id (FK)| | note |
| created_at | | stock |
| updated_at | | price |
+--------------+ +-----------------+
В таблице ProductVariant поле примечания представляет собой простое текстовое поле, в которое пользователи могут вручную вводить описания типа "Size: XL, цвет: красный".
🔍 Модели Django, основанные на этом дизайне:
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Product(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='products')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class ProductVariant(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='variants')
note = models.TextField() # Example: "Size: XL, Color: Red"
stock = models.PositiveIntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"{self.product.name} - {self.note}"
🎯 Почему я это делаю:
- Приложение предназначено для работы с вариантами продукции, которые часто предопределены и не меняются динамически.
- Пользователи будут вручную вводить описания вариантов на основе реальных физических продуктов, которые у них есть.
- Цель - избежать чрезмерной инженерии, устранив лишние таблицы и связи.
🤔 О чем я беспокоюсь:
- Я знаю, что большинство приложений используют хорошо структурированные реляционные модели для управления вариантами продукции.
- Однако реализация таких сложных структур кажется излишней для моего случая использования, и я беспокоюсь, что это может создать ненужные сложности.
- Меня беспокоит, что такой упрощенный подход может считаться "плохим дизайном", даже если он лучше подходит для моего случая использования.
❓ Вопрос:
Приемлема ли эта упрощенная конструкция, использующая ручные заметки для вариантов продукции, в сценариях, где варианты предопределены и записываются вручную? Какие потенциальные «подводные камни» я должен знать при использовании этой конструкции по сравнению с более «стандартной» реляционной моделью?
Что бы я подумал в этой ситуации, так это то, что теперь у вас есть столбец, состоящий из значений, основанных на словаре... И я бы не рекомендовал этого делать по нескольким причинам:
проверка будет сложнее, и у вас может быть возможность выполнять только мягкую проверку с использованием обработки django (а не жесткую проверку базы данных, которая является более согласованной).
размер этой таблицы будет больше по сравнению с таблицей с разделенными столбцами указанной роли.
использование фильтров по текстовому полю происходит медленнее (например, если вы хотите отобразить все продукты, которые выделены красным цветом).
В некоторых случаях такие столбцы могут подойти больше, если вы не гарантируете, что у вас всегда будут значения в столбцах параметров (разреженные таблицы). В случае разреженной таблицы у вас может быть столбец note
, и вы можете удалить пустые параметры.
Другое дело, что вы должны помнить о том, что ваш дизайн можно расширять, и вы всегда можете добавить к нему дополнительные функции, и, конечно, вы должны учитывать меняющиеся требования, например, что, если вдруг вам придется изменить некоторые параметры продукта, тогда у вас будет чтобы выполнить итерацию по столбцу note
и изменить значения каким-либо несогласованным образом.
Если дизайн соответствует вашему сценарию использования, то он по определению неплох. Не беспокойтесь о лучших практиках, если ваша текущая практика на самом деле удовлетворяет всем вашим потребностям, не подвергает вас каким-либо недостаткам и является достаточно эффективной.
Текущий дизайн
Для поля note
: попробуйте использовать JSONField
( (хотя обратите внимание на пункт о совместимости с базой данных) вместо TextField
.
Сохранение заметок в виде структурированных данных упростит синтаксический анализ во внешнем интерфейсе и значительно упростит поиск/фильтрацию/и т.д. во внутреннем интерфейсе (в частности, если вы используете Postgres, смотрите примечания к PG в связанной документации). Это также позволяет вам хранить более одного значения, а также метаданные и инструкции по синтаксическому анализу (например, размер шрифта, цвет или что-то еще, что вам нравится) атрибута.
Пример:
[
{
"1": {
"title": "Size",
"us_value": "XL",
"eu_value": 50,
"title_color": "red",
"value_color": "blue"
}
}
]
Возможные подводные камни:
- Этот подход быстро развалится, если вы захотите позволить пользователю добавлять сложные данные (т.е. любые данные, которые "превосходят" то, что легко вписывается в парадигму ключ-значение).
- Агрегирование данных по пользовательским атрибутам будет сложным в реализации, даже если вы используете
JSONField
. Если вы используетеTextField
, это будет очень сложно по практическим соображениям. - Если не использовать структурированные данные, подобные описанному выше подходу в формате JSON, поиск и фильтрация будут практически невозможны, если только производительность не будет абсолютно нулевой.
- Массовые обновления или любая ситуация, когда вам нужно обновить более одного экземпляра за раз, будут затруднительны как с точки зрения логики, так и с точки зрения производительности.
Альтернативный дизайн
"Сверхинженерный" подход, вероятно, был бы чем-то вроде набора EAV-моделей. Я знаю, что вы не просили конкретно об этом, но всегда полезно знать смежные концепции.
django-eav2 предоставляет хороший обзор EAV и вариантов его использования, и вы можете либо использовать библиотеку в этом ключе, если это кажется правильным, либо создать свою собственную, используя общие отношения.