NPM и left-pad: мы забыли как программировать? [Перевод]

статистика скачивания NPM-пакета isArray, сгенерировано с помощью http://npm-stat.com/

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

Это простейший NPM модуль под названием left-pad, который использовался в React, Babel и некоторых других проектах. Модуль, у которого на момент написания этой статьи 11 звёзд на GitHub. Весь модуль — это 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;
}

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

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

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

Всё это заставляет меня задуматься…

Не забыли ли мы как программировать?

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

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

Отдельные функции — это не NPM-пакеты

Отдельные функции слишком малы, чтобы стать модулем или зависимостью. Чистые функции ни с чем не связаны; это просто отдельные маленькие кусочки кода, и больше ничего. Для примера: кому нужен модуль “косинус”? Нам бы реально пригодился модуль “тригонометрия”, включающий в себя множество “хитрых” функций, которые нам бы не хотелось писать самим. Такой модуль был бы больше похож на то, как делаются основные библиотеки в .NET и других фреймворках. Они поддерживаются и проверяются создателями языка, практически гарантированно работают верно и не содержат ошибок.

Проблемы “третьей стороны”

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

Во-вторых, даже если эти микромодули и работают правильно, меня поражает факт, что разработчики добавляют в свои проекты зависимости ради этих однострочных функций. Функций, которые они должны уметь писать с закрытыми глазами. По-моему, если ты не можешь написать функцию left-pad, is-positive-integer или isArray за пять минут (включая время на “погуглить”), то на самом деле ты не знаешь как программировать. Любая из этих функций будет отличной задачкой для собеседования, чтобы определить, может кандидат программировать или нет.

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

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

Стремитесь к меньшему количеству зависимостей

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

Используйте модули для сложных по функционалу задач, которые потребовали бы много времени, денег и/или отладки при собственной реализации. Такие вещи, как data access layer (ORM) или caching client, должны быть зависимостями потому, что они сложны, и риск добавления зависимости в проект стоит сэкономленных сил и времени.

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

Оригинал статьи

Автор David Haney @haneycodes

Show your support

Clapping shows how much you appreciated Petushkov Sergey’s story.