コードをデバッグする方法としてのロギング

自分自身のデバッグを防ぐことがなぜそれほど重要なのですか?



プログラムをデバッグするとき、自分で気付かないうちに、1つのデバッグセッションで、このタスクのフレームワーク内で発生したすべての問題を修正すると考えてください。 しかし、私たちの近視眼は、実際には一つの問題ではなく、いくつかの問題があると信じたくありません。 そして、1つのデバッグセッションでは、これらすべての問題を解決することはできません。



そのため、このコードをデバッグモードで数回実行し、同じコードで何時間もデバッグする必要があります。 そして、プログラムのこの部分に多くの時間を費やしたのはあなただけです。 このコードを使用して「幸運な」各チームメンバーは、あなたが住んでいたのと同じストーリーを生きることを余儀なくされます。



チームの人々が変わる、チームが変わる、などは言うまでもありません。 工数も同じことになります。 やめて 私は本気です。 他の人に責任を負います。 彼らがあなたの人生の同じストレッチを経験しないように助けてください。



問題:複合コードのデバッグが難しい



問題を解決するための可能なアルゴリズム:



  1. 別々の部分に分割
  2. デバッグを破棄し、デバッグモードの使用を禁止します。
  3. 個々のパーツを分析します(それらの無効な状況、境界ケースを見つけます)
  4. アルゴリズム全体の個々の部分に対してテストを作成します
  5. テストでは、時には中間データを学ぶ必要がありますが...

    デバッグは使用できなくなったため、アルゴリズムの不正な実行の疑いがある部分にトレースを貼り付けます
  6. トレースすることにより、問題の原因を理解する必要があります
  7. 明確でない場合は、ほとんどの場合、別のテストを書くか、一歩前にトレースする価値があります


ソリューションは、ロギングを使用した自動テストです。 問題につながるすべての(またはほとんどすべての)状況のテストを作成します。 さらに、デバッグが必要な場合は、問題が見つかるまでトレースします。



したがって、他の人がこのコードをデバッグするのを防ぐことができます。 問題が発生した場合、その人はあなたのログを見て理由を理解します。 ロギングはアルゴリズムの重要な部分にすぎません。



例を見てみましょう。 すべてのインターフェース実装が個別に機能することを知っています(これを証明するためにテストが書かれているため)。 しかし、すべてがまとまると、不正な動作が発生します。 何が必要ですか? 「正しい」インターフェースからの応答を記録する必要があります。



void Register(User user) { //       , // ..      var isExists = _userRepository.IsUserExists(user); if (isExists) { throw new InvalidOperationException($"User already exists: {user}"); } //       , // ..       var roleInOtherService = _removeService.GetRole(user); _log.Trace($"Remote role: {roleInOtherService}") switch (roleInOtherService) { case "...": break; ... } //    ,     //    -  , //        foreach (var privilege in Privileges) { var isSuccess = _privilegeRemoteService.Grant(user, privilege); if (isSuccess) { _log.Trace($"Add privilege: {privilege} to User: {user}"); } else { _log.Trace($"Privilege: {privilege} not added to User: {user}"); } } ... }
      
      





この例では、アルゴリズムの個々の部分をトレースして、この段階またはその実行段階を修正する方法を示します。 ログを見ると、その理由が明らかになります。 実際には、このアルゴリズム全体を別々の方法に分割する必要がありますが、この本質は変わりません。



これにより、コードの記述が大幅に加速されます。 問題が発生したループの反復を理解するために、F10でループを実行する必要はありません。 サイクルの特定の反復で、特定の条件下で必要なオブジェクトの状態を宣言するだけです。



最後に、重要なログを残し、サイドログを削除します。たとえば、ループの特定の反復でオブジェクトの状態を認識した場合です。 そのようなログは同僚を助けません。なぜなら、 間違ったアルゴリズムの問​​題をすでに理解し、修正している可能性が高いです。 そうでない場合は、理由を見つけて問題を修正するまでブランチで開発します。 ただし、他のアルゴリズムの実行による重要な結果を記録するログは、誰もが必要とします。 したがって、それらは残す必要があります。



このゴミが必要ない場合はどうしますか? この場合、デバッグの一部としてのみトレースし、その後自分でクリーンアップします。



長所 短所
デバッグせずにアルゴリズムの実行を追跡することが可能です トレースコードを作成する必要があります
本番環境では、ログが必要なデータを収集する場合があります。 本番環境では、ログによって不要なデータが収集されることがあります
デバッグ時間が短縮されます 多くの場合、コードを実行し、すぐに実行結果を確認します(すべてが完全に表示されます) 自分の後にクリーンアップする必要があります。 これにより、トレースコードが書き直される場合があります。
同僚はログでアルゴリズムの実行を追跡できます 同僚はアルゴリズム自体だけでなく、その実行の痕跡も確認する必要があります
ロギングは、非決定的なスクリプト(マルチスレッドやネットワークなど)をデバッグする唯一の方法です 本番環境では、I / OおよびCPU操作によりパフォーマンスが低下します


最後に、私はこれを言いたいです:あなた自身の頭で考えてください。 極端から極端にジャンプする必要はありません。 時々、手動デバッグでここで実際に問題を解決できます。 しかし、何かが高速であることに気づくとすぐに、ここでは動作しません。今は、別のモードに切り替えるときです。



All Articles