「Application Architecture for .NET」を読んだ - 3部(前編)
.NETのエンタープライズアプリケーションアーキテクチャ 第2版 (マイクロソフト公式解説書)
- 作者: Dino Esposito,Andrea Saltarello,日本マイクロソフト(監訳),クイープ
- 出版社/メーカー: 日経BP社
- 発売日: 2015/06/04
- メディア: 単行本
- この商品を含むブログ (2件) を見る
「Application Architecture for .NET」を読んだ - 1部
「Application Architecture for .NET」を読んだ - 2部
の続き
第三部サポートアーキテクチャ(8, 9章)のメモ。
TL;DL
- ドメインモデル
- エンティティはビジネス空間に関連するオブジェクトであり同一性とライフタイムを持つ
- 値オブジェクトは空間内の無生物とも言える存在
- 一部のエンティティはコーディグや設計上の目的で集約に纏められる
- モデリングの際の一番の関心毎ではないものの、DB構造が制約である
3. サポートアーキテクチャ
8. ドメインモデルの紹介
データから振る舞いへの移行
- DDDはレコードの代わりにオブジェクトを使ってデータアクセスコードを記述するだけのアプローチではない
- ドメインモデルはビジネスのAPI
- クラスを基本的なビジネスコンセプトと一致させ、常に整合性を保つ事 => データより振る舞いに重点を置く
- DDDはドメインモデルの作成を優先し、モデリングされたドメインの永続化は後回しにする
- ドメインモデルは永続化に関与しない
ドメイン層の内側
- アプリケーション層はドメインとインフラ層を操作するためのオーケストレーションコード
- ドメインモデル: エンティティ/値オブジェクトから構成される
- モジュール: ドメインモデルを纏める名前空間
- リポジトリ: エンティティの永続化
- 契約(コンストラクト)はドメイン層、実装はインフラ層
集約
- モデル内のエンティティを纏めたり区切ったりする整合性の境界
ドメインモデルでは、複数のモデルを1つのコンテナに纏めたものを集約と呼ぶ
「集約とは、データを変更する目的で1つの単位として扱われる、関連するオブジェクトの集まりです」
- エンティティが参照できるのは、同じ集約内のエンティティか、別の集約のルートだけ
- 集約のルートの責務
- カプセル化されている全てのオブジェクトの永続化に対する責任
- クエリ操作で取得できるのは集約のルートだけ、内部オブジェクトへのアクセスは集約のルートのインターフェースを通じて発生しなければならない
// 集約ルートを示すmarker // 集約ルートだけがリポジトリを持つ、リポジトリの型制約として使う public interface IAggregateRoot { bool CanBeSaved { get; } } public class Order: IAggregateRoot { bool IAggregateRoot.CanBeSaved { get { return validate(); } } // ... }
ドメインサービス
- ドメインロジック(特定の集約に属さない、ほとんどの場合複数のエンティティにまたがっている)を実装するメソッドを持つクラス
- リポジトリ
- 永続化の為に存在する
- CustomerRepositoryのように集約ルート毎にリポジトリを1つ使用することになる
public interface IRepository<T> where T: IAggregateRoot { // interfaceを単なるmarker interfaceにしても良いし、一般的なメソッドを幾つか定義することも出来る T Find(object id); void Save(T item); }
public interface IDomainEvent {} public class CustomerReachedGoldMemberStatus: IDomainEvent { public Customer customer { get; set; } }
- 横断的関心事
9. ドメインモデルの実装
実用的なドメインモデルを作成するための護身術
- ドメインモデル貧血症
- エンティティが貧血と判断されるのは、エンティティに属しているものの¥、エンティティクラスの外側に配置されているロジックがある場合
- ex. メソッドがエンティティのメンバーのみを扱う場合は、そのエンティティに属している
DateTime EstimatedPayment(Invoice invoice)
- ex. メソッドがエンティティのメンバーのみを扱う場合は、そのエンティティに属している
- エンティティが貧血と判断されるのは、エンティティに属しているものの¥、エンティティクラスの外側に配置されているロジックがある場合
- エンティティのscaffolding
- 値オブジェクトのscaffolding
- 集約の特定
- 特別なケース
- モデルの永続化
「Application Architecture for .NET」を読んだ - 2部
.NETのエンタープライズアプリケーションアーキテクチャ 第2版 (マイクロソフト公式解説書)
- 作者: Dino Esposito,Andrea Saltarello,日本マイクロソフト(監訳),クイープ
- 出版社/メーカー: 日経BP社
- 発売日: 2015/06/04
- メディア: 単行本
- この商品を含むブログ (2件) を見る
「Application Architecture for .NET」を読んだ - 1部の続き
第二部アーキテクチャの考察のメモ。
TL;DL
- Domainを理解することは適切なアーキテクチャの発見に繋がる
- スムーズで流れるようなプロセスを中心に、ユーザタスクを構造化するのが重要
- ビジネス層をドメイン空間の現実のプロセスと忠実に一致させるのが重要
- 正しい事を行う事と、物事を正しく行う事
- 一方がもう一方から生じるのではなく、どちらも成し遂げる事が重要
- 正しい事を行う事と、物事を正しく行う事
5. ドメインアーキテクチャの発見
- ソフトウェアには現実の世界を正確に映し出すのが期待される
- ソフトウェアが現実世界のどの部分(Domain)をモデリングしているのか理解する
DDDの本当の付加価値
- DDDの目的は「ソフトウェアの核心にある複雑さに立ち向かう」
- 付加価値は、ビジネスcontextの境界を定義するために分析部分を使用することにある
- 境界付けられたcontext
- Domainの様々な領域の内、独自のユビキタス言語を持つため別個に扱った方が効果的な領域
ユビキタス言語
- 言葉の壁は業務の妨げにならないかもしれないが、進行を遅らせる
- 専門用語をcontextに合わせて調整する
- ユビキタス言語の目的は全ての関係者が全てのレベルで使用する共通用語を定義すること
- ビジネスcontextから開発contextに翻訳する必要が無くなり、明確さが促進され仮定しなければならないことが最小限に抑えられる
- ユビキタス言語はプロジェクトの公式言語
境界付けられたcontext
- 独自のユビキタス言語とアーキテクチャを必要とするアプリケーション領域
- 関係パターン
- 上流context(u): 下流に影響を与える、下流を強制的に変更する場合もある
- 下流context(d): 受動的、上流contextによって変更される
階層化アーキテクチャ
- Presentation層
- タスクを実行するユーザーインターフェースを提供(画面の集まり)
- Presentation層に追加される
ViewModel
== 画面から送信されバックエンドアクションを開始するApplication層の入力Model
- Application層
- Domain層
- Infrastructure層
- 永続化レイヤー、データアクセス層、具体的なテクノロジの使用に関するあらゆるもの
6. プレゼンテーション層
- 最初にプレゼンテーションに取り組めば、処理すべき注文やそれらの処理方法を素早く効果的に理解するのに役立つ
ユーザーエクスペリエンスファースト
- データではなくやり取りに焦点を当てるべき(UIとUXの違い)
- タスクベースの設計 => CQRS
- UIをUXに置き換える
- UXはUI以上のもの
- ユーザが操作しているのを見るまで、提案したUXの良し悪しを正確に判断することは出来ない
シナリオ
- controllerはApplication層やBusiness層の一部と見なすのではなく、出来るだけ薄く保つようすべき
- ApplicationService: ワーカーサービス(controllerとマッチする)
- Webサービスのデバイスサポート
- 機能検出による分岐(localStorageを対応していたらHTML5扱いみたいな)
- クライアント側でのデバイス検出によるレスポンシブの実現
- SPA
- ユーザアクションに続くタスクのオーケストレーションをクライアント側で行う
7, 伝説のビジネス層
- 従来のデータ中心の3層構造から、モデル中心のマルチレイヤーアーキテクチャーへ、イベント駆動型のアーキテクチャーへ
- Transaction Script Pattern
- Domain Model Pattern
- 期待される振る舞いと、動作させるデータの流れに焦点を合わせるアーキテクチャー(クラスという概念から再現する)
- Domainについて知れば知るほどそれをソフトウェアで模倣しやすくなる
- エンティティのプロパティよりもアクションに目を光らせる => 振る舞いを突き止めるのに役立つ(Tell Don't Ask)
- ADM(Anemic Domain Model)(アンチ) Pattern
- エンティティに含まれているのはプロパティだけで振る舞いがない
データからタスクへの焦点の移動
- Domain内でのタスクオーケストレーション
- ドメインモデルに存在しないデータの集まりをユーザインターフェースに持ち込みたいかもしれない etc => DTOを使う
- DTOは振る舞いを持たない単純なコンテナ
- エンティティからDTOを作成する
- AutoMapper, Adapter
- DTOは振る舞いを持たない単純なコンテナ
Mapper.CreateMap<Source, DTO> var dto = Mapper.Map<DTO>(sourceObj)
「Application Architecture for .NET」を読んだ - 1部
.NETのエンタープライズアプリケーションアーキテクチャ 第2版 (マイクロソフト公式解説書)
- 作者: Dino Esposito,Andrea Saltarello,日本マイクロソフト(監訳),クイープ
- 出版社/メーカー: 日経BP社
- 発売日: 2015/06/04
- メディア: 単行本
- この商品を含むブログ (2件) を見る
古めですが、ここに参考文献が上がっています
matarillo.com: .NETのアプリケーションアーキテクチャ
第一部基礎編のメモ。
TL;DL
アーキテクチャとはシステム開発の利害関係者(ステークホルダー)全体にまたがる共通理解を指す
- システム開発の利害関係者は、それぞれが異なった要望や関心事を持っている
1. 現代のアーキテクトとアーキテクチャ
- アーキテクトは役割
- ≒ Lead Developer
Architect extends Developer
- アーキテクチャは顧客のためのシステムを構築するもの
- 明確な答えはないが、見つけ出すことは仕事
- 良いアーキテクチャ: 変更が困難な決断が全て適正なものであることがわかる
- 重要な決断を下さなければならないことがアーキテクチャ
- プロジェクトの出来るだけ早い段階で正しく下さなけばならないもの(先送りにしたいもの)
2. 成功のための設計
- ソフトウェアプロジェクトの最大の敵はBBM
- 成功するソフトウェアプロジェクト
- ビジネスニーズを理解し、そこから上手くいくソリューションを引き出すプロジェクト
- 上手く設計されたソフトウェア
- 成功するプロジェクトを背景とし、既存のコードとインフラストラクチャを再利用した上で設計され、利用可能なテクノジと既知のベストプラクティスを踏まえて改良されたソフトウェア
- ボスは追従者を生み、リーダーは他のリーダーを生む
- マネージメントチームがリーダーシップを理解していてる + 開発チームがコードの品質について理解している == プロジェクトを成功に導く
- リファクタリングはプロジェクトに価値を生み出さないけど、行わないと価値が失われる
- Legacy Code: 側に置いてはいるが、側に置きたくないコード
- testが書かれていない == Legacy Code
- 幅広く利用されているため、置き換えるのが難しい
- これ以上、Legacy Codeを増やさないようにするのが問題
- 切り離されたブロック(black box) == 境界付けられたcontext
3. ソフトウェアの設計原則
- ソフトウェアアーキテクチャでは、柱の周りに振る舞いを実装することが鍵
基本的な設計原則
- 凝集性: 密接に絡み合った責務 - 高いのが理想
- 単一責任の原則
- 結合性
- AクラスBクラスの結合の度合い - 低いのが理想
- 内蔵型のobject(高凝集)が安定したinterfaceを通じて他のobjectとやり取りする(疎結合)ことを意味する
- 関心の分離 - AOP
オブジェクト指向設計(OOD)
- 関連のあるobjectを見つけ出し、相互にやり取りするobjectの結合性を最小限に抑え、コードを再利用する
- 合成と継承
- 派生classは親classのコードを継承するだけではなく、contextを警鐘し、そこから親classに対する可視性を手に入れる
- 合成は防御的
- 関心の分離
- 変化する可能性が高い部分を切り出す
- classが必要でないことがある。関数だけで良いなら、それを使用するだけにする
- 現実の世界がモデルではなく、イベントを表す、イベントがデータを運ぶもの
開発ベクトルと設計ベクトル
- SOLID原則
- 単一責務の原則(SRP)
- 責務とは変更の理由のこと
- 限界まで追及するとプロパティだけの貧血classになる危険がある
- 開放/閉鎖の原則(OCP)
- リスコフの置換原則(LSP)
- classを作成するとしたら合成の方が安全
- サブclassをその基底classと置き換えることが出来ないといけない
- 派生classはその基底classよりも多くのことを要求すべきではなく、それ以下のものを提供すべき
- class継承のcontextで「特殊な」という表現がされたら注意する
- インターフェース分離の原則(ISP)
- クライアントが使用しないinterfaceにクライアントを強制的に依存させてはならない
- 依存関係逆転の原則(DIP)
- 上位moduleを下位moduleに依存させるのではなく、両方のmoduleを抽象化に依存させるべき
- Service Locator
- Dependency Injection(constructor / setter / interface)
- 上位moduleを下位moduleに依存させるのではなく、両方のmoduleを抽象化に依存させるべき
- 単一責務の原則(SRP)
- coding vector
- プログラミング原則一覧 - Strategic Choice
- KISS(keep it simple, stupid)
- 完璧とは、付け加えるべきものがなくなった時ではなく、取り去るべきものがなくなった時のこと
- YAGNI(you ain't gonna need it)
- Tell, Don't Ask
4. 高品質なソフトウェアの作成
- テストされていないものは壊れていると思え
- どのようなシステム、どのようなcontextにおいても単純さは常に長所
- 依存関係を排除するテスト
- テストダブル(fakeとmock)
- fake object: objectの比較的単純なcopy(元のobjectと同じinterfaceを提供する。状態は無くハードコーディングされているケースが多い)
- やり取りに関心は無い
- mock object: fake object + 独自の特性を持つobject
- fake object: objectの比較的単純なcopy(元のobjectと同じinterfaceを提供する。状態は無くハードコーディングされているケースが多い)
- テストダブル(fakeとmock)
- TDDのテストの最終目的はカバレッジを広げることでは無く、「設計を改善する事」
- テストは目的では無く、良い設計を実現するための手段
- applicationのロジックを左右する重要な決断が下される場所(ビジネス層/ドメイン層)で、テストを重点的に行なうべき
- codeの拡張性
- 早まった拡張はソフトウェアの諸悪の根源になりかねない(過剰性能)
- 読み易さは主観的な問題
- coding以外の事をする十分な時間がない事を承知しているなら、最初から読み易いコードを書くように
- code comment: codeにおいて下される自明ではない判断について説明する文(特定の部分関する洞察に満ちた見解)
- code品質
- テスト容易性/拡張性/可読性
「Kent Beckの実装パターン」を読んだ
- 作者: ケント・ベック,Kent Beck,永田渉,長瀬嘉秀,株式会社テクノロジックアート
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2008/12/22
- メディア: 単行本(ソフトカバー)
- 購入: 30人 クリック: 502回
- この商品を含むブログ (91件) を見る
メモです。リーダブルコードをより具象化、パターン化した本という印象。
TL;DL
- 「他人が読んでわかるコード」が「よいコード」
- 読み手を意識しながらコーディングすることの重要性。いかに意図を正しく伝えるか
Implementation
実装パターン
- 「相手にこのコードで何を伝えたいか」を自問する思考方法
- 誇りの持てないものに対して無駄にする時間はない、よいコードを書くこと自体が喜びであり、そのコードを他の人が理解し、評価し、使用し、拡張してくれれば、さらに喜びは増す
「責任」についての本
- 自分とその相棒であるマシンのためだけではなく、他の人のためにコードを作成する
コードを通して考えを伝える
- 自分で何を考えているを意識出来るくらいに思考速度を落とす == 直感でコードを書く振りを止める
- 他人の重要性を認識する
卓越したプログラムに必要とされる要素 - 動機
- コミュニケーション
- 他の人はこれを見てどう感じるだろう
- シンプル
- 余分な複雑性を取り除き、本質を目立たせる
- 柔軟性
- 複雑を引き起こさない、シンプルから生まれる柔軟性
原則 - 行動
- 結果の局所化
- 変数のコストを低く
- 繰り返しの最小化
- 小さな部品を作る
- ロジックとデータの一体化
- ロジックが操作するデータは近くに
- 対称性
- 宣言型の表現
- 型に意図を詰める
- 変更頻度
- 同じタイミングで変更されるデータは近くに
Class
- classの名前が決まれば操作の名前は後から決まってくる
- 短く力強く、意味が豊富で的確な
- Interfaceとクラス階層は相互排他ではない
- 新しいSubInterfaceを導入することでInterfaceの拡張を安全に行う
- 状態を持たないVOで暗黙的なシーケンスを無視する
- static関数を格納したライブラリクラスはいつでもオブジェクトクラスに変換できるように
- classは関連する状態を一つに纏めるもの
State
- オブジェクトは、外部の世界に示される振る舞いと、その振る舞いを支えるために使用される状態のパッケージ
- 似たような状態(近くにあるか、同じ計算で使われている、発生・消滅のタイミングが同時か)は1つに纏め、異なる状態は離しておく
- flagに基づいて決定を行うコードが重複しているならstrategyパターンを検討する
- static fieldと引数の両方を使用できるなら引数でクラス間の結合を行う
- 変数の生存期間、スコープ、型は、コンテキストで伝えることが出来る
- 変数やメソッドを出来るだけ汎用的な型で宣言する
- 後から具象クラスを自由に変更できる
Behavior
- 実装を選択するためのメッセージを広範囲に使用すると、明示的な条件分岐のないコードになる(実行時の型に基づいて)
- 自分の意図をより明確に伝えるために説明メッセージを用いる
Method
- 出来るだけ汎用的な型で戻り値を宣言する
- 複雑なオブジェクト生成をコンストラクタではなく、ファクトリー(static method)に任す
- メソッド名では意図を伝達し、実装戦略が重要でないなら含めないべき(呼び出し側がどう見えるかによって命名する)
- 公開するものを少なくすることにより得られる柔軟性を重視する
- privateなヘルパーメソッドでサブルールンを隠蔽する + 共通部分を除去する
- 変換処理は変換後のオブジェクトに変換用のコンストラクタを定義する
Collection
- Collectionを継承するより委譲を活用するのが良い
- 意味のある操作だけ公開し、わかりやすい名前を付ける事が出来る
- 継承だと、不適切な(意図しない)メソッドまで保持することになる(ex. clear)
class Library { Collection<Book> books = new ArrayList<>(); // ... }
Extended to Framework
- clientのコードを壊すことなくFWの改善が行えるようにするためには複雑性が増すことの方がコスト的に有利な事がある
- clietnにはシンプルなインターフェースを提供する
- 目標のFWは、進化可能なくらい複雑だが、使用するのには十分シンプルであり。進化可能なくらいに応用範囲は狭いが、使用するのに十分適応範囲が広い
- 公開される詳細の数を減らし、変更される確率の低い詳細を公開する
see also
関数型プログラミングから得られる改善
関数型で書いた際に、どういった事が可能になるか。
- コード量が少なくなる
- 最適化がしやすい
- 並行/並列化がしやすい -ドキュメントが少なくなる
- 状態を持たないので、関数を組み合わせて利用しても相互に影響しない
- 定理と証明
see also
「許可を求めるな、謝罪せよ」の言葉を通して
「許可を求めるな、謝罪せよ」
こういった企業文化いいなと思ったので、幾つか抜粋メモ。
事前に許可がおりることを持っているより 思い立ったらとにかくやってみるといい、 うまくいかなくても後から謝り、改良すればよい というハッカーマインドを鼓舞する言葉
まずはやってみる
- まずは作る、思い立ったらスピードを最優先する方が結果最終的によい方向に進みやすい
- 半ば強引なまでの積極性がないと
- チャレンジグになりたい
- 従え、心の声に
最小の許可で、行動をしたい。
see also
「ピクサー流 創造するちから」を読んだ
ピクサー流 創造するちから―小さな可能性から、大きな価値を生み出す方法
- 作者: エド・キャットムル著,エイミー・ワラス著,石原薫訳
- 出版社/メーカー: ダイヤモンド社
- 発売日: 2014/10/03
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (9件) を見る
想像力と創造性を生みだす手助けとなるエッセンス、メッセージが沢山含まれている本であり、 エド・キャットムル氏が語るマネジメント論、ピクサーの想像力と創造性の秘密だけではなく、 各ヒット作の裏側。スティーブジョブズの人間性など、様々な側面が語られた本だと思う。
以下、メッセージをセクション毎に抜き出した。*1
デミングと日本企業に学んだこと
問題を見つけて直すのは、製造ラインの最上位の管理者から最も末端の人まで、すべての社員の責任である。 責任を持つことに許可はいらない。
いいアイデアといいスタッフ、どちらが大切か
正直さと素直さ
正直になることが義務のように感じられる人は、素直さを求められると多少気が楽になる。
できるだけ早く失敗しよう
失敗する可能性のあることに取り組むのが、本当に創造的な企業だ。
信頼とは、相手が失敗しないことを信じるのではなく、相手が失敗しても信じることである。
組織には野獣も必要
目標は緩く、意思は固くもつほうがいい。
創業者にしがみつかない
変化を止めて自分を守ろうとするか、変化を受け入れてそれを武器に返るのかどちらかだ。
ピクサーが集合的な思考の意識転換を図るために使用している8つのメカニズム
- 全員で問題解決(デイリーズ)
- 現地調査でつかむ本物感
テクニックは既知のもので、それを予期せぬ方法で使うのがアートだ。
- 制約の力
- テクノロジーとアートの融合
芸術は技術を挑発し、技術は芸術に刺激を与える。
- 短編で実験する
- 観察力を養う
- 反省会
- 学び続ける(ピクサー・ユニバーシティ)
生まれ変わったクリエイティブ集団
誰にとっても現金のボーナスは嬉しいが、それと同じくらい価値のあるものがある。
それは、尊敬する相手から面と向かって「ありがとう」と言われることだ。
まとめ
素直さや自由、建設な批判がピクサーの大切にしてある文化であり、
創造的になるための条件だと感じた。
パンチのある名言が満載でポジティブな気持ちになれる、また期間を開けて読み返そう。
see alsp
- ピクサーの魔法は「新しいアイデアが守られる文化」にあり | ライフハッカー[日本版]
- 第16回 『ピクサー流創造するちから 小さな可能性から、大きな価値を生み出す方法』 〜映画という特殊な商品をビジネスとして成功させ、スタジオに活気をもたらすには、どうしたら良いか? - 映画ジャーナリスト ニュー斉藤シネマ1,2|BOOKSTAND映画部!
*1:巻末付録に企業運営の指針が載っているのはとても親切