Класс должен проверить себя или создать другой класс для проверки его?

Скажем, у меня есть класс как:

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

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

const bool validate() const;

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

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

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

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

20
задан sivabudh 8 February 2010 в 17:36
поделиться

8 ответов

Наконечник: Используйте forall , чтобы определить, удовлетворяют ли все элементы в коллекции определенному предикату (например, равенство длины).

-121--2892418-

Определение собственного свопа . Эта функция должна вызывать std:: swap для любого типа T, кроме типов.

namespace help // my namespace
{ 

  template <class T> 
  void swap(T& t1, T& t2) 
  { 
     ::std::swap(t1, t2);  // Redirect to std for almost all cases
  } 

  // My special case: overloading
  template <class T> 
  void swap(MyType<T>& t1, MyType<T>& t2) 
  { 
     t1.swap(t2); 
  } 

}  //  namespace help 

// Sample
int main() 
{

   MyType<int> t1, t2; // may be add initialization
   int i1=5, i2=7;

   help::swap(t1, t2); //  Your swap
   help::swap(i1, i2); //  Redirect to std::swap
}
-121--2814119-

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

Однако «логически непротиворечивый и действительный» отличается от «имеет смысл в домене» , поэтому иногда является обязанностью внешнего класса обеспечить соблюдение правил домена . Например, PersonValidator может потребовать, чтобы Человек имел номер телефона, который находится в США. Но Лицо не обязательно должно знать что-либо о том, находится ли StartNumber в США.

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

23
ответ дан 30 November 2019 в 00:05
поделиться

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

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

7
ответ дан 30 November 2019 в 00:05
поделиться

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

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

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

3
ответ дан 30 November 2019 в 00:05
поделиться

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

1
ответ дан 30 November 2019 в 00:05
поделиться

Depends...

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

1
ответ дан 30 November 2019 в 00:05
поделиться

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

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

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

1
ответ дан 30 November 2019 в 00:05
поделиться

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

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

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

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

1
ответ дан 30 November 2019 в 00:05
поделиться

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

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

class GeoCoordinates
{
    double Latitude;
    double Longitude;
}

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

class Airport
{
    GeoCoordinates Location;
    ...
}
0
ответ дан 30 November 2019 в 00:05
поделиться