2016年3月28日
NPMとleft-pad : 私たちはプログラミングのやり方を忘れてしまったのか?
(2016-03-23)by David Haney
本記事は、原著者の許諾のもとに翻訳・掲載しております。
さあ開発者のみなさん、真面目な話の時間です。読者の皆様はおそらくすでにお気づきでしょうが、今週、ReactやBabelやその他大量の有名なNPMパッケージ群が壊れました。そしてその原因は少々驚くようなものでした。
ReactやBabel、その他のパッケージが依存する、left-padというシンプルなNPMパッケージがあります。この記事を書いている現段階で、このパッケージは GitHub上で11 star となっています。このパッケージは全体で 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回、2016年の2月全体で1800万回もダウンロードされています。 72個のNPMパッケージ がこれに依存していますが、その中身は たったの1行のコードです。
return toString.call(arr) == '[object Array]';
-
is-positive-integer ( GitHub ) というパッケージがあり、これは 4行という長さ で、昨日の段階で 3つのパッケージに依存していました。 その後作者がリファクタリングして依存対象が0個になりましたが、なぜ最初からそうしていなかったのか疑問を呈さざるを得ません。
-
Babel パッケージを1からインストールすると、 41,000個ものファイル が含まれることになります。
-
空の jspm/npm ベースのアプリのテンプレート は、 28,000個以上 のファイルからなります。
これらのことから、疑問に思わずにいられないのです。それは……
我々はプログラミングのやり方を忘れてしまったのか?
一体全体どう考えたら、過去の問題への正しい解決がこの方法だなんて言えるのでしょう?何百もの依存関係や、空のプロジェクトテンプレートに28,000ファイルも含まれている状況は、複雑怪奇や狂気と言わずして何なのでしょうか?
私の印象では、NPMのエコシステムの参加者は、マイクロパッケージという迷信を生み出してしまったように思えます。どんな関数やコードについても、自分で書くのではなく、他人の書いたものに依存することを好んでいるように見えます。NPMに参加する開発者の仕事が、「自分の個人的な/業務上のニーズに特有の新しい関数を作るために、既存のライブラリ呼び出しを羅列し、可能な限り最小の量のコードを書く」というだけになったかのように感じられるのです。
関数はパッケージではない
関数は、パッケージや依存関係にするにはあまりに小さなものです。純粋な関数には結合作用はありません。つまり、関数とはただのコードのランダムなスニペットであり、それ以外の何物でもありません。”コサイン関数”の依存関係なんて欲しい人はいないでしょう?そうではなくて、我々みんなが本当に欲しいのは”三角法”という依存パッケージのはずです。”トリッキー”であり、自力で書きたくないような関数をたくさん包含するようなもののことです。これは、.NETや他のフレームワークが、基本的な機能性の「コア」ライブラリを作っているのにより似ています。そのようなライブラリは、言語の設計者たちによって精査されており、正しくてバグもないことがもっと保証されています。
サードパーティ問題
他の人が書いたものが正しい保証、さらには動く保証なんてどこにもありません。もし正しかったとしても、それは本当に、ありうる限り最適な解決方法なのでしょうか?少なくとも、自分自身でコードを書いていれば、バグ修正や機能向上のために修正することが容易にできます。たった一行の関数にたくさんのバグが生まれることなんてそうそうないはずです。
2つ目に、仮にパッケージのロジックが正しかったとしても、目をつむったままでも書けないといけないレベルのたった1行の関数のために、開発者が依存関係を用いること、そのことに私は驚かずにはいられません。私の意見では、自分でleft-padやis-positive-integer, isArrayを(Google検索する時間を含め)5分で書けないのであれば、もはや コーディングの仕方を本当には知らない といえます。入社希望者がコーディングできるかを判断するためのコーディング面接において、そんな人は面接に通るような素晴らしいコードが書けるのでしょうか。
最後に、APIを羅列して、その行為を「プログラミング」と呼んでも、それがプログラミングになるわけではありません。 クラウドやオーバーエンジニアリング、実際に必要なレベルを超えるような複雑性などを含め、依存関係ハッキングの狂ったやり方です。
さらに悪いことには、もしあなたのコード(もしくはサードパーティ製ライブラリのコード)にバグがあったり壊れたりした場合、プログラミングのやりかたが分かっていなければデバッグする方法もわからないのです。
依存関係を少なくする努力を
それでも、あなたが使うあらゆるパッケージが、別の 依存関係 をあなたのプロジェクトに追加することでしょう。依存関係は、その名の通り、コードが動くために 必要 になってしまうものです。より多くの依存関係があればあるほど、より多くの欠陥が生まれ得ます。エラーが生じる可能性が増えることは言うまでもありません。あなたが日々用いている依存パッケージに関して、その関数を書いたプログラマについて精査したことがありますか?
どんな複雑さの機能にも依存関係を用いることは、結局は自分で書くための時間・お金・デバッグを伴うことになります。データベースアクセスレイヤ(ORM)やキャッシュクライアントなどのものについては、依存関係を用いるのがいいでしょう。何故なら、それらの機能は複雑なため、依存関係を用いるリスクが、依存関係から得られる効率・節約に見合うからです。
しかし、プログラミングへの愛に誓って、基本的なプログラミング関数を血生臭く自分で書きましょう。挙げたようなワンライナーのために依存関係を用いることは、ただ馬鹿げています。私の言うことが信用できませんか?Reactのチームに、「今週はどうだった?」「文字列の左を詰める11行の関数を、自分で書いていればよかったと思う?」とでも聞いてみてはどうでしょう。
Follow David Haney on Twitter at @haneycodes
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa