タスクを実行し、ステータスとしてブール値を返すメソッドの名前を付ける方法は?


33

方法がある場合

bool DoStuff() {
    try {
        // doing stuff...
        return true;
    }
    catch (SomeSpecificException ex) {
        return false;
    }
}

むしろ呼ばれるべきIsStuffDone()ですか?

ユーザーは両方の名前を誤って解釈する可能性があります。名前がDoStuff()理由である場合、ブール値を返しますか?名前がIsStuffDone()メソッドの場合、メソッドがタスクを実行するのか、結果のみをチェックするのかは明確ではありません。

この場合の規則はありますか?または、これは欠陥と見なされるため、代替アプローチですか?たとえば、C#などの出力パラメーターを持つ言語では、ブールステータス変数を1つとしてメソッドに渡すことができ、メソッドの戻り値の型はになりますvoid

編集:私の特定の問題では、メソッドはインターフェイス実装の一部であるため、例外処理を呼び出し元に直接委任することはできません。したがって、呼び出し側は、異なる実装のすべての例外を処理することはできません。これらの例外に精通していません。ただし、呼び出し元はStuffHasNotBeenDoneForSomeReasonExceptionnpintiのanswerおよびcommentで提案されたようなカスタム例外を処理できます。


2
これは、関数の使用法と実行されている内容に依存します。必要な場合、スタッフを正しく実行する必要がある場合、関数のユーザーがブール値フラグを逃し、例外によって提供される情報が不足する可能性があるため、このアプローチに欠陥があると考えます。
ベニ14年

7
ほとんどのboolean場合、例外をラップまたは渡す代わりにを返すことはほとんど常に間違っているため、「壊れた」と呼びます。
maaartinus

2
この種の例外ハンドラは、めったに良いアイデアではありません。すべてではなく、あなたが期待している特定の例外のみをキャッチします。そして可能であれば、そもそも投げるのを避け、キャッチする必要をなくします。
CodesInChaos 14年

2
うーん... BadlyDesignedMethodInSeriousNeedOfRefactoring?そして例外に関するあなたの質問に答えるために-呼び出し元にそれらを処理させるか、それらをキャッチしてから「このメソッドは仕事をしません」という意味のカスタム例外をスローします。共有してお楽しみください。
ボブジャービス-モニカの復職14年

5
例外を投げる(または渡す)だけで、このコードがどのように使用されているかについて根拠のない仮定を立てています。考えられるシナリオの1つは、増加するコストで問題のさらに大きなサブクラスを解決するさまざまなヒューリスティックな解決方法により、解決すべき問題があることです。のようなものを書くことは理にかなっていますif (FirstMethodSucceeds(problem) or SecondMethodSucceeds(problem) or ...) Hurray(); else UniversalSolve(problem);。(カスタム?)例外で同じことを行うと、無駄に複雑になります。
マークヴァンレーウェン

回答:


68

.NETでは、一方のメソッドが例外をスローする可能性のあるペア(DoStuff)があり、もう一方はブールステータスを返し、実行が成功するとoutパラメーターを介して実際の結果を返します(TryDoStuff)。

(Microsoftはこれを「Try-Parseパターン」と呼んでいます。おそらく最も顕著な例は、TryParseさまざまなプリミティブ型のメソッドだからです。)

Tryあなたの言語で接頭辞が一般的でない場合、おそらくそれを使用すべきではありません。


3
+1これは、この種のことを他の場所で見たことです。if (TryDoStuff()) print("Did stuff"); else print("Could not do stuff");私の意見では、かなり標準的で直感的なイディオムです。
カールニコル

12
TryDoStuffメソッドは、正常に失敗し、falseを返したときに副作用がないと想定されていることに注意してください。
トリリアン14年

参考までにRemove、たとえば.NETフレームワークには、データ構造(たとえばDictionary)から要素を削除し、bool。APIのコンシューマーは、APIを使用するか無視するかを決定できます。ただし、エラーは例外として報告されます。
オメルイクバル14年

18

呼び出し元のコードに例外を単に投げた場合はどうなりますか?

これにより、コードの使用者に例外処理を委任することになります。将来、次のことをしたい場合:

  • 例外がスローされない場合、アクションAを実行します
  • (たとえば)a FileNotFoundExceptionがスローされた場合、アクションBを実行します
  • 他の例外がスローされた場合、アクションCを実行します

例外をスローバックすると、上記の変更は単純に余分なcatchブロックの追加を必要とします。そのままにしておくと、メソッドとメソッドが呼び出される場所を変更する必要があります。プロジェクトの複雑さに応じて、複数の場所に配置することができます。


1
例外が委任できない種類のものであり、内部で処理する必要がある場合はどうなりますか?
リンボ亡命14年

2
@LimboExile:内部でそれを処理し、それから別の例外、おそらくあなた自身の例外を投げることができると思います。これは、起こるべきではないことが起こったことを示していますが、同時に、実際に何が起こっているのかを明らかにしなかったため、内部的に例外に対処したいと考えています。
npinti 14年

6
例外をスローすることは例外的なケースであるべきであることを心に留めておく価値があるでしょう。DoStuff失敗することが一般的または正常である場合、失敗の場合に例外をスローすることは、悪いことでプログラムフローを制御することに似ています。また、例外には固有のパフォーマンスコストがあります。場合はDoStuff失敗がエラーに珍しいケースでは、例外は間違い@npintiが示唆するように移動するための方法です。
カールニコル

1
@KarlNicoll何かが「例外的」であるかどうかは完全に主観的です。主な基準は、誰もエラーについて何もしなかった場合にプログラムをクラッシュさせるかどうか、およびエラーの可能性を関数のタイプに含めるかどうかです。さらに、例外が高価であることは事実ではありません。それは言語と投げ方によって異なります。例外はPythonでは安価であり、スタックトレース情報を取り除くと、Javaでも安価になる可能性があります。パフォーマンスコストが発生した場合でも、プロファイルを作成するまで心配するのは時期尚早の最適化です。
ドーバル14年

1
@Doval-私はそれが主観的であることに同意します。それがOPがnpintiの答えを完全に無視すべきではない理由です。私のポイントは、例外をスローすることが常に最善の方法とは限らないということでした。失敗が例外のスローとアプリケーションのクラッシュを正当化しない多くのケースがあります。たとえばDoStuff()、内部コードが例外をスローした後にOPのメソッドがクリーンアップされ、メソッドの事後条件がまだ正しい場合、エラーが処理されたため、リターンコードの方が適切なオプションである可能性があります。
カールニコル14年

7

DoStuff() 十分であり、関数の戻り値を文書化する必要があります。関数名でそれを言及する必要はなく、利用可能な多くのAPIを探します。

PHP

// this method update and return the number affected rows 
// called update instead of updateAndGetAffectedCount
$affected = $query->update(/* values */);

Cシャープ

// Remove item from the List
// returns true if item is successfully removed; otherwise, false.
public bool Remove( T item )

6

Javaでは、コレクションAPIはブール値を返すaddメソッドを定義します。基本的に、追加によってコレクションが変更されたかどうかを返します。そのため、List通常はアイテムが追加されたのでtrueを返しますが、Setアイテムが既に存在する場合はfalseを返す可能性がありSetます。

つまり、コレクションで許可されていないアイテム、たとえばnull値を追加すると、追加はNullPointerExceptionfalseを返すのではなくをスローします。

同じロジックをケースに適用する場合、なぜブール値を返す必要があるのですか?例外を非表示にする場合は、しないでください。例外をスローするだけです。そうすれば、何がうまくいかなかったかを確認できます。ブール値が必要な場合は、例外以外の何らかの理由で実行されていない可能性があるためDoStuff()、動作を表すため、method に名前を付けます。それは何かをします。


1

さまざまな理由、例外、通常の状態で失敗する可能性があるため、これを使用します。

boolean doStuff() - returns true when successful

重要なのは、ブール値の意味を文書化することです。


1

私は通常、メソッドがOperationResult(またはOperationResult<T>)を返しIsSuccessOperationResult適切にプロパティを設定します。「通常の」メソッドがvoidのOperationResult場合、return 、「通常の」メソッドがオブジェクトを返す場合OperationResult<T>ItemプロパティをOperationResult適切に返し、設定します。また、OperationResultなどのメソッドを持つことをお勧め.Failed(string reason).Succeeded(T item)ます。OperationResultシステムですぐに馴染みのあるタイプになり、開発者はその処理方法を知るようになります。


0

実際に使用している言語に依存します。一部の言語と同様に、多くの言語にはまったく存在しない、またはまったく存在しない規則とプロトコルがあります。

たとえば、Objective-C言語およびiOS / Mac OS X SDKのメソッド名は通常、次の行に沿っています。

- (returndatatype) viewDidLoad {
- (returndatatype) isVisible {
- (returndatatype) appendMessage:datatype variablename with:datatype variablename {

ご覧のとおり、viewDidLoadと呼ばれるメソッドがあります。独自のアプリケーションを作成するときは常に、このタイプの命名を使用することを好みます。これは、あなたが言ったように何かが起こることになっているかどうかをチェックするために使用できます。メソッドに名前を付けることについて深く考えすぎていると思います。ほとんどのメソッドは、それが何であれ、それが何をしているかのステータスを返します。例を挙げましょう:

PHPでは、接続が失敗するとmysql_connect()はfalseを返します。それはそうだとは言わないが、それはそうであり、ドキュメンテーションはそれがそうだと言っているので、プログラマーに誤解されることはない。


ああ、しかしviewDidLoadはコールバック通知のようなものです。ユーザーはビューをロードするためにそれを呼び出しません。むしろ、ビューがロードされた後に呼び出されます。同様に、isVisibleは可視性を設定せず、現在の値を返すだけです。何もしませ
リルビーディ

0

「Try」プレフィックスを使用することをお勧めします。これは、メソッドが成功するかどうかの状況でよく知られているパターンです。この命名パターンは、Microsoftによって.NET Framework で使用されています(TryParseIntなど)。

しかし、おそらくこれは命名に関するものではありません。メソッドの入力/出力パラメータをどのように設計するかについてです。

私の考えは、メソッドに戻り値がある場合、そのメソッドを呼び出す目的はその戻り値を取得することであるということです。そのため、操作のステータスを示すために戻り型を使用しないでください。

C#では、outパラメーターを使用することを好みます。outを使用して、パラメーターをサイドパラメーターとしてマークしています。特に、C#6はインライン変数宣言をサポートします。

DoStuff(out var isStuffDone); // The out parameter name clearly states its purpose.
DoStuff(out var _); // I use _ for naming parameters that I am ignoring.

0

メソッドの主要な役割に基づいて名前を選択します。実際、そのメソッドはブール値を返すため、「Is」プレフィックスは必須ではありません。「Is」プレフィックスを非常に広範囲に使用するJavaコードをいくつか見てみましょう。を見てくださいjava.io.File.delete()。戻りますがboolean、呼び出されませんisFileDeleted()。その理由は、metodの主な役割はファイルを削除することだからです。誰かがファイルを削除する目的でこのメソッドを呼び出します。

ブール値は、作業の結果を伝えるためだけにあります。一方、見てみましょうjava.util.Map.isEmpty()。明らかに、そのようなメソッドを呼び出して、コレクションが空かどうかを調べます。何かをしたくない。現在の状態が何なのかを知りたいだけです。

個人的に、私は間違いなく固執しDoStuff()ます。

これは私にとってやや重要な問題です。多くの場合、レガシーコードを管理するとき、個人的に「嘘をつく方法」と呼ぶものにつまずきます。名前はアクションAを示唆していますが、ボディはアクションBを行います。最も奇妙な例は、データベース内のデータを変更するゲッターメソッドです。

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