📦

packwerk + graphwerkでRailsアプリの依存グラフを眺めて見よう

2022/11/22に公開

こんにちは。エンジニアのMasaruTechです。

最近、packwerkが気になっているので触ってみていました。
その中でpackwerkのREADME.mdにgraphwerkという依存グラフを描画してくれるライブラリが紹介されているのを見つけました。
そのgraphwerkを使っていろいろなRailsアプリで描画して眺めていたらおもしろいなと感じたので、今日はそれの紹介をしたいなと思います。

packwerk導入とgraphwerkでのグラフ描画手順

  1. packwerk,graphwerkをGemfileに追加してインストール

※graphwerkはGraphvizを利用してます。ここではすでにインストールされている前提で書いてます

$ vi Gemfile

---追加---
gem 'packwerk'
gem 'graphwerk', group: %i[development test]

$ bundle instll
  1. packwerkをセットアップ
$ bundle binstub packwerk
$ bin/packwerk init
  1. app配下の各ディレクトリにpackage.ymlを配置して依存違反リストを生成
$ find app/ -name "*" -type d -d 1 -exec cp package.yml {} \;
# RAILS_ROOT/libがある場合
$ cp package.yml lib/
# 依存違反リストdeprecated_references.ymlを生成(rubocopの.rubocop_todo.ymlみたいなものっぽい)
$ bin/packwerk update-deprecations .
📦 Packwerk is inspecting 1985 files
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
....................................................................................................................................................................
.................
📦 Finished in 4.59 seconds

1 offense detected

✅ `deprecated_references.yml` has been updated.

  1. 依存グラフを生成

これで準備が整ったのでgraphwerkで依存グラフを生成します

# packwerk.pngが生成される
$ bin/rails graphwerk:update

いろいろなRailsアプリケーションの依存グラフを眺める

有名所のRailsアプリで依存グラフを生成してみましたので眺めてみましょう。

RubyGems

https://github.com/rubygems/rubygems.org

Rubyistなら誰もがお世話になるRubyGems。

標準的なRailsアプリの構成ですね。違和感のある双方向な依存関係はあまりなさそうですかね。

Redmine

https://github.com/redmine/redmine

プロジェクト管理で有名なやつ。

libとhelpersが双方向の依存になっていますね。少しみてみましょう。

lib/deprecated_references.yml
app/helpers:
  "::ApplicationHelper":
    violations:
    - dependency
    files:
    - lib/redmine/hook/view_listener.rb

https://github.com/redmine/redmine/blob/44c72fe7b0ee1921bc00c16ee1f1a328b1ab82e0/lib/redmine/hook/view_listener.rb#L24-L36

なるほど、この include ApplicationHelper が境界を跨いでいると検知されたんですね。
実際のpackwerkの導入でもこうやって見ていって整理していくんでしょうね。

Mastodon

https://github.com/mastodon/mastodon

Twitter騒動で最近また聞くようになってきましたね。

役割毎にディレクトリ分けされているようで、かなり線が複雑になってますね。
パッと見てきになるのは、controllersとmodelsの双方向の矢印でしょうか。

app/models/deprecated_references.yml
app/controllers:
  "::AccountableConcern":
    violations:
    - dependency
    files:
    - app/models/admin/account_action.rb
    - app/models/admin/status_batch_action.rb
    - app/models/form/account_batch.rb
    - app/models/form/custom_emoji_batch.rb
    - app/models/form/email_domain_block_batch.rb
    - app/models/form/ip_block_batch.rb
    - app/models/form/status_filter_batch_action.rb
  "::Authorization":
    violations:
    - dependency
    files:
    - app/models/admin/account_action.rb
    - app/models/admin/status_batch_action.rb
    - app/models/form/account_batch.rb
    - app/models/form/custom_emoji_batch.rb
    - app/models/form/email_domain_block_batch.rb
    - app/models/form/ip_block_batch.rb
    - app/models/form/status_filter_batch_action.rb
    - app/models/trends/preview_card_batch.rb
    - app/models/trends/preview_card_provider_batch.rb
    - app/models/trends/status_batch.rb
    - app/models/trends/tag_batch.rb

https://github.com/mastodon/mastodon/blob/48e136605a30fa7ee71a656b599d91adf47b17fc/app/controllers/concerns/accountable_concern.rb#L3-L13

https://github.com/mastodon/mastodon/blob/48e136605a30fa7ee71a656b599d91adf47b17fc/app/controllers/concerns/authorization.rb#L3-L23

controllersのconcernsにある証跡や認可のメソッドをmodelsでも使うためにincludeしているみたいですね。
こうなってくるとlibに移すなどを考えたほうがよさそうですかね。

自社アプリだとどうなのよ

許可もらえたので自社アプリの依存グラフも見てみましょう!

こうやって全体を眺めてみるのは初めてですが、自社アプリもかなり複雑な線になってますね。
jobsとworkersがいて双方向になっているのは、jobsの方に寄せようとしている途中だったりもします...
controllers->validatorsの矢印はvalidatorsにある定数を参照しているものですが、こうやって見てみると違和感がありますね。

最後に

packwerkは既存アプリにとりあえず入れてみて害になるようなものではないので、気になっている方はとりあえず導入してみて今回のように依存グラフを眺めながらメンバーと議論してみたりしてもよいのではないでしょうか?

packwerkは日本語だと情報がまだ少ないですが、最近だとKaigi on Rails 2022でnoteの嶋本さんがpackwerkについて発表していたので、それを見ればより導入についてのイメージがしやすくなるかと思います。

採用情報

レンティオでは絶賛、エンジニアを募集しています。
もし興味をお持ちいただけたらご応募を検討いただけますとうれしいです!
https://recruit.rentio.co.jp/engineer

Discussion