Автор — Дэвид Хейни (David Haney), ведущий инженер-программист Stack Overflow

Итак, разработчики, время для серьёзного разговора. Вы уже наверное в курсе, что на этой неделе React, Babel и куча других популярных пакетов на NPM сломались. Причина довольно удивительная.

Простой пакет NPM под названием left-pad был установлен как зависимость в React, Babel и других пакетах. Модуль, который на момент написания этого поста, имеет 11 звёзд на Github (сейчас 323 — прим.пер). Весь пакет состоит из 11 простых строчек, которые реализуют примитивную функцию вставки пробелов в левой части строк. Если какие-то из ссылок когда-нибудь умрут, вот его код:

module.exports = leftpad;
function leftpad (str, len, ch) {
  str = String(str);
  var i = -1;
  if (!ch && ch !== 0) ch = ' ';
  len = len - str.length;
  while (++i < len) {
    str = ch + str;
  }
  return str;
}
Что меня беспокоит, так это такое большое количество пакетов, где установлена зависимость от простой функции набивки строки пробелами, вместо того чтобы потратить 2 минуты и написать эту базовую функцию самому.

Узнав о бедствии, которое случилось из-за left-pad, я начал исследовать экосистему NPM. И вот что обнаружил, среди прочего:

  • Есть пакет под названием isArray, который скачивают 880 000 раз в день, 18 млн скачиваний в феврале 2016 года. У него 72 зависимых NPM-пакета. И вот его целая 1 строчка кода:
    return toString.call(arr) == '[object Array]';
  • Есть пакет под названием is-positive-integer (GitHub), который состоит из 4 строчек и которому на вчерашний день требовалось 3 других пакета для работы. Автор с тех пор провёл рефакторинг, так что теперь у пакета 0 зависимостей, но я не могу понять, почему это не было сделано сразу.
  • Свежая установка Babel включает 41 000 файлов
  • Чистый шаблон приложения на базе jspm/npm начинается c 28 000+ файлов

Всё это заставляет задать вопрос…

Мы разучились программировать?


В каком из параллельных миров вышеперечисленные решения являются наилучшими? Как сотни зависимостей и 28 000 файлов для пустого шаблона можно назвать чем-то ещё, кроме чрезмерной сложности и безумия?

Создаётся впечатление, что участники экосистемы NPM взрастили фетиш микропакетов. Вместо того, чтобы написать любую функцию или код, они как будто предпочитают установить зависимость на что-то написанное кем-то другим. Мне кажется, что вся работа программиста в экосистеме NPM сводится к написанию как можно меньшего количества кода, чтобы связать вместе существующие библиотеки, чтобы создать нечто новое, функционирующее уникальным образом для личных или коммерческих нужд.

Функции — это не пакеты


Функции слишком малы, чтобы попасть в пакет и зависимость. У чистых функций нет связи; это случайные фрагменты кода и ничего больше. Кому нужна зависимость от косинуса? Вместо этого нам бы по-настоящему понравилась зависимость от пакета «тригонометрия», который охватывает много хитрых функций, которые мы не хотим писать сами. Это гораздо больше похоже на то, как .NET и другие фреймворки создают базовую библиотеку с основной функциональностью. Такая библиотека проверена создателями языка и обладает в значительной степени гарантированной надёжностью, с отсутствием багов.

Проблема третьих лиц


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

Во-вторых, даже если логика в пакете правильная, меня поражает тот факт, что разработчики устанавливают зависимости на однострочные функции, которые сами должны уметь писать с закрытыми глазами. Если ты не можешь написать функцию left-pad, is-positive-integer или isArray за пять минут (включая время на поиск в Google), то ты вообще не умеешь программировать. Чёрт, любая из них может быть хорошим вопросом на собеседовании как проверка, умеет ли кандидат программировать.

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

Что ещё хуже, если в вашем коде или в коде сторонней библиотеки есть баг или код некорректно работает, то вы не будете знать, как отладить или исправить его, если вы не умеете программировать.

Боремся за уменьшение зависимостей


Каждый добавленный пакет прибавляет ещё одну зависимость к вашему проекту. Зависимости, по сути этого слова, — то, в чём вы нуждаетесь, чтобы код работал. Чем больше зависимостей, тем больше у вас точек отказа. Не говоря уже о большей вероятности ошибки: вы проверяли кого-нибудь из тех программистов, кто написал эти функции, от которых вы зависите ежедневно?

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

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

Комментарии (270)


  1. DenVdmj
    26.03.2016 20:34
    +1

    Хорошо, что просто удалил, а если бы внедрил вредоносный код?


  1. XGuest
    28.03.2016 02:40
    -1

    Доброго времени суток
    Пару дней назад я здесь написал:

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

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

    P.S. Вспомнил, сколько трачу времени на подбор и проверку подключаемых модулей.;)


  1. AnnieOmsk
    29.03.2016 05:13

    Хочется разбавить разговор своим скромным мнением. Я программист со стажем 20+, а последние 6 лет еще и компанию свою развиваю как собственник и директор. Так вот хочется из мира бизнеса аналогию привести.
    Если собственник свои ключевые компетенции полностью делегировал сотрудникам и при этом не знает, как они это делают, — он попадает в полную зависимость от них. Выстроить процессы так, чтобы все были маленькими винтиками и делали свою маленькую работу можно. Вроде бы здорово все, все работает, можно не переживать. Но увольнение или болезнь ключевого сотрудника — беда.
    А выход какой? Выход в том, что собственник должен как минимум уметь выполнять сам все ключевые функции. Поруководить цехом, продать клиенту услугу и так далее. В бизнесе все это известно уже лет 100, так почему в программировании должно быть иначе?
    На мой взгляд умение искать аналогии в окружающем мире и использовать их на пользу проекту/продукту/компании и есть один из главных признаков высокой квалификации. А вовсе не умение найти в гугле функцию на 3 строки. Поэтому я никогда не доверяла экосистеме Руби и Node.js. Просто второе бомбануло раньше в силу более бурного роста.
    Также все вышесказанное заставляет меня глубоко сомневаться в успехе ИТ-компаний, во главе которых не стоят программисты с опытом. Непрограммист смотрит на программистов как на чудаковатых волшебников и совершенно теряется, если кто-то из них не может или не хочет что-то делать, а он сам — собственник — не может стряхнуть пыль и расчехлить, чтобы временно заменить бойца. Не то, чтобы надо было постоянно бегать и тушить пожары, это как раз плохо. Но надо иметь возможность. Не терять хватку помогает обучение новых сотрудников и студентов — и в процесс не лезешь, и квалификацию не теряешь.