がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

Modelについて考えてみる

あちこちで「MVC」と言われつつ、なんか気がつくとMVPとかMVVMとか色々出てきて。
一方でじゃぁ「Model、って単語自体はは大体共通認識なのか?」と問うと、これがまた………。

というあたりで。
ちぃとごみごみと混雑しているように思われるので、一端、考察してみたいかなぁ、と。

以前に全く別の所でも書いたのですが。
大雑把に、フレームワーク(WAF)は
・ルーティングに従ってディスパッチして
ビジネスロジック呼んで処理して
・出力
ってな流れが、ものすごく大雑把なあたりで、主だった処理の流れだと思われまして。

んで、この「ビジネスロジック」の所が、実際には
・DBとやりとりをするところ
・データをごにょごにょする所
の2つがあると思うのですだす。

んで。
「Modelってなに?」って聞いたときに、確実に紛糾するのが、あるいは分離するのが、この聞き方。

・「Model ≒ ORM」は、true? false?

この判定式のboolean値によって、以降の内容が決まってくるわけでございます。
端的に「Modelの1インスタンスが、(大体)1テーブルの1レコードを意味している」のであれば、上述はtrueになる感じ。
とはいえ……昨今のフレームワークの多くは「true」なのではないかなぁ、と思うので、そのルートを前提に。

上述が概ねtrueだとすると、次の質問が

・「ビジネスロジック」は、どこに書くの?

というあたり。
これが「コントローラー」になるんなら、まぁ「トップハム・ハット卿*1になる」事は仕方が無いんじゃないかなぁ、と思うですよ基本的には。
勿論「ほかの場所に切り出してコントローラーをスリムにする」のはよいのですが、結局それって「コントローラーが抱え込む脂肪をほかのclassに押しつけている」だけ、なので、ほかのどこかがファットになるだけかなぁ、と。
で「んじゃぁ山盛りでclass作ってどこもスリムにする」と、今度はファイルの全体量とかクラスの数とかメソッドの数とかが半端なくなくなって可読性が落ちるので、個人的にはそっちの方が「よりお好まないかなぁ」と。
なので「必要な流れを必要な程度に書く」のは必要で、それが「特に分割するメリットがない」のであれば、ある程度長くなるのも、状況によっては「やむを得ない」と思うんですよ。

ただまぁ実際には「共通化」とか「テスタビリティ」とかの観点もあるかなぁ、と思うので。
「Model ≒ ORM」なのであれば、ビジネスロジックは「どこかにそれようのディレクトリとか名前空間とか掘って、そこに入れる」とよいんじゃないかなぁ、と。
おいちゃんは「Libs」とかよく使います。

つまり
・Contriollerは、基本的には「Libs」を呼ぶ
・Libsの中で、必要なテーブルに紐付いているModel(群)を呼ぶ
・「ORM使ったりSQL書いたり」は、Modelの中に閉じ込める
ってな感じ。

いやまぁ「ちょっとした処理くらいならControllerに直接書く」でもよいと思うのですが。
さじ加減が出来ない人がいると判断が面倒なので、その辺はチームメンバー(のレベル)とかコードレビューの文化の浸透具合とかと相談しつつ、適宜よしなに。

あと。
「Model ≒ ORM」の場合、Modelの1インスタンスは「1レコード」、1メソッドは「1レコードに対する処理」、1 staticメソッドは「1テーブルに対する処理」的に書いておくと、割と平和でございます。
まぁそうすると「JOINするようなモンはどこに書くのん?」ってなお話になるのですが、主従がはっきりしている関係であれば、主の側に書いておくと割と平和かなぁ、と。

んで。
「Model ≒ ORM がtrue」の時に「ビジネスロジックをModelに実装する」のは、思いっきりお勧めしません。
端的に、例えば「2つとか3つのテーブルを横断的に使うビジネスロジック」があったとして、それ、どのクラスに実装します? ってなお話になるので。
勿論「無理くり実装」は出来ますが、お勧めは、全くできないかなぁ、と思われます。

次。
「Model ≠ ORM」ってフレームワークは、あんまりないと思うのですが*2
その場合は「ビジネスロジックをModelに書く」のがコレクトかと思われまして、どちらかというと「んじゃ、データを扱うORM的な立ち位置をどうするの?」ってなお話になって、それを「Modelとは別のクラスに書いた方がいいんじゃね?」とかいうお話になります*3

あと。ORM自体については https://gallu.hatenadiary.jp/entry/2019/05/08/001034 で書いたので省略(っつかこのために書いたんだしw)。

最後に。
時々「ModelがただのSQL置き場になっている」ような実装を見かけまして、個人的には「一番お好まない」かなぁ、と。
本質的には「Modelの1インスタンスは"何を"表してますか?」ってな質問に、20文字以内で帰ってこないんなら「そのクラス設計、間違えてない?」ってとりあえず質問をしたくなる。
あと、基本的には
・ModelでSQL発行している(Model ≒ ORM)んなら、Modelの1インスタンスは「1レコード」であって欲しい
・基本的なSQLくらいは「基底クラスでメソッドが用意されていて、簡単に1行で記述できる」くらいの実装は欲しい
・「「Model ≠ ORM」なら、そもそも「ModelでSQL発行すんな」って思う
ってのがあるかなぁ、と。

おまけ。
・1つのModelクラスで、全然関係ないいろいろなテーブルへのSQLを渾然一体に発行している
のを見た事が数度ありまして、アレについては、殺意しか覚えませんでしたねぇ(苦笑
なので、番外。

ってなわけで。
いやまぁ「どんな実装しようが個人の自由だよねぇ」は勿論あるのですが。
とはいえ現実的に「メンテが厄介な実装」ってのは「後で、他人様の足を引っ張る」ので、おいちゃんとしては大変に「お好まない」かなぁ、と。

その辺を考えた時に、例えばModelであれば「Modelとはなんなのか? なにを書いて、なにを"書かない*4"クラスなのか?」ってのくらいは、現場毎に違って良いので、せめて「クリアな回答が欲しい」なぁ、とか思うですだす。

んでまぁその一方で「このフレームワークだから、ベースはこんな感じだよねぇ」ってのはあると思うので。
だとするとせめて「ビジネスロジックとORMが渾然一体と混ざり合った「もったりとしてコクがなく*5」な状態のクラスにならなきゃいいなぁ、とか、思ってみたりするです。

*1:「テレビシリーズでの英国版では原作と同様、基本的に「Fat Controller」と呼ばれる」……説明が必要なネタをやるな

*2:MagicWeaponが ≠ でございますちなみに

*3:MagicWeaponだと、data_clumpというクラスが「別のクラス」に相当します

*4:ここ大事

*5: (C)スレイヤーズ