javascript

Округление как зеркало корпоративной культуры в IT-продуктах

  • вторник, 30 декабря 2025 г. в 00:00:06
https://habr.com/ru/articles/981444/

Всё большое начинается с малого. (с) Дэвид. Фильм Прометей 2012

Представление чисел в IT сфере - одна из самых простых вещей, которую интуитивно знает каждый разработчик, аналитик, тестировщик, админ (нужное подчеркнуть).

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

Как округлить?
Как округлить?

Точные определения и механизмы легко гуглятся.

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

Курс доллара - 77.69 смотрим в интернете, говорим 77 или 78 рублей

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

Данная статья посвящается наблюдениям, как игнорирование важности простых математических операций коррелирует с качеством IT-продукта и с корпоративной культурой.

Почему едут сроки и откуда человеко-часы?

В project-менеджменте модно оценивать время выполнения декомпозированных задач, таскать тикеты на канбан-досках, планировать релизы итд.

Казалось бы, процесс отлажен, все прекрасно понимают бизнес-процессы, жизненные циклы ПО, технологии, а задачи превращаются в АД с последующим выгоранием.

А причем тут округление?

Давайте разберем пример достаточно простой однотипной задачи реализации загрузки изображения на сервер через форму.

Классическая постановка: добавить в форму поле с возможностью прикрепления изображения

В данном примере форматы jpg, png и прочие опустим, сконцентрируемся на размере файла.

Если в задаче отсутствуют требования к размерам, то разработчик сделает по дефолту. А какой у нас дефолт? В каждом проекте свой, где-то конфиг, где-то nginx ограничения, масса вариантов.

Далее программист реализует, что-то обязательно пойдет не так, и мы возвращаемся к требованиям. А где требования? С потолка?

Приходится вводить ограничения - например, не более 8 мегабайт.

И вот оно округление - явный формат размера файла можно интерпретировать как угодно, а в конфигах или в хард-коде, естественно, "кто в лес, кто по дрова".

Начинаем разбираться. 8 мегабайт - это:

  • 8 Mb

  • 8 MiB

  • 8 * 1000 Kib

  • ... и еще куча других вариантов

В итоге имеем - ограничение поставлено, а всё равно не работает, пользователи жалуются, опять идем требования дособирать, текст с label-ом делаем, валидацию, цикл повторяется.

Опять не работает, снова гневный отзыв?

А все почему? Упрощение и округление без четких требований.

Если файл хранится в БД, то там может быть ограничение на размер.

Если через php грузить - там в нескольких местах разные конфиги.

В Spring конфиге поддерживается разное написание.

И главное - каждый интерпретирует мегабайты на свой лад. Кому-то 8 mb это 8000кb, а кому то 8*1024*1024*1024.

А в разговорной речи и в подписи:

Загружайте картинки меньше 8МБ для тела публикации и меньше 1МБ для обложки публикации

Итог: задача разработки на 1 час времени затягивается на целый день, да еще с суетой, привлечением тестировщиков, аналитиков и менеджера.

В моей практике я такой кейс неоднократно встречал. Начал задумываться - а что здесь не так? Где узкое место?

Проблема в корпоративной культуре.

Там, где вокруг IT суетятся чайка-менеджеры в связке с программистами типа "солдат", простые требования, которые можно легко собрать, оформить в задачу и написать подробное разъяснение просто игнорируются.

А в компаниях, где отсутствует хаос, процессы налажены, внимание к деталям, таким как валидация и округление не игнорируется.

А теперь к коду

Все мы любим лайки и просмотры. Сервисы их собирают, считаю, агрегируют.

После прочтения поста или статьи, прослушивания аудио или просмотра видео хочется статистики и аналитики.

Упрощенно, одно полезное действие ведет к одному запросу на сервер. Можно простой REST, хук, асинхрон, WebSocket, да что угодно взять в качестве реализации, главное отправить событие на бэкенд. Далее оно обрабатывается, количества событий считаются, сохраняются.

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

Полезная нагрузка из ответа сервера:

{
  "postId": "d153e353-2a32-4763-b930-b27fbc980da5", // UUID для примера идентификатора поста
  "count": 1244128 // Количество просмотров
}

Сount = 1244128 для отображения на фронте нужно округлить.

Понимаете, к чему я веду?

1244128 просмотров превратится в 1.2M 👀 

Или в 1.3M 👀 ?

Задача простая, как правило отдается джуну или ИИ.

Давайте напишем простую функцию в лоб.

let data = {
        "postId": "d153e353-2a32-4763-b930-b27fbc980da5",
        "count": 1244128
    }

function ourRound (count) {

      if (count <= 0) {
          console.log("Число: " + count + "меньше нуля");
          return count;
      }

      if (count > 0 && count < 1000) {
          return count + '';
      }

      if (count >= 1000 && count < 1000000) {
          return Math.ceil(count/1000) + 'K';
      }

      if (count >= 1000000) {
          return Math.ceil(count/1000000) + 'M';
      }
}

console.log(ourRound(data.count));

// Упс! 2M ответ вместо наших 1.2M

Упс! 2M ответ вместо наших 1.2M

Конечно, надо поправить.

let data = {
        "postId": "d153e353-2a32-4763-b930-b27fbc980da5",
        "count": 1244128
    }

function ourRound (count) {

    if (count <= 0) {
        console.log("Число: " + count + "меньше нуля");
        return count;
    }

    if (count > 0 && count < 1000) {
        return count + '';
    }

    if (count >= 1000 && count < 1000000) {
        return parseFloat(
            ( count / 1000 )
        ).toFixed(2) + "K"
    }

    if (count >= 1000000) {
        return parseFloat(
                ( count / 1000000 )
            ).toFixed(2) + "M"
    }
}

console.log(ourRound(data.count));

Уже лучше 1.24M 👀 

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

Смотрите, я сам на JS/TS несколько лет не писал, в данном примере можно смело сказать, что я джун. Простая абстрактная задача у меня вызвала небольшие затруднения на 15-20 минут, я её сделал в лоб и не до конца, и вот так здесь её преподношу.

И это происходит в практически в каждом проекте.

Нить рассуждений:

  • Нужно какое-то округление, посмотри там и там, так щас в куче сервисов делают

  • Загуглить, скопипастить из какой-то либы, подсмотреть, сгенерировать

  • Навертеть приемлемый результат

  • Вывести на экран в нужном месте

Из плюсов - быстро, более-менее работает, протестируем, если что - поправим.

Из минусов:

  • А где требования?

  • Какой тип округления выбрать? ceil, floor?

  • До какого знака? А единообразие?

  • А как оптимально сократить расход ресурсов при клиент-серверном взаимодействии?

  • А в каких местах будет применяться округление?

  • Сколько нужно эндпоинтов? Может быть сделать на сервере сразу, или вообще в БД?

А что архитектура?

Микросервисы, микрофронты. Куда же без них?

Продолжаем рассуждения. Масштабируемость. Мы все хотим, чтобы сервисы летали и отдавали на фронт достоверные данные.

В реальности существует противоречие - синхронное действие, в нашем случае просмотр запоминается пользователем как "Я посмотрел, я лайкнул".

При переливке данных из одного модуля в другой происходит отставание, равное времени обработки, например, разбор очередей, вставка в таблицу статистики, очистка от дублей и прочее.

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

И снова мы получаем - кто в лес, кто по дрова.

И про культуру

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

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

И пользователям снаружи это заметно. Не сразу, но заметно. Тот же Вконтакте, Одноклассники, Facebook - регулярно слышим "скатились".

А почему? Потому-что нет культуры. И это подтверждается изнутри.

Мой знакомый по универу, топовый аналитик рассказал, что решил пойти поработать в VK после нескольких лет в Авито. Его хватило на несколько месяцев, сказал, что там внутри бардак ... и вернулся обратно в Авито на более высокую должность.

С моей стороны скажу - я некоторый период времени занимаюсь музыкой, активно продвигаю свою рок-группу в социальных сетях, и каждый раз наблюдаю нестыковки с округлением. Прилагаю скрины)

Округление 1K
Округление 1K
Округление 1.1K
Округление 1.1K

Итог

На самом деле цель данной статьи - порефлексировать. В моем опыте была пара неудачных компаний, где клали с прибором на требования, плодили хаос, кормили завтраками.

По факту работать было катастрофически сложно. Но я отдаю себе в этом отчет, это и моя вина - нужно уметь доносить до руководства информацию о правильном сборе требований, о налаживании процессов разработки и тестирования, минимизации халтуры, улучшения качества продукта.

Каждый из нас знает, что любой код можно допилить, улучшить, а можно бросить - и так сойдет.

Я понимаю, что сервисы и без округления прекрасно работают, приносят пользу, деньги зарабатываются, катастрофы не случается. Да и современные компы плюс-минус лишнее вычисление без проблем тянут, хотя фризы случаются.

Как говорится, нужен баланс, эстетика, удовольствие, а не хаотичная культура или её отсутствие в паре с выгоранием!

Спасибо за прочтение!