web-dev-qa-db-ja.com

Javaで複数の値を返すためのベストプラクティス?

今日、ブルートフォース攻撃を遅くするために、ログインフォームの後ろに追加のセキュリティチェックを追加しました。複数のログインフォームがあり、すべてのチェックを実行してから結果を返す関数を簡単に呼び出すことができます。

public static ValidateLoginResult validateLogin(HttpServletRequest request, String email, String password) {

問題は、結果が単一の値ではなく、結果が以下で構成されることです。

boolean ok
String errorMessage
boolean displayCaptcha

このために、新しいクラスを作成しました。これはすべて正常に動作します。

しかし、複数の値を返す便利なユーティリティ関数がよくあり、毎回結果の新しいクラスを作成するのは少し面倒です。

複数の値を返すより良い方法はありますか?それとも私は怠け者ですか? :)

29
TinusSky

いいえ、この種の構造はJavaには素朴に存在しませんが、 JavaTuplesライブラリ を見ることができます。を使って Triplet<Boolean, String, Boolean>

16
gma

「ベストプラクティス」についてはわかりませんが、実用的なオプションはMap<String, String>を返すことです。例えば。

myMap.put("result", "success");
myMap.put("usernameConfirmed", "bigTom");

return myMap;

おそらく100万のOO原則に直面して飛びますが、結果クラスの急増を避けたいと聞きます。

または、Map<String, Object>を使用して、文字列、ブール値、日付などの保存オブジェクトの型チェックをより厳密にすることもできます。

5
Brian

Pair<A, B>クラスとTriplet<A, B, C>クラスを定義できます。これにより、タイプセーフを確保しながら2と3の値を返す問題を解決できます。この特定の場合、署名は

public static boolean validateLogin(HttpServletRequest request,
            String email, String password, Pair<Message, Boolean> outputIfOk);

または、さらに良いことに、サーブレットのコンテキストでは、十分に文書化された要求属性を設定することが理にかなっている場合があります。

結果を非常に頻繁に返すために特別なクラスが必要な場合は、それらのクラスをリファクタリングして、共通の祖先を共有することができます(たとえば、 'ok'および 'message'フィールドを含むRequestStatusがあります)。

それ以外に、はい、あなたは怠け者です-カスタムクラスは常にペアとトリプレットよりも自己文書化されます。

5
tucuxi

クラスにカプセル化するよりも、関数から複数の値を返すより良い、よりクリーンで、よりオブジェクト指向の方法を本当に考えることはできません。

理想的には、返す複数の値は概念的にはすべて同じクラスの一部であるため、このようにグループ化することは理にかなっています。そうでない場合は、関数自体の外部で必要な値のそれぞれを返すいくつかの小さな関数で関数を分解する必要があります。

私の知る限り、いくつかのIDEには、クラスに複数の値をカプセル化するのに役立つ機能もあります。たとえば、EclipseにはRefactor --> Extract class...

4
Raibaz

Object []配列を返すことができます。Javaオートボックスを使用すると、より使いやすくなります。短距離のハンドオーバーの場合は、そうではありません。

しかし、その作成と使用は簡単です。

再び、静的な内部クラスがすばやく作成され、それを返すメソッドのすぐ隣に置くと、それを見つける場所(通常はOriginの近く)もわかります。

1
NikkyD

私はおそらく自分でクラスルートに行きますが、関数に返すものに応じて、値のコンテナのようなものを返すことで逃げることができるかもしれません。

0
DannyMac92