9月20日にアイスタイルさんで開催された、「アーキテクチャ ディスカッション Vol.1」というイベントに参加してきたので、その場でディスカッションされた内容の速記メモを残します。
一旦、タイポ・不十分な文章を承知の上で公開して、参加された方にとっては振り返り・参加できなかった方にとっては雰囲気が伝わればというものになっています。編集リクエストを送りやすいであろうQiitaで公開しているので、編集リクエストお待ちしています☆
今回の狙い
- 成功事例・赤裸々な失敗事案を共有したい
- Clean Architecture 達人に学ぶソフトウェアの構造と設計の内容をベースにクリーンアーキテクチャについて主に議論する
- 以下のようなテーマを考えている
- 導入済みかどうか
- xxに気をつけろ
- 「クラスのファイル増える」という指摘をする人に気をつけろなど、どう教育していくか
- DDD実践済みかどうか
- MVCからのマインド移行
- ディスカッション枠で参加されている方からは次のような疑問について話したいという冒頭の話もありました。
- repositoryクラスはどこにおくの?
- clean architectureのゴールは?
- 失敗談が聞きたい
ビジネスロジック層のモデリング
- テーブル = モデルから外れるモデリングが難しい。どう分析して作って・分離していくのか
- データベースを忘れるにはどうすればいいか
- 集約で考えるアプローチ
- トランザクション
- 整合性のあるモデリングに対して境界を引く
- どこまで整合性を保つのかを考えるのがモデリング
- データベースを考えないアプローチ
- ソフトウェアの内部構造
- 変更する責務が蜜に固まっている固まりを捉えていく
- ライフサイクルが同じであればまとめて管理するなど
- テーブル
- ローレベルの入出力はテーブル単位で考えることになるかもしれないが、ロジックはテーブルレベルに引きずられないほうが良い
- 業務フローから考えるアプローチ
- 業務フロー・usecaseを考える
- 業務をどうプログラムとしてシステムに反映できるか
- 業務で使用する名前を付箋などで分類していく、まとまりを作っていく
- 最終的にそれがエンティティになる
- サービス仕様・データを分析するというアプローチ
- データはDBのデータではなくサービス仕様で出てくる言葉
- ドメインモデリングという言葉を明示的に使うことでデータベースに引きずられない
- データモデリングもあるので、「モデリング」の各自の焦点が異なる
- 焦点を合わせることは成功した
- 単語に着目して付箋を貼っていてそれに振る舞いを与えていく
- いきなり全体を対象に実装・分析を書けるのは難しい
- 業務のいちばん重要なポイントを聞いてその人が何をしているのかを聞いていく
- メインのドメインはなんだ・何のドメインの話なのかという問いをするのが有用だった。
- 経済活動:ドメイン
- 図書館アプリを練習でやった。
- だれがほしいか => 会社
- 会社が何をほしいのか => 資産管理
- 在庫管理・資産管理をドメインと置く
- といったドメインの作り方をした
クリーンアーキテクチャを採用した話
- https://camo.qiitausercontent.com/aa4e4f88dd885f486d7ab736311f886a7538a1df/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f36303435372f38666534633336362d343636652d653434632d613761362d6633613734336636393138332e706e67
- 1年続けてこの形になった
- presentersを使わないものがネットには多い
- entitiesがORMになっている人もいる
- 図ではflow of controlが重要、UML
- MVC
- MVCはpresenter層
- Entitiesはトランザクションスクリプトでもドメイン駆動設計でもよい
- ヘキサゴナルアーキテクチャからの流れがクリーンアーキテクチャ
- オニオンアーキテクチャはドメイン駆動設計のクラス構造を表したものと解釈
- usecasesはドメイン駆動設計のアプリケーションサービスに該当する
- usecaseのinterface・diなどクラスが増えていくので、教育できないと判断し、ツールを作った
- presentersは使わなかった、非同期的なもので必要という感触。同期的なwebのようなアプリケーションではcontrollerが返してくれたほうがうれしい
- MVCフレームワークに乗るときはpresenterはいらなかった
- websocketであればpresenterを使う価値があると思った
- クリーンアーキテクチャ23章で説明されている内容では、presenterはハンブルオブジェクトパターン
- テストしやすいものとテストしにくいものを分けるという思想
- viewModelを作る人・レスポンスを作る人を分けたい
- 日付オブジェクトではこのようなものが用意されている
- 日付オブジェクトを文字列に変換 -> presenter
- 文字列を組み立てる -> view
- 変換部分はcontroller、DTOにしているからテストが書けるという自分自身への言い訳をしている
- サンプルコード
教育
- 手順を作ってこうやってとやると考えずにやってしまうのが怖いと思った
- クリーンアーキテクチャの話はチームに三回話している
- ツールを使った方が楽
- クリーンアーキテクチャはファイルが単純に増えるというつらい
- 保守フェーズがやったことがないエンジニアには伝わりにくい
- モノリシックなプロジェクトを担当させるのがいいかもしれない
- こいつのいうことは逆らえないという布石はうっておいた
- 設計は民主主義にした瞬間失敗する
- 進化的アーキテクチャ
- Java界隈にはパッケージの依存関係を矯正するものがあるよう
- クリーンアーキテクチャを守らせるためのCI環境
- check styleというものがある
- domain層からdatasource層にimportするとひっかかるというCIを作っている
- Javaのgradleも使っている
- check styleというものがある
- codeレビュー時にimport文を見たりしている、ぱっと見で依存関係がおかしいものはある
repository
- repositoryに何を引数に渡すか
- INSERTしかしないことにしてる
- entityを渡す設計をしたことがあった
- イベント = INSERT
- repositoryの中で変わった部分だけinsertするという手法は辛くてやめた
- entityを引数に渡してINSERT/UPDATEしている
- entity・テーブルには差がある
- リストを持っていたりする
- entity・テーブルには差がある
- 「入れたけどなかったことにしてくれ」という要件
- 削除したというイベントを残すようにしている
- イベントが絡む場合
- entity
- repository
- entityフレームワークなどで差分を見て更新してくれるなど
- repository
- entity自体をどう保存するかはおまかせしてる
repository 参照系・更新系でわけているか?CQRS
- 更新・参照を同じレポジトリで表現するか
- やっている例
- interactorそれ自体がqueryを発行する
- 構造化したusecase
- repositoryは経由
- イベントソーシング:Kafka
- IN/OUTも同じレイヤードアーキテクチャ
- 両方同じように扱いたいのでレイヤーを挟む
- システムにデータを入れた日付はドメインなのか
- ドメインに入れたくない
- 参照用のレイヤーを作ったりしている
- ドメインを守りたいニーズ
- データをただ連携してほしいという状況がある
cache
- cacheはどの層にいれるか
- databaseから近いところ、dbからexternal interface、cacheを持っているかどうかを意識したくないため
- ビジネスロジックとしてまとまった形でcacheしたいという状況はどうするか、ドメインをまたぎたい場合もある
- ドメイン = ドメインモデル、比較的大きめなEntityを表現したいケース
DDD
- 人と話さないと本当に必要なものは作れない気がしている
- 「ユース駆動設計」を読むとより理解しやすい
- クリーンアーキテクチャは人と話すのが苦手という人には難しいきがする
- ユースケースを分析せずコード書くのはどうなんだっていう
- ドメイン分析できて技術的な部分までやれるの超人すぎるのでは
- 自社サービスの場合は自分自身がドメインマスタなのでやりやすいかも、ステークホルダーが少ない。サービス利用者が目の前にいないので自分自身がサービス利用者になりきる
- ユビキタス言語を徹底していくとコードが日本語になっていく
- 日本語-英語の対応表
- enumを日本語で書くとわかりやすくなっていく、一部日本語で試してみるのは面白い試みかなと思う
- テストコードは日本語でどういうテストをしているのが書くのはわかりやすかった
Clean architectureをどう学んでいくか
- 実装のソースがない、大きいサービスにならないと細かい勘所がわからない。自分で練習して勘所を掴むのが難しい印象
- それ用の課題を用意して解いてもらう、ドメイン駆動設計でモデリングして実装するという教育をしている、最初1ヶ月教育をしている
- 全体をやってみないとわからないことがある、完全に理解できなくても「コピペであればできる」という状態になれる。
- 小さいサービスを使って実験する、RSSリーダーをつくるという鉄板のお題。DBにいれて外部ネットワークと接続するというお題を自分で作ってやってみる
- ただし、やっていくと思っていたのと違うということが当然出てくるのでその中で軌道修正していく
- チームの人と書くのも重要、わかりやすい・わかりにくいコードなども見えてくる
アーキテクチャの軌道修正の間際
- 軌道修正のやり方はどうするか、古いアーキテクチャを残しながらやると古い方を新しい人が使ってずれていくという反省があった
- つくりはじめて半年くらいであれば書き換えてしまうが、何年も動いているものを一人でやるのは無理。アナログに伝えていく。可能であればCIで落とす方法もあるがここには銀の弾丸は無い
- リファクタリングが必要なものはコードレビューなど検知、書き直しが必要なものがあれば事前に当事者と話しておいてあとでリファクタリングするなど
Fluxアーキテクチャ
- Fluxアーキテクチャはクリーンアーキテクチャと似ているのか
- UI表面やっている人がすくなったから盛り上がらなかった
- 古典的MVCやMVPと同様
Gameアプリケーションとクリーンアーキテクチャ
- ダメージ計算などはテストが必要だったためDDDを用いた
- Gameはインスタンスの生成などとの戦い
- スマホアプリとのサーバー通信のみクリーンアーキテクチャを適用するのは有効な気がする
- Android/Swiftの人はクリーンアーキテクチャの話をするかも、アプリを作ってみるのはいい学習方法かもしれない。
設計に対するモチベーション
- 13年続くサービスを一人で見ていて、あるべき姿を見たいという狙い、保守フェーズを経験した結果。
- 自分でクソコードを生み出して、どうやったら理想像に近づけるのかを知りたくてアーキテクチャを知りたくなった
- 勉強していったらたどり着いた。オブジェクト指向から始まって、
- 多くの人はテストしやすいクラスレベルでの興味にとどまっている印象がある
- 保守しやすいアプリケーションを作りたいというモチベーションからドメインをどうするかについて興味を持ち始めた
- 炎上案件がきっかけ、「テストコードを書きましょう」という部分からドメイン駆動設計というなんかわからんいいと言われている物があるからやってみようという感じ
- 今から見たら間違っているというか素朴なもの
- ただし、設計をよくしようという考えを持ちながらやっていくとチームのベロシティも上がって設計も良くなっていった
- 生き残るために必要だった
- ネストされた波動拳のコードもちゃんと動くからすごい!
- 本当に短命で終わるプロダクトはないという気持ちで望まないと、あとで突然組み込まれたりする
アーキテクチャを学ぶ意味
- 関心事によってアプローチが異なる、クリーンアーキテクチャは万能薬ではない
- ビジネス的な要求が変わりやすい場所にクリーンアーキテクチャはとても有効である
- 万能的なアーキテクチャはない、適切なものを選択する必要がある
- 絶対的なこれという答えがないからこそ面白い
- アーキテクチャ思想を知っているからこそ崩すことができる
DRYに関して
- 本物の重複・偶然の重複、DRY原則を守るために重複を排除するのにもいい方法と悪い方法もある
- だめな重複に対して「偶然の重複」という名前をつけてもらったのはとても使えるなぁと感じた。よく見るアンチパターンだったため。
- 初めからDRYを怖がってはいけない、やっていく中で学んでいく
- 同じようなコード重複して散見される方がまだいいというのもある、個々で書かれている事自体は間違っていないという意見、同じではないものを同じように扱われると間違っていると思う。
- 技術的な重複は一緒にしてしまう、ビジネス的なロジックは重複はまずい気がする
- 腹落ちがあった
- テストできるコード・設計(=モデリング)が良いコードは一致しない
- 設計(=モデリング)を良くする or テストしやすい を選ぶのであればあとから変更が後から容易になっているのであれば、テストしやすい選択肢を選ぶ
- 業務的な部分と技術的な部分で扱いを変える。業務的な部分は、偶然の重複の場合が多い。技術的な部分は、本物の重複の場合が多い。
コンウェイの法則
- コンウェイの法則に対する対策、組織はなかなか変えられないが、アーキテクチャはいい形に変えたい、そこのもやもやにどう向き合っているか
- マイクロサービスを推し進めている現場では、ジョブローテーションをして別サービスを開発してもらっている。色々なサービスを触ってもらう。知識の固定化を防ぐ意味合いでもやったほうがいい。
- アジャイル開発をやってみた結果の知見、全部スクラッチで実装していて横串のライブラリなどは出来ていない現状がある。個人的には横串で作っていくチームが必要だなという課題感、組織に対しても手を入れる必要性があると思う
- 進化論アーキテクチャ、ドメイン分析結果に応じて組織構造を返るというアプローチ、現実難しい気がする
- エンジニアが170人〜180人に対して逆コンウェイをやるのは理屈はわかるがビジネス成長を止めながらやることになってしまう気がする。
- コンウェイの法則は現実あてはまっていて、チームによる言語選択はわかり易い例。
- アーキテクチャ設計と組織設計はセット、組織設計から逃げる場合アーキテクチャ設計もうまくいかない