2024.10.21
お互い疑心暗鬼になりがちな、経営企画と事業部の壁 組織に「分断」が生まれる要因と打開策
リンクをコピー
記事をブックマーク
詳しくいきましょうか。実装例がどういうものか?
右下の図がすごく大事という話をしましたよね。これをもっと細かくしましょう。そういう図が実はクリーンアーキテクチャのWebと書籍にもありました。Robert C. Martin、この人はかなり有名な人で、あのSOLID原則を定義した人です。Robert C. Martinがこのクリーンアーキテクチャというのを発表して、iOSクリーンアーキ……iOSのほうでかな。発表して(※のちに勘違いだったとYouTube説明欄で訂正)、その後書籍を書きました。それが『Clean Architecture 達人に学ぶソフトウェアの構造と設計』です。
ここにある図ですね。これをよく見ると、この図、緑と赤ありますよね。それぞれがこれに対応しています。左上がControllerです。右上のあのカラフルな図は……Controller左側じゃないですか。Presenterが左下にあって、右上の図だと上にあります。
(スライドを指し)ControllerとController、PresenterとPresenter。赤い文字でInterfaceのIがここにあるよね。何が言いたいかというと、これ上下逆、逆さまになっているんですけど、もちろん用語も違うんですけど、実は同じなんです。
この図はその右上の図よりもさらにわかりやすく細かく区分けしたものです。
というわけで、クリーンアーキテクチャ、もちろんRobert C. Martinが言っているのはわかっているんですよ。クリーンアーキテクチャ自体を特定の形じゃないとは言っています。でも、彼自身こうやってサンプルを出してくれているんですよ。じゃあこれに従って実装すれば見えるものがあるんじゃない?
というわけで、じゃあ実装してみましょう。みなさんのわかりやすい感じにちょっと落としますね。いろいろなビジネスロジックがありますが、片や誰か知っているけど誰も知らないみたいな話をしちゃうと難しいじゃないですか。カートの話をしてもAmazonを使ったことがない人がいるかもしれない。なので、今回はユーザー作成機能。これなら言えるかな。
これでコードを確認して処理の流れを確認しましょう。順番に、まずはコードを確認していきます。それぞれのコードがどういったものか。そして、そのあと、処理の流れを確認していきます。1回コードをザーッと洗って、もう1回コードを当て込みながら順番を見ていきます。
まずコードの確認です。具体的にどういうコードを書くか? まずはどこからスタートするか? この左上のController、こういう図ですね。
(コメントで)「この図めっちゃわかりやすい」ですね。まさにそうそう。「SOLIDの原則知りませんでした」、SOLID原則はぜひとも調べてみて。
クリーンアーキテクチャの本を読むとわかるんですけど、本は22章ぐらいまでは「もう知っているよ、こんなこと」っていう話をしています。Robert C. MartinのSOLID原則にたどり着くまでの話をしていて、23章ぐらいからクリーンアーキテクチャの話、この図になってくるんですね。SOLID原則の話を突き詰めるとこのクリーンアーキテクチャの図になるよって話しています。だからクリーンアーキテクチャを理解するのにSOLID原則があれば、彼がこういうふうにこんなにクラス分けしている理由がわかるはずなんです。ぜひとも調べてみてください。
じゃあいきましょう。こういうものです。なんとなくオブジェクト指向プログラミングやったことがある人だったら読めるかなと思うんですけど、public class UserController。細かいところはどうでもいいんです。何をやっているかというと、アプリケーションが要求するデータに入力を変換する。入力を変換、Controllerなんですよ。
僕はいつもいろいろなところで言っていて、僕の「なるセミ」にある自分で作った動画にも書いてあるんですけど、Controllerの役目って僕の認識では司令官とかじゃないんですよ。
ゲームのコントローラは何をやっているかというと、ボタンを押したら、そのボタンを押した事実をそのまま送るんじゃなくて、ゲーム機にわかる信号に変換して送ります。Bボタンを押した事実は送れないですよね。Bボタンを押したことを電気信号に変えてコンピュータに送っているんです。コントローラがやっていることって入力の変換なんですね。コンピュータがわかるかたち、ゲーム機がわかるかたちに。
なので、このController、UserControllerがやっていることは、よくよく見るとこのcreateUser、入力ね、nameとroleId、String型をアプリケーション、addUseCaseっていうこのアプリケーション、ゲーム機が欲しがっているデータ、inputDataというのに変換しているんです。変換してそれを渡している。だからこれがController。
これSpring Bootじゃなくて、僕のサンプルコードは一応Play Frameworkです。Spring BootはちょっとMVCに慣れている人からすると、ちょっと取っつきづらかったので、Play Frameworkで書いています。
次、ここです。Input Data、入力データです。こういうやつね。右上に<DS>って書いてあるじゃないですか。DSって何かというと、Data Structure。つまりデータ構造体。
どういうものかというと、さっきのUserAddInputData、ユーザーの入力データ。そのままこうやってもう入力データをひとまとめにして、Input Dataとして定義しますってだけです。DTOとほぼ一緒ですよね。
次はInput Boundary。Input Portと呼ばれたものです。ポート・アダプターで言うところのポートですね。要するにポート。プラグを差すところです。
具体的にどういうものか? <I>がついているので、ただのインターフェースです。ダック・タイピングの言語だとインターフェースがないんですけど、要するにメソッドの実装がない、C++とかでいう仮想……Abstractクラスですよね。インターフェースを強制する。どういった引数、どういった入力データが必要なのかを定義する。
そして、次にいきましょう、このUse Case Interactor。これはどういったものかというと、実際のアプリケーションロジック、ビジネスロジック。アプリケーションロジックですね。
見ていくとわかるんですけど、ビジネス上のUserオブジェクトを作って、それを保存して……userRepository、リポジトリパターン。これはちょっとあとで説明します。保存する。saveだけ見て、保存します。そして、結果、OutputDataをPresenterに対してouput、出力する。
やっていることは入力したデータを使って、さっき言ったアプリケーション、すでにある世界のドメインのビジネスの世界でオブジェクトを作って、それを操作して保存する。それまでUserを作って保存できなかったから、保存するアプリケーションです。それを出力データとして作ってPresenterに引き渡します。
次いきましょう。Presenterとかの話にいきます。今のここ、右下、Data Access Interface、これどういったものかというと、<I>って書いてありますよね。インターフェース。やっぱりインターフェースです。さっきのリポジトリとかいい例ですね。もちろんほかにもあります。APIのラッパーとかあるので、こういったものをデータにアクセスするためのインターフェースを作りましょうって言っています。
アプリケーションがデータを保存したりデータを復元したりするときのインターフェースですね。これを見るとユーザーリポジトリがやっていることは、データを保存したりデータを削除したり、そしてデータ全検索、あとユーザーIDで検索したり……ということをするインターフェースです。仮想メソッドで、これが何かするわけではなく、これを実装したクラスが実際にやります。
クリーンアーキテクチャでいうイメージ、ここですね、Gateways。中心から外に対してデータベースとかにアクセスするためのインターフェース。
じゃあこの下のData Access、何かというと、ちょっとこれ見づらいんですけど、ここに白抜きの矢印が書いてあるんですよ。今のData Accessインターフェースを実装したもので、実際にOracleとかMySQLとかに接続するものです。今回でいうと、これはO/Rマッパー使っていますね。O/Rマッパーを使ってデータを保存して、データベースにデータを保存しにいっています。
いいことは、インターフェースなので、例えばさっきも言った「Oracleだったけど、保守費用高いからMySQLにしたいな」ってときに、このオブジェクトを入れ替えればいい。
今回で言うと、あれですね、O/Rマッパーを使っているからO/Rマッパーの設定でうまくいきそうですけどね。生のJavaで書いてたりするときとか、あとO/Rマッパー自体を変えたいときに、このオブジェクトは残しておいて新たなものを作って差し替えができますというやつですね。
あとは、わかりやすいのがモックですね。とりあえずテストで動かすための仕組みをやるときですね。
Entities。どういったものかというと、例えばUserオブジェクト。ビジネスの例えばユーザー、名前変更ができますよね。changeNameとかそういうメソッドがあるビジネスのロジックのあるオブジェクト。
ただ、本当だったらもっと複雑です。今回Userというすごく簡潔なものに、簡単なものにしたので、これだけロジックがぜんぜんないんですけど、ここに例えば注文するロジック、注文の実際の具体的な処理かな。そういうのが入ってきますね。
《スライド:https://speakerdeck.com/nrslib/clean-architecture-with-java?slide=154》
なかなか例が難しいですね。そういったビジネスの表現したもの、トラックとか燃費とか、そういうオブジェクトのイメージですね。
ユーザー名、これはわかりやすいですね。これを見るとユーザー名の仕様がわかりますよね。ユーザー名が3文字より小さかったり10文字よりも大きかったときに例外を吐く。本当だったらもっと違う例外だろうけど、まあ例外吐くので、これでユーザー名の仕様がわかりますよね。「ユーザー名は3文字以上10文字以下」。こういうビジネスのルールが書かれたオブジェクト。
データモデルとは違います。ここ重要ね。データを保存するモデルは別で作ったりします。
やっていることは出力……今Userを保存してできあがったものを結果として、生成したユーザーのIDを返すために出力としてオブジェクト、Inputのときと同じようにDTOを定義しています。Data Structure。データ構造体。
そしてこれをOutput Boundary。これもまたインターフェースなんです。今の出力データを渡すときのインターフェース。そうそう、今Twitterのほうで「Interfaceで責任を分けてあげることで交換が容易になる」。まさにそのとおりです。
(コメントで)「注文するのはユースケースで、カートに100個までしか入らない」。あっ、それはドメインルールですね。そうそう。カートを実際作ったりするのはアプリケーションなんですけど、そこに対して入れるときのチェックとかはドメインオブジェクト側でやる感じです。
今、Presenter、インターフェースを作って、この出力……ここに対してoutputDataを渡します。これを実装したPresenter、どういったものかというと、これを画面に表示する。画面はなんでもいいですよ。コンソールでもいいし、HTTPでもいいから、とにかく画面に出力するということをやります。
そして、それを使ってView Model。またここで<DS>なんですよ。実際に出力するんじゃなくて、ここでやるのは出力のために変換をするんですね。今のView Model、これですね、Data Structure、ここに詰め込む作業をします。その詰め込んだView Modelを……Data Structureです。本当にこれも。これを実際のViewに引き渡すということをやっていきます。ここでやっとViewで表示される。
(Twitterで)「“データモデルとドメインモデルは違う”(復唱)」。いいですね、それ大事ですよ。(コメントで)「Output BoundaryとPresenterは試しに作ったけど、なんかうまく扱えなかったな」。その話はこのあとするので、楽しみにしてください。
関連タグ:
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.21
40代〜50代の管理職が「部下を承認する」のに苦戦するわけ 職場での「傷つき」をこじらせた世代に必要なこと
2024.11.20
成果が目立つ「攻めのタイプ」ばかり採用しがちな職場 「優秀な人材」を求める人がスルーしているもの
2024.11.20
「元エースの管理職」が若手営業を育てる時に陥りがちな罠 順調なチーム・苦戦するチームの違いから見る、育成のポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.19
がんばっているのに伸び悩む営業・成果を出す営業の違い 『無敗営業』著者が教える、つい陥りがちな「思い込み」の罠
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは