密結合によって生じる問題と Plugins を利用した問題解決【Red Data Tools開発者に聞け!】

Red Data Tools

今回から新たなテーマ「RubyGemsとRDocの密結合を解消する」になり、今回が実質初回になります!(1回目のライブはネットワークトラブルで中止に…)

初回の今回は issue として挙がっている「RubyGemsとRDocの密結合」について、その問題点と解決のためにどんなアプローチが取れるのか?について触れていきます。

Red Data Tools開発者に聞け!第21回 「RubyGemsとRDocの密結合を解消する」Part2

RubyGems における RDoc への依存

gem install XXXbundle install XXX などで開発者は gem を自身の環境にインストールしてくることができます。gem のインストールにおけるコアな処理は大まかには以下のような感じです。

  • 対象の .gem をダウンロードしてくる
  • ダウンロードをした .gem を展開する
  • 展開したファイルを適切な場所に配置する

これで gem 自体は使える状態にはなるのですが、ただインストールしただけではやや不便な状態です。そこで RubyGems は開発者なら gem をインストールしたときに多くの人が必要としているであろうことを自動でやってくれています。

その中の一つとして RDoc によるドキュメントの生成を行なっています。

RDoc とはソースコードから HTML や Markdown 形式などのドキュメントを生成してくれるツールです。ネットに公開されているものだと Ruby on Rails API なんかは RDoc により生成されたドキュメントの例です。

RDoc により生成されたドキュメントを参照すれば、インストールしたての gem の使い方を簡単に知ることができて便利!なので RubyGems は自動でやってくれているというわけですね。

RubyGems が RDoc によりドキュメントを生成する処理は以下のコードの部分にあります。

Github

# frozen_string_literal: true

require_relative "../rubygems"

begin
  require "rdoc/rubygems_hook"
  module Gem
    RDoc = ::RDoc::RubygemsHook
  end

  Gem.done_installing(&Gem::RDoc.method(:generation_hook))
rescue LoadError
end

RubyGems の中から RDoc のメソッドを直接呼び出してこの処理を実現していることがわかります。この部分が RubyGems の RDoc への依存、言い換えれば密結合になっているというわけです。

密結合であることの問題点

密結合であることの問題点はメンテナンス性の悪さにあります。

もし RDoc 側が RubyGems でも使用している定数の名前を変更したくなったらどうでしょうか??

RDoc のメンテナーは自身のコードベースだけを見ていてもそれが RubyGems で使われているかどうかを気づくことができません。うっかり破壊的な変更を行なってしまえば RubyGems が動かなくなってしまうかもしれません。

運よく問題に気づいたとしてもコードは RubyGems 側にあります。メンテナンスする場合は RubyGems 側のメンテナーに修正を依頼して…と煩雑なやり取りが必要になります。密結合なアーキテクチャはこのようにどんどんと変更が難しいものになってしまうのです。

密結合を解消するアプローチ: Plugins

RubyGems は他のモジュールを使って自身を拡張することができる Plugins という機能があります。

Plugins - RubyGems Guides

インストールされた gem の中に rubygems_plugin というファイルがあれば、そこをエンドポイントにして RubyGems から拡張機能を実行することができるというものです。

拡張機能はインタラクティブに呼び出されるようなものもありますが、Hooks を使うことで gem のインストール前に実行する、といったように RubyGems が行う処理のフローの中に Plugins で実現される処理を埋め込むことも可能です。

今回はこれを利用して密結合を解消していくことになります。RDoc 側のコードベースに rubygems_plugin を作成して、 Hooks により gem の install 後にこの Plugin が実行されるようになっていれば良いわけです。

こうすることで RDoc によるドキュメント生成の処理は全て RDoc 側に寄せられます。今後は RubyGems 側のコードを意識することなく RDoc のメンテナーはコードをメンテナンスすることができます。

コメント

タイトルとURLをコピーしました