はじめに
この記事はRuby Advent Calendar 2023の記事です。参加しようとしたときにはすでに枠が埋まっていたのですが、12月2日の枠で「代わりに投稿」できそうだったので投稿しています。
Albaについて
Albaは私(@okuramasafumi)が開発しているRuby向けJSONシリアライザです。
ウリは高速さ・容易さ・機能性です。また、JRubyとTruffleRubyでも動作します。詳しくは上記リンクからREADMEを参照して下さい。
2023年までのコミット数
さて、Albaの開発は2020年から始まっており、2022年にはほぼ完成形と呼べるに至りました。バージョンとしては2.1.0がリリースされています。
実際、コミット数を以下のコマンドで調べると2023年は少な目となっています。
❯ git log --since="2020-01-01" --until="2020-12-31" --pretty=oneline | wc -l
216
❯ git log --since="2021-01-01" --until="2021-12-31" --pretty=oneline | wc -l
290
❯ git log --since="2022-01-01" --until="2022-12-31" --pretty=oneline | wc -l
229
❯ git log --since="2023-01-01" --until="2023-12-31" --pretty=oneline | wc -l
144
では、2023年は何をしていたのか、というのがこの記事のテーマです。
gemをメンテナンスする
2023年にはissueが約15個ほど投稿されました。ペースとしては月に1つくらいです。これらのうちのいくつかはHOW TO的な話だったりREADMEに書いてある内容だったりするのですが、一方で他のものはバグの報告だったりします。
バグがあるなら直さなくてはいけません。が、ここで「バグ」というのは完全に「壊れている」ということ以外に「こうなっているのが自然では?」というものも含みます。「含みます」と書きましたが、「含んでいます」のほうが正確かもしれません。つまり、Albaの開発においてはユーザーの自然な期待に反しているものについてバグとして扱うことにしています。ここで「自然な期待」というものはあえて広めに定義しています。
例えば以下のようなissueを考えます。
これはエラーというわけではありません。しかし、あるクラスに定義されたメソッドの優先度がシリアライズ対象のオブジェクトが持つ同名のメソッドよりも低いというのは直感的ではありません。歴史的経緯によりこうなっているという仕様であり、当初は修正を渋っていたのですが、最終的にはバグと見なして修正することにしました。
しかし、全てのissueについて修正を行うわけではありません。例えば以下のissueを取り上げます。
これは機能追加の要望ですが、既存の機能セットとの重複やコードの複雑性との兼ね合いを考えたとき、単純に追加するのはあまり良くないと思われたため、提案の形で返信をしたところ、納得してもらってクローズされました。
このような修正を続けた結果、現在のAlbaは非常に洗練されたもの(当社比)となっています。
ゼロissueの達成
https://gihyo.jp/news/report/01/rubykaigi2019/0003 にあるように、Jeremy Evansという人は自身の開発するgemのissueをゼロにするポリシーを持っているようです。非常にかっこいいポリシーだと思い、私も真似をしてみることにしました。
結果、無事にオープンなissueを0にすることができました。利用者がそこまでは多くないのと、わかりやすいバグや機能要望はすでに修正済みであることが大きいと思います。
Albaにおける面白いRubyコード
ここでは少し目線を変えて、Ruby的な側面からAlbaを紹介したいと思います(Ruby Advent Calendarの記事ですし!)
例えば以下のコードです。
このコミットで導入されたものですが、以前のコードでは各内部変数をループで初期化しており、その際にinstance_variable_set
を使っていたため速度に問題がありました。この部分がボトルネックではないことはわかっていたのですが、それでも遅いのは嫌だったので改善の方法を探りました。単純に変数を列挙すれば速度は改善しそうでしたが、それでは変数が増えたときの修正箇所が増えてしまいます。検討の結果、変数を単純に列挙したコードと同等のコードを文字列として生成してそれを一括でeval
することで両者のメリットを得ることができると判断しました。もちろんデメリットとしてはコードが複雑になることですが、initialize
メソッド内部で完結するので割に合うかなというところです。
それ以外にもいくつかちょっと凝ったコードはありますが、全体的には素直な書き方にして読みやすさを重視しています。
まとめ
gemをメンテナンスすることについて日本語で書かれた記事はあまり見かけないのでこの記事を書きました。何かの参考になれば幸いです。