The Fall Of Utils

古いコードの依存関係を整理するなか、"utils" というパッケージが依存関係の mess になっているのに気付く。Utils. そういえば昔はよく目にしたけれど、最近はあまり見なくなった。なぜかと考える。

プログラミング言語が強力になったのが理由の一つだろう。昔だったら Verb-er や NounUtils などと銘打ったクラスに追い出したくなる boilerplate ぽいコードが、今なら短くインラインで書ける。あるいは同じファイルの中に小さなクラスを定義するだとか適当に extension method を生やすとかでしのげるようになった。

あとは文法だけでなく標準ライブラリも充実した言語が増え、それまで各人が再発明していたコードが標準でついてくるようになった。これは言語デザインの主流が委員会ベースからコミュニティベースに移り、割と荒削りなものでも便利なら標準につけてしまうことが増えたおかげもある気がする。言語によるか。

理由2つめはオープンソースの普及。かつて Utils として書かれたようなコードは今ならだいたいサードパーティのオープンソースライブラリとして誰かが書いている。そもそも言語自体が大概オープンソースだから、標準ライブラリとサードパーティライブラリの境目も昔ほどはっきりしない。他人のコードに依存しすぎたせいでおこる left-pad 騒動 みたいな問題もないではない。でも総体としてutils 時代より間違いなく前進している。人気があるライブラリなら自分で書くより出来が良いことも多いし。

自分は "utils" を "manager" に匹敵する code smell と敵視していた時期があり、utils をどう解体すべきかについて意見があった。けれど今となっては manager と並んで一部の不幸な人以外にとってはどうでもいい話題だね。


以下、時代にとりのこされている人のための utils 解体講座。

utils とは要するに「名前や居場所を考えるのがめんどくさいコード置き場」であり、そういう雑さは規模が小さければ別にあっていいとおもう。が、量が増えてくると急速にデザインを腐敗されるのでどこかで真面目に切り分けないといけない。

Utils につっこまれるコードの代表格は、標準ライブラリやフレームワークの穴埋め役。本来ならそれらのライブラリに入っていて欲しかったけれど、入っていない機能たち。こういうコードは、自分のツリーの中に標準ライブラリやフレームワークを mirror したパッケージ構造を作って分類するのが定番。厳密に mirror するのが大げさすぎると感じるなら適当に簡略化してよい。あと java には java.util という台無しパッケージがあるのでこれは真似しない。Guava なり Scala なりもうちょっとマシな例に倣う。java.util というパッケージングはほんとにひどいとおもうけれども、20 年前の判断なので責める気にもならない。コレクションが util であることに人々が疑問を持たなかった時代。

Utils につっこまれるコードの別パターンは、自分のコードベースの既存パッケージにぴったりくるものがなく、とりあえず・・・とつっこまれたもの。気持ちはわかるけれど、まだ既存のパッケージに無理やりねじ込んでおく方が歪みが隠れなくて良いと個人的には思う。ある規模を超えたコードに utils のようなゴミ捨て場を作ってしまうと tragedy of commons が起きがち。

Messy なコードを整理したい立場からみると、こっちのとりあえずパターンは、ある程度機械的に扱える前のパターンより厄介。失敗したデザインを一つ一つ直していかないといけない。嫌がられつつ別のパッケージに移すのも場合によっては仕方ないと思う。責任転嫁。ゴミの可視化。

デザインの失敗は今も昔もある。でも utils という都合の良いゴミ捨て場のない近代的なコードベースはダメさが目に着きやすくて良い、のかもしれない。モダンなゴミ捨て場の姿には興味がある。どうなってんのかな。