プログラミングRubyといえばRails、RailsといえばActiveRecordというくらいに、事実上ActiveRecordはRuby界隈におけるORマッパのデファクトスタンダードだ。Solnicaというソフトウェア・エンジニアは、ActiveRecordパターンが常にスケーラブルなアプリケーションにとっての最適解ではないという思想から、ROM.rbというRubyアプリケーションにおけるレイヤ分割を強力にサポートするためのORマッパー*1を開発している。ROM.rbの何がよいのか?長期間にわたってRailsアプリケーションの中でActiveRecordを使ってきた経験があれば、ActiveRecordにおいてモデルの中にロジックがてんこもりになり、コードベースが肥大化してきてしまうのに悩んだ経験があるのではないかと思う。ActiveRecordには、データベースの構造とドメインモデルの構造を密結合なものにすることによって開発者がアプリケーション/データベース間におけるデータ構造のインピーダンス・ミスマッチを意識する必要がなくなるという強力な利点がある。同パターンにおいて、モデルはドメインモデルとデータアクセスの責務を同時に担っており、モデルの中にデータベースの操作に関するロジックと、アプリケーション固有のドメインに関するロジックが入り混じってしまいがちだ。した困りごとに関して、Rails界隈では様々なリファクタリング・パターンが考案され、駆使されてきた。GitLabやMastodonなどはActiveRecordとそれに関する責務分割のテクニックを駆使して、巨大だがメンテナブルなアプリケーションをRailsで構築してきた、いい例ではないかと思う。一方で、ROM.rbはこうしたARにまつわる問題点を考慮し、データマッパーパターン*2でアプリケーションを開発するために作られた永続化周りのモジュールになっている。ROM.rbを使うことによって、アプリケーションにおけるモデルを、データアクセスの責務を持たない純粋なドメイン・モデルないしアプリケーション・モデルとして扱い、データの永続化に関する処理をレポジトリレイヤに抽象化しながら、実装をアダプタレイヤに任せることによって、強力かつ明確な責務の分離をすることができる。ROM.rbの思想ROMの思想を理解するにあたっては、いわゆるレイヤード・アーキテクチャと呼ばれる、アプリケーションをいくつかのレイヤに責務分割することで変化に強いアプリケーションを作る手法に言及する価値がある。Martin)と呼ばれるアプリケーション設計界隈(?)の有名人によって考案されたクリーン・アーキテクチャの図だ。blog.tai2.netこの図は、アプリケーションがいくつもの階層(レイヤ)によって分割されて作られているということを示している。アプリケーションをこのようなレイヤに分割する大きな利点は、アプリケーションに対する変化を柔軟にするということだ。開発者がアプリケーションを作るとき、そのアプリケーションには、ほぼ必ず固有の処理がある。固有の処理は、一般にビジネス・ロジック(ドメイン・ロジック)と呼ばれ、最もアプリケーションの中で重要なものとして扱われる。一方で、開発者である私達がアプリケーションを開発する際に使われる言語、フレームワーク、ミドルウェア、インフラストラクチャなどは、一般的にはビジネス自体とは強い関連を持たない。それらの事象はビジネスをアプリケーションで表現するためのツールでしかないからだ。単なるツールであるものたちがアプリケーションのコアであるビジネス・ロジックと密接に関連してしまうと、アプリケーションは柔軟性を失うことになる。PostgreSQLを使っていたアプリケーションが、のちにパフォーマンス改善のために新たなBetterSQLと呼ばれるミドルウェアを使うことになったとする。なった際に、アプリケーションのビジネス・ロジックがPostgreSQLに強く依存した設計になっていれば、アプリケーション全体の設計を見なおさなければならない。これが大規模なアプリケーションになればなるほど、この移行作業はキツイものになる。アプリケーションの設計とスケーラビリティの関係はこうした依存をいかに減らしていくかというところに関わる。アプリケーションのレイヤ分割の意義とは、できるだけ粗結合なレイヤをアプリケーションの中に仕切りのように設けることで、来たる未来に備えるということだ。Interface)と緑(Gateway)のあたりだ。ROMは、永続化レイヤをアプリケーションのためだけのものとして扱わない。RedisやMemcacheのようなオンメモリ・データベースだったり、サードパーティのWebAPIもまた、データベースと同等な永続化レイヤの一部として扱うことができる。これを実現しているのは、ROMがアプリケーションから外部への入出力をリポジトリと呼ばれる責務でカプセル化し、具体的な実装をリポジトリに差し込まれたアダプタに任せるからだ。開発者はROMのアダプタを使ったり、必要な場合には自分で作ることで、アプリケーションとそれに対する外部入出力を永続化レイヤの責務としてとりまとめることができる。このようなアダプタによるプラガビリティの利点は、アプリケーション自体がその外側の具体的な実装を気にしなくて良くなるという点にある。具体的にROMの思想を知るには、ヘキサゴナル・アーキテクチャの図を見るのが良い。blog.tai2.net簡単に言うと、ヘキサゴナル・アーキテクチャは、アプリケーションとその外部の間にアダプタをおくことによって、アプリケーションを粗結合にするというものだ。それまでアプリケーションでStripeを使っていたが、とある事情でそれをPayJPに乗り換える必要が出てきたとする。この場合、アプリケーションの中で決済処理を行う箇所の具体的なAPIの操作がアダプタによって綿密にラップされていれば、アダプタをStripeのものからPayJPに差し替えるだけでよくなる。サードパーティAPIなどに依存しているアプリケーションであれば、WebPayのサービス終了などの事例を顧みるに、アプリケーションを出来る限り外の世界と粗結合にしておくことにこしたことはないだろう。OOこれ以外にも、ROM.rbは関数型プログラミングとしてのアプローチや、オブジェクト指向性を強く意識しているらしいが、さほど今回のイントロダクションでは重要ではないのでここでサラッと触れる程度に留める。さあ使ってみよう!残念ながら書くのにとても疲れたので、ROM.rbの具体的な使い方については、次の記事にしようと思う*3。自分で試しにアプリケーションを書いてみても良いが、ネット上にはROM.rbに関する記事が恐ろしく少ない。公式のドキュメントもはっきり言ってとても少ない。英語の記事はググるとわりとでてくるので、それらを試しに読んでみると良いだろう。2017でのROM.rbに関する講演がこのモジュールの思想や具体的な使い方を知る手助けになるだろう。このためだけに英語をしっかりと学ぶ価値さえあるのではないか、というくらいだ。Repositoryさーて、お待ちかねのROM.rb入門の第3回はRepositoryから。Relationさて、入門ROM.rbの第2回は、まずRelationから。(8)はてなブログをはじめよう!IzumiSyさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。