Xpoint
   [напомнить пароль]

Размышления на тему создания записей и показа html-форм

Метки: [без меток]
2009-03-13 11:40:59 [обр] triumvurat[досье]

Тема обсуждалась на PHPCLub, но решил открыть и здесь. Контекст задачи - PHP и MySQl.


Классическая форма добавления записи в базу выглядит примерно так:

Если POST
    Проверить данные
        Данные верны
            Записать их в базу
                Если ID существует
                    обновление
                Иначе
                    вставка
        Данные не верны
            подставить значения из POST в переменные формы

Если иначе GET
    Если есть ID записи 
        Выбрать записи, поместить их в переменные для подстановки в формы
    Иначе
        Инициализировать переменные с пустыми значениями

Показать форму

Проблема: создавать пустые переменные в программе, делать проверку на ID и в зависимости от ID делать UPDATE или INSERT.

Ситуация.

Допустим, у нас в системе есть зарегестрированный пользователь. Пользователь хочет добавить на сайт какие-то данные (резюме, например). Пользователь кликнет на ссылку "добавить резюме" и ему показывается форма. Никакой учетной записи его резюме не создано, в таблице резюме нет записи с его ID. Она появится только тогда, когда пользователь введёт правильно все данные и нажмет кнопку "сохранить".

Что придумалось.

Кликая по ссылке "создать резюме" автоматически создается пустая запись в БД ассоциирующаяся с этим пользователем и только после этого мы делаем referer на форму добавления резюме. Т.е. фактически резюме уже создано, ему присовин ID. Отличие лишь в том, что поля формы пустые, по дефолту.

Чем выгодно: алгоритм сценария резюме теперь выглядит так:

Если POST
    Проверить данные
        Данные верны
            Записать их в базу
        Данные не верны
            подставить значения из POST в переменные формы

Если иначе GET
        Выбрать записи, поместить их в переменные для подстановки в формы

Показать форму

как видно, количество действий сократилось. Теперь сценарий занимается только тем, что работает на UPDATE. "Никаких проверок" на существование ID резюме, никаких ветвлений. Для больших и сложных программ это очень позитивно, ИМХО.

Из обсуждения на пхпклубе мне намекнули на проблему пустых полей. Т.е. возможна ситуация, когда запись в таблице будет присутствовать, но все поля будут иметь пустое значение. Соответственно, при выводе записи это будет очень некрасиво. Нашлась идея создавать "флаг показа записи", который ставится в true только тогда, когда заполнен необходимый минимум строки таблицы.

Ваши мнения? Стоит так делать или нет?

спустя 1 час 6 минут [обр] GRAy(0/259)[досье]
triumvurat[досье] НМВЗ не стоит. Собственно зачем нагружать базу данных лишними строками? Просто чтобы сэкономить в коде пару строк? В конце концов есть такой оператор в mySQL - insert ... on duplicate key update ....
спустя 27 минут [обр] triumvurat[досье]

GRAy[досье] Ну строк на самом деле далеко не пара. Представте большую форму. Если в таблице нет записи, мы вынуждены создавать кучу пустых переменных или тащить значения столбцов по деволту.

Далее, ман:

В общем случае, следует избегать использования ON DUPLICATE KEY на таблицах со множеством уникальных (UNIQUE) ключей.

-- это уже ограничение.

Насчет

Собственно зачем нагружать базу данных лишними строками?

тут я не согласен с озабоченностью. Базе от пустых строк не тепло, ни холодно, но механизм определения пустых строк, как я уже писал, можно определять с помощью ключа. Т.е. как только заполнены все необходимые значения полей формы, обяхательные поля, то флаг=true. Т.е. запись становится активной.

Сейчас я реализую свою задумку. Посмотрим, что из этого выйдет.

спустя 17 минут [обр] Thirteensmay(0/157)[досье]
Нет не стоит.
  1. Как правило лучше иметь схему с подтверждением, и это касается не только данного конкретного случая а вообще. Т.е. пользователь сначала говорит что он хочет сделать, а потом делает и подтверждает. Если при выборе действия оно тут же происходит то во-первых это может озадачить пользователя так как он скорее всего ожидает традиционного поведения, т.е. вопрос юзабилити. Во-вторых появляется проблема обработки случайных (в торопях) нажатий и последствий этого, т.е. то что вы назвали проблемой пустых полей. Эту проблему необходимо решать дополнительными усилиями и костылями типа предлагаемого вами "флага показа записи", что в конечном случае сводит на нет всю экономию.
  1. Логику любого не критичного к производительности алгоритма (коим является наш случай) лучше всего держать в максимально человекоподобной, традиционной, (насажденной массой, тривиальной, блин слово забыл) форме, даже если это является несколько избыточным. Это окупается простотой ее понимания и поддержки, более того, как правило ведет к уменьшению усилий и проблем связанных с интегрированием и совместным использованием. По поводу увеличения количества строк кода - это не тот показатель на который надо обращать внимание в первую очередь.
спустя 7 минут [обр] GRAy(0/259)[досье]

Таблица с "множеством уникальных (UNIQUE) ключей" - это как-то очень странно, может в консерватории что-то исправить?

-- это уже ограничение.

Ну а вашем способе придётся либо снимать все Not null ограничения на поля таблицы, либо вставлять не полностью пустую строку.

Если в таблице нет записи, мы вынуждены создавать кучу пустых переменных или тащить значения столбцов по деволту.

Зачем? Почему просто нельзя создать строку при помощи insert into table(id) values(id) и тут же её проапдейтить тем же куском кода который бы её апдейтил если бы запись уже существовала? Отличие от вашего способа только в том когда делается insert пустой строки - ровно перед тем когда она будет нужна.

Если POST
    Проверить данные 
        Данные верны
            Записать их в базу
                Если ID не существует
                    вставка (полу)пустой строки 
                    (т.е. только тех значений которые нужны чтобы не нарушить ограничения наложенные на таблицу, в идеале только ID)
                Обновление
        Данные не верны
            подставить значения из POST в переменные формы
....
Базе от пустых строк не тепло, ни холодно

Ну ну, это пока этих строк относительно немного. Т.е. потом чтобы отфильтровать записи, которые действительно надо отображать вам придётся делать в запросах (во всех, обратите внимание) что-то типа is_need_to_show=1, а чтобы это ещё пошустрей работало неплохо было-бы и индекс по этому полю завести ;). База данных на каждом запросе будет тратить цпу чтобы этот фильтр применить, жрать больше памяти и в зависимости от эффективности хранения сильнее нагружать IO. Эх ;) нравятся последствия?

спустя 5 часов [обр] Алексей Севрюков(2/1280)[досье]
GRAy[досье] скорее всего имелся составной UNIQUE INDEX. IMHO.
спустя 1 день 6 часов [обр] Сергей Сирик(7/737)[досье]
Классический пример попытки экономии на спичках. Код не должен быть "коротким", код должен быть понятным и логичным.
спустя 9 дней [обр] triumvurat[досье]
ладно, отговорили...)
Powered by POEM™ Engine Copyright © 2002-2005