Пакетик, который смог и автор, который смог еще больше

4 дня назад произошел прелюбопытнейший инцидент. Автор одного очень популярного npm-пакета (ссылка на github) сделал его unpublish. Точнее, он удалил из npm-регистра все свои пакеты. О причине данного поступка можно прочитать на medium. В этой ситуации интересен не сам поступок, а те последствия, к которым он привел. Так как пакет был очень популярным (хоть и маленьким), после его удаления большое количество других модулей не смогли правильно «собраться» при их установке. Очень оживленная дискуссия по этому поводу ведется на Хабре (1 и 2) да и на других платформах — много людей в блогах описывают свое отношение к ситуации. Со своей колокольни у меня тоже есть точка зрения (немного «подправленная» за 4 дня чтения других источников). Начнем.

Почти с самого начала этой истории на уме крутится фраза Маленького Принца — «мы в ответе за тех, кого приручили». Разработчик, который включает ваш пакет в список своих зависимостей (это важное слово), доверяет вам. И уж точно он не ждет, что в какой-то не очень удачный день его проект перестанет собираться из-за того, что Вы удалили свой модуль из npm. В свете данной ситуации почти любой nodejs-проект выглядит даже не как карточный домик, а как сложная фигурка из домино, которая стоит на одной косточке (npm) и вершина которой — тоже одна косточка (ваш код). И при этом развалить ее можно убрав любую косточку. В общем, весьма хрупкая конструкция.

Двоякая ситуация. С одной стороны — автор модуля, который становится «вершителем судеб» местного масштаба, с другой стороны npm, который позволяет безболезненно стать автору таковым. Тут я не вижу других вариантов, кроме как убрать возможность делать unpublish по сиюминутному желанию. Немного детальнее:

  • Если модуль не является зависимостью ни к одному из других зарегистрированных модулей, то возможность его удалить никак не ограничивается.
  • Если от данного модуля зависят только модули этого же автора, то выдавать большой WARNING и после этого уже удалять.
  • Если автор хочет удалить свой модуль в пользу другого модуля (даже не своего), то необходимо уведомить всех, кто использует текущий модуль о более подходящем, и только через какое-то время (неделя/месяц/квартал) уже удалять.
  • Если автор хочет удалить свой модуль, от которого зависят другие модули, то делать это надо не «автоматически». Немного бюрократии не помешает. Заявка с внятным описанием причин удаления и «ручная» обработка таких заявок могут дать неплохой результат. Ну и конечно необходимо уведомить пользователей модуля, что он в скором времени будет удален (опять-таки, неделя/месяц/квартал).

Вышеуказанные действия требуют некоторых телодвижений со стороны владельцев npmjs, однако результат того стоит (мое мнение).

Еще раз. Удаление модуля — это серьезный шаг со стороны его автора. А ситуация, когда автор внезапно удаляет весь свой «парк» — это может быть сиюминутное «помутнение» в порыве гнева, а может и диверсия со стороны третьих лиц, которые получили доступ к учетным данным. Последний вариант был поднят в заметке от Armin Ronacher «Micropackages and Open Source Trust Scaling».

Идем дальше. Для себя я не вижу смысла в пакетах из одной функции. Пакеты должны давать комплексный набор функциональных решений в заданной области. Тут я согласен со сравнением пакета «Косинус» c одной функцией и пакета «Тригонометрия» с рядом функций. Второй для меня предпочтительнее. Но, раз уже существуют такие маленькие, но популярные модули, то, возможно, стоит взять их под небольшой контроль? Тот же left-pad был написал давно и обновлялся раз в год в лучшем случае (left-pad/commits). И, если б не вся эта ситуация, то никто б и не обратил внимания на некоторые проблемы модуля типа этой — O(n^2) time. Это при том, что у модуля были миллионы загрузок в месяц (не надо тут говорить, что часть из них — это зависимости зависимостей).

В npm сейчас порядка 260 000 зарегистрированных модулей. Распределение количества загрузок далеко от линейного. Другими словами, есть ряд очень популярных модулей, а есть «мертвые» с нулем загрузок. При чем, популярных очень и очень мало (если брать относительно). Что если установить такую себе планку — 1000 загрузок в месяц (или 2000, или 5000). Какой модуль перевалил через нее (а таких будем тем меньше, чем выше планка), попадает в «кандидаты на осмотр». Если это модуль типа d3, eslint, ember-cli, lodash (то есть, серьезные проекты со своими управляющими организациями или просто активным сообществом), то модуль оставляется сам по себе. А вот если это «модуль-однострочник» или «модуль на одну функцию», то имеет смысл изучить его детальнее и попытаться довести до состояния, близкого к образцовому.

Кто может этим заниматься? При текущем раскладе — разработчики-энтузиасты (open-source все-таки). В идеале — «официальная контора». Взгляд тянется в сторону npmjs. Но, «а оно им надо?». Чисто практически — вообще не надо. Им других забот хватает.

Тут незаметно подкралась другая проблема. Функция типа left_pad является часто используемой. В других языках ее аналоги доступны из коробки (PHP — str_pad, Ruby — String#rjust, C# — String.PadLeft), а вот в JS ее нет. Как нет и многих других. И у разработчика остается два варианта — написать самому или взять готовое. Часто писать самому лень/не интересно/нет времени. Долго что-то искать тоже желания нет. Вот и берется модуль по популярности (читай, по количеству загрузок). Если же писать свое не лень, то появляется много разных поделок. Достаточно на npmjs поискать по запросу «left pad» (ссылка) и найдется целый ворох модулей. И это не единичный случай (я сейчас даже не про right pad). В таком зоопарке очень легко потеряться. Что тут можно сделать? Неплохо бы группировать модули по функционалу (где-то на Хабре идея мелькала) — Strings → Formatting / Search / etc. Ну а можно ряд функций включить в сам язык из коробки. Но это процесс долгий (стандартизация — дело тонкое).

Все, что писалось выше, в большей степени относится к «власть имущим». Какие варианты я вижу для «простых» крестьян разработчиков? Перед любым npm i --save 100500 раз подумайте, а нужна ли вам данная зависимость? Если это маленький модуль на одну функцию, то неужели вы не напишете ее сами? Тут я не имею ввиду чисто алгоритмические решения типа Расстояния Левенштейна или Пирамидальной Сортировки (их проще взять готовыми, если есть). Я говорю о всяких одноусловных «типосверщиках» (привет, isarray) и подобных им. Если все же решились добавить модуль к себе, то посмотрите, сколько он тянет своих зависимостей. Лучше всего, чтоб вообще ничего не тянул. Но не всегда так бывает.

Если вопрос доступа к модулям является через чур критичным, то можно попробовать сделать свой npm-registry (см. доки) и в добавок еще shrinkwrap на проверенные зависимости.

Вместо заключения

Azer Koçulu показал очень хороший пример «эффекта бабочки», который ураганом прошелся по js-сообществу, указав на ряд проблем и недостатков внутри инфраструктуры nodejs-проектов и npmjs (а так же на разброд и шатания в головах некоторых разработчиков). Я не знаю, что и как будет дальше, но мне кажется, что что-то да поменяется. Хочется надеяться, что в лучшую более стабильную сторону.

UPD 30.03.2016 В блоге npm появилась заметка о новых правилах для unpublish — changes-to-npms-unpublish-policy.

, ,

Оставить комментарий

Top ↑ | Main page | Back