Все статьи | Код

Что такое Guard Expression и зачем применять этот подход в разработке

Что такое Guard Expression и зачем применять этот подход в разработке главное изображение

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

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

Цикломатическая сложность

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

Частично оценить их позволяет цикломатическая сложность — количество линейно независимых маршрутов через программный код. Эта мера была разработана Томасом Дж. Маккейбом в 1976 году. Если исходный код не содержит никаких точек ветвления или циклов, то сложность равна единице, поскольку есть только один маршрут следования через код. Но в ситуации, когда используются условия и циклы, цикломатическая сложность будет выше единицы.

// Complexity: 1
const f1 = () => {
 console.log('Hello');
};

// Complexity: 2
const f2 = (condition) => {
 if (condition) {
   console.log('Hello');
 }
}

// Complexity: ?
const f3 = (condition, language) => {
 message = ''

 if (condition) {
   switch (language) {
     case 'de':
       message = 'Guten Tag'
     case 'es':
       message = 'Hola'
     case 'fr':
       message = 'Bonjour'
     default:
       message = 'Hello';
   }
 }

 console.log(message);
}

В этом случае на помощь приходит Guard Expression. Этот подход (или паттерн), помогает лучше структурировать код сделать код более простым и понятным, иногда снизить цикломатическую сложность. В качестве примера рассмотрим функцию, которая принимает на вход пол и возраст. Для людей старше 18 в зависимости от пола она возвращает строку yes или no. Для всех остальных — null:

const f = (age, sex) => {
  if (age >= 18) {
    if (sex === 'male') {
      return 'yes';
    }
    if (sex === 'female') {
      return 'no';
    }
  }

  return null;
}

Эту функцию можно сделать проще, разбив условие и добавив условие «вернуть null, если младше 18 лет». Оно гораздо более простое и очевидное, почему поставим его первым:

const f = (age, sex) => {
  if (age < 18) {
    return null;
  }

  if (sex === 'male') {
    return 'yes';
  }

  if (sex === 'female') {
    return 'no';
  }
}

Уровень вложенности снизился. В такой реализации функции сложнее ошибиться: все, что пишется ниже guard expression (первая проверка в данном случае), попадает под требование «от 18 и старше». В первом примере код для этого условия нужно не забывать вставить внутрь соответствующего условия.

Читайте также: Как сохранять фокус на протяжении всего обучения: советы от Хекслета

Отсечение пограничных случаев

Вторая задача Guard Expression — сразу же обработать пограничные случаи. Речь идет о дополнительных проверках, которые могут усложнить и удлинить код, но не позволят функции или программе выполняться при определенных условиях.

const average = (numbers) => {
 // Если массив чисел пустой, то возвращаем сразу 0
 if (numbers.length === 0) {
   return 0;
 }

 result = 0;

 for (const number of numbers) {
   result += number;
 }

 return result / numbers.length;
}

console.log(average([1, 2, 3, 4, 5]));
// => 3

Рассмотрим это на примере решения задачи по проверке числа на простоту. Ее условие звучит так: простое число — это натуральное число, которое делится только на 1 и себя. 0 и 1 - не простые числа.

0 и 1 — это и есть крайние случаи: в функции нужно написать правило проверки только тех чисел, которые выше единицы. В коде это будет выглядеть так:

const isPrime = (num) => {
  if (num < 2) {
    return false;
  }

  for (let i = 2; i <= Math.sqrt(num); i += 1) {
    if (num % i === 0) {
      return false;
    }
  }

  return true;
};

Еще один пример: в проекте Hexlet SICP есть функция, которая отмечает прохождение пользователем упражнения. Она работает только для авторизованных пользователей, которые ранее не выполняли упражнение. Крайние случаи — отсутствие авторизации и прохождение упражнения два и более раз:

class ExerciseService
{
    public function completeExercise(User $user, Exercise $exercise): void
    {
        if ($user->hasCompletedExercise($exercise) || $user->isGuest()) {
            return;
        }

        $user->exercises()->syncWithoutDetaching($exercise);
        $this->activityService->logCompletedExercise($user, $exercise);
    }
}

Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях

Аватар пользователя Oleg Sabitov
Oleg Sabitov 10 июня 2022
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Фронтенд-разработчик
Профессия
Разработка фронтенд-компонентов веб-приложений
30 июня 10 месяцев
Иконка программы Python-разработчик
Профессия
Разработка веб-приложений на Django
30 июня 10 месяцев
Иконка программы PHP-разработчик
Профессия
Разработка веб-приложений на Laravel
30 июня 10 месяцев
Иконка программы Node.js-разработчик
Профессия
Разработка бэкенд-компонентов веб-приложений
30 июня 10 месяцев
Иконка программы Fullstack-разработчик
Профессия
Новый
Разработка фронтенд и бэкенд компонентов веб-приложений
30 июня 16 месяцев
Иконка программы Верстальщик
Профессия
Вёрстка с использованием последних стандартов CSS
в любое время 5 месяцев
Иконка программы Java-разработчик
Профессия
Разработка приложений на языке Java
30 июня 10 месяцев
Иконка программы Разработчик на Ruby on Rails
Профессия
Создает веб-приложения со скоростью света
30 июня 5 месяцев