なぜ使用の例外は明らかに「安全な」コードの取り扱い?

StackOverflow https://stackoverflow.com/questions/1894983

  •  19-09-2019
  •  | 
  •  

質問

、誰かがこのコードで例外を発生させることができるか、私を説明することがありますか?

function CreateBibleNames: TStrings;
begin
  Result := TStringList.Create;
  try
    Result.Add('Adam');
    Result.Add('Eva');
    Result.Add('Kain');
    Result.Add('Abel');
  except
    Result.Free;
    raise;
  end;      
end;
私は、Delphiを使用しているので、

私は、おそらく一度の例外処理を使用していました。私は上記のコードを結び付ける力プログラマによって書かれたことを考えると、私は例外が重複しているとは思いません。しかし、それでもまだ、この概念に例外処理を使用することは、私にとっては謎のまま。 (最後を除いてみずに)安全なコードのようです。私はそれが必要だ証明していなかった私の経験、にも関わらず、このようにそれを書くための良い理由は、おそらくそこにある理由です、このような何回も同様のコードスニペットを見てきています。

また、何かが失敗したときに、私は例外の説明を取得します....

ありがとう

役に立ちましたか?

解決

さて、そのコードは奇妙ですが、私は同意し、それがそのように書かれてしまった理由を私は全く理解しています。コードの基礎となる前提が間違っているので、しかし、それはそのように書かれていました。構築物は奇妙なようという事実は、「コードのにおい」であるべきであり、何かが可能な最善の方法を行って取得されない場合がありますことを教えなければならない。

まず、ここにあるなぜブロックを除き、試して...では珍しい構造。この関数はTStringListのが作成されますが、何かがそれを充填する過程で問題が発生した場合、その後に作成されたTStringListには、ヒープ上で「失われた」とメモリリークになるだろう。だから、元プログラマーは守勢だったと例外が発生した場合、TStringListには解放されるだろうし、その例外が再び上昇になるだろうことを確認しました。

今ここに「悪い前提」の部分です。機能はTStringsのインスタンスを返しています。これは、常にこのことについてに行くための最善の方法ではありません。そのようなオブジェクトのインスタンスを返すことは質問「私が作成したこの事を処分しようとしているの?」頼みます。呼び出し側に - - TStringsのインスタンスが割り当てられていることを忘れるためにそれは簡単かもしれない状況を作成します。

A「より良い練習は、」ここに関数がパラメータとしてTStringsのを取り、その後、既存のインスタンスに記入することです。この方法では、(呼び出し側)のインスタンスを所有しているので、その寿命を管理する必要があります誰かについては疑いがあります。

ですから、関数が手続きになり、次のようになります。

procedure CreateBibleNames(aStrings: TStrings);
begin
  if aStrings <> nil then
  begin
    aStrings .Add('Adam');
    aStrings .Add('Eva');
    aStrings .Add('Kain');
    aStrings .Add('Abel');
  end;      
end;

さて、これはオブジェクトのインスタンスを返すことは毎回悪いことであると言っているわけではない - それは、例えば、非常に便利なFactoryパターンの唯一の機能です。しかし、このような、より「一般的」な機能のために、上記のは、物事の「より良い」の方法です。

他のヒント

これは、関数から新たに建設されたオブジェクトを返すときにあると良い習慣です。文字列リストよりも複雑なシナリオでは、いくつかの不変のは、壊れたまたはその他の発生するエラー、ひいては例外かもしれないが、その場合には、あなたは戻り値は解放されたいです。これが発生する可能性があらゆる状況を調べるために持っているのではなく、それは良い練習が新たに構築されたオブジェクトを返すための単一のパターンを持っているし、どこでも、それに従うことが一般的です。

彼らは例外をスローするために起こる場合は、将来の変化を構築しているオブジェクトの実装は、あなたはまだ安全だ

そのように、ます。

私が見ることができる例外のための唯一の潜在的な理由がにOutOfMemory例外であり、このような場合には - 全てのベットはとにかくオフになっています。私の意見では、これは有効な概念の濫用の一例です。

クラッタを除く試しの

過度及び不当利用コードと読みすることがより困難になります。

私はいくつかの理由で、そのようにコードを記述します:

1)メモリの割り当てがどのように見えるか標準化することで、すべての行を読まなく、何かが欠けているかどうかを確認するために、ソースコードを検査することは容易です。ここで、あなただけの.Createを見て、その例外処理に気づく良いですが、あなたは除いて...しようとの間の部分を読む必要はありません。

2)あなたはメモリの割り当てをコーディング方法を標準化することで、あなたも、必要なときに、それを行うことを決して忘れない。

3)後で、ソースコードを変更するいくつかのコードを挿入し、.Addがどのように機能するかを変更するなど何か他のもの、とのTStringListを置き換えたい場合、それは、このコードを壊しません。

4)それはあなたがTStringList.Addは()より多くの価値を提供し、他の仕事のためにあなたの脳を軽減、例外をスローしない、またはかどうかについて考える必要がないことを意味します。

最も明らかな例外は、DelphiがOutOfMemoryExceptionのために使用するものは何でもなります。リストにカップルの文字列を追加するための十分なメモリがない場合は、リスト全体を解放し、例外を再スローます。

所定の名前のリストを作るために過度に防御的プログラミングのように思えること - 。あなたがメモリ不足であることに起因する一つの例外を取得する場合、一般的に、アプリケーション全体がまずいている。

TStringListのためのソース、または正式な文書がなければ、あなたは本当に知っていることはできません。ただ、例示的な目的のために、のは、TStringListには、メモリがきつくなったとき、それはあなたがあなたのディスクと同じ大きさのリストを管理することができ、ディスクにしてから、リストの一部をスワップを開始するように書かれていると仮定してみましょう。今、呼び出し側はまた、I / Oエラーの色域の影響を受けやすいです。ディスクスペースのうち、不良ブロックに遭遇、ネットワークタイムアウトなど

行き過ぎこのような例外を処理していますか?審判のコールシナリオに基づきます。我々は、彼らが何を考えてNASAのプログラマーを求めることができる。

コードのそのようなものは、古典的な「工場」のパターンです。その例は自明であり、それは極端なコーナーケースで例外を発生させる可能性があるため、例外処理を必要としない場合があります。 工場出荷時のコードははるかに複雑である場合でも、前の作成されたインスタンスを解放するために正しいの再調達インスタンスが作成された場合、例外はありませんでした前に、呼び出し側が知ることができないので、どんな遭遇し、例外を調達。任意の例外が返された場合、インスタンスが作成または解放されていなかったと仮定して、はるかに良いです。 工場が返されるインスタンスは、必ずしも同じでなくてもよい場合に有用である(すなわち、任意の階層のクラス)、そしてときにパラメータがインスタンスを作成するためには、発信者ではなく、工場出荷時に「unknonwn」です。このような場合には、発信者は、単に適切なパラメータを「埋め」することが、既に作成されたインスタンスを渡すことはできませんが、ちょうどインスタンス要求するようにしている - それは、発信者が作成したインスタンスの「所有者」になり明確にする必要があり、もちろんをます。

興味深い注意点として、ジャワの著者のいくつかは今間違いであることを事実上すべての場合に例外のキャッチを必要とする決定を検討します。ほとんどの例外は本当に殺されるプログラムにつながるためですので、あなたにも、ランタイムシステムは、プログラムを強制終了し、むしろ例外をキャッチして、プログラマを強制するよりも、スタックトレースを出力せていただく場合があります...よく、ちょうど何かを印刷して殺しますプログラム。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top