patorashのブログ

方向性はまだない

「現場で役立つシステム設計の原則」読書会 vol.3

第3回の感想です。前回はこちら。

patorash.hatenablog.com

会社のブログのレポートはこちら。

tech.rhizome-e.com

3章 業務ロジックをわかりやすく整理する

私が書いていた箇条書きのメモ。

  • データクラスと機能クラスの話。真っ先に思い浮かんだのは、Fat Controllerである。モデルに機能を書かないでコントローラーのアクションに処理をまとめてしまうせいで、再利用できないようになってしまうやつ。やはり悪手として紹介されていた。どこに業務ロジックが定義してあるかがわかりにくくなる。
  • そして、共通化の手法として、汎用クラスの話があった。UtilsやCommonだが、これらもよくないとは直感的に思っていたが、やはりそうだった。同じような処理がたくさんできて、使い分けがわからなくなるというのは、ちょうど前回の読書会の感想で参加者メンバーの1人が言っていた話と同じだなと思った。
  • 前にいた会社(12年以上前)だと、メンバー全員がオブジェクト指向を全然理解してなかったので共通化処理を継承元のクラスにガンガン追加していくというやり方を取っていたことを思い出す。当時はテストを書く習慣もなかったので、今考えると相当恐ろしい。
  • Railsのモデルはデータと業務を寄せていくところなので、まさにここに書いてあることに合致する。しかし、現状のプロジェクトだと値オブジェクトを使ってないから、まだまだ半分正解っていうところだろうか。
  • メソッドは必ずインスタンス変数を使うっていうのはよい指針だと思う。
  • クラスが肥大化したら分けるというのも、値オブジェクトを導入するいいタイミングっていうことなのだろう。共通で使えるパーツが増えていくと、再利用性が増すのでとてもよい。
  • パッケージにまとめる話。クラスを宣言するときにpublicって付けなかったらパッケージ内のみのスコープのクラスになるという話だったかと思う。他のところで通用しない、プロジェクト単位では再利用できない業務ロジックをそのパッケージ内に収めるという意味ではよさそう。これはたぶんRubyではできない気がする。パッケージはないけれど、それと似たようなことができるのが、モジュールで名前空間を作ることなので、そこは積極的に利用していきたいところだが、コードがかなり冗長になるので、やりすぎには気をつけたい…。Javaだと、importでパッケージを指定するので、あまり冗長にならない。
  • 3層とドメインモデルの話があったが、この3層をきれいに分けるパターンへのアンチテーゼみたいなのがRailsで、Railsだとデータソース層とドメインモデルが一体化したのがモデルになっている。そのおかげで高速に開発できる反面、複数のドメインモデルを使ってデータソースに保存する場合に、どこのモデルにロジックを書くべきかに困る。そして、どれかのモデルに書いてしまうと、そのモデル同士が密結合になってしまう。そこそこ大きなRailsアプリになってくるとぶつかってしまう壁みたいなものだ。この本を読んでいるとRailsの良いところと悪いところが同時に見えてきて面白い。

雑感

大体のメンバーが、Fat Controllerの話に似ているのでビジネスロジックはModelに持っていくやつ、という感じのことを言っていたように思います。そこら辺は同じチームの後輩氏には最初のほうで叩き込んであるので、普段からちゃんとできているなぁと思います。他のチームも多分そのあたりは大丈夫なはず…。

しかしまぁ、ドメインオブジェクトを意識したコードにはまだできていないので、まだまだ半分正解っていうところです。

最近、自分の書くコードはこの本の影響を受けていて、コトを意識したドメインオブジェクトを作る等して、コントローラーから更に処理を剥がしてドメインオブジェクトもしくはサービスオブジェクトにして関心を分離し、テストしやすいように変えています。コントローラーはそれを呼び出すだけ(新しく作ったところだけですが)。

ここまでテストしてあると、わざわざシステムテストで確認する必要も感じなくなりました(JSが絡むフロントエンド側のテストは別だけれど)。System Spec(いわゆるブラウザテスト)は止めて、APIのテストと同じくRequest Specで済ませました(権限チェック等によるリダイレクトのテスト等はしておきたかったので)。

CommonとかUtilsとかを作るのは、ドメインオブジェクトを作ることから逃げているなぁと考えるようになったので、どこかのタイミングでリファクタリングで撲滅させておきたいと思います。