При ответе на данный вопрос всегда необходимо задаться вопросом эволюции ПО. Какая часть системы с наибольшей вероятностью будет меняться, а какая скорее всего останется постоянной?
Будем рассматривать данный вопрос на примерах. Рассмотрим несколько задач, регулярно возникающих в более-менее крупных системах. Причины возникновения данного вида задач выносятся за рамки данного поста, здесь же останавливаемся на реализации.
Формы бывают похожие: добавил одно поле, убрал другое, урезали возможные значения до чисел, сделал множественный выбор вместо единственного и т.д. С точки зрения представления — мелкое изменение. Насколько при этом меняется внутренняя логика?
Первое, что приходит в голову, глядя на простые формы — сопоставить форме объект, для каждого поля формы предусмотреть соответствующее поле объекта. При получении request'а записываем все поля формы в соответствующие поля объекта, валидируем, если есть ошибки — выдаем их пользователю с привязкой к полям и даем подредактровать, если все ок — передаем на дальнейшую обработку (как оно будет обработано — это уже зависит от задачи), если в результате обработки возникли ошибки — отрисовали ошибки (возможно, вместе с формой).
Будем развивать идею.
Посмотрим на эволюцию форм. Как правило, имеются тенденции к (возможны любые комбинации):
Отсюда могут возникнуть следующие проблемы:
Какие напрашиваются выводы?
P.S. В следующих топиках рассмотрим генерацию отчетов, разбор «сырых» данных сетевых протоколов и другие проблемы по желанию хабрасообщества.
Будем рассматривать данный вопрос на примерах. Рассмотрим несколько задач, регулярно возникающих в более-менее крупных системах. Причины возникновения данного вида задач выносятся за рамки данного поста, здесь же останавливаемся на реализации.
Обработка данных web-формы
Формы бывают похожие: добавил одно поле, убрал другое, урезали возможные значения до чисел, сделал множественный выбор вместо единственного и т.д. С точки зрения представления — мелкое изменение. Насколько при этом меняется внутренняя логика?
Первое, что приходит в голову, глядя на простые формы — сопоставить форме объект, для каждого поля формы предусмотреть соответствующее поле объекта. При получении request'а записываем все поля формы в соответствующие поля объекта, валидируем, если есть ошибки — выдаем их пользователю с привязкой к полям и даем подредактровать, если все ок — передаем на дальнейшую обработку (как оно будет обработано — это уже зависит от задачи), если в результате обработки возникли ошибки — отрисовали ошибки (возможно, вместе с формой).
Будем развивать идею.
Посмотрим на эволюцию форм. Как правило, имеются тенденции к (возможны любые комбинации):
- Добавлению новых полей
- Удалению необязательных полей
- Изменению контекста
- Изменению обязательности заполнения (в обе стороны)
- Удалению обязательных полей (= изменение обязательности + удаление необязательного поля)
- Изменение возможных значений поля, в том числе смена типа значений
Отсюда могут возникнуть следующие проблемы:
- Добавлено новое поле. Набор полей для ранее одинаковых форм со временем может стать совершенно различным.
- Удалено какое-либо необязательное поле. Просто удаляем обработчики данного параметра. Хорошо бы еще почистить таблицу в БД и код работы с этим полем, но не критично.
- Поле было обязательным, стало необязательным. Проверки на null основательно портят жизнь.
- Поле было необязательным, стало обязательным. Проблема в уже существующих данных: как обрабатывать, если значения нет, но оно требуется для проведения операции?
- Изменение возможных значений поля, в том числе смена типа значений. Думаю, проблемы очевидны, все зависимости от типа поля надо менять.
Какие напрашиваются выводы?
- Делать в БД проверки на NULL нужно только для гарантированно обязательных полей. Это такие поля, без которых запись в БД теряет смысл. Как правило, этих полей немного, и частелько они представляют собой альтернативный ключ (или его подмножество). Если не верить — попробуйте рассмотреть возможность введения анонимных пользователей (т.е. пользователей без регистрации).
- Если в похожих по семантике формах сильно меняется набор полей в зависимости от контекста (например, формат анкеты для разных заказчиков), имеет смысл вводить атрибутивную логику, где одна запись в БД соответствует одному значению поля (а не всему множеству полей формы).
- Если необязательных полей много, и они предназначены только для хранения каких-либо данных, также имеет смысл использовать атрибутивную логику — их набор на практике подвержен изменениям.
- Если на какое-либо необязательное поле завязывается различная логика в разных частях системы — имеет смысл консолидировать ее в одно место. Пусть сначала это будет класс с двумя-тремя методами — потом их число запросто вырастет до 15-20. Это также поможет решить потенциальную проблему в случае, когда поле станет обязательным.
- Для устранения проблем с типизацией для каждого поля храним его тип, и передачу значения данного поля всегда производим вместе со ссылкой на метаинформацию о поле и его типе. Если нужно обмениваться со внешними системами — вводим четкие правила сериализации (например, в строку, в т.ч. в XML) и обработки ошибок парсинга.
- Регулярными рефакторингами необходимо удалять старый код для работы с уже не существующимим полями. Никаким комментариев с блоками кода — историю оставим для системы контроля версий.
P.S. В следующих топиках рассмотрим генерацию отчетов, разбор «сырых» данных сетевых протоколов и другие проблемы по желанию хабрасообщества.