@rd_nino
программист-любитель

Создание элемента — какая схема лучше?

Здравствуйте.
Возник вопрос реализации добавления нового элемента.

Есть два варианта:
1. Создать в базе данных элемент с значениями по-умолчанию, получить его id и отобразить пользователю диалог изменения свойств уже существующего элемента. Т.е. использовать унифицированный метод Create.
Пользователь заполнит поля, нажмёт "Сохранить" и мы просто используем метод Update.

2. Не создавать элемент, отобразить пользователю диалог изменения свойств.
Пользователь заполнит поля, нажмёт "Сохранить" и мы используем метод Create, в котором создаём элемент, заполняем свойства и сохраняем в базе данных.

Во втором варианте после нажатия кнопки "Сохранить" нам нужно будет определять - элемент уже существует или нет.
И соответственно использовать метод Create или Update.
Как бы лишнее ветвление получается.

Как быть? Какую схему лучше выбрать7
  • Вопрос задан
  • 233 просмотра
Решения вопроса 1
@d-stream
Готовые решения - не подаю, но...
Как-то на практике чуть удобнее получается нечто типа 2 еще и с объединенным функционалом в виде create or update в "полунеявном" виде.

То есть если объект не имеет UID, то при сохранении - это явный знак, что он "новый" и надо insert, есть - значит update

Первый подход - получается двухшаговым, с отсутствием гарантии наличия второго шага. Грубо пользователь захотел создать новую запись - она создалась с дефолтами, а потом пользователь выключил комп...
В итоге в базе наплодится гора "пустых записей".
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@vintage
Совсем идеальный вариант: клиент генерирует GUID и для него создаёт свою локальную запись. Далее сразу или по нажатию кнопки "сохранить", происходит синхронизация с сервером. Если на сервере нет записи с таким GUID, то она создаётся. Если есть, то проверяются права доступа и если всё ок, то изменения применяются.

Чем это хорошо:
1. Все запросы идемпотентные (их можно безопасно повторять при затыках сети).
2. Даже у не сохранённой на сервере записи есть уникальный идентификатор, что сильно упрощает клиентскую логику.
3. Не захламляется база данных временными записями.
4. Логика работы клиента не зависит от протокола взаимодействия. Вам не нужно предварительно создавать запись, прежде чем её редактировать, не нужно иметь две различные логики работы для записей с локальными идентификаторами и с серверными. Просто создаёте записи и работаете с ними, а взаимодействие с сервером обеспечит отдельный заменяемый адаптер.
5. GUID можно генерировать сразу человекопонятным. Например, для блога это может быть "vintage/2017-03-08T12:47:33". Обратите внимание, что тут мы не позволяем создавать более одного поста в секунду. Записи, созданные в одну и ту же секунду будут одной и той же записью.
6. Вы сами решаете когда и как сохранять данные на сервер и это не навязывается вам протоколом.
7. На запись, которая ещё не сохранена, уже можно дать ссылку. Фактически создана она будет лишь после первого редактирования. Актуально для вики проектов, где вы сначала создаёте ссылку, потом по ней переходите, и только тогда уже заполняете.

Чем это плохо:
1. сквозная нумерация не представляется возможной. Но она и редко когда необходима.
2. Идентификаторы получаются относительно длинными. С другой - они могут содержать некоторую метаинформацию. Например - когда, кем и где создана.
3. В базе для GUID должна быть дополнительная текстовая колонка с уникальным индексом. Но скорее всего всё-равно у вас такая будет, когда начнёте внедрять [slug](https://ru.wikipedia.org/wiki/Семантический_URL#Slug) для человекопонятности.
Ответ написан
gzhegow
@gzhegow
aka "ОбнимиБизнесмена"
Попробуй немного изменить представление о программировании. Воспринимай все как "источники данных".

Есть у тебя база - это источник.
Есть у тебя пользователь - это тоже источник, НО временный (!).

Заранее назначать идентификатор нужно только в том случае, если тебе нужно сохранять и потом восстанавливать (навсегда, а не временно). Ты можешь присвоить ID сразу от пользователя, а потом зачем-то делать соответствие база-пользователь через "внешний id" (который ты заранее в программе присвоил) - но пользователь сам не сохраняет свои данные, он отдает их тебе, поэтому ему ID без надобности.

А вот базе твоей ID - нужен. Потому пользователь заполняет поля, жмет сохранить, а уже потом ты проверяешь - было ли в твоем источнике такая запись по некоторым критериям - например - по символьному коду "Гриша" - "grisha".

Почему программисты любят цифры? Потому что они уникальны в рамках мира. В любых кодировках, в любых языках, строчные или прописные, арабские цифры все равно выглядят как арабские цифры и при поиске соответствия - вероятность найти результат - выше.

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

Чтобы уменьшить такую вероятность, ты:
а) в идеальном случае рассказываешь ему про ID и даешь выбрать записи из списка, а список - привязывает уже к ID
б) приводишь введенный им текст по собственному алгоритму - вырезая лишние пробелы, и понимая что в конце получится более менее адекватная строка для сверки - символьный код. Но будь внимателен - алгоритм этот добавляет и другую проблему - введет пользователь два пробела после имени - наверное он ожидал, что это будет другое имя, раз два пробела. И когда он увидит "запись уже есть" - у него возникнет вопрос. Дизайном это нужно обыграть, запретами и тд.

Таким образом ID - это указатель (!) - как в жизни - указывает "в-туда" - на место хранения записи в конкретной системе. Если ты сделаешь ID в пределах своей программы (пока она запущена) - то в твоей базе тебе придется делать связь "время_запуска_ID_программы_ID_базы" - а это ужас сколько проблем - работа с временными интервалами.

Используй ID чтобы пронумеровать запись в конкретном источнике, а второе поле - внешний ID - чтобы сделать связь с другим источником, и постарайся, чтобы эта связь не была забыта со временем.

Например при работе с Европейской системой SAP-кодов - мы имеем следующую проблему. Когда клиент покупает себе в фирму SAP (миллион Евро между прочим) - ему выдается набор доступных ID-шников под его продукцию. Но продукции бывает больше, чем ID-шников, искать впадлу, а второго миллиона нету, и продавец исключает товары из продажи, присваивая старым ID-шникам новые товары.

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

Вот так где-то.

ps. https://docs.google.com/spreadsheets/d/1nxHJiDv6dR...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы