メソッドに複数の出口点がある場合に、メソッドの戻り値をトレースする最良の方法を見つけようとしています。トレースを追加したいメソッドがたくさんあります。私が試したことを実行します。
最初に、次のような単一の出口点を持つように各メソッドをリファクタリングしてみました。
StatusCode CreateResource(string name, string type)
{
Trace.LogEvent("BEGIN CreateResource name=" + name + " type=" + type);
StatusCode status = StatusCode.Ok;
if (!IsValidResourceName(name))
status = StatusCode.InvalidName;
else
{
if (!IsValidResourceType(type))
status = StatusCode.InvalidType;
else
{
if (!SystemOnline())
status = StatusCode.SystemOffline;
//continues to nest with more conditions
}
}
Trace.LogEvent("END CreateResource result=" + status);
return status;
}
しかし、ネストされた if ステートメントは見苦しく、読みにくくなっています。私は初期の終了ポイントをガード ステートメントとして多用しており、それをすべてリファクタリングすると混乱が生じ、デ リファクタリングのように感じます。
私が試したもう1つのことは、戻り値をトレースする別のメソッドで各メソッドをラップすることでした:
StatusCode CreateResource(string name, string type)
{
Trace.LogEvent("BEGIN CreateResource name=" + name + " type=" + type);
StatusCode status = CreateResource_DONT_CALL_THIS_METHOD(name, type);
Trace.LogEvent("END CreateResource result=" + status);
return status;
}
StatusCode CreateResource_DONT_CALL_THIS_METHOD(string name, string type)
{
if (!IsValidResourceName(name))
return StatusCode.InvalidName;
if (!IsValidResourceType(type))
return StatusCode.InvalidType;
if (!SystemOnline())
return StatusCode.SystemOffline;
return StatusCode.Ok;
}
問題は、将来、他の開発者 (または私) がラップされたメソッドを呼び出してトレースをバイパスするのを防ぐ方法です。したがって、ラップされたメソッドのばかげた (そして矛盾する) 名前です。内部メソッドの匿名メソッドを定義して呼び出すこともできますが、これはプロジェクト全体で使用するには非常に厄介なパターンです。
私が見つけた最も堅実で読みやすい方法はこれでした。これは一種のOK IMOですが、このforステートメントの使用がコードレビューで飛ぶことになるとは思えません。
StatusCode CreateResource_Internal(string name, string type)
{
Trace.LogEvent("BEGIN CreateResource name=" + name + " type=" + type);
StatusCode status = StatusCode.Ok;
for (int i = 0; i < 1; i++)
{
if (!IsValidResourceName(name))
{
status = StatusCode.InvalidName;
break;
}
if (!IsValidResourceType(type))
{
status = StatusCode.InvalidType;
break;
}
if (!SystemOnline())
{
status = StatusCode.SystemOffline;
break;
}
}
Trace.LogEvent("END CreateResource result=" + status);
return status;
}
try finally ブロックを使用してバリエーションを試しました。
StatusCode CreateResource_Internal(string name, string type)
{
Trace.LogEvent("BEGIN CreateResource name=" + name + " type=" + type);
StatusCode status = StatusCode.Ok;
try
{
if (!IsValidResourceName(name))
{
status = StatusCode.InvalidName;
return status;
}
if (!IsValidResourceType(type))
{
status = StatusCode.InvalidType;
return status;
}
if (!SystemOnline())
{
status = StatusCode.SystemOffline;
return status;
}
}
finally
{
Trace.LogEvent("END CreateResource result=" + status);
}
return StatusCode.Ok;
}
ここでの欠点は、戻る前に 'status' 変数を設定するのを忘れる可能性があることです。その場合、トレースは実行されません。
私の質問は、これを行うためのベストプラクティスはありますか? 単一の出口点にリファクタリングする必要がありますか? ラップされたメソッドが他の場所から呼び出されるのを防ぐ方法はありますか? トレースをバイパスできるようにすることの危険性は、単一の出口点へのリファクタリングの乱雑さよりも悪いですか?
ps アスペクト指向プログラミングのような重いものは持ち込みたくありません。