2

外部リソース (DB、Web サービス呼び出しなど) を使用する私のプロジェクトのすべてのメソッドは、ログを記録する必要があります。問題は、何らかの形で重複したコードが大量に発生することです。文は同じように見えますが、パラメーターが異なります (つまり、メソッド名)。

これは、コードをリファクタリングするための非常に良いポイントのようです。AOP ライブラリとは別に、少なくともマジック ストリングを回避し、使い捨てオブジェクトを記述して、次のように using ステートメント内にメソッド本体をラップする方法を考えていました。

public void LoggedMethod(int param)
{
    using (new AutoLog())
    {
        // do whatever needs to be done
    }
}

AutoLogのクラスは破棄可能で、インスタンス化と破棄の時点でログ呼び出しを書き込みます。これにはクラスを(悪用) 使用できる可能性が高いことはわかってStackTraceいますが、この特定のクラスは非常に遅いため、これによりメソッドが大幅に遅くなる可能性があります。

私のログエントリは次のようになります(もちろん、すべてにメソッド名が含まれています):

  • メソッド呼び出しの開始
  • メソッド呼び出しの終わり
  • (オプション) メソッドのパラメータ - もちろんシリアル化 (JSON?)
  • (オプション) 実行時間

質問

AutoLogできるだけ速く動作するようにクラスを実装するにはどうすればよいですか? メソッドのパラメーターも読み取ることができれば、さらに良いので、それらをシリアル化してログに記録することもできます。

4

1 に答える 1

1

外部リソース (DB、Web サービス呼び出しなど) を使用する私のプロジェクトのすべてのメソッドは、ログを記録する必要があります。

信じられません。ログが多すぎる可能性があります。

文は同じように見えますが、パラメーターが異なります (つまり、メソッド名)。

その場合、コードに一般的な抽象化が欠けている可能性があります。私の経験では、次のことを行う必要があります。

アーキテクチャに強く関連するコードの一般的な抽象化を持っています。

たとえば、コマンド ハンドラーに関するこの記事と、リポジトリとカスタム クエリに関するこの記事をご覧ください。どちらの記事も、アーキテクチャの概念に関する単一の汎用インターフェイスを定義しています。(私の回答の残りの部分を理解するには、少なくとも最初の記事を読む必要があります)。

汎用インターフェイスを使用すると、関連する一連の操作全体をデコレータで簡単にラップできます。たとえば、ユース ケースを実行するすべての操作をラップできる次のデコレータを考えてみましょう。

public class LoggingCommandHandlerDecorator<TCommand>
    : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> decoratee;
    private readonly ILogger logger;

    public LoggingCommandHandlerDecorator(
        ICommandHandler<TCommand> decoratee,
        ILogger logger)
    {
        this.decoratee = decoratee;
        this.logger = logger;
    }

    void ICommandHandler<TCommand>.Handle(TCommand command)
    {
        using (new AutoLog())
        {
            this.decoratee.Handle(command);
        }
    }
}

AutoLog クラスをできるだけ速く動作させるには、どのように実装すればよいですか?

ご存知のように、デコレータは単なる薄いラッパーであり、オーバーヘッドはほとんどありません。このアプローチにより、通常はすべてのメソッド引数が 1 つのオブジェクトにパックされます。TCommand全体を XML、JSON、またはより読みやすい形式に単純にシリアル化でき、このコードを 1 回記述するだけで済むため、これはロギングに非常に便利です。

これはジェネリック型であるため、パフォーマンスが心配なので、LoggingCommandHandlerDecorator<TCommand>その型に静的コンストラクターを追加し (静的コンストラクターは、そのインターフェイスのクローズされたジェネリック バージョンごとに 1 回実行されます)、コードをプリコンパイルして、効率的にそのコマンド メッセージをシリアル化します。それに匹敵するものは絶対にありません。AOP フレームワークでさえ、リフレクションを使用し、メソッドのパラメーターにアクセスするときにボックス化を使用して動的配列を構築します。

このようなデコレータを適用することについて、「貧弱な」ことは何もないことに注意してください。ただし、アーキテクチャがSOLIDの原則に従っていない場合にこれを試すと、すぐに問題が発生します。これらの原則は、柔軟で保守可能なソフトウェアを入手するための鍵です。

于 2013-04-03T14:28:06.880 に答える