-
Notifications
You must be signed in to change notification settings - Fork 0
MS_DesignPatterns
- 戻る(.NET開発)
-
過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、
名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したもの。 -
後述の GoF や Code Complete などの書籍が有名。
-
.NET のクラスライブラリの中でどのように使用されているか?
などの例を挙げながら、ぼちぼち書き足していく。
移行メモ(誤字): 移行元の「例を上げらながら」を
「例を挙げながら」に修正した。
-
多数のソフトウェアパターンの中で最も広く知られている。
-
GoF とは、書籍『オブジェクト指向における再利用のためのデザインパターン』の著者である、
エーリヒ・ガンマ、リチャード・ヘルム、ラルフ・ジョンソン、ジョン・ブリシディースの
4 人を指す。 -
特定の規約に従ってカタログ化。
- 生成に関するパターン
- 構造に関するパターン
- 振る舞いに関するパターン
- マルチスレッドプログラミングに関するパターン
補足(GoF は 3 分類である): 上記の 4 分類のうち、
「マルチスレッドプログラミングに関するパターン」は GoF には含まれない。【GoF の 23 パターンの分類】★ ・生成(Creational) 5 個 ・構造(Structural) 7 個 ・振る舞い(Behavioral)11 個 → 【合計 23 個。これで全部】 【マルチスレッド系のパターンの出典】 ・GoF ではなく、 - 『Pattern-Oriented Software Architecture』(POSA) - Doug Lea『Concurrent Programming in Java』 - 結城浩『Java言語で学ぶデザインパターン入門 マルチスレッド編』★ などに由来する → 本ページの後半で挙げられている Producer-consumer / Thread pool / Readers-writer lock 等はこの系統 → 【並列に扱われていること自体は有用】だが、 出典が異なる点は押さえておくとよい
- よく使われる設計を一般化された形で(コンセプトとして)まとめたもの。
- サンプルコードは、実装例に過ぎない。
- デザインパターンは、すべての状況における最善の設計ではない。
- デザインパターンをむやみに適用するのは不適切で、コードの複雑さを無意味に高める。
- 一部のデザインパターンは、プログラミング言語の機能の欠損の印と主張されることがある。
補足(最後の批判は .NET で実証されている): 「言語機能の欠損の印」という
主張は、C# の進化がそのまま裏付けになっている。【言語機能に吸収されたパターン】★ Iterator → 【yield return / foreach】★ IEnumerator を手で書く必要がなくなった Observer → 【event / IObservable<T>】★ Command → 【デリゲート / Action / Func】 「操作をオブジェクトにする」ために クラスを作る必要がない Strategy → 【デリゲート / ラムダ式】 小さな戦略なら 1 行で渡せる Singleton → 【static / Lazy<T> / DI コンテナ】★ 自前実装は不要 Null Object → 【Nullable 参照型 / null 合体演算子】 Decorator → 【拡張メソッド】(一部の用途) Template Method → 【デリゲートの注入】 Visitor → 【パターン マッチング(switch 式)】★ C# 8/9 以降、型による分岐が簡潔に書ける Prototype → 【record の with 式】★ 【残っているもの】 ・Factory / Abstract Factory → DI コンテナが実質的に担う ・Facade / Adapter / Proxy → 【設計上の意図】であり、言語機能では消えない ★ ・Composite / Mediator / State → 構造そのものが必要な場合は今も有効 → 「パターンを知る意味」は 【実装手順】ではなく【設計の語彙】にある ★ (「ここは Adapter」と言えば意図が通じる)
- 関連する一連のインスタンスを状況に応じて、適切に生成する方法を提供する。
- 接続文字列を生成する SqlConnectionStringBuilder など。
- 複合化されたインスタンスの生成過程を隠蔽する。
- データ プロバイダのインスタンスを生成する DbProviderFactory など。
- 実際に生成されるインスタンスに依存しない、インスタンスの生成方法を提供する。
- ICloneable.Clone(), Object.MemberwiseClone() などがある。
- 同様のインスタンスを生成するために、原型のインスタンスを複製する。
- GetInstance メソッドを持つクラス、WCF の IInstanceProvider インターフェイスなどが該当。
- あるクラスについて、インスタンスが単一であることを保証する。
補足(.NET の実例に対する注記): 挙げられている実例は的確だが、
現在の推奨と食い違うものがある。【ICloneable は使ってはいけない】★ ・Microsoft 自身が【使用を推奨していない】 ・理由:Clone() が 【浅いコピーか深いコピーか規定されていない】 → 呼ぶ側が判断できない → 自前の Clone メソッドか、 【record の with 式】を使う ★ var b = a with { Name = "x" }; 【Singleton は自前実装しない】★ ・スレッド セーフな実装は意外に難しい (二重チェック ロック、メモリ バリア) ・現在は - 【DI コンテナのシングルトン登録】★ services.AddSingleton<IFoo, Foo>() - 【Lazy<T>】 - static readonly フィールド(型初期化子) で足りる ・そもそも 【グローバル状態はテストを難しくする】 → DI で注入する形にすれば テスト時に差し替えられる ★ 【DbProviderFactory は現在も現役】 → [ADO.NETデータプロバイダ](MS_ADONETDataProvider) 参照 → 「DB の種類を設定で切り替える」ための仕組み
- TableAdapter、DataAdapter などがある。
- 元々関連性のない 2 つのクラスを接続するクラスを作る。
- クラスなどの実装と、呼出し側の間の橋渡しをするクラスを用意し、実装を隠蔽する。
- 例えば、DataTable は DataColumn や DataRow などから構成される。
多数の UI Control をホストする、Form(Windows Forms や Web Forms)なども。 - 再帰的な構造を表現する。複雑なオブジェクトモデルを持つオブジェクト。
- System.IO.Stream クラス系のデコレート・パターンが有名(ファイル IO +暗号化など)。
- あるインスタンスに対し、動的に付加機能を追加する。Filter とも呼ばれる。
- 業務系では、Transaction ルートを定義する際に使用される。
- 複数のサブシステムの窓口となる共通のインタフェースを提供する。
移行メモ(誤字): 移行元の「Transaction ルートを定義する際にしようされる」を
「使用される」に修正した。
- 多数のインスタンスを共有し、インスタンスの構築のための負荷を減らす。
-
透過プロキシ
(System.Runtime.Remoting.Proxies.RealProxy)などで利用されている。 - 共通のインタフェースを持つインスタンスを内包し、利用者からのアクセスを代理する。
Wrapper とも呼ばれる。
補足(
System.IO.Streamは Decorator の教科書的な実例): 本ページで
「有名」とされているこの例は、実際に .NET を理解する近道である。【Stream の合成】★ FileStream … 実体(ファイル) └ CryptoStream … 暗号化を足す └ GZipStream … 圧縮を足す └ StreamWriter … 文字列で書けるようにする using var fs = File.Create("a.dat"); using var enc = new CryptoStream(fs, transform, Write); using var gz = new GZipStream(enc, CompressionMode.Compress); using var sw = new StreamWriter(gz); sw.Write("hello"); → 【どれも Stream 型】なので 好きな順に積み重ねられる ★ → 継承ではなく【合成】で機能を足す = Decorator の本質 【同じ発想の現代的な例】 ・ASP.NET Core の【ミドルウェア パイプライン】★ app.UseHttpsRedirection() .UseAuthentication() .UseAuthorization() → 各段が次を包む=Decorator の連鎖 ・【DelegatingHandler】(HttpClient) → リトライ・ログ・認証を層として足す → [AOP](MS_AOP) の発想とも通じる【Proxy と RealProxy の現況】★ ・RealProxy は【.NET Remoting の一部】であり、 【.NET Core 以降には存在しない】★ ・現在 AOP 的な差し込みを行うなら - 【DispatchProxy】(.NET Standard 2.0〜)★ → RealProxy の後継。動的プロキシを作れる - Castle DynamicProxy(OSS) - 【ソース ジェネレータ】(コンパイル時に織り込む) - DI コンテナのインターセプタ機能 → 詳細は [.NETにおいてAOPを実現する透過プロキシ](MS_TransparentProxyForAOP)
- イベントの送受信を行う複数のオブジェクトを鎖状につなぎ、
それらの間をイベントが渡されてゆくようにする。
- 複数の異なる操作について、それぞれに対応するオブジェクトを用意し、
オブジェクトを切り替えることで、操作の切替えを実現する。
- 構文解析のために、文法規則を反映するクラス構造を作る。
-
配列、Collection、Generic など、沢山のものがある。
- System.Collections.IList、System.Collections.Generic.IList(T) インターフェイス
- System.Collections.IEnumerator、
System.Collections.Generic.IEnumerator(T) インターフェイス - System.Collections.IEnumerable、
System.Collections.Generic.IEnumerable(T) インターフェイス - System.Collections.ICollection、
System.Collections.Generic.ICollection(T) インターフェイス
-
複数の要素を内包するオブジェクトのすべての要素に対して、
順番にアクセスする方法を提供する。反復子。
- オブジェクト間の相互作用を仲介するオブジェクトを定義し、
オブジェクト間の結合度を低くする。
- データ構造に対する一連の操作のそれぞれを記録しておき、
以前の状態の復帰または操作の再現が行えるようにする。
- Reactive Extensions(Rx) などが有名。
- インスタンスの変化を他のインスタンスから監視できるようにする。
Listener とも呼ばれる。
- オブジェクトの状態を変化させることで、処理内容を変えられるようにする。
- 後述の IoC、AOP → DI → 依存性反転原則
- データ構造に対して適用する一連のアルゴリズムをカプセル化し、
アルゴリズムの切替えを容易にする。
- 後述の IoC、AOP → DI → 依存性反転原則
- あるアルゴリズムの途中経過で必要な処理を抽象メソッドに委ね、
その実装を変えることで処理が変えられるようにする。
- データ構造を保持するクラスと、それに対して処理を行うクラスを分離する。
補足(
Iteratorは C# の中核機能になった): 本節で最も.NET と
深く結び付いているパターンなので補っておく。【yield return が生成するもの】★ IEnumerable<int> Take3() { yield return 1; yield return 2; yield return 3; } → コンパイラが 【IEnumerator<T> を実装したステートマシン】を 自動生成する ★ → 手で Iterator を書く必要がなくなった 【遅延評価という副産物】★★ ・yield は【呼ばれるまで実行されない】 ・LINQ の Where / Select も同じ → 巨大なファイルを 1 行ずつ処理できる → 【メモリに全部載せなくてよい】 ・落とし穴 - 【列挙するたびに再実行される】★ → 副作用があると 2 回起きる → 必要なら .ToList() で確定させる - デバッグ時に「なぜここで例外?」となる (実際に走るのは foreach の時点) 【非同期版】 ・【IAsyncEnumerable<T> / await foreach】(C# 8〜)★ → DB やネットワークからの ストリーミング読み取りに使う【Strategy / Template Method と DI の関係】★ 原文が両者に [IoC、AOP → DI → 依存性反転原則] を 充てているのは【的確】である。 Template Method … 継承で差し替える(静的) Strategy … 合成で差し替える(動的)★ DI … Strategy を 【外部から注入する】仕組み → 「継承より合成」(GoF の原則)が DI という形で標準化された、と読める
- 前提条件が満たされるまで待機するための機構。
- System.Threading.SpinLock 構造体、逆セマフォなど。
-
リソースに対して 1 つのスレッドが「ロック」をかけて、
その間は他のスレッドがそのリソースにアクセスしたり変更を加えたりできないようにする。 -
Windows OS のスレッド同期ツールキットを使う、
- lock ステートメント
- System.Threading.Mutex クラス
- System.Threading.Semaphore クラス
などがある。
-
参考
- マルチスレッドで高速なC#を書くためのロック戦略
https://qiita.com/tadokoro/items/28b3623a5ec58517d431
- マルチスレッドで高速なC#を書くためのロック戦略
- 排他的に実行しなければならないメソッド群を持つ
オブジェクトをスレッドセーフに利用できるようにするための機構。 - 名前の通り、System.Threading.Monitor クラスがある。
-
「生産者」 (producer) スレッド群がデータを生成して「通信路」に追加し、
「消費者」 (consumer) スレッド群がそのデータを「通信路」から取り出して
処理するという構造。 -
Producer-consumer を取り入れたクラスに、System.Threading.ThreadPool がある。
- 書き込みは排他アクセスが必要だが、読み込みは並行に行えるようにしたい場合の
ためのロック機構。 - 名前の通り、System.Threading.ReaderWriterLock がある。
-
Windows OS にノンプリエンプティブなマルチタスク、協調的マルチタスクを実現するための
ファイバー(fiber)があるが、.NET にはない(マイクロスレッドで実装することはできる)。 -
シングルスレッドで実行される処理の実行を各スレッドに許可するタイミングを明確に制御する。
-
参考
- [サンプル] イテレータとマイクロスレッド - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
https://ufcpp.net/study/csharp/sp2_microthread.html
- [サンプル] イテレータとマイクロスレッド - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
- 多数のスレッドを作成して、それらに多数のタスクを処理させる。
- 一般に、前述の Producer-consumer パターンを使って実現される。
- 名前の通り、System.Threading.ThreadPool クラスがある。
Windows の OS 機能に TLS: Thread Local Storage がある。
- この、TLS には、ThreadStatic 属性や ThreadLocal オブジェクト経由でアクセス可能。
- 静的変数・グローバル変数のように扱えるが
スレッドごとに異なる内容を格納できるメモリ領域を提供する。
補足(.NET の並行処理は「パターンを書かない」方向へ進んだ): 本節の
一覧は概念の整理として有用だが、実装手段は大きく変わった。【現在の .NET での対応物】★ Future → 【Task / Task<T>】★ (原文が空欄なのは執筆時期による) Active Object → Actor モデル(Akka.NET / Orleans) または Channel + 単一コンシューマ Producer-consumer → 【System.Threading.Channels】★★ または BlockingCollection<T> Guarded suspension→ SemaphoreSlim.WaitAsync / TaskCompletionSource Readers-writer lock → 【ReaderWriterLockSlim】★ (ReaderWriterLock は非推奨。遅い) Thread pool → Task.Run(内部でプール利用) Scheduler → TaskScheduler / SynchronizationContext Two-phase termination → 【CancellationToken】★★ (協調的キャンセルの標準形) 【いちばん重要な変化】★ 「スレッドを直接扱う」から 【「Task と async/await で書く」】へ移った → ロックを書く機会そのものが減った → 待つ間スレッドを占有しない【Channels(現在の Producer-consumer)】★ var ch = Channel.CreateBounded<Item>(100); // producer await ch.Writer.WriteAsync(item); ch.Writer.Complete(); // consumer await foreach (var i in ch.Reader.ReadAllAsync(token)) Process(i); → 【バックプレッシャ】(容量上限)を持てる → 非同期で待てる(スレッドを消費しない)★ → BlockingCollection は同期ブロックするため 現在は Channels が推奨【ロックに関する現代的な注意】★ ・【async メソッド内で lock してはいけない】 → await を挟めない(コンパイル エラー) → 【SemaphoreSlim.WaitAsync】を使う ★ ・lock の対象は private readonly object にする → this や typeof(X) をロックしない ・.NET 9 では【System.Threading.Lock】型が追加され、 lock ステートメントが最適化された ・そもそも【共有状態を作らない】のが最良 → イミュータブル、Channel での受け渡し
-
Ruby on Rails では、
- データベース定義からほぼ自動で CRUD 操作を備えたクラスを生成する。
- 一方でその性質上、複雑な設計のデータベースとは相性が悪い。
-
Active Record - Wikipedia
https://ja.wikipedia.org/wiki/Active_Record
-
後述の多層アーキテクチャのデータ・アクセスに合致。
-
Data Access Object - Wikipedia
https://ja.wikipedia.org/wiki/Data_Access_ObjectJava では、Data Access Object は数々の複雑で多様な 永続性技術
(JDBC、JDO、EJB CMP、TopLink、Hibernate、iBATIS など)
からアプリケーション本体を隔離するのに利用される。
-
DTO(POXO : Plain Ordinary XXXX Object とも)
- .NET:POCO
- Ruby:PORO
- Swift:POSO
- PHP、Python:POPO
- Java、JavaScript:POJO
-
アプリケーションソフトウェアのサブシステム間でデータを転送するのに使う。
-
もともと、EJB における後述のモックオブジェクト文化から広まったらしい。
-
また、JavaScript では、Ajax の分野で利用された JSON 文化から広まった。
-
Data Transfer Object - Wikipedia
https://ja.wikipedia.org/wiki/Data_Transfer_Object自身のデータの格納と取り出し機能
(アクセサメソッドとミューテータメソッド)しか持たない。
補足(Active Record と DAO の対立軸): この 2 つは
データ アクセス設計における根本的な選択である。【Active Record】★ ・【データとその永続化ロジックを同じクラスに置く】 user.Save(); user.Delete(); ・利点:書く量が少ない。学習が容易 ・欠点 - ドメイン モデルが【DB のテーブル構造に縛られる】 - 単体テストで DB が必要になりやすい ★ - 「複雑な DB と相性が悪い」(原文の指摘どおり) 【DAO / Repository】 ・【データと永続化を分離する】 repository.Save(user); ・利点:ドメイン モデルが DB から独立する ・欠点:クラスが増える 【.NET での現在地】★ ・【Entity Framework Core】は 両者の中間(Unit of Work + Repository に近い) → DbContext が Unit of Work → DbSet<T> が Repository → 【EF Core の上にさらに Repository を被せるか】は 長年の論争がある ★ - 被せる派:テスト容易性、DB 非依存 - 被せない派:EF Core 自体が抽象化済み、 IQueryable の表現力を殺す ・【Dapper】は DAO 寄り → SQL を書き、結果を POCO に詰める 【DTO について】★ ・現在の .NET では 【record】が DTO に最適 public record UserDto(int Id, string Name); → イミュータブル、値等価、簡潔 ・API の境界では 【エンティティをそのまま返さない】のが定石 ★ → 過剰な情報の露出を防ぐ → DB スキーマの変更が API 契約に漏れない
ASP.NET MVC などで利用されている。
- Model View Controller - Wikipedia
https://ja.wikipedia.org/wiki/Model_View_Controller
前述の MVC と同様に「プレゼンテーションとドメインを分離」することで、
アプリケーション開発における保守性・開発生産性に寄与する。
-
Model View ViewModel - Wikipedia
https://ja.wikipedia.org/wiki/Model_View_ViewModel元来 WPF/Silverlight の世界で生まれた考え方ではあるが、
現在は Android やウェブブラウザ上での JavaScript の世界でも
MVVM の利用は広がっている。
補足(MVVM の詳細は別ページにある): 本 Wiki 内では
XAMLの書き方(2) に MVVM の節があり、
ガイドラインと現在の実装手段(CommunityToolkit.Mvvm 等)が整理されている。
後述の「プレゼンテーション層のパターン」の Front Controller を参照。
-
非同期メッセージングパラダイムの一種。
-
メッセージキュー・パラダイムと対比されるため、メッセージ・システムは、
出版-購読型とメッセージキューの両モデルをサポートしている。 -
特徴
- メッセージの送信者(出版側)が特定の受信者(購読側)を想定せずに
メッセージを送るようプログラムされたもの。 - 出版側と購読側の結合度が低いため、スケーラビリティがよく、
動的なネットワーク構成に対応可能。
- メッセージの送信者(出版側)が特定の受信者(購読側)を想定せずに
-
実装
- 出版側のメッセージはクラス分けされ、購読者に関する知識を持たない。
- 購読側は興味のあるクラスを指定しておき、
そのクラスに属するメッセージだけを受け取り、出版者についての知識を持たない。
-
出版-購読型モデル - Wikipedia
https://ja.wikipedia.org/wiki/%E5%87%BA%E7%89%88-%E8%B3%BC%E8%AA%AD%E5%9E%8B%E3%83%A2%E3%83%87%E3%83%AB
-
アプリケーションを複数の "層" に分け、それらを独立したモジュールとして開発・保守する。
- 各層はインタフェースを定義しモジュール化されたソフトウェアであり、
- テクノロジーの進歩や要求の変化に合わせて各層を個別に置換できる。
-
例
-
クライアントサーバモデル
- ユーザインタフェース
- ビジネスロジック
- データアクセス
-
Web 開発
- プレゼンテーション層 : 変化しないコンテンツを供給する Web サーバ
- 中間層 : 動的コンテンツを生成するアプリケーションサーバ。
- データ層 : データベースとその管理システム。
-
-
多層アーキテクチャ - Wikipedia
https://ja.wikipedia.org/wiki/%E5%A4%9A%E5%B1%A4%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3
補足(
Service locatorは現在アンチパターン扱い): 一覧に名前だけ
挙がっているが、評価が定まっているので補足しておく。【Service Locator】★ ・「必要な依存をコンテナから【自分で取りに行く】」 var svc = ServiceLocator.Get<IFoo>(); 【なぜアンチパターンとされるか】★★ ① 【依存関係が signature に現れない】 → コンストラクタを見ても何に依存しているか不明 → 実行して初めて分かる ② テストで【何をモックすべきか分からない】 ③ ロケータ自体がグローバル状態になる 【DI(コンストラクタ注入)との違い】 ✕ Service Locator class Foo { void M() { var b = Locator.Get<IBar>(); } } ○ 依存性の注入 ★ class Foo { Foo(IBar bar) { _bar = bar; } } → 【依存が明示される】 → コンパイラが不足を教えてくれる 【例外的に使われる場面】 ・DI コンテナを使えない層(静的メソッド、 レガシー コードとの境界) ・フレームワークの内部(コンテナ自身) → 【アプリのコードでは避ける】★ → 詳細は [DI](MS_DI) / [IoC、AOP → DI → 依存性反転原則](MS_IoCAOPDI)【出版-購読型モデルの現在】★ ・.NET 内 → MediatR、[Reactive Extensions(Rx)](MS_ReactiveExtensions) ・プロセス間 → 【Azure Service Bus / RabbitMQ / Kafka / MQTT】★ ・注意点 - 【メッセージの順序保証】は自明でない - 【at-least-once】が基本 → 受信側の【冪等性】が必須 ★ - 疎結合の代償として 【全体の流れが追いにくくなる】 → 分散トレーシング(OpenTelemetry)が要る
MVC 系のフレームワークに実装されているアレ
-
プレゼンテーションロジックからビジネスロジックを強制的に分離
-
すべてのリクエストの最初のアクセスポイントとしてコントローラを使用する。
-
コントローラは、リクエストにおける次の側面を処理する。
- 認証
- 承認
- セッション管理
- ナビゲーション
- デバッグ
- ローカリゼーション
-
参考
MVC 系のフレームワークに実装されているアレ
-
一般的なサービスを処理する埋め込み可能なフィルタのロールを定義
- セキュリティ
- ログ
- ステート管理
- デバッグ
-
例えば、ASP.NET MVC の FilterAttribute 的な。
-
参考
MVC 系のフレームワークに実装されているアレ
-
ビューからすべてのビジネスロジックを排除し、これを、
ヘルパークラスとしてモデルロジック層またはビジネスロジック層に移動 -
ASP.NET MVC ヘルパ(View ヘルパ、HTML ヘルパなどと呼ばれるものがある)。
-
参考
補足(この 3 つは ASP.NET Core でも健在): 「MVC 系のフレームワークに
実装されているアレ」という説明のとおり、現在も中核にある。【ASP.NET Core での対応】★ Front Controller → 【ルーティング ミドルウェア】 すべてのリクエストが 1 つのパイプラインを通る → 認証・認可・ローカライズも 原文の一覧どおりここで処理される ★ Intercepting Filter → 【ミドルウェア】(パイプライン全体) → 【フィルター】(MVC の中)★ - Authorization / Resource / Action / Exception / Result フィルター - [Authorize]、[ValidateAntiForgeryToken] 等 View Helper → 【タグ ヘルパー】(asp-for 等)★ → 【ビュー コンポーネント】 → HTML ヘルパー(@Html.*)は今も使えるが、 タグ ヘルパーの方が HTML らしく書ける【ミドルウェアとフィルターの使い分け】★ ミドルウェア … 【全リクエスト】が対象 MVC を知らない(静的ファイルも通る) → 圧縮、CORS、認証、例外の最終防壁 フィルター … 【MVC のアクション】が対象 モデル バインド結果を見られる ★ → 認可、入力検証、キャッシュ → 「どちらで書くか」の判断は 【MVC の文脈が必要かどうか】で決まる
前述の「データ・アクセスのアーキテクチャに関するパターン」の
Data Access Object を参照。
補足(この節の出典): 「多層アーキテクチャのパターン」以下に
列挙されているパターン名は、J2EE パターン カタログに由来する。【出典】★ 『Core J2EE Patterns』 (Deepak Alur, John Crupi, Dan Malks / Sun Microsystems) ・プレゼンテーション層 / ビジネス層 / インテグレーション層 の 3 層に分けて パターンをカタログ化したもの ・2001年(第 1 版)/ 2003年(第 2 版) 【現在の評価】 ・【EJB 2.x 時代の制約への対処】が動機のものが多い - Business Delegate … リモート呼び出しの隠蔽 - Session Facade … 粒度の細かい呼び出しの削減 - Transfer Object … リモート越しのデータ転送 → EJB 3 以降、これらの制約が緩和され 【不要になったパターンがある】★ ・一方、【今も有効なもの】 - Front Controller / Intercepting Filter / View Helper(前述のとおり現役)★ - Data Access Object - Service Activator(≒ メッセージ受信ハンドラ) 【読み方の指針】★ ・パターン名を「覚える」のではなく、 【どんな制約への対処だったか】を見る ・制約が消えていれば、パターンも不要になる → 本ページ冒頭の「注意および批判」の 「言語機能の欠損の印」という指摘と同じ話 ★
ソフトウェアテスト時、特に
- テスト駆動開発
- ビヘイビア駆動開発
における代用の下位モジュールスタブの一種。
- モックオブジェクト - Wikipedia
https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%83%E3%82%AF%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88
補足(テスト ダブルの用語整理): 「モックオブジェクト」は
総称として使われがちだが、実は下位分類がある。【テスト ダブル(Test Double)の分類】★ ・【Dummy】 … 引数を埋めるためだけ。使われない ・【Stub】 … 決まった値を返す(状態の検証)★ ・【Spy】 … 呼ばれたことを記録する ・【Mock】 … 【呼ばれ方を検証する】(振る舞いの検証)★ ・【Fake】 … 簡易だが動く実装 (インメモリ DB、偽のメール送信)★ → 原文が「スタブの一種」としているのは 広義の使い方であり、 厳密には Stub と Mock は【検証の観点が違う】 【.NET での実装】 ・【Moq】/ NSubstitute / FakeItEasy → 動的プロキシでインターフェースを実装する ・【インターフェースを切っていないと使えない】★ → だから DI と組み合わせる 【モックを使いすぎる弊害】★ ・実装の詳細に結び付いたテストになり、 リファクタリングのたびにテストが壊れる → 【Fake(動く簡易実装)】や 【Testcontainers で本物の DB を立てる】方が 壊れにくいことが多い ★ → 詳細は [単体・結合テスト方式](MS_UnitAndIntegrationTestMethods)
(いずれも IoC、AOP → DI → 依存性反転原則 の該当節を参照)
-
デザインパターン (ソフトウェア)
https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2) -
Category:デザインパターン (ソフトウェア)
https://ja.wikipedia.org/wiki/Category:%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2) -
アンチパターン
https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
- Template Method パターン
https://ja.wikipedia.org/wiki/Template_Method_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3 - Factory Method パターン
https://ja.wikipedia.org/wiki/Factory_Method_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3 - Strategy パターン
https://ja.wikipedia.org/wiki/Strategy_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3 - Service locator pattern
https://en.wikipedia.org/wiki/Service_locator_pattern
- Factory Methodパターン(2002年12月号)
https://www.hyuki.com/pi/#n01 - Template Methodパターン(2003年1月号)
https://www.hyuki.com/pi/#n02 - Generation Gapパターン(2003年2月号)
https://www.hyuki.com/pi/#n03 - Null Objectパターン(2003年3月号)
https://www.hyuki.com/pi/#n04 - Thread-Specific Storageパターン(2003年4月号)
https://www.hyuki.com/pi/#n05 - Producer-Consumerパターン(2003年5月号)
https://www.hyuki.com/pi/#n06 - Single-Active-Instance Singletonパターン(2003年6月号)
https://www.hyuki.com/pi/#n07 - Multi-Phase Startupパターン(2003年7月号)
https://www.hyuki.com/pi/#n08 - Mock Objectパターン(2003年8月号)
https://www.hyuki.com/pi/#n09 - Model-View-Controllerパターン(2003年9月号)
https://www.hyuki.com/pi/#n10 - Fork/Joinパターン(2003年10月号)
https://www.hyuki.com/pi/#n11 - Essenceパターン(2003年11月号)
https://www.hyuki.com/pi/#n12
-
Iterator
http://qiita.com/toshi0607/items/cdc589c58f21c0fc513d -
Adapter
http://qiita.com/toshi0607/items/374373a8bd656f7188d4 -
Template Method
http://qiita.com/toshi0607/items/cc8a87a3049bd7af52df -
Factory Method
http://qiita.com/toshi0607/items/d95bdd31da363e0f04a9 -
Singleton
http://qiita.com/toshi0607/items/c172bb4478e72ae6ced7 -
Prototype
http://qiita.com/toshi0607/items/f4358020befca048d2e0 -
Builder
http://qiita.com/toshi0607/items/13e37d54e04b61bc69b5 -
AbstractFactory
http://qiita.com/toshi0607/items/b8a19a4328849cdf1d99 -
Bridge
http://qiita.com/toshi0607/items/13e37d54e04b61bc69b5 -
Strategy
http://qiita.com/toshi0607/items/72829d34ef9595f5b3b0 -
Composite Pattern
-
Decorator Pattern
http://qiita.com/toshi0607/items/a65d1abb95a97970ab8c
移行メモ(リンクの重複・欠落): 上記の Qiita 一覧には
Builder と Bridge が同一の URL(13e37d54e04b61bc69b5)に
なっている箇所がある(Bridge 側が誤りと思われる)。
また Composite Pattern には URL がない。
いずれも移行元のまま残した。
デザインパターンの使い方連載一覧
https://codezine.jp/article/corner/207
-
Singleton
https://codezine.jp/article/detail/2804 -
Composite
https://codezine.jp/article/detail/2818 -
Template Method
https://codezine.jp/article/detail/2819 -
Flyweight
https://codezine.jp/article/detail/2915 -
Chain of Responsibility
https://codezine.jp/article/detail/3116 -
Interpreter
https://codezine.jp/article/detail/3291 -
Prototype
https://codezine.jp/article/detail/3825 -
Abstract Factory
https://codezine.jp/article/detail/3824
移行メモ(リンク切れ): 参考の
www.samuraiz.co.jp/adobeproduct/jrun/...(Adobe JRun は
2011 年頃に提供終了)は到達しない可能性が高い。記録として残す。
Tags: 移行, プログラミング, .NET開発
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。