ディレクトリ
アウトライン
フィールドサービス - この記事では、ドメイン駆動設計(DDD)戦術的なモード別の非常に重要な概念について説明します。前の2つのブログ記事では、我々は、オブジェクトとエンティティの値が何であるかを学んだ、と自分自身の行動をより明確に位置付けすることができます。しかし、いくつかの点で、あなたは、単一のエンティティまたは値オブジェクト本体に陥る可能性は思えない企業行動のいくつかを見つけるだろう、とビジネスロジックと混同のこの部分に配置されます。この時点で、あなたはフィールドサービスの操作を完了する必要があるかもしれません。
だから、最終的にはサービスの分野は何ですか?どのようにサービスエリアの分野では、それを見つけましたか?従来のサービスエリアとアプリケーション・サービス、それがどのような違いを生むのでしょうか?どの「フィールドサービス」という概念、および対応するコードフラグメントを与える再発見するためにもたらすこと(このチュートリアルのコードスニペットを使用している異なる観点から、この資料のC#を、実際のプロジェクトの後半にも基づいている過去ログコアプラットフォーム)。
サービス部門は何ですか
始める前に、または私はそれを少し余談を言う必要があります:あなたはこのシリーズの前回の記事を読めば、おそらく、一連のスタイルは、元の最初から解析され、その後のためのケースとシナリオの自身の実際の数と結合していることがわかりますドライブの分野における概念のいくつかを解釈します。私はあなたが何か提案を持っているので、もし、あなたがコメント欄にメッセージを残すことができ、我々はより明確に理解できるように書くのこの方法を知らない、私は慎重にあなたの意見や提案に耳を傾けます。
記事では、私は時々、確かに非常に便利な省略が、(例えば、一部の学生は、ESと略記好むイベントソースなど)速記名のすべての種類を回避しようとしますが、ことによって見えない人との間の通信のコストを行います大規模なので、私のブログの記事での長い私は速記を使用することはありませんノー速記のように。
もう一つのポイントは、それは、より多くの可能性が高い早期概念的なものに属しているので、ご参考のための既製のgithubのコードが存在しない、私たちは(私たちのいくつかは、我々のコードの時間を開始したことを学習の概念が完了した後、ずっと心配する必要はありません● '◡' ●)。
メイントピックに戻る、サービスの分野は何ですか?オリジナルのオリジナル見て「ドメイン駆動設計:それへのコアソフトウェアの複雑応答」をコンセプトはのサービスエリアで述べました:
いくつかのケースでは、明確な、最も実用的なデザインは、概念的にはどのオブジェクトにも属していないいくつかの特別な操作が含まれます。むしろ彼らは、これはサービス(サービス)でどのような強制の、流れにモデルに新たな要素を導入行く方が良いです起因します。
責任の分野におけるプロセス欲求または変換動作は、オブジェクトまたはエンティティの自然値に属していない場合、別の操作としてモデル・インターフェースに加え、そしてサービスとして宣言されなければならない。言語モデル定義されたインタフェースを使用するには、操作は用語ユビキタスLANGUAGEの名前であることを確認します。また、サービスはステートレスとして定義する必要があります。
金額。。。。「李杰ロング住んでいます。」理解することは、この概念が難しい理由は:まず、それはその後、我々はすでにさまざまなオブジェクトと作用するその能力に対応する分割領域を持っているこの時点で言うことです多くの分野「特別な操作が含まれている」、を検討していることを前提としてい私たちは(このサブジェクトエリアサービスでは、我々である)、「サービス」の伝説を抽出考えてみましょう。しかし、多くの場合、現実は初心者のように、我々はできる合理的に抽象的でない各オブジェクトであり、かつ優れたケースの経験があることを考えていません。だから私たちは、「これらのアクション」の概念を見つけることができなかった、時間のこの概念は非常に混乱している読んで、それはサービスが何であるかを理解することはできませんさらに、何もされています。
“在自己的私人飞机里面玩儿电子游戏是什么感觉呢? 呃.....好像前提是我得有钱买一架飞机吧?”
実際の場面から開始します
私は、「サービスエリア」を表現するために、いくつかの方法を考えて、それは長い時間のように思えるが、人々が理解させるのは簡単ではありません。だから、考え始めるボーエンのケースを使用して起動し、私は誰もが、この場合の有用性にサービスの分野を理解することができます願っています。
記事を見て、「DDDを使用する方法-実体」私たちが抽出されたことを物理的なオブジェクト:
public class Itinerary
{
public int ID { get; set; }
public List<Person> Participants { get; set; }
public List<Address> Places { get; set; }
public ItineraryNote Note { get; set; }
public ItineraryTime TripTime { get; set; }
public ItineraryStatus Status { get; set; }
//ctor
public void ChangeNote(string content)
{
Note = new ItineraryNote(content);
}
}
エンティティオブジェクトは、旅のストロークを示します。現在、一例として、我々は唯一の記事では、我々はそれを行動修正のメモを与えるように、この分野では、私たちは備考旅行情報を変更することを可能にすることを知っています。
プロジェクトの進捗状況によると、私たちは今、別の需要を獲得している:旅行は、旅行にユーザーのアクセスを終了していない場合、システムは、ユーザが現在、おいしい食べ物の近くに位置している場所に基づいてユーザーにお勧めします。
また、これは非常にユーザーフレンドリーで便利な機能が、製品やシステム競争優位の同じタイプの他の製品です。だから我々は検討するフィールドでそれを配置する必要があります。機能要件の記述から、私たちは何をする必要がある食品の推奨動作です。しかし、私たちは、逆説的に、食品の動き、我々はそれが誰に属している必要がありますことをお勧めします聞かせ?旅へ?料理を推薦する旅エンティティをしてみましょうか?もちろん、あなたはそれをしませんでした。旅は、これだけの旅行についての基本的な情報、場所、文字や時間に関係している、我々はそれを汎用性の高いマシン作り、その料理にこのアクションをお勧めしません。
上記の概念を確認するには:「いくつかのケースでは、明確な、最も実用的なデザインは、概念的にはどのオブジェクトにも属していないいくつかの特別な操作が含まれます。」慎重に数回読んで、ナニを?これは、この状況であると言っているわけではありませんか?今、このケースでは、我々は食品の操作があるお勧めしますが、それは任意のオブジェクトに属していません。
私たちは、この時点で到着したとき、我々はサービス部門のほとんど理解している可能性があります。次に、我々はダウンし続けています。今、私たちは理解しなければならない、我々は、この操作を処理するためにサービスが必要な場合があります。確立しようとしRecommendFoodsServiceを。
public class RecommendFoodsService
{
public List<RecommendFoodInfo> RecommendFoods(Itinerary currentItinerary)
{
//todo
}
}
サービス部門では、そこに、現在の旅を介して取得することで、メソッドRecommedFoods、あるお勧めの料理のリストを返します。このような内部の実装かもしれ:(ここでは、想定する旅程の場所最後の場所では、私たちの現在の場所であり、我々はすでにレストランを持つと呼ばれるレストランレストランに関する情報を提供する情報エンティティのシリーズそして、行動。もちろん、あなたが)固体部分の印象を深めるために、そのような実体を試すために、独自のレストランを構築することができます
public class RecommendFoodsService
{
public List<FoodInfo> RecommendFoods(Itinerary currentItinerary)
{
var recommendFoods = new List<FoodInfo>();
//Get Last Address
int lastCountIndex = currentItinerary.Places.Count -1;
var currentAddress = currentItinerary.Places[lastCountIndex];
var nearbyRestaurants = Restaurants.Where(s=> s.Address.isNearby(currentAddress)).ToList();
foreach(var restaurant in nearbyRestaurants)
{
var food = restaurant.GetRankNoOneFood();
recommendFoods.Add(new FoodInfo(food,restaurant.Address));
}
return recommendFoods;
}
}
OK、これまでのところ、我々はサービスエリアのデモ版を完了した、サービスに、私たちは、位置に応じて、現在の旅の位置にレストランのコレクションを取得レストラン距離最寄りの場所を見つけるために、システムから存在しますその後、ユーザーへの一品を評価し、これらのランキングの1で最高のレストランをお勧めします。
物事が表示されている上記の行動を見て、私たちの旅の最初の、そしてレストランを取ります。2つのエンティティ間の合理的なプロセスの関係、私たちは、食べ物を当社の経営シリーズを完了し、情報の収集を返してきた(レストラン情報ここでは、オブジェクトの値を定義します)。我々はいくつかの値とオブジェクトだけでなく、それらの間で異なる動作を使用することを含んでいるエンティティの数を持っていますが、この食品はビューの動作点から推奨されているが、彼らが実際にあることに注意してください全体、処理ロジックは密接にリンクされています(フォーカスをノック!!!)。
現実に近いです
上記のバージョンでは、我々は彼はデモ版では、私たちはしばしばを通じてので、実際の状況では、定義することになるとして店舗情報エンティティのコレクションを取得するための(リポジトリは、コンテンツに関する情報は、記事の後半で紹介します) 、ちょうど上記のコードのように。レストラン。そこに近い私たちのコードの現実には、次のようなことかもしれないが、それが伴うため、私たちは、このようなアプローチを検討することはできませんリポジトリ(リポジトリを倉庫)と集約ルート(AggregateRoot)の概念を、そして今、私達はちょうどに必要フィールドサービスだけで罰金をよく理解。
public List<FoodInfo> RecommendFoods(int currentItineraryID)
{
var recommendFoods = new List<FoodInfo>();
//Get Last Address
var currentItinerary = itineraryRepository.Get(currentItineraryID);
int lastCountIndex = currentItinerary.Places.Count -1;
var currentAddress = currentItinerary.Places[lastCountIndex];
var nearbyRestaurants = restaurantRepository.GetNearbyRestaurant(currentAddress);
foreach(var restaurant in nearbyRestaurants)
{
var food = restaurant.GetRankNoOneFood();
recommendFoods.Add(new FoodInfo(food,restaurant.Address));
}
return recommendFoods;
}
今、私たちの理解とコンテンツの発見によると、さあ、サービスエリアの機能のいくつかを見てみましょう:
- サービスエリアは、実体としてのオブジェクトのフィールドで処理し、オブジェクトの値ようにされています
- フィールドサービススケジューリングプロセスは、フィールド上のオブジェクトの一連の責任があります
- 私たちはアクションが値オブジェクトまたはエンティティを割り当てることができず、営業およびビジネスプロセスは非常に重要であることを見つけたとき、私たちはしばしばサービス部門を使用する必要があります
- フィールドサービスオペレーション、視野の観点から、それが全体であります
あなたは、以下の操作を行っている場合、それはあなたがフィールドサービスを必要となるかもしれません。
- AとBによって、Cを得ました
- 結果B.を得るために面倒な内部ポリシーの必要性
(シモンズ:Aは、B、Cは、物体またはターゲットエンティティのフィールド値を参照します)
フィールドサービスアプリケーションサービスVS
実際には、使用中のドライブの分野では、アプリケーション・サービスと呼ばれるサービスがあり、アプリケーション・サービスは、サービス、アプリケーション層に分割されています。サービスが呼び出されるため、多くの場合、最終的な結果は、どちらか(レイヤで処理されるすべての論理レイアウト)非常に大規模なアプリケーションサービスによって引き起こされる違いである、または非常に弱いアプリケーション・サービスは何すべてのサービスエリアからそれを区別することは困難です(これは、呼び出し元のコードフィールドサービスです)。アプリケーションサービスが混乱し始めたとき、サービスの元のフィールドのロジックを使用して、アプリケーションサービス、アプリケーションサービスを提供することができ、ロジックはサービスエリアを与えたので、同様に、フィールドサービスは、混乱になります。
私たちは、伝統的なドメイン駆動設計を提供して2つの比較の前に、4つのアーキテクチャ図を見てみましょう:
図からわかるように、アプリケーション層への参照は、アプリケーション層で言っているドメイン層との間の関係を維持するには、ドメインオブジェクトにアクセスすることができます。だから、聞かせてアプリケーション層はまた、ドメインオブジェクトをスケジュールする能力を持っています。これには多くの場合、我々は増加した上でアプリケーションサービスおよびフィールドサービスの難しさを区別し、当社のドメインオブジェクトと同じの機能です。
アプリケーションサービスについて、オリジナルのIに対応するキーの文を見つけられませんでしたので、ご参考のために、オンラインでいくつかの結論を選択しているため。
アプリケーションサービスは、主な手段は、ケースを使用して、ユーザーストーリー(ユーザー・ストーリー)式です。
アプリケーション層は、アプリケーション・サービス・インターフェースを介してシステムの機能を完全に露出させます。編成自体がビジネスユースケースの実行順序だけでなく、アセンブリの結果のための唯一の責任があるの目標を達成するために1つ以上の領域に委託機能を実現するためにそれを転送する責任があるアプリケーションサービスの実現で。
私たちは、おそらく知ることができる上記の結論から、アプリケーションサービスは、アプリケーションが使用してサポートする外部ユーザーをアクセスオブジェクトへとフィールド論理フィールドのレベルを実行できるようにすることです。dotnetooreのように、ユーザーが当社のコントローラを訪問して定義された当社のビジネスオブジェクトにアクセスすることができ、また、ビジネス・ロジックを実行するために、コントローラ・インタフェースを介して公開することができます。
中間アプリケーションサービスは、ビジネスロジックを実行したがって、我々は考えることができる(そのように定義され、非常に良いではない場合があります)、それは任意の論理プロセスのコア領域を伴わない、それはいくつかの検証、サポート、およびその他のコンポーネントのために責任がある(のようなログ、パフォーマンスの監視、など)。
上記の要件を拡張します
上記の認識フィールドサービスでは、我々はこのような要求をキャプチャしている:「旅は終わっていない場合は、ルートへのアクセスをユーザに、システムは、ユーザが現在おいしい食べ物の近くに位置している場所に応じて、ユーザーに推奨されます。」その後、需要が増加しています1:「我々は顧客に食べ物を通知するテキストメッセージを使用することができます。」
だから我々は、私はそれを入れなかったこの機能SMS通知を実現するべきで、このような要求を検討?またはテキストメッセージ操作どこでこの動作?のは彼がフィールドにサービスに置かれるように考えてみましょう:
public class RecommendFoodsService
{
public List<FoodInfo> RecommendFoods(Itinerary currentItinerary)
{
var recommendFoods = new List<FoodInfo>();
//Get Last Address
int lastCountIndex = currentItinerary.Places.Count -1;
var currentAddress = currentItinerary.Places[lastCountIndex];
var nearbyRestaurants = Restaurants.Where(s=> s.Address.isNearby(currentAddress)).ToList();
foreach(var restaurant in nearbyRestaurants)
{
var food = restaurant.GetRankNoOneFood();
recommendFoods.Add(new FoodInfo(food,restaurant.Address));
}
//在这里添加短信发送?
SmsUtil.Send(currentItinerary.Participants,recommendFoods);
return recommendFoods;
}
}
私たちは、元のコードに基づいて、そのSMS通知を実現するために、コードの行を追加し、そして今、これは私たちのニーズを満たしています。しかし!!!!SMS通知は大丈夫、ここに配置されますか?この問題を解決するために、我々は検討する必要があります:「SMSは私のフィールド抽出動作です?」「この行動がなければ、ビジネスロジックに影響を持っています」?
そして、それから抽出されたテキストメッセージのフィールドについて考えますか?私たちは旅の懸念となっている、様々な旅の目的は、私たちの主な関心事であることは明らかです。テキストメッセージは、我々が抽出されているものではありませんので、それだけで何も含まれ、当社のサポート機能を必要とします。
だから、この動作せず、それのビジネスロジックに影響がありますか?それは私の完全なグルメがこの動作をお勧めは影響しないのだろうか?もちろん、ありません!我々はそれがフィールドサービスを言う、上記の特徴を覚えておいてください:操作をサービスの分野では、視野の観点から、それが全体です。その一部の損失の全体が事業を完了できない場合。だから今の推奨食品事業は、それのようなレストランの外観の一部を削除した場合?OMG、このサービスは、その機能を失っている、廃止されました。あなたはそれを削除したテキストメッセージを送信する場合は?これは、影響を受けた少し見えません。
最後にそれを置く場所を次にメッセージは、送信されますか?アプリケーションサービス!!!!!
public class ItineraryApplicationService
{
public string RecommendFoods(int currentItineraryID)
{
Logger.Log("执行推荐美食业务");
var participants = itineraryRepository.Getparticipants(currentItineraryID);
var foods = RecommendFoodsService.RecommendFoods(currentItineraryID);
SmsUtil.Send(foods);
return foods.toJson();
}
}
私たちは、アプリケーション層での名前を定義ItineraryApplicationServiceのそれは外の提供、アプリケーションサービスをRecommendFoodsクライアントインターフェース(アプリケーション、Webページなど)がAPIを介して操作の料理シリーズをお勧め達成することができます。我々は、サービスの分野でカプセル化されている推奨される食品の行動、アプリケーションサービスはまた、我々は上記の言っていることが確認され、操作の内部ロジックを完了することができます知っている必要はありません:視野、全体としてサービス部門の観点から。
それは、最も一般的な認証および認可サービス業
一般的なアプリケーションでは、アプリケーションの認証および認可サービスで。なぜ?それだけでシステムを維持することが多いですので、あなたが基本的な機能を提供することができますが、あなたの分野で行われてはいけません。我々はサービスエリアを見てみて、それを定義しようとしなければならないので、おそらく、これは、理解することは容易ではありません。私たちは今、アイデンティティの検証コードを置き換えるために、サービスのフィールドにテキストメッセージを送信した後、第一の方法ブロックに配置された、我々はフィールドサービスの間違ったバージョンを実装し、テキストメッセージに例を考えてみましょう。どうしましたの?上記の質問に答えるために続けて、彼らは全体doがありますか?このコードを剥奪した場合、行動に何らかの影響がありますか?ゆっくりとあなたはそれが過去にサービス部門から来ます。
あなたがソフトウェアで能力を実装している場合しかし、それはフィールドで定義することができます。一連の操作は、あなたの分野で認定されているので、あなたのアプリケーションを失う可能性があり、認証コードが正常な機能を提供することができません一度真剣に、それについて考える必要があります。
フィールドサービスを使用します
分野の専門家と、あなたはフィールドに関連する複数のエンティティの概念について話しましたが、あなたは行動を「所有」されたエンティティわかりません。この動作は、いずれかのエンティティに属しているように見えませんが、あなたはそれらに対処するために任意のエンティティの行動への適応を強制しようとすると、少しトリッキーになります。思考のこのモードは、フィールドサービスの強い兆候が必要です。[ハッシュ、この文の私のコピーです。(* ^ __ ^ *)]
あまりにも多くのサービスエリアを使用しないでください
どのようなので、それは、値オブジェクトとエンティティにオブジェクトフィールドサービススケジューリングの領域だけではないのですか?もちろんない、アプリケーションサービスも利用できます。
また、共通の問題をみんなで:完全なビジネス・ロジックを介してすべてのエンティティ、値オブジェクト、倉庫、フィールドサービスオーケストレーション。非常に薄いので、アプリケーションサービス層、技術及びサービスを呼び出すコードのしばしば唯一のライン(ロギング、いくつかの前のフレームで自動的に演奏コード)。
アプリケーション部分の派遣サービスに割り当てる権限しようとすると、それがより明確に読んでようになります、お住まいの地域コードの読みやすさには影響しません。あなたのエンティティやバリューオブジェクト間のあなたの呼び出し動作だけ論理的な配置を見つけることが、そのようなAPIを取得するための旅として、時間の分野で完全なビジネス慣行を(構成するものではありませんが、場所の距離関数を表現するときは、この機能を持つことができませんその後、倉庫でのこの旅行の旅程のアドレスを取得するためにIDを渡すことによって、アプリケーション・サービスにおけるサービスエリアを考慮、した後、変換からシステムまでの距離を計算するために、クライアントに返される)、それを考慮アプリケーションサービスへ。
サービス部門の行動のあまりを与えてはいけません
なぜあなたは言うのですか?あなたは、フィールドでのモデル、エンティティとオブジェクトの振る舞いのみ散発的なポイントの値、およびオブジェクトと操作の動作を達成するための行動の真の価値を構築することが判明した場合、フィールドサービスによって行われます。さて、あなたは間違っているサービスエリアを使用する場合があり、再知っている、あなたは彼らに自分の行動を与え、エンティティと値オブジェクトを識別するために、間違ったサービスエリアを削除します。
概要
今回は、ドメイン駆動設計戦術的なモードの紹介サービスエリアを。また、一部には、あまりにも完全な説明ではないかもしれないサービスやアプリケーションサービスの領域を、比較して、私は2つの例の違いから、誰もがあれば、後者は専門的な区別するために皆のためのブログを書く時間を持っていることが理解されて願っていますフィールドサービスやアプリケーションサービス。説明の過程で、我々はまた、このようなリポジトリやAggregateRootなど、すべての戦術的なモードは、これら2つの概念は記事の後半に皆をもたらすために導入される他の概念に関連します。
- @todo友人で、15階のコメントは良い提案を与えた、それは問題を無視して書くことに時間です。
小さな卵
非常に今、皆のための漫画の映画をリリース推奨、「あなたは波に相乗り場合」。アニメーションのような学生は見逃すことはできません。