Map
を処理するメソッドprocessDataAssumingLinkedHashMapInput()
があります。 Map
は、値順に並べられたLinkedHashMap
である必要があります。データはgetStrIntMap(query)
から取得されます。このメソッドはSQLからresultSetを取得し、それをLinkedHashMapに配置します。コードは次のとおりです。
_public void processDataAssumingLinkedHashMapInput(){
String query = "select MYID, MYVALUE from MYTABLE order by MYVALUE";
Map<String, Integer> map = SQLTools.getStrIntMap(query);
for (Map.Entry<String, Integer> entry : rawEntryToSortOrderMap.entrySet()) {
//do something, assuming that values are ordered
}
//do more stuff
}
//SQLTools method, used by multiple other classes
public static Map<String, Integer> getStrIntMap(String query){
Map<String, Integer> map = new LinkedHashMap<>();
//ResultSet to map
return map;
}
_
私の懸念は、誰かがgetStrIntMap(String query)
をMap<String, Integer> map = new HashMap<>();
に変更することを決定した場合(たとえばパフォーマンス上の理由で)、processDataAssumingLinkedHashMapInput()
が壊れることです。 getStrIntMap
の戻り値の型を具体的な実装に変更することはできますが、見栄えが悪く、誰かが抽象Map
に戻すことになります。 1つはMap
を返し、もう1つはLinkedHashMap
を返す、2つの本質的に同一のメソッドを作成できますが、これはDRYの原則に違反します。 processDataAssumingLinkedHashMapInput
メソッドの始まりですが、これもDRYルールに違反しています。この場合のベストプラクティスは何ですか?
少しIoCを使用します。呼び出し元がマップインスタンスを挿入できるようにリファクタリングします。これにより、他の開発者がより効率的なマップを使用できるようになり、必要な機能でマップを使用できるようになります。
public static void fillStrIntMap(String query, Map<String, Integer> map){
//ResultSet to map
}
提供されたMap
から呼び出し元が提供した空のquery
を設定するメソッドをライブラリに追加することをお勧めします。
物事を乾いた状態に保つと、getStrIntMap
メソッドはこの他のメソッドを呼び出し、新しいLinkedHashMap
を渡し、そのMap
を返します(インターフェイスとして、その署名は変更されません)。
次に、呼び出し元は、疎結合用のgetStrIntMap
インターフェイスを返す標準のMap
を選択できます。または、呼び出し元は、選択したMap
を渡す他のパスを選択できます。マップが実際にLinkedHashMap
であることが明確に保証されていますが、ライブラリAPIが具象型を公開する必要はありません。
1つの可能性は、抽象マップを拡張してそれを返すOrderedMapと呼ばれる新しい抽象型を作成することです。そうすれば、メソッドは引き続き抽象化を返しますが、順序付けられたマップタイプを返すように強制されます。既存の呼び出し元は、必要に応じて、返されたオブジェクトを基本マップとして扱うことができます。または、HashMapなどの戻り値に変更されないように実装が保護された状態で、返されたオブジェクトが順序付けられていることを確信できます。