npmとは、node.jsにおけるパッケージシステムのことだ。npmを使えば、他人の書いたnode.jsベースのプログラムとライブラリの入手と利用がとても簡単になる。
そのnpm界隈が混乱している。発端は以下のURLだ。
I’ve Just Liberated My Modules — Medium
Azer Koçuluはkikという名前のnpmパッケージを公開していた。このkikというソフトウェアの中身についてはここでは関係がない。
さて、それとは別に、kik.comというスマフォ用のチャットアプリを出しているKik Interactive社がいて、kikという名前のパッケージをnpmで出したいので、名前を明け渡すように要求した。
Azerはこの要求を拒否した。すると、Kik Interactive社はnpmの管理者に片っ端からメールを投げまくり、そのうちの一人が反応して、Azerの意思に反して、何の法的根拠もなくパッケージを消した。
Azerはこの行動に対し、npmはもはや信頼できないとし、npmに出していたすべてのパッケージを削除した。
そして阿鼻叫喚の世界に突入する。Azerは様々なCLIツールやライブラリをnpmで公開していた。中でも影響力のあったAzerのパッケージは、left-padだ。
azer/left-pad: String left pad
left-padとは、文字列の左側(先頭)を指定した文字数になるように、指定した文字か指定されない場合は空白文字でパディング(埋める)だけの処理を行う簡単なJavaScriptで書かれたleftpadという名前のライブラリだ。空行を抜けば、10行ぐらいしかない簡単なコードだ。
このコードは有名なnpmパッケージで使われていたらしく、間接的に様々なnpmパッケージが依存していたため、世界中で大混乱を引き起こすことになった。
傑作なのは、当のKik Interactive社すらleft-padに依存していたということだ。Kik Interactive社は今回の件について、メールをすべて公開している。
A discussion about the breaking of the Internet — Medium
Kik社はパッケージ取り下げの理由を、ユーザーの混乱を招くためとしているが、すでに公開されたパッケージの中身が変わる方が混乱を招くし、名前だけ見て中身を確認せずにパッケージを使うバカは混乱して当然だ。
npm運営は、これについて議論しているフォーラムを建設的ではないとして閉じるなど、その後の対応も疑問がある。
今回の件について、興味深い指摘がある。
NPM & left-pad: Have We Forgotten How To Program? | Haney Codes .NET
そもそも、leftpadの中身は10行程度のコードである。空行を抜けば、以下の通り。
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;
}
実に多くのパッケージが、このleftpadに依存している。しかし、この程度の関数は数分で書けるのだから、なんでわざわざ依存するんだ?
もっと憂うべきパッケージがある。isArrayだ。このパッケージは一日88万回もダウンロードされていて、2016年2月だけの一ヶ月間に1800万回もダウンロードされていて、72個ものNPMパッケージが依存している。
isArrayの中身はこうだ。
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
結局、このコードは本質的にたった一行のコードである。
その他、is-positive-integerという整数が正の整数かどうか判定するパッケージがあるが、これも本質的には4行のコードである。ところが、このパッケージは昨日まで3個もの依存を持っていた(今は0個になっている)
なぜこんなにも多数のパッケージに依存をするのだ?
leftpad, isArray, isPositiveInteger程度、ググる時間を含めても5分程度で書けるはずである。書けない奴はそもそもコードが書けないと言っていい。NPM界隈の人間はコードが書けないのか?
今回の騒動で、以下のような面白いネタパッケージシステムが開発されている。
曰く、「Twitterには編集ボタンがないので、最適なJavaScriptモジュールをホストである」
このパッケージシステムを使うには、まずソースコードを自分でツイートして
https://twitter.com/rauchg/status/712799807073419264
しかる後に使う。
const leftPad = await requireFromTwitter('712799807073419264');
console.log(leftPad(1, 5)); // '00001'
console.log(leftPad(1234, 5)); // '01234'
console.log(leftPad(12345, 5)); // '12345'
Twitter社さえ信用すればよい。
ドワンゴ広告
ドワンゴの採用面接を受けると日本Node.jsユーザーグループの「元」代表の@mesoとお話ができるそうだ。
ドワンゴは本物のC++プログラマーを募集しています。
CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0
車輪の再発明するよりはマシだから、別にleftpadに依存するのは問題ない。
ReplyDelete問題なのは、既に名前空間取られてるのに後発のバカ企業がテメエの都合で勝手に名前空間を横取りしようとしたことと、npm側の管理者が勝手に削除したことだよ。
問題なくはない。
ReplyDeleteこのモジュールを探してくる手間暇があったら書ける、コピペできるし、
このモジュールをダウンロードする負荷を考えたら最初から直書きしておいた方が明らかに効率的だ。
何言ってるの?コピペするくらいならleft-padを探して利用した方がはるかにマシです。
ReplyDeleteleft-padは既にnode.jsや今回イチャモン付けてきたkik社でも使われてるほどポピュラーなモジュール。
真っ当なnode.js使いなら探すまでもなく知ってるモジュールだ。
もしコピペしたleft-padにバグがあって、上流で直してくれた場合はどうするのさ。
君のコピペしたleft-padはバグが含まれたままだよ。
自分で書いてもいいけど車輪の再発明だし他の人が再利用することもできない。
だからモジュール化してみんなでコードを再利用しましょうって流れでnpmやrubygems、cpan、pip等が作られたんだよ。
そして、それが今回の事態を招いた、と。
ReplyDelete面白いね。
短絡思考だね。
ReplyDelete確かに今回の事態を招いたのは事実だが、これはある意味レアケース。
レアケースが起きたから車輪を再発明したりコピペの方が良いと論じるのは間違い。
npmのパッケージの粒度が他の言語と比べて細かい理由は、
ReplyDelete実行環境の性質上、コードサイズに対する要求が厳しいため、
必要な部分だけつまみ食いできる形態のパッケージが好まれるためです。
ためしにlodashの作者が公開しているnpmのパッケージリストをご覧ください。
https://www.npmjs.com/~jdalton
lodashは数百の関数を持ったそこそこの大きさのパッケージですが、
単機能に分割されたlodash.isarrayなどのパッケージも多数配布されています。
これらnpmの文化について良し悪しを語るつもりはありませんよ。
あえて言えば大嫌いですけどね。
それは認識が大きくズレてる
ReplyDeletenpmの文化でパッケージの粒度が細かいという話と
lodashのようなライブラリがサブセットもしくは機能単品で公開してるという話
lodash本体はそれらの寄せ集めで作られてるわけでもないので関係ない
ダウンロードする負荷って一体何時代に生きているのかと。なんか考え方がコンシューマゲーム制作してる人っぽいんだよな。
ReplyDeleteつまりこの程度の機能標準に入れとけよと
ReplyDelete毎回noncopyable書くのめんどいし、
かといってそれだけのために他に依存したくないよと
効率とかの問題じゃない。依存は不安定だ。
ReplyDelete10年後、同じソフトウェアを再構築するには困難が伴うだろう。今、10年前の環境を構築しようと思ってもそこまで苦労はしないだろうが、今後は苦労が続くだろう。
機能ひとつひとつをパッケージに分割するのは果たして良いことがわからない。これは効率の問題だな。
Unixの静的ライブラリでは、オブジェクトファイルをまとめてアーカイブファイルにし、その必要なものをコンパイル時に自動的に取り出すから無駄がない。最近はオブジェクト同士のつながりを最適化させるためのLTOだってある。
その、単機能に分けたものは、果たして自動的に選別できて、適切な最適化ができるのだろうか。
果たして、Node.jsコミュニティは数十年前のUnixの車輪の再発明、しかも劣化したもの、に終わってはいないのか。