mvc

Service を作ってはならない - 3層アーキという歴史的背景から見る? 勘違いMVCについて

えっらい今更な話という気もするし、そもそも愚痴半分な気もする。

何が言いたいの

MVC するならせめてまともな Model でやらせろ。勘違いクソ MVC のクソ Model で爆発したアホ Controller のメンテ/改修クッソダルいんだよ!!
もう馬鹿 SIer と大連やら北京やらのファッキンどもの尻拭いはいやだお。

前置き

Service というものが、どの時代から生えてきたものなのかはちょっとわからない。
RoR の "行き過ぎた Fat Model" 論争の頃か、あるいは MVC の "Fat Controller はどう処すべきか" 論争の頃だと思う。どちらにしてもそれなりに前のことで、これらは "Controller を痩せさせるための存在" として現れ、今なお再生産され続けている。
こいつらは邪悪である。今あるものも出来ることなら抹殺したほうがよいし、そうでなくとも「どこにカウントされるものなのか」知らなくてはならない。

(念のため繰り返すが、これは Controller のロジックを分離したものとして存在する Service / Logic の話をしていることに注意して欲しい)

勘違いMVC

以下は現在の現場 (某大規模EC) で実際に存在する (現在進行形でこれの塊) なパターンである。というか、割とどこもこんなんばっかなのではなかろうか。
なお、現在の現場はJavaでSpringだがBootではなく、DBアクセスはmybatis、テンプレートエンジンはthymeleaf、やや保守的ながらマシなほうかつオーソドックスな構成だ。

まず View がある。thymeleaf なので HTML テンプレートだ。JSP でないのは幸いだった。HTML には 部品 と 画面 があり、部品は画面の部分をくくりだして共通化したものだ。
そして画面ごとに Controller がある。Controller のメソッドがリクエストのエントリポイントのようなものなのはいつもどおりだ。
次いで Service がある。xService は xController と 1v1 で対応する。xService は基本的に実装 xServiceImpl ひとつだけを持つ。
xServiceImpl は対応する xServiceRepository を参照する。xServiceRepository は mybatis のDBアクセス用リポジトリだ。Interface + XML のパターンが採用されるが、大抵は単にレコードそのままなPOJOが返ってきて、オブジェクトへのマッピングはなぜかJava側で無意味にゴリゴリやっている。
Service 間で共用されるものは ~Util や ~Logic や ~SharedService なるよくわからないクラスが保有し、定数はそれぞれの利用される場所か ~Const に記述される。

Rubbish.

何が悪いのか?

割と何もかも悪いのだが、とりあえず最も致命的な (……というか、今回言いたい) ところを見よう。
Controller と 1v1 に対応する "Service" だ。
意味がわからない。View と Controller が 1v1 なのはまだ理解できる部類なんだが。

まず MVC とは何かを思い出そう。そう、Model, View, Controller だ。
悲しいことにもうほとんどお約束な勘違いに、Model ≒ DB というものがある。ふざけんな。お前が今使っている言語は何指向だ

3層 クライアント - サーバ

さて、わざとちょっとずれた歴史的な話をする。
一昔前お約束だったアプリケーションの構造に クライアント - サーバ というものがあった。クライアントは今ならブラウザに相当するが、全部自前で作ることも珍しくなかった時代の話である。
そしてこの時期、3層 クライアント - サーバ と呼ばれるアーキテクチャが存在した。

この3層というのは以下の3つのことを指す。

  1. プレゼンテーション層
  2. アプリケーション層
    (これはファンクション層だったりトランザクション層だったりビジネスロジック層だったりする)
  3. データ層

気づいたかもしれないが、これが言いたいことだ。
馬鹿な勘違いMVCは、この 3層 クライアント - サーバ アーキテクチャと同じことをしているのだ。

実際のところMVCモデルと3層アーキテクチャを混同するのもまあ無理は無いというか、パッと見確かによく似ている……似て……あー、少なくとも3つに分かれているところは同じだ1

ではどう違うのかと言えば全部だ。より厳密にはすべての層それぞれがどうやってもきれいに対応しない

3層アーキテクチャももともと2層アーキテクチャ (データサーバ - クライアント とでも言うべき構造、クライアント側がロジックを持つ) の改良案として出たもの、という事情がある2
かつてはロジックもクライアントが持つものだった。もちろんロジック側がクライアント送りというのはサーバの負荷軽減と言えなくもなかったのだが、データ伝送量は増えるしセキュリティはめんどくさくなるしバグは直しづらいしとろくなことがなかったのである。

というわけで、"3層アーキテクチャ脳"の世界観では「データがあって、クライアントがあって、データはロジックを通さないとクライアントで使えない」という理解になる。
そして「Model?データ層か。View?ああ、プレゼンテーション層だな。Controller?ハン、カッコつけおって。つまりロジックではないか」と言い出すわけだ。rubbish.

Controller はどこから来たのか

ここでもう一つ歴史。MVCの始まりは XEROX のパロアルト研究所だという。
これは Smalltalk-80 の実装において考案されたものだったが、考案されてからオブジェクト指向向けのデザイン・パターンとして知られるまで15年ほどかかっている (というのも、そもそも概念が論文としてが出たのが9年後らしい) 。そう、オブジェクト指向なんだ。
その後 JavaServer Pages Model 2 なるサーバサイド実装が登場し、これがどうも普及の決定打となった……らしい。

さて、Controllerの負う責務は何か?
それは "ユーザの入力を、より大きく、意味のあるイベントにラップして割り振る" ことだ3

例えば、ユーザがログイン・ボタンをクリックしたとする。
「ログイン・ボタンがクリックされた」、まずこれが View の理解だ。
では Controller の理解は何か?「ユーザがログインしようとしている、ログイン処理を呼び出せ!」。

これだ。「ログイン・ボタンがクリックされた」を「ログイン処理を呼び出せ!」に変換している。
Controller は View という受付の報告を元に Model へ「命じる」存在なのだ。ロジックは Model の担当なのである

Controller はUI、3層アーキテクチャでいうプレゼンテーション層には状態遷移がつきものであり、状態遷移をUIの中で管理すると凄まじい勢いで肥大化する、そのくせUIそのものの本質的な内容ではない、というわけで分離した結果生まれれた存在である。
つまり、本来 Controller は遷移専門なのだ。

「お前は何指向の言語を使っているんだ?」

MVC は Smalltalk において登場した概念であり、OOP向けデザイン・パターンとして紹介され (あきらかにアーキテクチャなのでデザイン・パターンと言われることはもうないが) 、その後広まった。オブジェクト指向の中で生まれたのだ
しかし MVC の M はロジックを含んでいるんだ!というと「データとロジックを混ぜるな馬鹿者!3層アーキも(ry」と言い出す者がいる4

オブジェクト指向の特徴を思い出せほんとろくなのがいないな日本のコンピュータ界隈の老人。もっとも古めかしい部類の3要素、継承・カプセル化・多態性においてさえ「データとロジックを一つのオブジェクトへ封入し、一体のものとして扱う」というものが根付いているのだ。OOPのある世界で、データとロジックの無為な分離は死に値する

「Controller は遷移専門で Model に命令するだけの存在って、じゃあロジックはどこに書けばいいんだ!」と思ったら、オブジェクト指向をよく思い出せば解決する。
カプセル化だ。ロジックはデータとともにある。そしてデータはどうあがいても Model 以外のどこにもない。よって、ロジックは Model の一部なのだ
ここまで言えばいい加減わかっただろうが、Service / Logic が存在してはいけないその真の理由は、Controller にロジックを書くことは、そもそも MVC が拠って立つ OOP に背く愚かしい行為だからだ。
もちろん、解釈次第では「Model の時点で DB アクセスはカプセル化されているのだ! OOP に背いてなどいない!」と言うことも出来るだろう5。言い張るだけなら誰にでもできる。繰り返しになるが、結局 Controller にロジックを書いた時点で、データそのものとロジックを分離していることには変わらない。DB アクセスを隠蔽したからなんだというのだ。

終わりに

だから、もしも MVC で C にロジックを書くやつがいたらこう言ってやろう。
お前の今使っている言語が何指向か知らないのか?6

ところで

P.S.

ときたま View にロジックを書くやつがいる。というかぶっちゃけ JSP にゴリゴリ Java 書くやつがいる。
これはもはやそういう次元ではないので直ちに上司を動かして首を切らせよう。Controller に書く馬鹿以上に仕事が進まなくなる。マジで。7


  1. 人によってはプレゼンテーション層とViewは同じだろうという。私の感覚だといやそれはねーよ黙れよ、という感じだが。 

  2. 少なくとも国内ではそうだと習った。正しい知識かはちょっとわからないが、反証が見つからないのでそう思うことにしている。 

  3. Wikipedia にさえそう書いてある。というか、珍しく出典がある程度きっちりしているしよくまとまっているので割とオススメできる。https://ja.wikipedia.org/wiki/Model_View_Controller 

  4. 実際に何人か出くわした。まあわかりやすい無能だ。 

  5. これも体験談。 

  6. いやこれマルチパラダイムじゃし、ってのはないものとする。 

  7. これまた体験談。この手の体験談も年齢の割に多い気がするが、でもマシな部類なんだろうなあ……