8

私が最初にオブジェクト指向プログラミングを学び始めて以来、私が苦労してきた問題があります: 「適切な」OOP コードでロガーを実装するにはどうすればよいでしょうか?

これは、コード内の他のすべてのオブジェクトがアクセスできるようにするメソッドを持つオブジェクトを意味します。このメソッドは、ログに使用するコンソール/ファイル/その他に出力します。したがって、このオブジェクトはロガー オブジェクトになります。

ロガー オブジェクトをグローバル変数として設定したくありません。なぜなら、グローバル変数は良くないからです。しかし、すべてのオブジェクトで呼び出すすべてのメソッドのパラメーターで logger オブジェクトを渡す必要もありません。

大学時代、このことを教授に持ち込んだとき、彼は実際には答えてくれませんでした。この機能を実装する可能性のあるパッケージ (Java など) が実際に存在することを認識しています。しかし、私が最終的に探しているのは、これを適切かつ OOP の方法で自分で実装する方法の知識です。

4

16 に答える 16

13

You do want to establish the logger as a global variable, because global variables are not bad. At least, they aren't inherently bad. A logger is a great example of the proper use of a globally accessible object. Read about the Singleton design pattern if you want more information.

于 2008-09-17T19:26:13.390 に答える
4

非常によく考えられた解決策がいくつかあります。OO をバイパスし、別のメカニズム (AOP) を使用するものもあります。

ロギングは、実際には OO にはあまり適していません (これは問題ありませんが、すべてがそうであるわけではありません)。自分で実装する必要がある場合は、各クラスの先頭で「ログ」をインスタンス化することをお勧めします。

プライベート最終ログ=新しいログ(これ);

すべてのロギング呼び出しは簡単です: log.print("Hey");

これにより、シングルトンよりもはるかに使いやすくなります。

ロガーに渡したクラスを認識させ、それを使用してログに注釈を付けます。log のインスタンスがあるため、次のようなことができます。

log.addTag("ビル");

また、ログは各エントリにタグ ビルを追加できるため、表示のフィルタリングを改善できます。

ただし、log4j とチェーンソーは、すぐに使える完璧なソリューションです。単に学術的ではない場合は、それらを使用してください。

于 2008-09-17T19:30:06.190 に答える
2

グローバルにアクセス可能なロガーは、テストが面倒です。「集中型」ロギング機能が必要な場合は、プログラムの起動時に作成し、ロギングが必要なクラス/メソッドに挿入します。次のようなものを使用するメソッドをどのようにテストしますか。

public class MyLogger 
{
    public static void Log(String Message) {}
}

どのようにモックに置き換えますか?

より良い:

public interface ILog 
{
    void Log(String message);
}

public class MyLog : ILog 
{
    public void Log(String message) {}
}
于 2008-10-26T22:58:06.563 に答える
1

私は常にシングルトン パターンを使用してログ オブジェクトを実装してきました。

于 2008-09-17T19:25:38.900 に答える
0

おそらく、透過的な方法でロギングを挿入することは、アスペクト指向プログラミングのイディオムに属するでしょう。しかし、ここではオブジェクト指向デザインについて話しています...

私の意見では、シングルトンパターンが最も役立つ可能性があります。LoggingServiceクラスのパブリックな静的メソッドを介して、任意のコンテキストからLoggingサービスにアクセスできます。

これはグローバル変数によく似ているように見えるかもしれませんが、そうではありません。シングルトンクラス内に適切にカプセル化されており、すべての人がアクセスできるわけではありません。これにより、実行時でもロギングの処理方法を変更できますが、ロギングの動作を「vilain」コードから保護します。

私が取り組んでいるシステムでは、さまざまなサブシステムからのメッセージを区別できるようにするために、いくつかのロギング「シングルトン」を作成します。これらは実行時にオン/オフを切り替えることができ、フィルターを定義することができ、ファイルへの書き込みが可能です...あなたはそれに名前を付けます。

于 2008-09-17T19:37:02.680 に答える
0

私は過去に、ロギングにアクセスする必要のあるクラスの基本クラス(または言語がサポートしている場合はインターフェース)にロギングクラスのインスタンスを追加することでこれを解決しました。何かをログに記録すると、ロガーは現在の呼び出しスタックを調べ、そこから呼び出し元のコードを判別し、ログステートメントに関する適切なメタデータ(ソースメソッド、利用可能な場合はコード行、ログに記録されたクラスなど)を設定します。多くのクラスにはロガーがあり、ロガーは自動的に決定できるメタデータで特別に構成する必要はありません。

これかなりのオーバーヘッドを追加するので、本番ロギングには必ずしも賢明な選択ではありませんが、そのように設計すると、ロガーの側面を条件付きで無効にすることができます。

現実的には、私はほとんどの場合コモンズロギングを使用します(私はJavaで多くの作業を行います)が、上記で説明した設計には有益な側面があります。他の誰かがすでにデバッグにかなりの時間を費やしている堅牢なロギングシステムを持つことの利点は、よりクリーンな設計と見なすことができるものの必要性を上回りました(特にこの投稿の詳細が不足していることを考えると、これは明らかに主観的です)。

静的ロガーでpermgenメモリの問題が発生する問題が発生したため(少なくとも、それが問題だと思います)、おそらくすぐにロガーを再検討する予定です。

于 2008-09-17T19:39:45.247 に答える
0

私は log4* と一緒に AOP に賛成です。これは本当に助かりました。たとえば、Googleはこの記事をくれました。そのテーマについてさらに検索を試みることができます。

于 2008-09-17T19:33:30.940 に答える
0

シングルトンパターンを見ることができます。

于 2008-09-17T19:24:47.343 に答える
0

ロガーをシングルトン クラスとして作成し、静的メソッドを使用してアクセスします。

于 2008-09-17T19:25:01.960 に答える
0

もう 1 つの考えられる解決策は、ロギング/ストアド プロシージャをカプセル化する Log クラスを使用することです。new Log();そうすれば、シングルトンを使用しなくても、必要なときにインスタンス化できます。

データベース経由でログを記録している場合、注入する必要がある唯一の依存関係はデータベースであるため、これが私の推奨するソリューションです。ファイルを潜在的に使用している場合、依存関係を注入する必要はありません。グローバルまたは静的ロギング クラス/関数を完全に回避することもできます。

于 2010-04-09T07:32:47.080 に答える
0

(IMHO)「ロギング」がどのように行われるかは、ソリューション設計の一部ではなく、Java のシステムやカレンダーなど、たまたま実行している環境の一部です。

あなたの「良い」ソリューションは、特定のロギング実装に可能な限り疎結合されているものであるため、インターフェースを考えてください。Sun がどのようにそれに取り組んだかの例については、こちらのトレイルをチェックしてください。おそらく、Sun は非常に優れた設計を考え出し、学習できるようにすべてをレイアウトしました!

于 2008-09-17T19:34:03.577 に答える
0

静的クラスを使用すると、オーバーヘッドが最小になり、単純なアセンブリ参照内のすべてのプロジェクト タイプからアクセスできます。

シングルトンは同等ですが、不要な割り当てが含まれることに注意してください

複数のアプリ ドメインを使用している場合は、メイン ドメイン以外のドメインから静的クラスにアクセスするためにプロキシ オブジェクトが必要になる場合があることに注意してください。

また、複数のスレッドがある場合は、出力のインターレースを避けるためにログ機能をロックする必要がある場合があります

IMHO ロギングだけでは不十分なので、CALMと書きました

幸運を!

于 2008-09-17T19:34:16.553 に答える
0

グローバル変数を避けるために、グローバル REGISTRY を作成し、そこにグローバルを登録することを提案します。

ロギングについては、シングルトン クラスまたはロギング用の静的メソッドを提供するクラスを提供することを好みます。

実際には、既存のロギング フレームワークの 1 つを使用します。

于 2010-08-27T22:29:35.677 に答える
0

I think you should use AOP (aspect-oriented programming) for this, rather than OOP.

于 2008-09-17T19:26:08.820 に答える
0

私の意見では、実際にはシングルトン/グローバルメソッドはうまく機能します。できれば、グローバルなものは、コンソール出力用、データベース出力用、Windows EventLog 出力用など、さまざまなリスナー (オブザーバー パターン) を接続できる単なるフレームワークです。

ただし、過剰設計に注意してください。実際には、グローバル メソッドだけを持つ単一のクラスが非常にうまく機能することがわかっています。

または、使用している特定のフレームワークが提供するインフラストラクチャを使用することもできます。

于 2008-09-17T19:26:19.773 に答える
0

MicrosoftのPattern & Practices グループから提供されているEnterprise Library Logging Application Blockは、OOP 環境でロギング フレームワークを実装する好例です。ロギング アプリケーション ブロックをどのように実装したかについての優れたドキュメントがあり、すべてのソース コードを自分で確認または変更することができます。

他にも同様の実装があります: log4net、log4j、log4cxx

彼らが Enterprise Library Logging Application Block を実装したLogger方法は、実際にログ操作を実行する多数の異なるメソッドを持つ静的クラスを持つことです。パターンを検討している場合、これはおそらくシングルトン パターンの優れた使用方法の 1 つです。

于 2008-09-17T19:28:59.593 に答える