Основной источник сложности в JavaScript | OTUS
🔥 Начинаем BLACK FRIDAY!
Максимальная скидка -25% на всё. Успейте начать обучение по самой выгодной цене.
Выбрать курс

Курсы

Программирование
iOS Developer. Basic
-25%
Python Developer. Professional
-25%
Разработчик на Spring Framework
-25%
Golang Developer. Professional
-25%
Python Developer. Basic
-25%
iOS Developer. Professional
-25%
Node.js Developer
-25%
Unity Game Developer. Professional
-25%
React.js Developer
-25%
Android Developer. Professional
-25%
Software Architect
-25%
C++ Developer. Professional
-25%
Backend-разработчик на PHP Web-разработчик на Python Алгоритмы и структуры данных Framework Laravel PostgreSQL Team Lead Разработчик голосовых ассистентов и чат-ботов Архитектура и шаблоны проектирования Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT IoT-разработчик Подготовка к сертификации Oracle Java Programmer (OCAJP) Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Azure для разработчиков"
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-25%
DevOps практики и инструменты
-25%
Архитектор сетей
-25%
Инфраструктурная платформа на основе Kubernetes
-25%
Супер-интенсив «ELK»
-16%
Супер-интенсив «IaC Ansible»
-16%
Administrator Linux. Professional MS SQL Server Developer Безопасность Linux PostgreSQL Reverse-Engineering. Professional CI/CD VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Administrator Linux.Basic Супер-интенсив "Tarantool"
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Основной источник сложности в JavaScript

Это прозвучит странно, но основным и самым большим источником сложности является сам код. Собственно говоря, именно отсутствие какого-нибудь кода — это лучший способ написать безопасное и надёжное программное приложение. К сожалению, это возможно далеко не всегда, но выход всё же есть — уменьшить объём кода, ведь чем меньше кода, тем меньше сложность и меньше пространства для ошибок. Не зря в IT-мире говорят, что в то время, когда джуниоры пишут код, сеньоры его удаляют )).

Проблема № 1: длинные файлы

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

Как известно, многие разработчики продолжают вмещать в один и тот же файл всё больше кода. А если ограничения на длину файла будут отсутствовать, файлы иногда растут бесконечно. При этом специалисты утверждают, что файл, содержащий более 200 строк кода, становится чересчур большим для восприятия. Такие файлы трудно поддерживать, а код делает слишком много, что, в свою очередь, нарушает принцип единственной ответственности.

Проблема решается путём разбиения больших файлов на более детализированные модули.

Конфигурация, предлагаемая ESLint:

rules:
  max-lines:
  - warn
  - 200

Проблема № 2: длинные функции

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

Давайте посмотрим на фрагмент кода express.js, предназначенный для обновления записи в блоге:

router.put('/api/blog/posts/:id', (req, res) => {
  if (!req.body.title) {
    return res.status(400).json({
      error: 'title is required',
    });
  }

  if (!req.body.text) {
    return res.status(400).json({
      error: 'text is required',
    });
  }

  const postId = parseInt(req.params.id);

  let blogPost;
  let postIndex;
  blogPosts.forEach((post, i) => {
    if (post.id === postId) {
      blogPost = post;
      postIndex = i;
    }
  });

  if (!blogPost) {
    return res.status(404).json({
      error: 'post not found',
    });
  }

  const updatedBlogPost = {
    id: postId,
    title: req.body.title,
    text: req.body.text
  };

  blogPosts.splice(postIndex, 1, updatedBlogPost);

  return res.json({
    updatedBlogPost,
  });
});

Мы видим, что тело функции обладает длиной в 40 строк, плюс решает целый ряд задач: — выполняет анализ идентификатора сообщения; — ищет существующее сообщение в блоге; — осуществляет проверку данных, введённых пользователем, возвращая ошибку, если ввод неправилен; — обновляет коллекцию сообщений, возвращая обновлённые сообщения в блоге.

Всё это мы могли бы преобразовать в несколько функций объёмом меньше. Результат мог бы выглядеть приблизительно так:

router.put("/api/blog/posts/:id", (req, res) => {
  const { error: validationError } = validateInput(req.body);
  if (validationError) return errorResponse(res, validationError, 400);

  const { blogPost } = findBlogPost(blogPosts, req.params.id);

  const { error: postError } = validateBlogPost(blogPost);
  if (postError) return errorResponse(res, postError, 404);

  const updatedBlogPost = buildUpdatedBlogPost(req.body);

  updateBlogPosts(blogPosts, updatedBlogPost);

  return res.json({updatedBlogPost});
});

Смотрим конфигурацию ESLint:

rules:
  max-lines-per-function:
  - warn
  - 20

Проблема № 3: сложные функции

Рядом с длинными функциями идут сложные функции. Что делает функцию сложнее? Например, вложенные колбэки (callback) либо высокая цикломатическая сложность.

Те же вложенные колбэки нередко становятся причиной колбэк-ада (callback hell). При этом проблему можно решить с помощью промисов (promise) и асинхронных функций await() и async().

Рассмотрим функцию с глубоко вложенными колбэками:

fs.readdir(source, function (err, files) {
  if (err) {
    console.error('Error finding files: ' + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.error('Error identifying file size: ' + err)
        } else {
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
              if (err) console.error('Error writing file: ' + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

Теперь несколько слов про цикломатическую сложность, перегружающую функции. Речь идёт о числе логических операторов в вашей функции: (операторы if, switch-утверждения, циклы). Воспринимать такие функции трудно, поэтому их применение следует ограничивать:

if (conditionA) {
  if (conditionB) {
    while (conditionC) {
      if (conditionD && conditionE || conditionF) {
        ...
      }
    }
  }
}

Что предлагает ESLint:

rules:
  complexity:
  - warn
  - 5

  max-nested-callbacks:
  - warn
  - 2
  max-depth:
  - warn
  - 3

Осталось напомнить, что есть ещё один способ уменьшить объём вашего кода — декларативное программирование. Но о нём мы уже писали.

Источник

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться
🎁 Максимальная скидка!
Черная пятница уже в OTUS! Скидка -25% на всё!