データベースでデータの変更(挿入、更新、削除)を実行するいくつかのメソッドがあります。 [〜#〜] orm [〜#〜] これらのタイプのメソッドには、行に影響される戻り値のint値を使用しています。操作の成功/失敗の状態を示すために、「私のメソッド」に対して何を返す必要がありますか?
int
を返すコードについて考えてみます。
A.1
public int myLowerLevelMethod(int id) {
...
int affectedRows = myOrm.deleteById(id)
...
return affectedRows;
}
次に、使用法:
A.2
public void myOtherMethod() {
...
int affectedRows = myLowerLevelMethod(id)
if(affectedRows > 0) {
// Success
} else {
// Fail
}
}
ブール値を使用する場合と比較してください。
B.1
public boolean myLowerLevelMethod(int id) {
...
int affectedRows = myOrm.deleteById(id)
...
return affectedRows > 0;
}
次に、使用法:
B.2
public void myOtherMethod() {
...
boolean isSuccess = myLowerLevelMethod(id)
if(isSuccess) {
// Success
} else {
// Fail
}
}
どちらが良いですか(AまたはB)?またはそれぞれの長所/短所?
別のオプションは、基本タイプの代わりに結果オブジェクトを返すことです。例えば:
OperationResult deleteResult = myOrm.deleteById(id);
if (deleteResult.isSuccess()) {
// ....
}
これにより、何らかの理由で影響を受ける行の数を返す必要がある場合は、単純にOperationResultにメソッドを追加できます。
if (deleteResult.isSuccess()) {
System.out.println("rows deleted: " + deleteResult.rowsAffected() );
}
この設計により、既存のコードを変更せずに、システムを拡張して新しい機能(影響を受ける行について知っている)を含めることができます。
操作の進行状況に関する追加情報を提供するため、影響を受ける行の数を返す方が優れています。
操作中に変更があったかどうかを確認するためにこれを書かなければならないので、プログラマはあなたを責めません。
if(affectedRows > 0) {
// success
} else {
// fail
}
しかし、影響を受ける行の数を知る必要があり、その数を取得する方法がないことに気づくと、彼らはあなたを非難します。
ところで、「失敗」によって構文クエリエラーが発生した場合(影響を受ける行の数は明らかに0です)、例外をスローする方が適切です。
どれもお勧めしません。代わりに、成功した場合は何も返さず(void)、失敗した場合は例外をスローします。
これは、クラスの特定のメンバーをプライベートとして宣言することを選択したのとまったく同じ理由です。また、機能が使いやすくなります。より多くの運用コンテキストが常により良いことを意味するわけではありませんが、それは確かにより複雑であることを意味します。約束が少ないほど、抽象化が進むほど、クライアントは理解しやすくなり、実装方法を選択する自由が広がります。
問題は、成功/エラーをどのように示すかです。この場合、例外をスローして失敗を通知し、成功しても何も返さないことで十分です。ユーザーのニーズ以上のものを提供する必要があるのはなぜですか?
失敗/例外的な状況が発生する可能性があり、その場合はそれらに対処する必要があります。それを行うためにtry/catchを使用するか、戻りコードを調べるかは、スタイル/個人的な好みの問題です。 try/catchの背後にあるアイデアは、通常のフローを例外的なフローから分離し、例外を最も適切に処理できる層まで泡立たせることです。したがって、多くの人がすでに指摘したように、失敗が本当に例外的であるかどうかによって異なります。
「これよりいいの?」 2つの選択肢が同じことを行わない場合、これは有用な質問ではありません。
影響を受ける行数を知る必要がある場合は、mustバージョンAを使用します。必要がない場合は、バージョンBを使用できますが、コードが少ないという利点があります。両方のバージョンをオンラインフォーラムに投稿する手間がかかったため、作成の労力はすでになくなっています。
私のポイントは次のとおりです。どちらのソリューションの方が優れているかは、このアプリケーションに対する具体的な要件に完全に依存し、私たちよりはるかに優れた状況を知っていることです。業界全体で、安全に使用でき、ベストプラクティスはありませんが、それよりも優れた選択肢はありません一般的に;あなたはそれについて自分で考えなければなりません。そして、この決定のように簡単に修正できる決定のために、それほど多くの時間を費やす必要もありません。
保守可能なソフトウェア設計で最も重要な2つの原則は、[〜#〜] kiss [〜#〜]とです。 [〜#〜] yagni [〜#〜]。
すぐには必要のないロジックを今すぐに置くことは、ほとんど決して良い考えではありません。他の多くの人々の間で、Jeff Atwood(StackExchangeの共同創設者) これについて書いた 、そして私の経験では、彼とこれらの概念のその他の支持者は完全に正しいです。
プログラムに追加する複雑さには、コストがかかり、長期間にわたって支払われます。プログラムは読みにくくなり、変更が複雑になり、バグが侵入しやすくなります。「念のため」に何かを追加するという罠に陥らないでください。それは誤った安心感です。
初めてコードを正しく取得することはめったにありません。変更は避けられません。未知の将来の不測の事態を防御的に準備するために投機的ロジックを追加しても、将来があなたとは異なることが判明したときに、コードを実際にコードのリファクタリングから保護することはできません期待された。不必要な/偶発的なロジックを維持することは、欠けている機能を追加するために後でリファクタリングすることよりも、保守性の問題です。
したがって、今のところプログラムに必要なのは操作が成功したか失敗したかを知ることだけなので、提案されたソリューションB(単一のブール値を返す)が正しいアプローチです。要件が変更された場合は、後でいつでもリファクタリングできます。このソリューションは最も単純で、複雑度が最も低く(KISS)、必要なことだけを実行し、それ以上は実行しません(YAGNI)。