#architecture #database-design
#архитектура #база данных-проектирование
Вопрос:
Что ж, эта архитектурная проблема некоторое время бродила у меня в голове. Предположим следующий сценарий:
у меня есть Licenses
таблица. Концептуально, каждая лицензия может быть ограничена (типами лицензий):
- Тип 1: Количество попыток. (например, допускающий запуск 7 раз)
- Тип 2: Пробная версия (ограничена по времени).
- Тип 3: Полный
- …
Итак, каждая лицензия должна хранить некоторое пользовательское значение. (Тип 1: целое число, тип 2: дата-время, Тип 3: null)
Какая архитектура является наилучшей для этого сценария?
- Если я решу поместить все лицензии в одну таблицу, у меня останется по крайней мере 1 неиспользуемый столбец для каждой строки (конечная дата будет равна нулю для типа 1, время выполнения будет равно нулю для конечной даты, и оба будут равны нулю для типа 3):
LicenseID---LicenseType---CustomerID---EndDate---TryTimes
С другой стороны, я бы хотел, чтобы мой дизайн был максимально гибким (возможно, в будущем появится больше типов лицензий?) - Другим возможным решением было бы использование некоторого подхода, подобного метаданным:
LicenseID---LicenseDefinition---CustomerID---
Где LicenseDefinition содержит информацию о типе и ограничении лицензии и анализируется на стороне кода.
Какую из них вы предлагаете использовать более традиционно? Вы предлагаете какой-либо другой способ ее реализации?
ОБНОВЛЕНИЕ: Только что узнал о Sparse
столбцах SQL Server. Звучит очень многообещающе…
Комментарии:
1. Как насчет хранения данных в поле varchar и наличия дополнительного столбца, который определяет тип. Вам нужно будет выполнить некоторые преобразования в вашем коде, но это должно быть довольно просто
2. @Andrew: довольно близко к моему второму решению. Почему вы не отправили это в качестве ответа? Пока мой предпочтительный вариант.
Ответ №1:
На первый взгляд (я еще не реализовал ничего подобного), я мог бы сделать что-то вроде этого:
Создайте таблицы базы данных для Customer
и License
. Внутри Customer
, наряду со всей другой общей информацией о клиентах, я бы добавил столбец для licenseType
, который был бы reference
License
таблицей.
License
будет хранить licenseId
, а также любые соответствующие метаданные. Это не будет включать правила, зависящие от лицензии.
На стороне кода я бы создал LicenseFactory
класс, который создавал бы экземпляр лицензионного интерфейса ( ILicense
). ILicense
может выглядеть примерно так (в PHP):
interface ILicense
{
public isValid($customer);
}
Тогда у меня были бы реализации, зависящие от лицензии:
class TrialLicense implements ILicense
{
public isValid($customer)
{
// business logic for this specific license type here
}
}
Класс factory будет выглядеть примерно так:
class LicenseFactory
{
public static function getInstance($type)
{
switch($type)
{
case 0:
return new TrialLicense();
break;
}
}
}
Итак, теперь мой код приложения может выглядеть примерно так:
public function isLicenseValid($customer)
{
return LicenseFactory::getLicense($customer->licenseType)->isValid($customer);
}
Ничего из этого не было протестировано, и это всего лишь мои (довольно пространные) первоначальные мысли. Надеюсь, это немного поможет (даже если ваше приложение может не управляться php :))
Редактировать: Забыл упомянуть — преимуществом этого подхода является расширяемость. Каждый раз, когда вы хотите добавить новый тип лицензии, вы просто добавляете новую строку в License
таблицу и новую ILicense
реализацию с любыми требуемыми бизнес-правилами.
Комментарии:
1. Очень интересный Демиан. Единственное ограничение, которое я вижу, заключается в том, что клиенты не могут иметь более 1 лицензии.
2. Тогда решением было бы создать таблицу CutomerLicense, которая могла бы содержать отношение «один ко многим» (один Cutomer ко многим CutomerLicense)
3. … И, конечно, вам также пришлось бы модифицировать функцию isLicenseValid для обработки нескольких лицензий (на данный момент обрабатывает только одну).
Ответ №2:
Вы должны вести отдельную таблицу для каждого типа лицензии:
LicenseID(PK)---Type
LicenseID(FK)---EndDate
LicenseID(FK)---TryTimes
а также поддерживать целостность данных, например, во вторую таблицу будут помещаться только пробные лицензии.
Это также будет довольно масштабируемая модель, вам нужно будет добавить еще одну таблицу, еще одно правило целостности и еще один интерфейс, чтобы добавить другой тип лицензии.
Комментарии:
1. По правде говоря, я не уверен почему, но я думаю, что это может ограничить расширяемость. Я просто не чувствую себя правильно по этому поводу. Но, думаю, мне нужно еще подумать. хотя 1 за идею.
Ответ №3:
У вас может быть одна таблица в качестве родительской, а три другие таблицы, ссылающиеся на базовую таблицу, расширяют схему.
Это первый вариант.
Другим вариантом является использование простой базы данных NoSQL с небольшим объемом памяти или OO базы данных, такой как db4o, или даже простых хранилищ данных, таких как зашифрованный XML
файл.