Скидки до 20% + 2-ая профессия бесплатно и подарки на 50 000₽

Главная | Все статьи | Код

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

Время чтения статьи ~4 минуты 29
Что такое 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
29
Похожие статьи
Рекомендуемые программы
профессия
Верстка на HTML5 и CSS3, Программирование на JavaScript в браузере, разработка клиентских приложений используя React
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на Python, Разработка веб-приложений и сервисов используя Django, проектирование и реализация REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
Тестирование веб-приложений, чек-листы и тест-кейсы, этапы тестирования, DevTools, Postman, SQL, Git, HTTP/HTTPS, API
4 месяца
с нуля
Старт 26 декабря
профессия
Программирование на Java, Разработка веб-приложений и микросервисов используя Spring Boot, проектирование REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
новый
Google таблицы, SQL, Python, Superset, Tableau, Pandas, визуализация данных, Anaconda, Jupyter Notebook, A/B-тесты, ROI
9 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на PHP, Разработка веб-приложений и сервисов используя Laravel, проектирование и реализация REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на Ruby, Разработка веб-приложений и сервисов используя Rails, проектирование и реализация REST API
5 месяцев
c опытом
Старт 26 декабря
профессия
Программирование на JavaScript в браузере и на сервере (Node.js), разработка бекендов на Fastify и фронтенда на React
16 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на JavaScript, разработка веб-приложений, bff и сервисов используя Fastify, проектирование REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
новый
Git, JavaScript, Playwright, бэкенд-тесты, юнит-тесты, API-тесты, UI-тесты, Github Actions, HTTP/HTTPS, API, Docker, SQL
8 месяцев
c опытом
Старт 26 декабря