Clojureの作成者である このビデオはRich Hickeyによる で、Javaのようにクラスを使用してデータを表すのではなく、マップを使用してデータを表すことをお勧めしています。 APIユーザーが単純にマップとして表されている場合、入力キーが何であるかをどのようにして知ることができるのか、私はそれがどのように良くなることができるか理解していません。
例:
PersonAPI {
Person addPerson(Person obj);
Map<String, Object> addPerson(Map<String, Object> personMap);
}
2番目の関数では、APIユーザーは、人を作成するための入力をどのようにして知ることができますか?
Exagg'itive Summary (TM)
あなたはいくつかのものを得ます。
致命的な欠点が1つあります。
、um、introspectionを使用してイントロスペクションを取得できます。これは通常発生します。
つまり、FPとのインターフェースが不要になった場合は、Rich Hickeyのアドバイスに従う必要はありません。
最後に、ただし重要ではありませんが、String
をプロパティキーとして使用するのが最も簡単ですが、String
sを使用する必要はありません。多くのレガシーシステムAndroid™を含むは、フレームワーク全体で整数IDを広範囲に使用して、クラス、プロパティ、リソースなどを参照します。
両方の世界を幸せにすることもできます。
Javaの世界では、通常どおりゲッターとセッターを実装します。
FP世界の場合、
Object getPropertyByName(String name)
void setPropertyByName(String name, Object value) throws IllegalPropertyChangeException
List<String> getPropertyNames()
Class<?> getPropertyValueClass(String name)
これらの関数の内部では、はい、醜いコードですが、IDEプラグインがあり、それを埋めてくれます...ええと、スマートプラグインreads yourコード。
Java側は通常どおりパフォーマンスが向上します。コードのその醜い部分を使用することはありません。Javadocから非表示にすることもできます。
FP世界の側は、彼らが望むどんな「リート」なコードも書くことができます、そして彼らは通常、コードが遅いことについてあなたに怒鳴りません。
一般に、オブジェクトの代わりにマップ(プロパティバッグ)を使用することは、ソフトウェア開発では一般的です。関数型プログラミングや特定の種類の言語に固有のものではありません。特定の言語の慣用的なアプローチではないかもしれませんが、それを必要とする状況があります。
特に、シリアライゼーション/デシリアライゼーションでは同様の手法が必要になることがよくあります。
「オブジェクトとしてのマップ」に関するいくつかの一般的な考え。
それは彼が何を話しているのかを本当に知っている誰かによる素晴らしい話です。読者には全体を見ることをお勧めします。長さはわずか36分です。
彼の主なポイントの1つは、単純であることは後で変更の機会を開くことです。 Person
を表すクラスを選択すると、指摘したとおり、静的に検証可能なAPIを作成することですぐにメリットが得られますが、それには、機会を制限したり、変更や再利用のコストを増やしたりするコストが伴います。
彼のポイントは、クラスを使用することは合理的な選択かもしれないが、それはコストを完全に意識することを伴う意識的な選択であるべきであり、プログラマーは伝統的にそれらを考慮に入れることはもちろん、それらのコストに気づくという非常に貧弱な仕事をします。その選択は、要件が大きくなるにつれて再評価する必要があります。
以下は、Person
オブジェクトのリストを使用するよりもマップのリストを使用するほうが簡単な可能性があるいくつかのコード変更(1つまたは2つは講演で説明されています)です。
Map
のプリミティブを送信可能な形式にするために作成された関数は、再利用性が高く、ライブラリで提供される場合もあります。APerson
オブジェクトは、同じジョブを実行するためにカスタムコードを必要とする可能性があります)。私たちは常にこの種の問題を解決し、そのためのパターンとツールを用意していますが、最初に単純でより柔軟なデータ表現を選択することで作業が簡単になるかどうかについて考えることはめったにありません。
データがほとんどまたはまったく動作せず、変化する可能性のある柔軟なコンテンツがある場合は、マップを使用します。 IMO(N-フィールド、Nセッター、Nゲッターを含む Anemic Domain Model で構成される典型的な「javabean」または「データオブジェクト」)は時間の無駄です。ファンシースマンシークラスでそれを包むことによって、美化された構造体で他の人を感動させようとしないでください。正直に言うと 意図を明確にする で、マップを使用します。 (または、ドメインに意味がある場合は、JSONまたはXMLオブジェクト)
データに重要な実際の動作がある場合、a.k.aメソッド( Tell、Do n't Ask )の場合、クラスを使用します。そして、本当のオブジェクト指向プログラミングを使うために背中を軽くたたいてください:-)。
データに必須検証動作と必須フィールドが多数ある場合は、クラスを使用します。
データに適度な量の検証動作がある場合、それは境界線です。
データがプロパティ変更イベントを発生させる場合、それは実際にはMapを使用する方が簡単ではるかに面倒ではありません。ちょっとしたサブクラスを書いてください。
Mapを使用する場合の主な欠点の1つは、ユーザーが値をStrings、ints、Foosなどにキャストする必要があることです。これが非常に煩わしく、エラーが発生しやすい場合は、クラスを検討してください。または、関連するゲッターでMapをラップするヘルパークラスを検討してください。
map
のAPIには2つのレベルがあります。
APIは、慣例によりマップに記述できます。たとえば、ペア:api api-validate
をマップに配置したり、:api-foo validate-foo
を規則にしたりできます。地図にはapi api-documentation-link
も格納できます。
規則を使用すると、プログラマーは、マップとして実装された「タイプ」間のアクセスを標準化するドメイン固有の言語を作成できます。 (keys map)
を使用すると、実行時にプロパティを決定できます。
マップには魔法はなく、オブジェクトにも魔法はありません。すべて発送です。