何でも屋エンジニアのブログ

ソフトウェア関連技術、コミュニティ、日々の雑貨

Ruby のコード品質のメトリクスを取得する Gem の CodeKeeper v0.6.1 をリリースした

CodeKeper とはRuby のコード品質のメトリクスを取得する Gem のことである。

blog.ebihara99999.com

ある程度形にしてからずっと触れていなかったのだが、以下の PR を頂いたので確認してマージした。

github.com

その際 EOL の Ruby の CI を回していることに気づきサポートを切った。

github.com

ダウンロード数はある程度あるんだけど使っているみたいな話を聞くことはなかったので、今回 PR を頂けて非常にうれしかった。 余談で僕は必ず issue や PR 投げるときには「 Thank you for the great gem. 」 と書くようにしている(使っているので実際すごく感謝している)が、今回頂いた PR に類似のお礼が書いてあって「こんなにうれしいんだ」と感動したので、続けていこうと思った。

この Gem を作ったときは自分が見ていたサービスのコードを使い品質のマネジメントに使おうと思っていたのだが、とある経緯で CTO を目指すことになり、あまりそちらに時間を割けなくなってしまい使えずじまいだった。(このような試みは大事だが、 CTO は一経営者なのでまずは経営陣に認めてもらう実績やふるまいをする必要があり優先度がさがってしまったのであった。)

今はフリーランスとして活動しているが、コードの品質という部分に自分はとても興味があるんだと改めて感じていて、何か OSS のメトリクスをとったりこの Gem に機能を追加しつつ育てたり活用していきたいな、と思った矢先に PR を頂けたのですごくタイミングが良かった。次は S3 に json あげて解析できるようにしたいのでやっていく。

ActiveModel::AttributeMutationTracker を読んだ

今日は朝刊(yyagi さんの「なるようになるブログ」)で取り上げられてた PR から ActiveModel::AttributeMutationTracker を読んだ。

y-yagi.hatenablog.com

属性変更をトラッキングするクラス。ActiveModel::Dirty とかで使われていそうで馴染みがあったのでシュッと読めたが、ForcedMutationTracker クラスが何のためのクラスかわからなかった。

コミットログから高速化の目的で切り出されているのが分かった。 force_change を track するために切り出したクラスなんだけど、ivar backed のものと attributes backed のものを一緒に動かすとすごく遅かったので切り出したとのこと。ソースとにらめっこしたりオブジェクトの中身見たりしたけど、いまいちなぜこれでここまで高速化されるかが分からない...ぐぬぬ。それにしてもすごい成果だ。

PR

github.com

「良いテストコード」の議論から気づいた価値観の違いの由来について

良いテストコード、と言われて思い浮かぶ要素はいくつかあるだろう。

  • 過度に DRY になっていない
  • 上から下に読み下せる
  • 仕様を網羅している
  • テストデータが過不足なく当該セクションで作られている

など。

たまたま良いテストコードについて議論する機会があったのだが、DRY 具合について話していたとき

過度なDRYを行わず、APIドキュメントだと思って書く 脳内メモリを消費させない“リーダブルなテストコード”の書き方 | ログミーBusiness

のようなリンクを見せ説明したが僕のいわんとすることがあまり伝わらなかった。そして相手が重要視していることも正直なところあまり理解できなかった。 価値観が違うのだろうということは話していて感じていたが、どうしてこういう違いが生まれるのだろうということを疑問に思った。「育ってきた環境が違うから」とは思うものの、より本質的に理解するにはもう少し何かが必要だなと感じ考えていた。

僕はテストを(特にユニットテストを)きれいな設計・実装を助ける道具だと捉えていて、そういう世界を実現するために使っている。依存関係を正常に切り出し、インターフェースを整え、ケースを整理しデバッグするための手段の一つだと捉えている。一方、おそらく議論した方はあまりテストを書くのが得意でないか、もしくは実装は開発環境で確認しすべて実装が終わったあとに品質のためある種の義務として書くものというように捉えているように見えた。

これでは良いテストについての価値観が違うのは当然で、どっちが良いというわけでなく使う道具の目的が違うんだからそれに求めるものや理想が異なるのは当然のことだろうと腹落ちした。(もちろんテストを使いこなすメリットは大きいとは思うが、色々な開発方法がありバリューを出しやすい方法を採用すれば良いと思うのでその是非はここでは問題にしていない。)

僕が PC に求めるものと営業の方が PC に求めるものは違うだろうし、趣味ランナーの僕がランニングシューズに求めるものとプロランナーがシューズに求めるものは違うだろう。

どっちが良いとか悪いではなく、そういうことなのである。

ActiveRecord::Reflection を読んだ

空いた時間に Rails コードリーディング。今日は ActiveRecord::Reflection をザーッと読んだ。

ActiveRecord::Reflection は model の関連付けに関するデータを保持するクラスという感じだった。例えば、belongs_to の実装では

def belongs_to(name, scope = nil, **options)
  reflection = Builder::BelongsTo.build(self, name, scope, options)
  Reflection.add_reflection self, name, reflection
end

のように add_reflection を呼んでいる。

細かいオブジェクトのふるまいを見たかったのだが、binding.irb を使うと

SyntaxError: /home/vscode/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/irb-1.13.0/lib/irb.rb:1600: syntax error, unexpected `end'

というエラーが出てしまうの、IRB の不具合だったりするのだろうか。全然ちゃんと調べてないけど地味に困っている。

ActiveModel::Access について調べたメモ

Rails のコードリーディング、久しぶりにしてみようと思いどこから読もうか眺めていたらたまたま見たことないモジュールが見つかったので読んだ。

ActiveRecord::Base#sliceActiveRecord::Base#values_at を ActiveModel に移植したもの。non-Active Record なモデルで利用したかったからという理由。

github.com

テストを回して挙動を確認した

irb(#<AccessTest:0x00007f095f9d5bb0>):008> @point
=> #<AccessTest::Point:0x00007f095f504398 @vector=[123, 456, 789]>
irb(#<AccessTest:0x00007f095f9d5bb0>):009> @point.x
=> 123
irb(#<AccessTest:0x00007f095f9d5bb0>):010> @point.y
=> 456
irb(#<AccessTest:0x00007f095f9d5bb0>):011> @point.z
=> 789
irb(#<AccessTest:0x00007f095f9d5bb0>):012> @point.slice(:x, :y, :z)
=> {"x"=>123, "y"=>456, "z"=>789}
irb(#<AccessTest:0x00007f095f9d5bb0>):013>

dotfiles を chezmoi を使って管理するようにした

今までMitamaeで管理していたが、例えば Ruby のインストールする場合 itamae の plugin を使うと便利なのだが依存関係が多くなり、dotfiles 管理・セットアップのためにはちょっと複雑すぎる印象があった。実際、Itamae を理解し使いこなすというより Ruby の中でシェルコマンドをたたいてあれこれする集合体になってしまっていた。それなら Mitamae である必要はないだろうと思い、かつ Windows でも使えるものが欲しいなと思い chezmoi を選んだ。

@mattn_jp さんの投稿で以下の比較表を知ったおかげできちんと比較し選べた。

www.chezmoi.io

シュッと WSL2 Ubuntu のセットアップスクリプトや設定ファイル群は移行して動くようにしたので、気が向いたときに Windows の方も育てていく。ちゃんと試していないが、会社用・個人用のような分岐もシュッとできるようなので便利そうだ。