数量

数量と単位の両方で次元付き値を表します。

これは、私が2000年代半ばに行ったエンタープライズアプリケーションアーキテクチャ開発の更なる発展に関する記述の一部です。残念ながら、それ以来、多くの他の事柄に注意が奪われ、それ以上取り組む時間がありませんでしたし、近い将来、時間を見つけることも難しいでしょう。そのため、この資料は非常に草稿段階のものであり、再び取り組む時間が見つかるまで、修正や更新は行いません。

コンピュータで次元付き量(6フィートや30キログラムなどの値)を表す必要があるケースは数多くあります。通常、これらは素数の数値として表されます。これは主に、言語が提供する限定的な型システムではこれが最善の方法だからです。

しかし、オブジェクトを使用すると、値を追加するたびに新しい基本型を追加することができ、次元付き量に特定の型を持たせることで、かなりの価値が追加されます。これは、次元付き量が金額である場合に特に当てはまります。金額は数量の特別なケースですが、多くの人が喜んでお金を使ってお金を見る準備をしているため、おそらく最も広く使用されているケースでもあります。

仕組み

数量の基本的な考え方は、数量と単位を組み合わせたクラスです。数量は単純な表現であると言えます。しかし、数量の真の面白さは、適用できる動作にあります。

最初の動作の種類は算術演算です。2つの数量を、2つの数値を足し合わせるのと同様に簡単に足し合わせる必要があります。さらに、数量は加算と減算に関してインテリジェントである必要があります。少なくとも、6フィートと180ポンドを足し合わせることを防ぐ必要があります。

加算に関するより複雑な問題は、500メートルと3キロメートルなど、類似の単位を足し合わせようとする場合に発生します。最も単純なアプローチは、その加算を拒否し、クライアントに換算を強制することです。より洗練されたアプローチは、一方の引数を他方に変換できるかどうかを確認することです。可能であれば、加算を実行できます。これを実行できる程度は、コンバータの洗練度に依存します。

乗算には、洗練度において同様のバリエーションがあります。最も単純なアプローチは、スカラー数値による乗算と除算のみを許可することです。より洗練されたアプローチは、他の数量による乗算を許可することですが、その場合、結果の単位を計算する必要があります。したがって、150マイルを2時間で割ると、75マイル/時になります。

比較演算が必要なので、6フィートが5フィートよりも大きいかどうかを確認できます。ここでの問題は、加算の場合とほぼ同じで、どの程度の変換を行うかを選択する必要があります。

数量に対して直接変換を許可する単純なインターフェースを提供することは有用ですが、変換作業は通常、個別のコンバータオブジェクトに任せるのが最善です。ただし、単位が数個しかない場合は、数量クラスに直接埋め込む方が簡単です。

数量に与えることができる最も便利な動作の1つは、文字列を簡単に生成し、文字列から数量を生成できる印刷および解析メソッドを提供することです。この単純なパターンは、ファイルへの入出力やGUIインターフェースなど、多くの入出力動作を簡素化するために役立ちます。

単純な印刷では、最初に数量を印刷してから単位を印刷するデフォルトを使用できます。ただし、場合によっては、数値の前に単位を印刷する場合と、後で印刷する場合があるため、これはうまくいきません。通常、この種のバリエーションは単位に依存するため、これらの場合は、印刷と解析の動作を単位に配置し、それに委任できます。

金額

私はほとんどすべてのシステムで数量を使用していますが、物理単位を表すことはめったにありません。ほとんどの場合、金額を表すために使用しています。物理単位に関する多くのコメントは同じですが、金額には、作業時に考慮すべき独自の側面があります。

最大の変更は、変換の全領域を取り巻いています。物理単位の変換形式は時間とともに変化しませんが、金額の為替レートは常に変化しています。これは明らかに変換操作に影響しますが、その影響は加算、減算、比較操作にも波及します。

金額を変換する際には、少なくとも何らかの時間参照を提供する必要があります。その粒度はアプリケーションによって異なります。しかし、多くの場合、異なるコンテキストで個別の変換を行う場合があります。

これらすべてをまとめると、金額の算術演算または比較演算における自動変換にはるかに注意する必要があります。多くの場合、それらは許可されません。

数量の機能に加えて、金額で特に便利な機能は、丸めの処理です。金額は小数部で表されることがよくありますが、金額の処理には決して実数を使用すべきではありません。その理由は、実数の丸めの動作は、金額に必要な動作とほとんど一致しないことがあり、この事実を無視すると、額は小さいが不満は大きい断続的なバグが発生しやすいためです。

しかし、金額オブジェクトは独自の丸めルールをエンコードできるため、ほとんどの場合、金額を操作している間は丸めルールを意識する必要がありません。

これと関連しているのが、除算という難しい問題です。100ドルを3で割ると、どうなるでしょうか?通常、答えは33.33ドルというほど単純ではありません。問題は、33.33ドルを掛けると99.99ドルになることです。つまり、1セントが不足します。会計士は1セントが不足することを好みません。そのため、対象の状況に適用されるポリシーを調べる必要があります。多くの場合、ルールは、誰かが余分な1セントを得るべきだということです。誰がもらうかは関係ありません。そのため、金額オブジェクトに、除算から渡す必要がある金額のコレクションを返すメソッドを入れることができます。

リレーショナルデータベース

数量に関するよくある質問は、新しい軽量型を作成できないリレーショナルデータベースやその他のシステムにどのように使用するかということです。金額と通貨コードをすべての金額の値と一緒に保存しますか?

ここで問題になるのは、特定のコンテキストですべての金額を同じ通貨にする制約がある場合です。多くのエントリを持つアカウントがある場合を考えてみてください。各エントリには、エントリの金額を示す金額属性がありますが、アカウント上のすべてのエントリは同じ通貨です。アカウントに通貨を一度保存し、エントリ全体で通貨を複製しないのは妥当でしょうか?

この質問については、データベース設計の具体的な内容に任せる傾向があります。コードでは依然として金額オブジェクトを使用することを強くお勧めします。それらをデータベースにどのように保存するかは、あなた次第です。結局のところ、データベースは数量から何らかの動作上の利点を提供しません。コードでのみそれらの利点が得られます。

使用する場合

お分かりのように、私は少なくとも金額のバリエーションでは数量を多用しています。実際、オブジェクト指向環境では、それを使用しない理由があまりありません。私は、多くの人がこのような小さなオブジェクトの使用を、主に不慣れのために恐れていることに気づいてきました。パフォーマンスはしばしば懸念事項として挙げられますが、数量がパフォーマンスにとって本当に問題になっているのを目撃したり聞いたりしたことはありません。

単位が1つしかない場合は数量を使用する価値がないという議論があります。そのため、通貨が1つしかない場合は金額を使用するべきではありません。しかし、金額の価値の多くは、マルチユニット機能ではなく、その動作に由来するため、その場合でも使用します。

さらに読む

金額のバリエーションについては、P of EAAでより詳細に説明されています。