﻿# Предупреждения помогают писать лаконичный код

Некоторые предупреждения анализатора или компилятора сложно однозначно классифицировать как ложное срабатывание или указание на настоящую ошибку\. Бывает, что формально анализатор/компилятор прав, но и код работает правильно\. Что делать? Возможно, это повод упростить код\.

![0968_simplify_ru/image1.png](https://import.viva64.com/docx/blog/0968_simplify_ru/image1.png)

Известным недостатком всех статических анализаторов кода является выдача ими [ложных срабатываний](https://pvs-studio.ru/ru/blog/terms/6461/)\. С предупреждениями компилятора приблизительно такая же история\.

Существуют различные способы подавить явно ложные срабатывания и даже [сценарии](https://pvs-studio.ru/ru/blog/posts/0743/) внедрения методологии статического анализа в большие legacy\-проекты, где таких срабатываний точно будет много\.

Что интересно, про часть предупреждений сложно сказать: ложные они или нет\. Про них мы сегодня и поговорим\.

Бывает, что анализатор/компилятор совершенно прав, выдавая предупреждение, но при этом код работает ровно так, как и задумывалось\. Ошибки в нём нет\. Обычно это свидетельствует о том, что код избыточен, переусложнён или "с запахом"\. Чтобы было понятнее, давайте сразу перейдём к практическому примеру и рассмотрим фрагмент кода из проекта Blender:

```cpp
static bool lineart_do_closest_segment(....)
{
  int side = 0;
  ....
  /* No need to cut in the middle,
     because one segment completely overlaps the other. */
  if (side) {
    if (side > 0) {
      *is_side_2r = true;
      *use_new_ref = true;
    }
    else if (side < 0) {          // <=
      *is_side_2r = false;
      *use_new_ref = false;
    }
    return false;
  }
  ....
}
```

Анализатор PVS\-Studio выдаёт здесь предупреждение "[V547](https://pvs-studio.ru/ru/docs/warnings/v547/): Expression 'side < 0' is always true" на строчку, выделенную комментарием\.

Уберём всё лишнее и рассмотрим код подробнее\.

```cpp
if (side) {
  if (side > 0) {
    *is_side_2r = true;
    *use_new_ref = true;
  }
  else if (side < 0) {
    *is_side_2r = false;
    *use_new_ref = false;
  }
  return false;
}
```

Первое условие отсекает случаи, когда переменная _side_ равна 0\. Далее в зависимости от того, меньше или больше нуля эта переменная, в переменные записываются разные значения и функция завершает свою работу\.

В момент вычисления условия _side < 0_ анализатор уверен, что переменная всегда меньше 0, поэтому и выдаёт предупреждение\.

Формально анализатор прав\. Всегда истинные/ложные условия часто свидетельствуют о наличии в коде опечатки или другой ошибки\. Вот [сотни примеров ошибок](https://pvs-studio.ru/ru/blog/examples/v547/), которые выявляет диагностика V547\.

Однако здесь видно, что никакой ошибки нет\. Это просто немного избыточный код\. Лишнее условие написано для красоты или для перестраховки\. Ещё один вариант – избыточность возникла в процессе рефакторинга\. Такое тоже бывает, и в некоторых статьях я рассматривал такие случаи\.

Тем не менее, вернёмся к срабатыванию анализатора\. Программист прав\. Анализатор прав\. Что делать? Самый простой вариант – точечно подавить предупреждение с помощью специального комментария:

```cpp
if (side) {
  if (side > 0) {
    *is_side_2r = true;
    *use_new_ref = true;
  }
  else if (side < 0) {    //-V547
    *is_side_2r = false;
    *use_new_ref = false;
  }
  return false;
}
```

Такой вариант избавиться от предупреждения мне нравится меньше всего\. Давайте подумаем, какие ещё варианты изменения кода возможны\. Причём хочется, чтобы код остался таким же понятным и красивым\. Собственно, изначальный код совсем неплох и хорошо читается\.

Сразу отмечу, что здесь не будет какого\-то идеального решения\. Будет рассмотрено несколько вариантов, и каждый может остановиться на том, который ему больше нравится или больше соответствует стандарту кодирования, принятому в команде\.

Следующий простой способ избавиться от предупреждения анализатора – это удалить лишнюю проверку:

```cpp
if (side) {
  if (side > 0) {
    *is_side_2r = true;
    *use_new_ref = true;
  }
  else {
    *is_side_2r = false;
    *use_new_ref = false;
  }
  return false;
}
```

Собственно, ничего не изменилось\. Просто исчезло одно условие, и вместе с ним исчезнет предупреждение\. Однако лично мне такой вариант не очень нравится, так как читать код стало чуть сложнее\. В голове нужно помнить, где какое значение имеет переменная _side_\.

Возможно, если бы я писал код, то он был бы таким:

```cpp
if (side > 0) {
  *is_side_2r = true;
  *use_new_ref = true;
  return false;
}
else if (side < 0) {
  *is_side_2r = false;
  *use_new_ref = false;
  return false;
}
```

Нет вложенных _if_\-ов\. Сложность кода уменьшилась\. Он легко читается и сразу понятен\. Вероятно, я бы остановился именно на таком решении\.

Тем не менее, если вы ценитель короткого кода, то можно продолжить\. Как вам такой вариант?

```cpp
if (side) {
  const bool sideGreaterThanZero = side > 0;
  *is_side_2r = sideGreaterThanZero;
  *use_new_ref = sideGreaterThanZero;
  return false;
}
```

В целом, короткий и понятный код\. Хотя, на мой взгляд, его сложнее читать, чем предыдущий фрагмент\. Возможно, это дело вкуса\.

Можно ещё короче? Можно:

```cpp
if (side) {
  *use_new_ref = *is_side_2r = side > 0;
  return false;
}
```

Впрочем, я не в восторге от такого кода\. Это уже из области "смотрите, как я могу"\. Не буду рекомендовать такой вариант\. Тем не менее, получилось интересно\. Обратив внимание на избыточное условие и проведя рефакторинг, можно сократить количество строк кода с 11 до 4\.

Какой именно вариант изменения кода выбрать – решать вам\. Моей целью было показать, что, когда анализатор/компилятор выдаёт срабатывание на корректный код, не стоит спешить подавлять предупреждение\. Возможно, это повод для небольшого рефакторинга и упрощения кода\.

**Дополнительные ссылки:**

1. Другие заметки по мотивам мониторинга проекта Blender: [0](https://pvs-studio.ru/ru/blog/posts/cpp/0807/), [1](https://pvs-studio.ru/ru/blog/posts/cpp/0817/), [2](https://pvs-studio.ru/ru/blog/posts/cpp/0910/), [3](https://pvs-studio.ru/ru/blog/posts/cpp/0922/), [4](https://pvs-studio.ru/ru/blog/posts/cpp/0924/), [5](https://pvs-studio.ru/ru/blog/posts/cpp/0936/)\.
1. [Анализатор кода не прав, да здравствует анализатор](https://pvs-studio.ru/ru/blog/posts/cpp/0779/)\.
1. [Почему PVS\-Studio не предлагает автоматические правки кода](https://pvs-studio.ru/ru/blog/posts/cpp/0776/)\.
1. И в конце ещё одна ссылочка, уже не наша статью, но на ту же тему: [False positives are our enemies, but may still be your friends](https://blog.sonarsource.com/false-positives-our-enemies-but-maybe-your-friends/)\.