セキュリティ制限により、サービスがnullを返すか、例外をスローする必要がありますか?[閉まっている]


11

私はこの問題に関して、より経験豊富な開発者と少し意見の相違があり、他の人がそれについてどう思うか疑問に思っています。私たちの環境は、Java、EJB 3、サービスなどです。

私が書いたコードは、物を取得して物を作成するサービスを呼び出します。私が遭遇した問題は、意味をなさないヌルポインタ例外を受け取ったことです。たとえば、サービスにオブジェクトの作成を依頼すると、nullが返されます。既知の有効なIDを持つオブジェクトを検索しようとすると、nullが返されます。私は自分のコードで何が間違っていたのかを理解しようといくつかの時間を費やしました。私は経験が少ないので、私は通常、何か間違ったことをしたと思いますが、nullリターンの理由はセキュリティであることがわかります。私のサービスを使用しているユーザープリンシパルがターゲットサービスに対する適切なアクセス許可を持っていなかった場合、単にnullを返します。ここにある他のほとんどのサービスもあまり文書化されていないので、明らかにこれはあなたが知っておくべきことです。

これは、サービスと対話するコードを作成する開発者としてはかなり混乱します。サービスに例外があり、ユーザーにこの物をロードしたり、物を作成したりするための適切なアクセス許可がないことを教えてくれるなら、それは私にとってはるかに理にかなっています。そうすると、サービスが期待どおりに機能しなかった理由がすぐにわかります。

サービスを書いた経験豊富な開発者は、データの要求はエラー状態ではなく、例外はエラー状態でのみスローされるべきであり、ユーザーがデータにアクセスできないときではないと主張しました。このデータは多くの場合GUIで検索され、適切な権限のないユーザーの場合、これらは単に「存在しません」。要するに、質問は間違っていないため、例外ではありません。これらのユーザーには「存在しない」ものがあるため、getメソッドはnullを返します。ユーザーがそのモノを作成することを許可されなかった場合、Createメソッドはnullを返します。

これは正常なものですか?何が起こっているのかを知るのがずっと簡単だと思うので、例外を使うことを好みます。そのため、たとえば、nullを返すのではなく、無効なIDを持つオブジェクトを要求した場合にNotFoundExceptionをスローすることも好みます。



@ChrisF:1)null参照を避けている人々についてですが、私はそうではありません。多くの場合、それらは適切であり、私は彼らがこの1つにいるとは思わない。2)パラメータをチェックすることについてであり、例外をスローするのと同じように結果の種類をアサートしませんか?3)例外とエラーコードは、問題の原因を「表示」する両方の方法であるため、別の問題でもあります。たとえば、例外をサポートしていないシステムに通知する必要がある場合や、エンドユーザーにコード以外のものを見せたくない場合は、エラーコードが適切です。
Svish

ここで私が尋ねる問題は、「何かが存在しない、または発生しなかったふりをする」対「何かが存在しない、または発生しなかった理由を伝える」ことです。
Svish

3
私はそれらが重複していることを示唆しませんでした-彼らはあなたのために有用な情報を持っているかもしれません。
ChrisF

確かに、それについてすみません!なんらかの理由で「重複の可能性がある」コメントとしてそれを取りました...おそらく睡眠不足のためです。
Svish

回答:


20

例外は、エラーが発生した場合にのみスローされるべきであり、何かを求めることはエラーではありません。

何かを求めることはエラーではないかもしれませんが、あなたが要求したものへのアクセス権を持っていないことは確かにある種のエラーです。例外は、特別な戻り値の代わりに使用される例外条件を報告する別の方法です(null記述したように、物事がうまくいかない理由が1つ以上ある場合、これはまったく役に立ちません)ちょうど1つの考えられる理由、次のバージョンでは2つの考えられる理由がある可能性があるためnull、戻り値として失敗を示す値を使用すると、自分自身を隅に追いやることになります)。サービスが、あなたが要求したことをしない理由を何らかの形で報告しない場合、それは間違いなく悪い設計です。

特別な戻り値を使用するかどうか(負の整数は、通常、負でない整数を返す関数に便利です)、例外、グローバルエラーハンドラ、またはロガーなどは、最終的に実装の詳細です。選択は言語、状況、慣習に依存し、好みの問題でもあります。主なポイントはそこにあるべきであるということであるいくつか見つけるの直接的な方法なぜ何かが動作しません。それ以外の場合、唯一のオプションは、さまざまなオプションや、ブラックボックスの動作と相関するものを見つけるために何でも探し回ることであり、時間の無駄です。

String.substring()IndexOutOfBoundsExceptionインデックスが範囲外の場合にスローします。null-哲学的に-がStringその境界の外側に何も含まないのでnull、論理的な戻り値になると主張することができますが、代わりに返すことの利点を考えることはできません。論理哲学的であることと実用的であることは、明らかに2つの異なる動物です。


substring()が範囲外のインデックスの値を返す場合、インデックス間の文字列の一部(空の場合もある)を返す必要があります。これにより、いくつかの呼び出しコードでテストを保存できます。
ケビンクライン

2
はい、終わりのない「空の値」とnullの議論があります。バインドされていないインデックスのサブストリングはnullですか、それとも空のストリングですか。私は知りません、両方とも事実上「何もない」(まあ、nullは空の文字列よりも「何もない」のでしょうか?)が、どちらも例外が行う情報量を与えません。
ジョナスプラッカ

@kevincline:null参照が空の文字列を示す慣用的な手段であるフレームワークを使用していない限り、null参照substringを返すための根拠はありません。私見では、2つの別個の関数が必要です。1つは、要求された文字数を返すか例外をスローすることを約束し、1つはできるだけ多くを返します。コンテキストによっては、各メソッドは他のメソッドよりもかなり優れています。
-supercat

@supercat:nullを返すことについては何も言わなかった。私は「戻る...部品...おそらく空っぽ」と言った。Oracleを除き、空の文字列はnullではありません。
ケビンクライン

@JoonasPulakka:前回のコメントにあなたにpingを送信する必要がありました。
-supercat

5

それは契約とは何かに帰着します。存在しないものを要求できると契約が言っている場合は、何が起こるか(nullまたはnullオブジェクト)を伝える必要があります。

一方、コントラクトで別のメソッドを最初に呼び出して(DoesSomethingExist())、次にメソッドを呼び出す必要Getがあると言っている場合、コントラクトは存在するものだけを取得できると言い、そうでない場合は例外をスローします。例外メッセージは、「必ずDoesSomethingExist()最初に呼び出してください」などのようなもので、有用なエラーメッセージです。


この場合、おそらく存在しないidを要求しないので、存在しない何かを要求するのは普通ではないと言うでしょう。通常、最初に物事のリストを取得してから、それらの特定のものを検索して詳細を確認します。findAllThingsメソッドがある場合、表示が許可されていないものまたはすべてのものがある場合は、空のリストまたはサブセットを返すのが適切だと思います。同じように、ブログでは、現在のユーザーに属する編集用の投稿のみをリストします。しかし...そのユーザーがURLおよび編集異なるポストを微調整しようとした場合
Svish

4

質問に対する単一の万能の答えはありません。例外を使用するか、nullを返すかは、状況によって異なります。

これを純粋に独断的な観点から見る代わりに、インターフェースをユーザーインターフェースとして見てください。ユーザーインターフェースは使用可能であるべきです。したがって、何かを行う「正しい」方法についてのあなた自身の意見に関係なく、あなたのインターフェースを使用している誰かの観点から最も使いやすい方法を選んでください。

呼び出し元がオブジェクトが返されない理由を知る必要がある場合、例外が適切です。ただし、一般的な概念が「許可がない場合は存在しない」場合、nullは許容されます。

具体的には、呼び出し元がサーバーへのログインまたはサーバーへの接続を最初に必要とする場合、nullはアイテムの検索に完全に許容されると思います。それはあなたが許可を持っているか持っていないことを告げられる時です。ゲートを通過すると、表示する権限がない(または存在することさえ知っている)ものを検索するときに、nullを取得するのが合理的です。

一方、初期接続またはログイン手順がない場合は、例外が理にかなっています。呼び出し元がアイテムが存在することを知っていて、それを取得できない場合、nullを返すだけではAPIは役に立ちません。

ただし、アイテムを作成する場合、それは別の話です。おそらく、失敗する多くの理由がある可能性があります-許可なし、不適切なパラメーター、サーバーのメモリー不足など。 。

したがって、質問に答えるには、サービスを使用している人の観点から最も有用なソリューションは何かを自問してください。それはあなたがそれを使用している方法が非定型であるかもしれません、そして最も一般的なケースのために、nullは正しい答えです。

ですから、これをめぐって宗教戦争に巻き込まれないで、この特定の問題に何が正しいかを決めてください。


これをめぐって戦闘用具を装着するつもりはない、へへ。自分が何を考えていたのか、まったく考えていなかったのかを知りたいだけでした。学びたいのですが、一人がそう言うからといって、何かにジャンプするのは好きではありません。特に、それが自分の経験や論理に反する場合(どんなに小さくても)。とにかく、もしこれがエンドユーザーインターフェースなら、それは本当に理にかなっているかもしれないことに完全に同意します。これは、私の知る限り、唯一のコードによってアクセスできるBeanですので、私は、開発者として、と言うでしょうであるユーザー。
Svish

1
そして、開発者として、エンドユーザーがそれについて知っておくべきことに関わらず、何かが間違っている理由を気にします。
Svish

ブライアンに完全に同意します。開発者でさえ、ユーザーです。つまり、他の開発者コードをいくつか消費しています。throwまたはnullの判定は、特定のタスクに役立つインターフェース/ GUIの一種です。論理または哲学の一般的な用語だけではありません。
独立

3

私は間違いなくそれが悪いデザインだと思います。ヌルポインターは私にとって有効な答えではなく、管理が難しい場合があります。

ユーザーが適切な資格情報なしでサービスに接続しようとする場合、明確で簡潔な回答で返信する必要があります。答えは、例外または特別なオブジェクトですが、nullではありません。

ネットワークリンクが壊れているか、その他の予期しない重大な誤動作が発生した場合は、null回答のままにしてください。

さらに、ヌルを取得した理由を理解するのに費やす時間は、強力な議論です。どのコードも理解しやすく使いやすいものでなければなりません。null値を持つことは当てはまりません。


あなたの最後の文で、「ネットワークリンクが壊れているときなどにだけnullを返すべきだ」などと言いますか?または「ネットワークリンクが壊れた場合などにnullを返すのをやめる必要があります」?
ペテル

@PéterTörök:「return null;」を明示的に使用することはお勧めしません。ただし、大規模な故障が発生した場合、一部のサービスがnullを返すことは許容されます。
アミン

予期しない重大な誤動作が発生した場合、例外の方が適切ではありませんか?
Svish

2
@Amine:それは、nullを返すのに最も適切ではないケースだと思います。
マイケルボルグワード

@Svish:主要な内訳を検出できれば、もちろん例外も素晴らしいでしょう。
アミン

3

優れたソフトウェア設計を念頭に置いて、プロジェクトの寿命について考える必要があります。前述のように、を
返すことによりnull、クライアントに情報を提供しません。あなたに何が起こったのかを見てください。最初は、問題がどこにあるのか理解できませんでした。さらに、ドキュメントが提供されていない場合、これは混乱です。

例外をスローすることで、何がうまくいかなかったかを知ることができます。必要に応じて、表示されるテキストをより具体的にカスタマイズすることもできます。

一方、返品nullすることで、クライアントに何が起こっているのかを調査させます。

さらに、他の場所にアクセスしたため問題が発生したことに気づきましたNullPointerException。ここで、その関数の戻り値を保存しないと想像してください...その関数への各呼び出しをif elseブロックで囲む必要があります...

私の観点から、帰国nullは悪い習慣です。


2

サービスを書いた経験豊富な開発者は、データの要求はエラー状態ではなく、例外はエラー状態でのみスローされるべきであり、ユーザーがデータにアクセスできないときではないと主張しました。

私の観点からは、これは意味がありません。

許可なくデータを照会することはすべきことがあるので、例外が発生し、予期せぬ全く結果を得るていないために- -適切なアクセスせずに結果。

類推許可なしの応答コードGET200 okデータなしではなく、実際に401 Unauthorizedです。


1

nullを返すのは良くありません。何も教えてくれません。あなたの例を挙げると、アプリが何かを調べようとしていて、セキュリティの問題に対する応答がnullであり、アイテムが存在しない場合、2つの違いをどのように見分けますか?

意味のある応答により、アプリケーションは次に何をすべきか、または問題を解決する方法について論理的な選択を行うことができます。


そこにないオブジェクトと、それを見るための許可が与えられていないオブジェクトとの違いをどのように伝えるかを尋ねます。たぶん、システムの設計にはあなたが知らないことが必要だ。この特定の場合に答えるのに十分な情報はないと思います。すべての場合に有効な答えはありません。あなたがそれを見ることができない場合、事実上そこにない完全に有効なユースケースがあります。そして、もしあなたがそれを見ることができないならば、あなたがあなたができない理由を言うために例外を与えられるべきであるユースケースがあります。
ブライアンオークリー

「システムの設計には、知らないことが必要です」とはどういう意味ですか?それはどんなデザインでしょうか?
Svish

2
セキュリティポリシーで表示が許可されていないと表示されている場合、ほとんどの場合、セキュリティポリシーが存在することを知ることはできません。これにより、「見つかりません」を返すことが完全に受け入れられます。
Blrfl

1

根本的な原因が認証されていないユーザーである場合、おそらくpretty-message-pageへのリダイレクト(および気になる人への通知)を伴うハードHTTP 401応答を好みます。認可関連の原因は、ケースバイケースです。HTTPエラー(403など)を返すための引数と、サービス応答で特別な整形式のコード/メッセージを返すための引数があります。

例外は例外的な状況でのみ使用されるべきであり、何かが間違っていることを意味します。「許可されない」ことを意味するためにオーバーロードする必要があることに同意しません。(nullの戻り値についても同じことが言えます。「許可されていない」という意味で使用することに同意しません。)


さて、GUIではこれを行うことができますが、舞台裏で処理を行うサービスを実装するBeanについては、例外と特別な戻り値のみを自由に使用できます。もちろん、ユーザーが例外を取得する必要があるわけではありませんが、たとえば、例外をWebサービス/サーブレット/何でもキャッチして、適切なことを行うことができます。どこかに、ハードなhttp 4xxページ、または他の何かにリダイレクトします。
Svish

良い点ですが、AOPのようなパラダイムを使用してこれらのケースをキャプチャできます。アスペクトは、与えられた操作を呼び出す特権をテストし、必要に応じて処理をリダイレクト/許可することができます。
マーク

0

悪魔の擁護者を演じるために、私はヌルを返すという側面をとろうとします。

私の意見では、この種の対応がほぼ受け入れられる状況は1つだけであり、この場合のように、セキュリティが関係している場合です。

許可されていない人が知る必要のないシステムの詳細を誤って漏らすことは非常に簡単です。これは避けるべきです。

たとえば、ユーザー名とパスワードチェッカーを考えてみましょう。「ユーザー名が見つかりません」エラーと「間違ったパスワード」エラーを個別のエラーコードとして返すと、誰かが最初に有効なユーザー名を探してからパスワードを探す可能性があるため、深刻なセキュリティ上の問題が明らかになります。一般的な「無効なユーザー名/パスワード」を返す方が良いオプションです。

したがって、この特定の場合、私はそれが戻ることはほとんど大丈夫であると言うでしょうnullが、私は同意する、それは一緒に働くことは非常に不愉快であろう。


ええ、私は同意しません。私の意見では、適切な応答は例外ですが、ユーザー名が見つからない場合とパスワードが間違っている場合でも同じです。FailedToLogin、InvalidCredentials、何でも。
Svish

@Svish-しかし、失敗の理由についてまったくヒントを与えようとしない場合、返されるのはまったく役に立たないnull応答です。システムに関する何かを発見するために、他のほとんどすべてのものが潜在的に使用できます。OPが不満を述べた理由は、nullリターンが何も説明しなかっただけでなく、役に立たなかったからです。それは意図的な目的です...絶対に何も言わず役に立たないことです。私の考えではミッションは達成されました。
OldCurmudgeon

まあ、それはそうかもしれませんが、私はそれをすることはまだ悪いと言います。少なくともシステム内。エンドユーザーが物事を見る端で、確かに、私は同意するかもしれません。しかし、システム内では、開発者がユーザーであり、なぜ世界で私たち自身をもっと混乱させたいのでしょうか?ソフトウェアを開発することは難しい既に十分...ではないかのように
Svish

1
そして、ログインの例で、私は、少なくとも言うのではないとユーザーエクスペリエンスのためにそれの悪いと言うだろう何か、何も彼らは(彼らを考えた)ときの状況に見えたん理由については、資格情報を入力します。ページが更新され、ログインの試みが無視されたように見える場合は、入力した内容が間違っていたのではなく、システムに何らかの問題があると想定します。
Svish

-2

クライアントがこのメソッドを呼び出してnullを返すと、nullを返すのはフレンドリーではないと思います、クライアントは何が起こったのか、なぜnullを返したのかわかりません。そのため、意味のある実行をスローし、この実行を説明するドキュメントを提供する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.