Хранение в БД
С таблицей рецептур в общем-то все понятно. Делаем таблицу Receipt с полям: ID (ключ), Title (название рецептуры), Description (краткое описание – заказчик не просил, но думаю не помешает), CreatedDate (дата создания, тоже пригодится).
А вот как хранить команды рецептуры это хороший вопрос. Команды разного типа. Общего у них: ID (ключ), ReceiptID (ID рецептуры), CommandType (тип команды). А различного у них – параметры команды. Для загрузки компонентов это ID компонента и вес в кг. Для паузы – величина задержки в сек. И т.д.
Вариант хранения всех команд в одной таблице мне не нравится – будет много пустых столбцов, а добавлять новые типы команд будет затруднительно. Вариант хранения каждого типа команд в отдельной таблице тоже не нравится – слишком сложно будет читать данные. Для такой просто задачи это перебор.
И тут срабатывает ограничитель лени J Он говорит, что задача слишком простая, база данных слишком локальная и вообще надо быть проще… Не могу с ней не согласиться.
Вариантов упрощения жизни у меня два. Первый – сделать отдельную таблицу команд ReceiptCommand со всеми перечисленными выше полями, но параметры хранить в столбце Params типа string в виде XML. Тогда все будет просто – все что нужно будет сделать, это прочитать данные из таблицы команд для нужного ReceiptID, создать нужные типы команд и отдать им их XML-параметры. А уже каждая команда для себя решит как ей понять свои параметры. Сохранение точно так же, только каждая команда сохраняет свои параметры в виде XML и мы записываем их в это поле.
Второй вариант еще проще, но с точки зрения архитектуры менее красивый – текстовый столбец Commands в таблице Receipt. Тип у него text. А хранить я в нем буду список команд в виде XML, т.е. даже не раскладывать команды по строкам. Никаких “лишних” таблиц, чтение и запись данных будет элементарная. Правда с преобразованием в список будет немного возни, но тут тоже не сложно – рецептура выбирается один раз при старте системы, т.е. достаточно редко, а список рецептур редактируется тоже редко и не требует постоянных преобразований. Так что все получится.
Важно! Этим примером я не призываю ломать типизацию, но хочу обратить внимание, что иногда условия задачи складываются так, что можно позволить себе упрощение архитектуры без ее ухудшения. Конечно, не нужно доводить эту идею до маразма – а то можно дойти до одной таблицы и одного поля, в которое нужно будет писать XML содержащий вообще все. Нет, конечно. Но конкретно для хранения параметров некоторых объектов, которые отличаются только этими параметрами – вполне можно.
В результате я выбрал второй вариант, совсем простой. Аргументы у меня были (если не считать лени) такие: при создании рецептуры и при чтении списка команд оба варианты примерно равноправны. А вот при редактировании будут различия. В первом варианте нужно будет либо удалять все строки, соответствующие ID рецептуры и потом сохранять их заново, либо, что значительно сложнее, пытаться вносить в них изменения. А если стирать и заносить заново, то какая разница между этим и вторым вариантом, когда я храню сразу XML со списком команд? Задачи получить нужную команду по ее номеру у меня нет - список команд не разделим на части и команда по отдельности смысла не имеет. Запросы "дай мне все рецептуры, где используется этот тип команды" тоже смысла не имеют. Получается что второй вариант проще. Но - только в данных конкретных условиях задачи.
Продолжение следует...