Одна часть моей программы извлекает данные из многих таблиц и столбцов в моей базе данных для обработки. Некоторые из столбцов могут быть null
, но в текущем контексте обработки это ошибка.
Этого не должно "теоретически" происходить, поэтому, если это так, это указывает на неверные данные или ошибку в коде. Ошибки имеют различную серьезность, в зависимости от того, какое поле null
; то есть для некоторых полей обработка должна быть остановлена, и кто-то должен уведомить об этом, а для других обработка должна быть разрешена для продолжения и просто уведомить кого-то.
Есть ли хорошая архитектура или принципы дизайна для обработки редких, но возможных null
записей?
Решения должны быть реализованы с помощью Java, но я не использовал этот тег, потому что я думаю, что проблема несколько не зависит от языка.
Некоторые мысли, которые у меня были:
Использование NOT NULL
Проще всего было бы использовать ограничение NOT NULL в базе данных.
Но что, если первоначальная вставка данных важнее, чем этот последующий этап обработки? Таким образом, в случае, если вставка вставит null
в таблицу (из-за ошибок или, может быть, даже по какой-то уважительной причине), я бы не хотел, чтобы вставка не удалась. Допустим, что многие другие части программы зависят от вставленных данных, но не от этого конкретного столбца. Поэтому я бы предпочел рискнуть ошибкой на текущем шаге обработки вместо шага вставки. Вот почему я не хочу использовать ограничение NOT NULL.
Наивно в зависимости от NullPointerException
Я мог бы просто использовать данные, как если бы я ожидал, что они будут всегда (и это действительно должно иметь место), и перехватить результирующие NPE на соответствующем уровне (например, так, чтобы обработка текущей записи остановилась, но не весь ход обработки) ). Это принцип «быстро провал», и я часто его предпочитаю. Если это ошибка, по крайней мере, я получаю зарегистрированный NPE.
Но затем я теряю способность различать различные виды пропущенных данных. Например, для некоторых отсутствующих данных я мог бы их опустить, но для других обработка должна быть остановлена и администратор уведомлен.
Проверка null
перед каждым доступом и выдача пользовательских исключений
Пользовательские исключения позволили бы мне выбрать правильное действие на основе исключения, так что это похоже на путь.
Но что, если я забуду где-нибудь это проверить? Кроме того, я затем загромождаю свой код пустыми проверками, которые никогда или редко ожидаются (и, следовательно, определенно не являются частью потока бизнес-логики).
Если я решу пойти по этому пути, какие шаблоны лучше всего подходят для этого подхода?
Любые мысли и комментарии по поводу моих подходов приветствуются. Также лучшие решения любого типа (шаблоны, принципы, лучшая архитектура моего кода или моделей и т. Д.).
Редактировать:
Есть еще одно ограничение: я использую ORM для преобразования из БД в объект персистентности, поэтому проверка на ноль на этом уровне не будет работать (так как одни и те же объекты используются в тех частях, где ноль не приносит никакого вреда) , Я добавил это, потому что ответы, предоставленные до сих пор, оба упомянули эту опцию.
Ответы:
Я бы поставил нулевые проверки в вашем коде отображения, где вы строите свой объект из набора результатов. Это помещает проверку в одно место и не позволит вашему коду пройти половину процесса обработки записи до появления ошибки. В зависимости от того, как работает ваша прикладная программа, вы можете захотеть выполнить сопоставление всех результатов как этап предварительной обработки вместо сопоставления и обработки каждой записи по одной.
Если вы используете ORM, вам придется выполнять все проверки на ноль перед обработкой каждой записи. Я бы порекомендовал
recordIsValid(recordData)
метод -типа, чтобы вы могли (снова) хранить всю логику проверки нуля и другую проверку в одном месте. Я определенно не стал бы смешивать нулевые проверки с остальной частью вашей логики обработки.источник
Похоже, вставка нулевого значения является ошибкой, но вы боитесь применять эту ошибку при вставке, потому что не хотите терять данные. Однако, если поле не должно быть нулевым, а есть, вы теряете данные . Поэтому лучшим решением является обеспечение того, чтобы нулевые поля не были ошибочно сохранены.
Для этого убедитесь, что данные верны в одном полномочном постоянном хранилище этих данных, базе данных. Сделайте это, добавив ненулевые ограничения. Тогда ваш код может перестать работать, но эти сбои немедленно уведомят вас об ошибках, что позволит вам исправить проблемы, которые уже приводят к потере данных. Теперь, когда вы легко можете идентифицировать ошибки, протестируйте свой код и проверьте его дважды. Вы сможете исправить ошибки, приводящие к потере данных, и в процессе значительно упростить последующую обработку данных, поскольку вам не нужно беспокоиться о пустых значениях.
источник
В отношении этого предложения в вопросе:
Я всегда ценил эту цитату (любезно предоставленную этой статьей ):
По сути: звучит так, будто вы одобряете закон Постеля , «будьте консервативны в том, что вы посылаете, будьте либеральными в том, что вы принимаете». Несмотря на большой теоретический потенциал , на практике этот «принцип надежности» приводит к тому, что программное обеспечение не является надежным , по крайней мере, в долгосрочной перспективе, а иногда и в краткосрочной перспективе. (Сравните статью Эрика Аллмана « Пересмотренный принцип надежности» , которая является очень тщательным рассмотрением предмета, хотя в основном и сосредоточена на случаях использования сетевых протоколов.)
Если у вас есть программы, которые некорректно вставляют данные в вашу базу данных, эти программы повреждены и требуют исправления . Описывание проблемы только позволяет ей продолжать ухудшаться; это эквивалент программного обеспечения, позволяющий наркоману продолжать свою зависимость.
Прагматично говоря, однако, иногда вам нужно разрешить «сломанному» поведению продолжаться, по крайней мере, временно, особенно в рамках плавного перехода от слабого нарушенного состояния к строгому, правильному состоянию. В этом случае вы хотите найти способ, позволяющий неправильным вставкам успешно выполняться, но при этом позволить «каноническому» хранилищу данных всегда быть в правильном состоянии . Есть несколько способов сделать это:
Один из способов обойти все эти проблемы - вставить слой API, которым вы управляете, между программами, которые создают записи, и реальной базой данных.
Похоже, что частью вашей проблемы является то, что вы даже не знаете всех мест, которые генерируют неправильные записи, или что их просто слишком много для обновления. Это страшное состояние, но оно никогда не должно было возникать.
Как только вы получите больше , чем несколько систем, которые разрешено изменять данные в каноническом производстве данных хранения вы собираетесь быть в беде: нет никакого способа , чтобы централизованно поддерживать что - либо об этой базе данных. Лучше было бы разрешить как можно меньшему числу процессов выполнять записи и использовать их в качестве «привратников», которые могут предварительно обрабатывать данные перед вставкой по мере необходимости. Точный механизм для этого действительно зависит от вашей конкретной архитектуры.
источник
« Есть ли какая-нибудь хорошая архитектура или принципы дизайна для обработки редких, но возможных нулевых записей? »
Простой ответ - да.
ETL
Выполните некоторую предварительную обработку, чтобы обеспечить достаточное качество данных для помещения в базу данных. Все, что находится в файле перетаскивания, должно быть сообщено обратно, и любые чистые данные могут быть загружены в базу данных.
Как человек, который был одновременно браконьером (dev) и хранителем игр (DBA), я по горькому опыту знаю, что третьи стороны просто не решат свои проблемы с данными, если их не заставят. Постоянный изгиб назад и массирование данных через создает опасный прецедент.
Mart / Repository
В этом сценарии необработанные данные помещаются в базу данных хранилища, а затем очищенная версия помещается в рыночную базу данных, к которой затем получают доступ приложения.
Значения по умолчанию
Если вы можете применить разумные значения по умолчанию к столбцам, тогда вам следует, хотя это может потребовать некоторой работы, если это существующая база данных.
Провалиться рано
Соблазнительно просто решить проблемы с данными на входе в приложение, набор отчетов, интерфейс и т. Д. Я настоятельно рекомендую вам не полагаться только на это. Если вы подключите какой-либо другой виджет к БД, вы потенциально столкнетесь с теми же проблемами снова. Решить проблемы качества данных.
источник
Всякий раз, когда ваш вариант использования позволяет безопасно заменить NULL на хорошее значение по умолчанию, вы можете выполнить преобразование в
SELECT
операторах Sql с помощьюISNULL
илиCOALESCE
. Так что вместоможно написать
Конечно, это будет работать только тогда, когда ORM позволяет напрямую манипулировать операторами выбора или предоставлять изменяемые шаблоны для генерации. Следует убедиться, что никакие «реальные» ошибки не маскируются таким образом, поэтому применяйте его только в том случае, если замена значением по умолчанию - это именно то, что вам нужно в случае NULL.
Если вы можете изменить базу данных и схему, и ваша система БД поддерживает это, вы можете рассмотреть возможность добавления значения по умолчанию к определенным столбцам, как предложено @RobbieDee. Однако для этого также потребуется изменить существующие данные в базе данных, чтобы удалить все ранее вставленные значения NULL, и это впоследствии лишит возможности различать правильные и неполные данные импорта в дальнейшем.
Из своего собственного опыта я знаю, что использование ISNULL может работать на удивление хорошо - в прошлом мне приходилось поддерживать устаревшее приложение, в котором оригинальные разработчики забыли добавить ограничения NOT NULL для большого количества столбцов, и мы не могли легко добавить эти ограничения позже по некоторым причинам. Но в 99% всех случаев 0 по умолчанию для числовых столбцов и пустая строка по умолчанию для текстовых столбцов были полностью приемлемыми.
источник
ОП предполагает ответ, который объединяет бизнес-правила с техническими деталями базы данных.
Это все бизнес-правила. Бизнес-правила не заботятся о нулевом per se. Всем известно, что база данных может иметь значение NULL, 9999, "BOO!" ... это просто другая ценность. То, что в СУБД null имеет интересные свойства, а уникальное использование является спорным.
Единственное, что имеет значение, это то, что означает «нулевое значение» для данного бизнес-объекта (ов) ...
Да.
Бросать исключение при извлечении данных не имеет смысла.
Вопрос в том, должен ли я хранить «плохие» данные? Это зависит:
источник
Существует множество способов обработки нулей, поэтому мы перейдем от уровня базы данных к уровню приложения.
Уровень базы данных
Вы можете запретить нули ; хотя тут это нецелесообразно.
Вы можете настроить значение по умолчанию для каждого столбца:
insert
, поэтому не охватывает явную вставку нуляinsert
ошибочно пропущен этот столбецВы можете настроить триггер так, чтобы при вставке отсутствующие значения автоматически вычислялись:
insert
Слой запроса
Вы можете пропустить строки, где присутствует неудобство
null
:Вы можете указать значение по умолчанию в запросе:
Примечание: инструментирование каждого запроса не обязательно является проблемой, если у вас есть какой-то автоматизированный способ их генерации.
Прикладной уровень
Вы можете предварительно проверить таблицу на запрещенное
null
:Вы можете прервать обработку при обнаружении запрещенного
null
:null
а какие нетВы можете пропустить строку при встрече с запрещенным
null
:null
а какие нетВы можете отправить уведомление при обнаружении запрещенного
null
, либо по одному, либо в пакетном режиме, что дополняет другие способы, представленные выше. Однако наиболее важным является «что тогда?», В частности, если вы ожидаете, что строка будет исправлена и вам потребуется повторная обработка, вам может потребоваться убедиться, что у вас есть какой-то способ отличить уже обработанные строки от строк, нуждающихся в перерабатывается.Учитывая вашу ситуацию, я бы обработал ситуацию в приложении и комбинировал бы либо:
Я хотел бы просто пропустить, если это возможно, чтобы хоть как-то гарантировать небольшой прогресс, особенно если обработка может занять время.
Если вам не нужно повторно обрабатывать пропущенные строки, то достаточно просто зарегистрировать их, и электронное письмо, отправленное в конце процесса с количеством пропущенных строк, будет подходящим уведомлением.
В противном случае я бы использовал боковую таблицу для строк, которые должны быть исправлены (и повторно обработаны). Эта дополнительная таблица может быть либо простой ссылкой (без внешнего ключа), либо полной копией: последняя, даже более дорогая, необходима, если у вас нет времени для обращения к ней
null
перед очисткой основных данных.источник
Нули могут быть обработаны при переводе или отображении типов базы данных в языковые типы. Например, в C #, вот универсальный метод, который обрабатывает ноль для вас для любого типа:
Или, если вы хотите выполнить действие ...
И затем в сопоставлении, в данном случае с объектом типа «Образец», мы обработаем нуль для любого из столбцов:
Наконец, все классы сопоставления могут быть автоматически сгенерированы на основе задействованного запроса SQL или таблиц, просмотрев типы данных SQL и переведя их в типы данных для конкретного языка. Это то, что многие ORM делают для вас автоматически. Обратите внимание, что некоторые типы баз данных могут не иметь прямого сопоставления (геопространственные столбцы и т. Д.) И могут нуждаться в специальной обработке.
источник