Должен ли класс подтверждать себя или создать другой класс для его проверки? - PullRequest
20 голосов
/ 08 февраля 2010

Допустим, у меня есть такой класс:

class NavigationData
{
  float roll;
  float pitch;
  double latitude;
  double longitude;
}

и если я хочу создать метод:

const bool validate() const;

, который в основном проверяет, содержат ли 4 поля допустимые значения.

Должен ли validate () быть частью класса NavigationData или я должен создать что-то вроде NavigationDataValidator, которое содержит метод validate (const NavigationData &).

Я просто привожу простой пример, очевидно, мой настоящий класс намного сложнее, чем этот. Я ищу хорошие принципы ОО.

Говоря по-другому: учитывая метод, как мы узнаем, должен ли он принадлежать классу или он должен принадлежать отдельному классу?

Ответы [ 8 ]

23 голосов
/ 08 февраля 2010

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

Однако "логически непротиворечивый и действительный" отличается от "имеет смысл в области" , поэтому иногда ответственность внешнего класса заключается в обеспечении того, чтобы Правила домена соблюдаются . Например, PersonValidator может потребовать, чтобы у Person был номер телефона, который находится в США. Но Person не обязательно должен знать что-либо о том, находится ли PhoneNumber в США.

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

7 голосов
/ 08 февраля 2010

Правильный ответ: это зависит .

Естественное место для размещения такой объектной логики - сам объект. Иногда, хотя правила проверки могут зависеть от механизма правил или какой-то более крупной «структуры», которая проверяет вещи. Другая ситуация, когда вы не хотите выполнять проверку внутри объекта, - это когда проверка принадлежит другому уровню, или слою, или приложению, например слою представления.

3 голосов
/ 08 февраля 2010

Ваш класс должен быть спроектирован таким образом и предоставлять такие методы, которые validate () имеет значение всегда true :

  • после вызова любого публичного конструктора
  • до и после вызова любого открытого метода
  • (в C ++ - land) до вызова деструктора

Такие методы validate () называются инвариантами класса и являются важной частью Проектирование по контракту .

1 голос
/ 08 февраля 2010

Это зависит от контекста. Иногда ваш объект является абсолютно допустимым внутри, но в контексте его значения не являются приемлемыми.

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

Если у вас есть класс Domain Model, он должен выполнить некоторую проверку.

P.S. просто мое личное предпочтение: isValid () вместо validate (), когда метод возвращает логическое значение.

1 голос
/ 08 февраля 2010

Я бы сказал, что он проверяет себя, пока действительные значения не зависят от того, какие другие классы используют NavigationData.

В основном, поскольку широта и угол всегда должны быть в пределах +/- 90 градусов, а долгота и крен всегда должны быть в пределах +/- 180 градусов, сохраняйте валидатор в классе.

(Кстати, а как насчет заголовка?)

1 голос
/ 08 февраля 2010

Зависит ...

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

1 голос
/ 08 февраля 2010

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

0 голосов
/ 08 февраля 2010

Как уже было сказано, это зависит.

Но в вашем случае я бы выбрал другое решение, создав новый неизменный класс для гео-координат

class GeoCoordinates
{
    double Latitude;
    double Longitude;
}

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

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