Також відомий як Introduce Assertion

Рефакторинг Введення перевірки твердження

Тут під перевірками мається на увазі використання викликів assert().

Проблема

Коректна робота ділянки коду припускає наявність якихось певних умов або значень.

Рішення

Замініть ці припущення конкретними перевірками.

До
double getExpenseLimit() {
  // should have either expense limit or a primary project
  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.getMemberExpenseLimit();
}
Після
double getExpenseLimit() {
  Assert.isTrue(expenseLimit != NULL_EXPENSE || primaryProject != null);

  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.getMemberExpenseLimit();
}
До
double GetExpenseLimit() 
{
  // should have either expense limit or a primary project
  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.GetMemberExpenseLimit();
}
Після
double GetExpenseLimit() 
{
  Assert.IsTrue(expenseLimit != NULL_EXPENSE || primaryProject != null);

  return (expenseLimit != NULL_EXPENSE) ?
    expenseLimit:
    primaryProject.GetMemberExpenseLimit();
}
До
function getExpenseLimit() {
  // should have either expense limit or a primary project
  return ($this->expenseLimit != NULL_EXPENSE) ?
    $this->expenseLimit:
    $this->primaryProject->getMemberExpenseLimit();
}
Після
function getExpenseLimit() {
  assert($this->expenseLimit != NULL_EXPENSE || isset($this->primaryProject));

  return ($this->expenseLimit != NULL_EXPENSE) ?
    $this->expenseLimit:
    $this->primaryProject->getMemberExpenseLimit();
}
До
def getExpenseLimit(self):
    # should have either expense limit or a primary project
    return self.expenseLimit if self.expenseLimit != NULL_EXPENSE else \
        self.primaryProject.getMemberExpenseLimit()
Після
def getExpenseLimit(self):
    assert (self.expenseLimit != NULL_EXPENSE) or (self.primaryProject != None)

    return self.expenseLimit if (self.expenseLimit != NULL_EXPENSE) else \
        self.primaryProject.getMemberExpenseLimit();

Причини рефакторингу

Ділянка коду створює припущення про щось (наприклад, про поточний стан об'єкту, значення параметра або локальної змінної). Зазвичай це припущення ніколи не буде порушено хіба що за наявності якоїсь помилки.

Зробіть ці припущення явними, додавши відповідні перевірки. Як і підказки типів в параметрах методів, ці перевірки можуть грати роль живої документації коду.

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

Переваги

  • Якщо якесь припущення невірне і в результаті код дає також невірний результат, краще відразу зупинити виконання, поки це не привело до фатальних наслідків і псування даних. Крім того, це означає, що ви забули написати якийсь тест в наборі тестів вашої програми.

Недоліки

  • Іноді замість простої перевірки краще вставити виключення. При цьому ви можете вибрати необхідний клас виключення і дати іншому коду можливість коректно його обробити.

  • В яких випадках виключення краще простої перевірки? Якщо до нього може привести діяльність користувача або системи, і ви можете обробити це виключення. З іншого боку, звичайні безіменні необроблювані виключення роблять теж саме, що й перевірки - ви їх також не обробляєте, вони можуть бути викликані тільки як результат бага в програмі, який ніколи не повинен був виникнути.

Порядок рефакторингу

Коли ви розумієте, що передбачається якась умова, додайте перевірку цієї умови, щоб перевірити її напевно.

Додавання перевірки не повинне змінювати поведінку програми.

Не переборщуйте з використанням перевірок для всього, що тільки можна, на вибраній ділянці коду. Треба перевіряти лише ті умови, без яких код перестане коректно працювати. Якщо ваш код нормально працює, у тому числі, у разі, коли перевірка не проходить успішно, таку перевірку можна прибрати.

Замучились читати?

Збігайте за подушкою, в нас тут контенту на 7 годин читання.

Або спробуйте наш новий інтерактивний курсу. Він набагато цікавіший за банальний тест.

Дізнатися більше...