2024.10.01
自社の社内情報を未来の“ゴミ”にしないための備え 「情報量が多すぎる」時代がもたらす課題とは?
リンクをコピー
記事をブックマーク
詳しくいきましょうか。実装例がどういうものか?
右下の図がすごく大事という話をしましたよね。これをもっと細かくしましょう。そういう図が実はクリーンアーキテクチャの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.10.29
5〜10万円の低単価案件の受注をやめたら労働生産性が劇的に向上 相見積もり案件には提案書を出さないことで見えた“意外な効果”
2024.10.24
パワポ資料の「手戻り」が多すぎる問題の解消法 資料作成のプロが語る、修正の無限ループから抜け出す4つのコツ
2024.10.28
スキル重視の採用を続けた結果、早期離職が増え社員が1人に… 下半期の退職者ゼロを達成した「関係の質」向上の取り組み
2024.10.22
気づかぬうちに評価を下げる「ダメな口癖」3選 デキる人はやっている、上司の指摘に対する上手な返し方
2024.10.24
リスクを取らない人が多い日本は、むしろ稼ぐチャンス? 日本のGDP4位転落の今、個人に必要なマインドとは
2024.10.23
「初任給40万円時代」が、比較的早いうちにやってくる? これから淘汰される会社・生き残る会社の分かれ目
2024.10.23
「どうしてもあなたから買いたい」と言われる営業になるには 『無敗営業』著者が教える、納得感を高める商談の進め方
2024.10.28
“力を抜くこと”がリーダーにとって重要な理由 「人間の達人」タモリさんから学んだ自然体の大切さ
2024.10.29
「テスラの何がすごいのか」がわからない学生たち 起業率2年連続日本一の大学で「Appleのフレームワーク」を教えるわけ
2024.10.30
職場にいる「困った部下」への対処法 上司・部下間で生まれる“常識のズレ”を解消するには