Куда относится этот метод? - PullRequest
4 голосов
/ 21 апреля 2009

Допустим, у меня есть модельный адрес, который вводится из пользовательского интерфейса. Я должен подтвердить, что адрес никогда не сохраняется в системе в неполном состоянии (что бы это ни значило для бизнеса).

Когда пользователь вводит адрес в пользовательском интерфейсе, он сериализуется в объект Address. Поэтому мне было интересно: куда относится метод, подобный isComplete? Валидатор или модель?

Если я помещу этот метод в модель адреса и вызову address.isComplete() в валидаторе перед сохранением, это означает, что неполный адрес является допустимым состоянием системы; если я проверяю полноту в валидаторе, создается впечатление, что валидатор слишком много знает о внутренних адресах.

Мне интересно, по какому общему правилу следуют другие?

РЕДАКТИРОВАТЬ: Как упомянуто ниже, в приведенном выше примере объект адреса повторно используется в нескольких системах, и «полный» объект в одной системе может не означать «полный» объект в другой системе. Таким образом, не существует единого способа принудительного применения «Объект никогда не должен создаваться в недопустимом состоянии» в глобальном масштабе, поскольку недопустимое состояние зависит от контекста.

Ответы [ 11 ]

1 голос
/ 21 апреля 2009

Я создаю класс данных для каждого вида данных, которые я использую. Я не использую типы "string" и "int", кроме как внутри этих классов данных. Мои классы данных имеют значимые имена и используются в тех случаях, когда конкретные ограничения класса имеют смысл.

Например, если у вас есть поле «оценка», которое имеет смысл только со значениями от 1 до 100, тогда у вас есть БЕЗ БИЗНЕСА , хранящее его в классе «int», диапазон которого равен -2 147 483 648. до 2 147 483 647. Если вы делаете это, получайте удовольствие, пытаясь проверить его избыточно везде, где вы его проходите, и получайте удовольствие, выясняя, когда и где вам нужно его проверить, и получайте удовольствие, когда вы забываете место и позволяете неверным данным проникать в вашу систему, и забавно пытаться объяснить мне, как ошибка, которая не является ошибкой программиста, возможна в программном обеспечении, написанном для детерминированного цифрового оборудования.

Когда / Где проверить:

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

После того, как вы выполнили первоначальную проверку, поместите данные в соответствующий значимый класс данных, такой как «Оценка», где конструктор выполнит окончательную / достоверную проверку . Эта достоверная проверка должна быть настолько простой и эффективной, насколько это возможно, но абсолютно достаточной для гарантии того, что значение действительно. Это логическая проверка; данные либо действительны, либо выдается исключение, подходящее для чтения программистом. Если код проверки вашего класса данных представляет собой, например, просто совпадение с регулярным выражением, рассмотрите возможность включения имени класса данных, строки регулярного выражения и самих данных в сообщение об ошибке. Все базовые классы данных должны быть неизменяемыми, как и сам класс строки; однажды построенный, он гарантированно будет действительным и останется таковым.

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

1 голос
/ 21 апреля 2009

валидатор, по двум причинам.

Во-первых, в адресе практически отсутствует внутреннее поведение - это просто данные.

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


Ответ на комментарии: отличаются ли данные между BillingAddress и ShippingAddress? Или правила меняются? А правила собраны в камне или, возможно, они изменятся в будущем (например, UKBillingAddress, USBillingAddress)?

Я согласен, что бывают случаи, когда полезно, чтобы система типов применяла правила данных (измерения являются хорошим примером; Google для зонда Марса, который использовал счетчики в одном месте и футы в любом). Однако я подозреваю, что адреса не относятся к таким случаям.

1 голос
/ 21 апреля 2009

Похоже, вам нужен AddressFactory, в котором вы передаете данные для адреса, и он либо даст вам действительный адрес, либо ошибку (исключение / что угодно). Вы правы, когда понимаете, что не идеально создавать неверный адрес.

Если вы сделаете это, вы должны определить, кто может создавать объекты Address и могут ли они быть созданы без использования AddressFactory. Если это так, то сам объект Address должен защищаться от недопустимых входных данных, и аргумент для самого объекта Address, имеющего проверку достоверности, становится сильнее.

0 голосов
/ 21 апреля 2009

Хм, я бы рассмотрел следующие вещи:

  1. Какие домены / подсистемы требуют правильного адреса?
  2. Сколько таких доменов?
  3. В каких доменах может существовать недействительный адрес?
  4. Существуют ли дополнительные обстоятельства, которые влияют на определение достоверности (каков ваш источник проверки). Является ли валидатор отличным объектом от домена, для которого требуется действительный адрес. (это может быть, например, удаленный сервис)

Если существует несколько доменов, каждый из которых требует разных определений валидности, для них имеет больше смысла обеспечивать достоверность при передаче им адреса, и предполагается, что все встреченные адреса недействительны, если не доказано иначе. С другой стороны, если когда-либо существует только одно определение того, что составляет действительный адрес, то для отправителя может иметь больше смысла выполнять проверку перед предоставлением адреса, и для них предполагается, что они действительны. Если валидатор является отдельным (подключаемым?) Объектом, это может быть отдельный сервис.

0 голосов
/ 21 апреля 2009

если это приложение для ввода данных, в котором пользователь должен заполнить всю форму / адрес до того, как что-либо будет сохранено, то Валидатору должен принадлежать метод isComplete, и модели никогда не придется иметь дело ни с чем, кроме полных адресов

НО, если пользователю может потребоваться сохранить частичные результаты и продолжить их позже (например, если форма, содержащая адрес, является лишь одним шагом в последовательности «мастера», которую можно прервать / продолжить), то isComplete принадлежит модели, и «неполное» является допустимым состоянием для адреса.

Альтернативно , метод isComplete может принадлежать Валидатору (, что бы это ни значило в вашей структуре! ), но его полное / неполное состояние становится частью данных адреса.

0 голосов
/ 21 апреля 2009

ИМХО ... вам понадобится 2 уровня проверки.

  • Уровень клиента / пользовательского интерфейса: найдите правила, которые имеют низкую привязку к изменениям, но которые легко изменить, и вставьте их в пользовательский интерфейс. например содержимое этого поля «должно быть числовым», или содержимое этого поля должно «соответствовать этому шаблону» или «обязательно». Здесь действуют декларативные правила. Предоставление пользователю немедленной обратной связи.
  • Уровень модели: переведите все остальное в модель / бизнес-правила. Все, что может измениться, должно войти сюда. Вы не можете покончить с проверкой модели, потому что я могу сделать это с помощью кода в обход GUI
Address a = new Address();
// set fields as I deem fit
a.Save();

ДЛЯ ИТОГА: Попытайтесь пометить проблемы и отсеять неверный ввод, насколько это возможно, не затрагивая модель. Модель является вашей последней линией защиты и гарантирует, что никакие плохие данные не пройдут ее.

0 голосов
/ 21 апреля 2009

Я думаю, что все, что вы предложили, имеет отношение к делу. Есть несколько способов сделать это:

Сделать валидатор интерфейсом:

Это можно сделать как

Validator addressValidator = new AddressValidator();
bool valid = addressValidator.validate(map);
if (valid) {
    Address address = addressValidator

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

Поместите isComplete в адрес:

Хорошая эвристика - говорить, что все объекты должны конструироваться с допустимым состоянием, но это не всегда верно. Помните, что oop максимизирует информацию времени компиляции, которой вы можете воспользоваться, то есть вынуждаете столько ошибок при компиляции, чем во время выполнения. Пользовательские интерфейсы будут мешать этому на всех поворотах. Вы как бы где-то нарушаете это. (Я думаю, что соглашение J2EE состоит в том, чтобы создавать объекты без параметров и вызывать, например, сотню сеттеров.)

Адрес разделения на два объекта:

Если вы хотите быть техническими в отношении действительного состояния, то у вас действительно есть два разных стандарта: состояние, возвращаемое вашим пользовательским интерфейсом, и состояние, необходимое для вашей модели. Почему бы не сделать различие явным? Например, если в моем пользовательском интерфейсе доступно 12 полей, у меня может быть объект UIAddress, который имеет 12 полей String. Я контролирую это: независимо от того, что делает пользователь, я могу убедиться, что пользовательский интерфейс возвращает 12 полей. Затем вы можете создать экземпляр UIAddress и вызвать isComplete() для этого:

UIAddress uiAddress = uiForm.getAddress();
if (uiAddress.isComplete()) {
    Address modelAddress = uiAddress.cleanedData();
}

Все будет зависеть от вашего намеченного дизайна, но для вас действительно есть большая гибкость. ИМХО, способ "сделать это" - это ввести isComplete в Адрес.

0 голосов
/ 21 апреля 2009

Модель адреса IMO должна содержать информацию о том, является ли адрес полным или неполным.

Допустим, позже, если бизнес-логика изменится и станет неполной, значит не менее 5 символов. Тогда зачем валидатору беспокоиться об этом изменении логики?

Я считаю, что объекты должны содержать свои данные и состояние.

0 голосов
/ 21 апреля 2009

isComplete () - это проверка или команда?

Если это проверочная функция (if (isComplete ()) {}), то она входит в валидатор. Поскольку у вас есть пользовательский интерфейс и модель, я предполагаю, что у вас есть контроллер, который координирует между ними. В этом случае просто вызовите функцию проверки из валидатора, прежде чем вызывать подпрограмму сохранения, которая пометит вашу модель как завершенную.

Если isComplete () - это команда, которая помечает ваши данные как завершенные, то я думаю, что вы должны изменить эту часть дизайна. Слишком грязно для моих вкусов.

0 голосов
/ 21 апреля 2009

Вы можете посмотреть на Композит. Иметь базовый валидатор, а затем подклассифицировать к конкретному AddressValidator. Теперь для валидатора имеет смысл знать, как работают адреса, но не для того, чтобы беспокоиться о том, как проверять любые другие элементы.

Затем сгруппируйте множество валидаторов в ValidatorCollection и вызовите его метод .Validate (), и он вызовет то же самое для всех дочерних элементов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...