Также известен как 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 часов чтения.

Или попробуйте наш интерактивный курс. Он гораздо более интересный, чем банальный текст.

Узнать больше...