コードレビューの後、デザインの選択について議論したところです。あなたの意見は何でしょうか。
このPreferences
クラスは、キーと値のペアのバケットです。NULL値は正当です(重要です)。特定の値がまだ保存されていない可能性があり、要求されたときに事前定義されたデフォルト値で初期化することにより、これらのケースを自動的に処理したいと考えています。
説明したソリューションでは、次のパターンを使用しました(注:これは実際のコードではなく、明らかに-説明のために単純化されています)。
public class Preferences {
// null values are legal
private Map<String, String> valuesFromDatabase;
private static Map<String, String> defaultValues;
class KeyNotFoundException extends Exception {
}
public String getByKey(String key) {
try {
return getValueByKey(key);
} catch (KeyNotFoundException e) {
String defaultValue = defaultValues.get(key);
valuesFromDatabase.put(key, defaultvalue);
return defaultValue;
}
}
private String getValueByKey(String key) throws KeyNotFoundException {
if (valuesFromDatabase.containsKey(key)) {
return valuesFromDatabase.get(key);
} else {
throw new KeyNotFoundException();
}
}
}
アンチパターン- フローを制御するための悪用例外として批判されました。KeyNotFoundException
-その1つのユースケースのみに命を吹き込みます-このクラスの範囲外では決して見られません。
それは本質的に、単に何かを相互に通信するためにフェッチを行う2つのメソッドです。
データベースに存在しないキーは、驚くべきものでも例外でもありません-新しい設定が追加されるたびにこれが発生することが予想されるため、必要に応じてデフォルト値で適切に初期化するメカニズムです。
反論は、getValueByKey
現在定義されているプライベートメソッドには、値とキーが存在するかどうかの両方についてパブリックメソッドに通知する自然な方法がないことです。(そうでない場合は、値を更新できるように追加する必要があります)。
完全に正当な値であるためnull
、返すことはあいまいであるためnull
、キーが存在しないことを意味するのか、またはが存在するのかはわかりませんnull
。
getValueByKey
Tuple<Boolean, String>
キーが既に存在する場合、ブール値をtrueに設定して、とを区別できるように、何らかのaを返す必要が(true, null)
あり(false, null)
ます。(out
パラメーターはC#で使用できますが、それはJavaです)。
これはより良い代替手段ですか?はい、の効果に対していくつかの使い捨てクラスを定義する必要がありますTuple<Boolean, String>
が、その後、を取り除きKeyNotFoundException
、そのようなバランスを取ります。また、例外を処理するオーバーヘッドも回避していますが、実際的な意味では重要ではありません-パフォーマンスに関する考慮事項はありません、それはクライアントアプリであり、ユーザー設定が毎秒数百万回取得されるというわけではありません。
このアプローチのバリエーションでOptional<String>
は、カスタムの代わりにGuavaを使用できます(Guavaはプロジェクト全体で既に使用されています)。Tuple<Boolean, String>
次にOptional.<String>absent()
、「proper」と区別することができnull
ます。しかし、見やすい理由でまだハック感があります-2つのレベルの「ヌル」を導入するOptional
と、そもそもsの作成の背後にあった概念が乱用されるようです。
もう1つのオプションは、キーが存在するかどうかを明示的にチェックすることです(boolean containsKey(String key)
メソッドを追加し、getValueByKey
既に存在することをアサートしている場合のみ呼び出します)。
最後に、プライベートメソッドをインライン化することもできますが、実際のgetByKey
コードサンプルよりもやや複雑なので、インライン化すると非常に見苦しくなります。
私はここで髪を分割しているかもしれませんが、この場合のベストプラクティスに最も近くなるためにあなたが何に賭けるか興味があります。OracleまたはGoogleのスタイルガイドに答えが見つかりませんでした。
コードサンプルのように例外を使用しているのはアンチパターンですか、それとも代替物があまりきれいでないことを考えると許容可能ですか?そうである場合、どのような状況で問題ないでしょうか?およびその逆?
getValueByKey
公開されている場合は、より興味深いものになると思います。