Как гласит недавний отчет Stack Overflow (а также отчеты GitHub), самый популярный язык программирования в мире на данный момент — JavaScript. Отчасти язык популярен своей небывалой распространенностью в браузерах, отчастью он обязан своей популярностью и серверной платформе NodeJS, позволяющей писать программы, выполняемые не только в браузерах клиентских машин, но и на серверах.

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

Как правильно перевозить грузы

Такая модульность стала своего рода традицией экосистемы NPM. Модули стали писать по случаю и без. На каждый чих — свой модуль, и вряд ли еще остались слова английского (и не только) языка, не занятые под название модуля с модной припиской “JS” на конце.

И вот эта страсть к высокодробной модульности и вышла NPM и его обитателям боком. На неделе разгорелся небольшой скандал на почве обрушения части NPM из-за смешного инцидента. Некий Азер Кочулу (Azer Koçulu), автор более 250 модулей к NodeJS, являвшийся владельцем модуля под названием kik, получил письмо от сотрудников мессенджера Kik, попросившего его уступить им «кошерное» название в NPM. Азер отказался пойти навстречу, и сотрудники мессенджера Kik отправили аналогичное письмо руководству платформы NPM. NPM решила отнять у Азера красивое имя для модуля и отдать его мессенджеру Kik. Тут Азер, по понятным причинам, негодуя от такой несправедливости, выпилил весь свой зоопарк модулей с NPM (напомню, это более 250 наименований)...

И тут главный прикол всего цирка: оказалось, что от его модулей зависит куча крупных проектов, в числе которых такие монстры, как Фейсбуковский React, JavaScript-транскомпилятор Babel и, по цепочке, огромное количество других модулей и программ. А так как Азер отозвал свои поделия, то вся эта инфраструктура рухнула как карточный домик. И что еще более смешно в этой непростой ситуации, модуль под названием leftpad, от которого зависило множество других крупных проектов, состоял из… 11 строчек кода! И ладно бы в этих 11 строках кода были бы заключена вселенская мудрость или хотя бы результат большой научной работы, сконцентрированный в лаконичную формулировку (E = mc²). Нет, модуль делал довольно тупую и банальную вещь — добавлял нули или пробелы в левой части заданной строки или числа!

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;
}

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

'{0:06d}'.format(6)

То есть, крупнейшие и сложнейшие проекты включили в себя модуль из десятка строк тупого кода, который можно было бы оформить буквально за две минуты самостоятельно (без создания лишних зависимостей). И в среде NPM такое на каждом шагу — это часть культуры! Прекрасным примером этому может послужить небольшое исследование Дэвида Хейни (David Haney), который прошерстил NPM на предмет наличия подобных «модулей».

Трюк с байками

Например, оказалось, что есть такой замечательный модуль, как isArray. Этот модуль скачало 880 000 человек за один день, кроме того, он был загружен 18 миллионов раз только в одном феврале этого года! От этого модуля напрямую зависят 72 пакета в NPM. И что же это за чудесный модуль такой?

return toString.call(arr) == '[object Array]';

А модуль этот состоит из одной. ОДНОЙ! Строчки дурацкого кода, приведенного выше. И призван проверять — не массив ли перед нами…

Есть еще один чудесный модуль с говорящим названием is-positive-integer (GitHub), до смешного банальный — он проверяет, положительное ли целое число ему передано. Состоит из целых четырех строк кода (!!!) и (внимание!) требует три зависимости для своей работы! То есть требовал, недавно автор «отрефакторил» свой код, и теперь его важнейший модуль не требует зависимостей вообще (вот он — подвиг программиста)!

Индийский мотоциклетный парад

А вот еще один пример, приведенный в комментариях на Хабре — очередной модуль «для проверки типа» — isnumber. Одна тупая строчка:

return !isNaN(parseFloat(n)) && isFinite(n);

И вот такая вот развесистая система приводит к тому, что какой-нибудь Babel включает в себя 41 000 файлов (и это свежеустановленный пакет!), а также генерирует чистый шаблонный проект (jspm/npm) с… более чем 28 000 файлов! Эта, вроде бы неплохая изначально идея компактных модулей, была доведена до полнейшего, абсолютного, феерического абсурда. Мало того, что с каждой такой дурацкой зависимостью вы добавляете еще одну точку отказа в своем коде (которую нельзя потом оперативно отладить), так еще и автоматически полагаетесь на качество кода горе-программистов (типа упомянутого выше, что проверял положительность целого числа тремя зависимостями).

Индийский мотоциклетный парад

P.S. Кстати, теперь уже печально известный модуль leftpad, удаленный Азером, в итоге восстановили без его одобрения, в качестве экстренной меры, чтобы не «поломать систему».


В разделах программирование и языковое
Андрей Баксаляр  :: 10 мар 2016, в 23:09

Работая с греческим алфавитом в Unicode, в Python 3.4.3, наткнулся на странный баг (по всей видимости, здесь косяк как Пайтона, так и таблиц Юникода). Если у вас интерпретатор версии 3.4-3.5, то проблема легко воспроизводится следующим образом:

'ΰ'.upper().lower() == 'ΰ'

Интерпретатор неожиданно выдаст вам False. Несмотря на то, что по логике вещей ΰ == ΰ. После преобразований регистра из-за проблемы с правилами меппинга Unicode, Пайтон подменяет ΰ на ΰ:

'ΰ'.upper().lower().encode('utf-8')
b'\xcf\x85\xcc\x88\xcc\x81'
'ΰ'.encode('utf-8')
b'\xce\xb0'

Как видно, исходный символ и символ, возвращаемый lower() — разные, второй возвращается с другим диакритическим знаком, что даже визуально заметно в редакторе (да и на странице видно невооруженным глазом), хотя так быть точно не должно.

ΰu → ΰu

При дальнейшем гуглении оказалось, что о данном глюке уже было сообщено. И сообщение пайтоновского багтрекера даже успели закрыть с формулировкой «исправлено» более четырех лет назад, перед выпуском Python 3.3, только вот баг остался даже в свежей версии Python 3.5.1 (а также 3.4.3), а вот во второй ветке (проверено на Python 2.7.6 от 22 июня 2015) он исправлен.

Воспроизведение бага в Python 2.7.6, 3.4.3 и 3.5.1

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

Например…

(
unicodedata.name('Ω'.upper().lower()),
unicodedata.name('Ω')
)

... неожиданно возвращает:

('GREEK SMALL LETTER OMEGA', 'OHM SIGN')

Написал сообщение в тикет, будем ждать ответа. Также попробовал обновить Пайтон до самой последней версии, однако это не помогло.

P.S. Интересно, что данная проблема затрагивает и NodeJS версий 5.6.0 (стабильная) и 5.8.0 (самая свежая):

Воспроизведение бага в NodeJS 5.6

Воспроизведение бага в NodeJS 5.8

Однако в консоли браузера (Firefox 44.0.2) проблема уже не воспроизводится:

Воспроизведение бага в JavaScript внутри браузера Firefox 44.0.2

P.P.S. В качестве костыльного решения в Пайтоне предлагается использовать такой подход:

unicodedata.normalize('NFC', 'ΰ'.upper().lower()) == 'ΰ'
True
Исходник.upper().lower()Снова .upper()
µ (0xb5)Μ (0x39c)μ (0x3bc)Μ (0x39c)
ß (0xdf)SS (0x5353)ss (0x7373)SS (0x5353)
İ (0x130) (0x69307) (0x49307) (0x69307)
ı (0x131)I (0x49)i (0x69)I (0x49)
ʼn (0x149)ʼN (0x2bc4e)ʼn (0x2bc6e)ʼN (0x2bc4e)
ſ (0x17f)S (0x53)s (0x73)S (0x53)
ǰ (0x1f0) (0x4a30c) (0x6a30c) (0x4a30c)
ͅ (0x345)Ι (0x399)ι (0x3b9)Ι (0x399)
ΐ (0x390)Ϊ́ (0x399308301)ΐ (0x3b9308301)Ϊ́ (0x399308301)
ΰ (0x3b0)Ϋ́ (0x3a5308301)ΰ (0x3c5308301)Ϋ́ (0x3a5308301)
ς (0x3c2)Σ (0x3a3)σ (0x3c3)Σ (0x3a3)
ϐ (0x3d0)Β (0x392)β (0x3b2)Β (0x392)
ϑ (0x3d1)Θ (0x398)θ (0x3b8)Θ (0x398)
ϕ (0x3d5)Φ (0x3a6)φ (0x3c6)Φ (0x3a6)
ϖ (0x3d6)Π (0x3a0)π (0x3c0)Π (0x3a0)
ϰ (0x3f0)Κ (0x39a)κ (0x3ba)Κ (0x39a)
ϱ (0x3f1)Ρ (0x3a1)ρ (0x3c1)Ρ (0x3a1)
ϴ (0x3f4)θ (0x3b8)Θ (0x398)θ (0x3b8)
ϵ (0x3f5)Ε (0x395)ε (0x3b5)Ε (0x395)
և (0x587)ԵՒ (0x535552)եւ (0x565582)ԵՒ (0x535552)
(0x1e96) (0x48331) (0x68331) (0x48331)
(0x1e97) (0x54308) (0x74308) (0x54308)
(0x1e98) (0x5730a) (0x7730a) (0x5730a)
(0x1e99) (0x5930a) (0x7930a) (0x5930a)
(0x1e9a) (0x412be) (0x612be) (0x412be)
(0x1e9b) (0x1e60) (0x1e61) (0x1e60)
(0x1e9e)ß (0xdf)SS (0x5353)ss (0x7373)
(0x1f50)Υ̓ (0x3a5313)ὐ (0x3c5313)Υ̓ (0x3a5313)
(0x1f52)Υ̓̀ (0x3a5313300)ὒ (0x3c5313300)Υ̓̀ (0x3a5313300)
(0x1f54)Υ̓́ (0x3a5313301)ὔ (0x3c5313301)Υ̓́ (0x3a5313301)
(0x1f56)Υ̓͂ (0x3a5313342)ὖ (0x3c5313342)Υ̓͂ (0x3a5313342)
(0x1f80)ἈΙ (0x1f08399)ἀι (0x1f003b9)ἈΙ (0x1f08399)
(0x1f81)ἉΙ (0x1f09399)ἁι (0x1f013b9)ἉΙ (0x1f09399)
(0x1f82)ἊΙ (0x1f0a399)ἂι (0x1f023b9)ἊΙ (0x1f0a399)
(0x1f83)ἋΙ (0x1f0b399)ἃι (0x1f033b9)ἋΙ (0x1f0b399)
(0x1f84)ἌΙ (0x1f0c399)ἄι (0x1f043b9)ἌΙ (0x1f0c399)
(0x1f85)ἍΙ (0x1f0d399)ἅι (0x1f053b9)ἍΙ (0x1f0d399)
(0x1f86)ἎΙ (0x1f0e399)ἆι (0x1f063b9)ἎΙ (0x1f0e399)
(0x1f87)ἏΙ (0x1f0f399)ἇι (0x1f073b9)ἏΙ (0x1f0f399)
(0x1f90)ἨΙ (0x1f28399)ἠι (0x1f203b9)ἨΙ (0x1f28399)
(0x1f91)ἩΙ (0x1f29399)ἡι (0x1f213b9)ἩΙ (0x1f29399)
(0x1f92)ἪΙ (0x1f2a399)ἢι (0x1f223b9)ἪΙ (0x1f2a399)
(0x1f93)ἫΙ (0x1f2b399)ἣι (0x1f233b9)ἫΙ (0x1f2b399)
(0x1f94)ἬΙ (0x1f2c399)ἤι (0x1f243b9)ἬΙ (0x1f2c399)
(0x1f95)ἭΙ (0x1f2d399)ἥι (0x1f253b9)ἭΙ (0x1f2d399)
(0x1f96)ἮΙ (0x1f2e399)ἦι (0x1f263b9)ἮΙ (0x1f2e399)
(0x1f97)ἯΙ (0x1f2f399)ἧι (0x1f273b9)ἯΙ (0x1f2f399)
(0x1fa0)ὨΙ (0x1f68399)ὠι (0x1f603b9)ὨΙ (0x1f68399)
(0x1fa1)ὩΙ (0x1f69399)ὡι (0x1f613b9)ὩΙ (0x1f69399)
(0x1fa2)ὪΙ (0x1f6a399)ὢι (0x1f623b9)ὪΙ (0x1f6a399)
(0x1fa3)ὫΙ (0x1f6b399)ὣι (0x1f633b9)ὫΙ (0x1f6b399)
(0x1fa4)ὬΙ (0x1f6c399)ὤι (0x1f643b9)ὬΙ (0x1f6c399)
(0x1fa5)ὭΙ (0x1f6d399)ὥι (0x1f653b9)ὭΙ (0x1f6d399)
(0x1fa6)ὮΙ (0x1f6e399)ὦι (0x1f663b9)ὮΙ (0x1f6e399)
(0x1fa7)ὯΙ (0x1f6f399)ὧι (0x1f673b9)ὯΙ (0x1f6f399)
(0x1fb2)ᾺΙ (0x1fba399)ὰι (0x1f703b9)ᾺΙ (0x1fba399)
(0x1fb3)ΑΙ (0x391399)αι (0x3b13b9)ΑΙ (0x391399)
(0x1fb4)ΆΙ (0x386399)άι (0x3ac3b9)ΆΙ (0x386399)
(0x1fb6)Α͂ (0x391342)ᾶ (0x3b1342)Α͂ (0x391342)
(0x1fb7)Α͂Ι (0x391342399)ᾶι (0x3b13423b9)Α͂Ι (0x391342399)
(0x1fbe)Ι (0x399)ι (0x3b9)Ι (0x399)
(0x1fc2)ῊΙ (0x1fca399)ὴι (0x1f743b9)ῊΙ (0x1fca399)
(0x1fc3)ΗΙ (0x397399)ηι (0x3b73b9)ΗΙ (0x397399)
(0x1fc4)ΉΙ (0x389399)ήι (0x3ae3b9)ΉΙ (0x389399)
(0x1fc6)Η͂ (0x397342)ῆ (0x3b7342)Η͂ (0x397342)
(0x1fc7)Η͂Ι (0x397342399)ῆι (0x3b73423b9)Η͂Ι (0x397342399)
(0x1fd2)Ϊ̀ (0x399308300)ῒ (0x3b9308300)Ϊ̀ (0x399308300)
(0x1fd3)Ϊ́ (0x399308301)ΐ (0x3b9308301)Ϊ́ (0x399308301)
(0x1fd6)Ι͂ (0x399342)ῖ (0x3b9342)Ι͂ (0x399342)
(0x1fd7)Ϊ͂ (0x399308342)ῗ (0x3b9308342)Ϊ͂ (0x399308342)
(0x1fe2)Ϋ̀ (0x3a5308300)ῢ (0x3c5308300)Ϋ̀ (0x3a5308300)
(0x1fe3)Ϋ́ (0x3a5308301)ΰ (0x3c5308301)Ϋ́ (0x3a5308301)
(0x1fe4)Ρ̓ (0x3a1313)ῤ (0x3c1313)Ρ̓ (0x3a1313)
(0x1fe6)Υ͂ (0x3a5342)ῦ (0x3c5342)Υ͂ (0x3a5342)
(0x1fe7)Ϋ͂ (0x3a5308342)ῧ (0x3c5308342)Ϋ͂ (0x3a5308342)
(0x1ff2)ῺΙ (0x1ffa399)ὼι (0x1f7c3b9)ῺΙ (0x1ffa399)
(0x1ff3)ΩΙ (0x3a9399)ωι (0x3c93b9)ΩΙ (0x3a9399)
(0x1ff4)ΏΙ (0x38f399)ώι (0x3ce3b9)ΏΙ (0x38f399)
(0x1ff6)Ω͂ (0x3a9342)ῶ (0x3c9342)Ω͂ (0x3a9342)
(0x1ff7)Ω͂Ι (0x3a9342399)ῶι (0x3c93423b9)Ω͂Ι (0x3a9342399)
(0x2126)ω (0x3c9)Ω (0x3a9)ω (0x3c9)
(0x212a)k (0x6b)K (0x4b)k (0x6b)
(0x212b)å (0xe5)Å (0xc5)å (0xe5)
(0xfb00)FF (0x4646)ff (0x6666)FF (0x4646)
(0xfb01)FI (0x4649)fi (0x6669)FI (0x4649)
(0xfb02)FL (0x464c)fl (0x666c)FL (0x464c)
(0xfb03)FFI (0x464649)ffi (0x666669)FFI (0x464649)
(0xfb04)FFL (0x46464c)ffl (0x66666c)FFL (0x46464c)
(0xfb05)ST (0x5354)st (0x7374)ST (0x5354)
(0xfb06)ST (0x5354)st (0x7374)ST (0x5354)
(0xfb13)ՄՆ (0x544546)մն (0x574576)ՄՆ (0x544546)
(0xfb14)ՄԵ (0x544535)մե (0x574565)ՄԵ (0x544535)
(0xfb15)ՄԻ (0x54453b)մի (0x57456b)ՄԻ (0x54453b)
(0xfb16)ՎՆ (0x54e546)վն (0x57e576)ՎՆ (0x54e546)
(0xfb17)ՄԽ (0x54453d)մխ (0x57456d)ՄԽ (0x54453d)

Пока комментариев нет, будь первым!

Войти через...


Это даст читателю возможность голоса, комментария, создания закладки, и даже написания поста, не говоря о множестве других мелких ништяков.

Популярное


Путешествия Макса Майорова во времени 21 фев, в 00:53

Cool-ибин 19 фев, в 09:00

Неоновый Китай 8 фев, в 06:32

По США на товарняках 2 апр, в 14:12

Новое Оно на подходе 30 мар, в 15:45

Соациализируемся


Также найти меня можно в других злачных местах:

Все еще использую электронную почту:
andreybaksalyar@ya.ru