国境では、アプリケーションはオブジェクト指向ではありません

最近の一連のポカヨケデザインポストについて、多くのフィードバックを受け取りました(そうでなければ、怒ってしまいます)。 これらのレビューの多くは、アプリケーションの境界で一般的に使用されるさまざまなシリアル化または翻訳技術に関連しています:シリアル化、XML(de)ハイドレーション(翻訳者注:シリアル化と同じ)、UI検証など この変換は、アプリケーションの境界だけでなく、永続性レベルでも発生することに注意してください。 ORMは翻訳メカニズムでもあります。

多くのコメントに共通しているのは、ほとんどのシリアル化テクノロジにはデフォルトのコンストラクタが必要だという主張です。 たとえば、 XmlSerializerクラスには、既定のコンストラクターと、書き込み可能なパブリックプロパティが必要です。 私が研究したほとんどのオブジェクトリレーショナルコンバーターには、同じ要件があるようです。 Windows FormsコントロールとWPFコントロール(UIはアプリケーションのフロンティアでもあります)には、ほとんどの場合、既定のコンストラクターが必要です。 これはカプセル化を破壊しますか? はい、いいえ。



境界線上のオブジェクト

アプリケーションの境界上でオブジェクト (ドメイン)を公開すると、カプセル化は確実壊れます。 単純なXMLドキュメントを考えてみましょう。

<name> <firstName>Mark</firstName> <lastName>Seemann</lastName> </name>
      
      





正式な契約(XSD)の存在に関係なく、要素firstNameおよびlastNameが必須であることに同意できます。 そのような契約にもかかわらず、私はそれを侵害する文書を冷静に作成できます。

 <name> <firstName>Mark</firstName> </name>
      
      





コンパイル段階を含めることができないという理由で、この契約を促進することはできません( 翻訳者に注意してください:強制的に実行すること )。 入力(および出力)を検証できますが、これはまったく別の問題です。 誤った形式の入力を作成するのは非常に簡単であるため、契約の履行を強制することはできません。 同じ引数は、UIの入力フォームおよびあらゆる種類のシリアル化されたバイトシーケンスに適用できます。 したがって、入力は期待どおりに処理する必要があります。

これはまったく新しい観察ではありません。 「 エンタープライズアプリケーションテンプレート 」という本で、 Martin Fowlerはそのようなオブジェクトをデータ転送オブジェクト(DTO)として説明しました。 ただし、名前にもかかわらず、DTOオブジェクトは実際にはオブジェクトではないことを理解する必要があります。 そして、これも新しいことではありません。 2004年、ドンボックスは、サービス指向に関する4つの規定を策定しました。 (はい、私は彼らがもはや流行ではなく、 人々が彼らを休息に送りたいことを知っていますが、それらのいくつかはまだ多くの意味を成しています)。 特に、3番目の条項はこの投稿に関連しています。

サービスは、クラスではなくスキームと契約を共有します。


はい、それはオブジェクトではないことを意味します 。 DTOは、オブジェクト指向言語にマッピングされたデータの一部の表現です。 これは、カプセル化の意味でそれらをオブジェクトにしません。 想像することは不可能でしょう。 入力が予想されるため、不変条件を進める(サポートする)ことはできません。

通常、 Craig Stantsが以前の投稿の1 つへの コメントで指摘したように、入力が正しくない場合でも、正しいエラーメッセージを表示するために入力で受け取ったものをキャプチャする必要があります(この引数はマシン間の境界にも適用されます)。 これは、DTOが非常に弱い不変式を持っていることを意味します(まったくない場合)。

DTOオブジェクトはオブジェクトではないため、カプセル化を壊しません。


ツールにだまされないでください。 .NETフレームワークは、実際には、DTOオブジェクトを実際のオブジェクトと見なすことを本当に望んでいます。

これはコード生成の結果です。

このような自動生成されたクラスによって提供される厳密な型指定は、誤ったセキュリティの感覚を与えます。 コンパイラーから高速のフィードバックが得られると考えるかもしれませんが、実行時エラーが発生する可能性のある状況は数多くあります(最も顕著なのは、発生したもので、回路の更新後に自動生成されたコードの更新を忘れることです)。

入力データと出力データをオブジェクトとして表すことのさらに悪い結果は、多くの開発者が、それらをオブジェクトの実際のモデルとして操作することです。 一貫した結果は貧血領域モデルです。

ますます、この一連の議論は、私たちが過去10年間使用してきたDTOメンタルモデルは行き止まりであると結論付けることにつながります。



アプリケーションの境界で何が起こるべきか

オブジェクト指向コードを記述し、境界のデータがオブジェクト指向オブジェクト以外のものであると仮定します。 どのように彼らと仕事をしますか?

一つの選択肢は、私たちが持っているものをそのまま使うことです。 この場合、穴を埋めるために、DTOオブジェクトを適切にカプセル化されたドメインオブジェクトに変換できる変換レイヤーを開発する必要があります。 これは私の本の例で従う道です。 しかし、この決定はますます最善ではないと思う。 サポートの問題が発生します。 (ところで、このような問題は本を書くときに発生します。終了するまでに、あなたはそれを始めたときに知っていた以上のことを知っています...私は本を非難していません、それは理想的ではありません...)

もう1つの可能性は、データをオブジェクトとして扱うのをやめて、それらを実際に構造化データと見なし始めることです。 プログラミング言語に構造化データという別の概念があれば素晴らしいでしょう...興味深いことに、C#はこのようなことはしませんが、F#には動作のないデータ構造をモデリングするための可能性がたくさんあります。 おそらく、これはデータを扱うためのより正直なアプローチです...これを試す必要があります...

3番目のオプションは、動的型に注目することです。 Dino Espositoは、記事「 On the Edge:Expando Objects in C#4.0 」で、構造化データの消費に対する動的なアプローチを概説します。これは、自動生成コードを短縮し、構造化データの軽量APIを提供します。 また、有望なアプローチのように見えます...コンパイル段階ではフィードバックを提供しませんが、結局は単なる誤ったセキュリティ感覚です。 素早いフィードバックを得るために単体テストに頼らなければなりません、私たちは皆TDDを練習していますよね?

結論として、私のカプセル化シリーズ全体は、 オブジェクト指向プログラミングに関連しています 。 データを「オブジェクト」として表示するための多くの技術がありますが、それらは偽のオブジェクトです。 ボーダーでオブジェクト指向を使用しても、このコードはオブジェクト指向とは関係ありません。 したがって、ポカヨケデザインルールはここでは適用されません。

最初に戻って投稿を読み直し、「DTO」を「Entity」(またはORMがリレーショナルテーブルの行を表すものとして参照するもの)に置き換えます。オブジェクトリレーショナルコンバーターの概要が表示されます。疑わしい。



All Articles