読みにくい try..catch..finally ブロックの書式設定?
-
06-09-2019 - |
質問
try..catch.finally ブロックをどのようにフォーマットしていますか?特に、少量のコードをラップするだけの場合は、すべてが台無しになり、コードがかなり読みにくく見苦しくなります。
のような:
try
{
MyService service = new Service();
service.DoSomething();
return something;
}
catch (Exception ex)
{
LogSomething();
return somethingElse;
}
finally
{
MarkAsComplete();
service.Dispose();
}
これら 7 行のコードは 16 行の混乱に変わりました。
try..catch..finally のフォーマットを改善するための提案はありますか?
解決
実は、これは私には非常によく読みます。あなたの実際のコードは次のようにたくさん見える場合、私は本当にそれを心配しないでしょう。何が起こっているのか非常に明確である。
あなたの実際のコードが複雑であれば、よく名前のメソッドにブロックを壊す検討します。
他のヒント
あなたは、明示的using
の代わりにDispose()
ブロックを使用することができ、そうしない確率はあなたのためにすることを行いusing
ブロック、それを配置する前にnullをチェックする必要があります。残念ながら、それがないの増加ネスト= /
try
{
using(MyService service = new MyService())
{
service.DoSomething();
return something;
}
}
catch (SpecificException ex)
{
LogSomething(ex);
return somethingElse;
}
finally
{
MarkAsComplete();
}
まあ、私はそれだけで罰金だと思います。これのいくつかは、彼の中括弧の配置の議論intot取得します。あなたがこれを行うことができます:
try {
//
} catch(Exception ex) {
//
} finally {
//
}
私はあなたがが持っているものを好みます。ただし、1つのだけのreturn文を持つようにあなたのコードを改訂検討する必要があります。私はそれが少し良くデザインです見つけます。
Iは、同じ行に括弧を使用してコードをフォーマット
try {
MyService service = new Service();
service.DoSomething();
return something;
} catch (Exception ex) {
LogSomething();
return somethingElse;
} finally {
MarkAsComplete();
service.Dispose();
}
私は、私はより多くのスペースが必要な場合は空白行を追加することを好みます。それはまた、コードの論理ブロック間のセパレータとして機能します。
あなたは、コンテナ(非常にスマート工場)とアドバイス(すべての厄介な詳細を処理するために)を考えるかもしれません。
Dear Mr. Container Sir,
Whenever I request from you an instance object of the interface ISomething,
please construct for me an instance of the concrete class SomethingImpl;
in addition, please see to it (however you do it) that, whenever I call a
method on this instance, it is wrapped within a complicated and messy try-
catch-finally which logs exceptions and mark calls as completed. That way,
all I have to do is write the business logic that goes into the SomethingImpl
and I don't have to worry about all the messy infrastuctural details.
Sincerely,
Mr. Agile.
あなたはとして、コード内で、これを見るかもしれません
//a class that knows how to take care of the messy infrastructure details
public class MyMessyInterceptor : IInterceptor {
public void Intercept(IInvocation invocation) {
//handle the messy details of continuing with the method-invocation,
//but within a try-catch-finally that includes exception handling and
//call logging.
}
}
//a function that will configure a container (very smart factory)
public IContainer CreateContainer() {
var builder = new ContainerBuilder();
//tell the container-builder about the interceptor
builder
.Register(c => new MyMessyInterceptor())
.Named("keep-my-code-clean")
;
//tell the container what to do when you ask it for a ISomething
builder
.Register<SomethingImpl>()
.As<ISomething>()
.InterceptedBy("keep-my-code-clean")
;
return builder.BuildContainer();
}
//some function out there in your code somewhere that needs to make a
//service call; there's hundreds of functions out there just like this
//in your code, and they all just got much simpler
public object GottaGoDoSomething() {
//find the container
var container = GetTheSingletonContainerObject();
//ask for an instance of ISomething - it knows to provide a
//SomethingImpl wrapped in an interceptor that takes care of all
//the logging and exception handling
var something = container.resolve<ISomething>();
//call the big method
return something.DoSomething();
//magically (not really), the exception handling and logging are
//already taken care of
}
インターセプタクラスを考え出すことは一度だけ発生します。各インターセプタとサービスクラスを登録することも、一度だけ発生します。コンテナ(非常にスマート工場)を設定すると、確かに複雑です。
ただし、サービスオブジェクトを使用する必要があり、そのような例外処理やロギングなど、複雑で厄介なインフラストラクチャの詳細内にその利用を埋め込むために持っているあなたのコード内のすべての場所は、ちょうど非常にきれいで、非常にシンプルです。一つだけCreateContainer
がありますが、GottaGoDoSomething
sの何百もありますので、それは複雑なの少しのコストで簡単に全体の多くのです。
(注意:コード例はAutofacコンテナフレームワークと城インターセプタフレームワークを使用して私は、これはサービス・ロケーション・パターンではなく、依存性注入パターンの例であるが、ポイントはインターセプタを説明するためであったとすることを認識しています。依存性注入を説明するのではなく、コンテナでそれらを登録する。)
空白。最低限として、私はいつも「ものをやって」と、コードのセクションを「変数の作成」の間のすべてのreturn文の前と中に空白の1行を置きます。
try
{
MyService service = new Service();
service.DoSomething();
return something;
}
catch (Exception ex)
{
LogSomething();
return somethingElse;
}
finally
{
MarkAsComplete();
service.Dispose();
}
はるかに優れています。
私はあなたの書式設定があまりにもよく読み込むと思います。私の提案は難catch
ステートメントを使用することです。あなたが実際に何かをキャッチする必要がある場合にのみ、それを使用しています。そうしないと、プログラムの他の部分は、例外を処理させることができます。全体のコンセプト「早期に失敗」ます。
try
{
//do something that may throw an exception.
}
finally
{
//handle clean up.
}
//let a method further down the stack handle the exception.
個人的に、私はそれは、コメントをする余地を与え、より良い私のロジックの流れを示しています...私のコードでは、前のスタイルに従う傾向がある。
... <私はそれの側をオンにワイドスクリーンを持っているので、空白はさまざまな列がうまく並べることができますし、私はそんなに画面不動産を持っているので、それは非常にあるようということを私を傷つけることはありません。 / P>
try { // getting a service
MyService service = new Service();
service.DoSomething();
return something;
}
catch (Exception ex) { // the fact that a service might be full/timedout
LogSomething();
return somethingElse;
}
finally { // remove any resources the service may still hold.
MarkAsComplete();
service.Dispose();
}
私も、あなたがもともと持っていたものなどがあります。 .csファイル内の物理回線はあなたに何も費用がかかりませんし、あなたの最終的な出力コードを変更しないでください。だから、あなたやあなたのチームのための最高の読みやすさを提供するために必要なすべてを使用します。
実際には、あなたが実際に16以上のラインを使用してみてください、あなたは自分のコメントや他の人を追加することで、ときにコードをここに表示されます。
追加することで
// a comment that says what's going on
頻繁に、あなたはより良いあなたが6ヶ月後にそれに戻って行くときに、このTry.Catchがやっていることになっているものを思い出すことができます。
私はいつも試してみて、私のtry catchブロックのすべてをリファクタリングして、独自の方法でそれらをカプセル化します。
これは、常にすべてのものを読みやすくているようだ、それに加えて、あなたの方法は一つだけを行うようにする優れたプログラミング手法です。オッズは、あなたが上とあなたのtry-catch-finallyステートメントの下のコードを持っている場合、あなたは複数の事をやっているということです。
本当に解消したいのであれば、 必須 しかし 醜い書式設定 (はい、同意します:p)
をやる アスペクト指向プログラミング, 、そして、あなたは試してみる...キャッチ...最終的にあなたのアセンブリに無料で埋め込まれ、例外が自動的にログに記録されます。
試す ポストシャープ または Spring.Net