February 25, 2021
Hot Topics:

Can You Hear Me Now?

  • By Paul Kimmel
  • Send Email »
  • More Articles »

If I were just a bit of a cynic, I would say that open source is a nice spin on freeware. Freeware is free. Generally, freeware comes with source code, but calling free code open source seems to have a legitimizing quality about it. And, in fact, sometimes freeware carried a connotation that the code was hacky. I am not sure if it was Eric Raymond's great book The Cathedral and the Bazaar that elevated the status of freeware or great products such as NUnit, but whatever combination of events occurred, we programmers are benefiting from open source code.

In this article, I want to talk about a synergy that includes the excellent open source NUnit (www.nunit.org) testing tool, instrumenting your code for tracing, and TraceListeners. Collectively, these three aspects of .NET programming can make debugging and testing a ton of fun and help you come off as a real pro when you deliver bulletproof code.

Rather than assume you have had time to familiarize yourself with any of these things—TraceListeners, NUnit, and the notion of instrumenting your code—I will briefly introduce all three things and show you a nice way to tie them together. If you want more information about NUnit, for example, check earlier articles on www.codeguru.com (such as "Testing Visual Basic .NET with NUnit").

Instrumenting Your Code

Instrumenting is a term that is gaining in popularity. We programmers use the term to mean adding code that helps us diagnose and keep track of how our code is behaving. Years ago, we'd add some print statements and send some text to the console; this text might tell us that our code entered a specific method or dump some state information. With Visual Basic, we began using the Debug.Print method to send text to the Immediate window. In Visual Basic .NET, we can use Debug.WriteLine or Trace.WriteLine. Adding these statements to your code is part of what we mean by instrumenting your code.

To add Trace.WriteLine statements to your code, add an Imports statement for the System.Diagnostics namespace, and add some strategically placed Trace.WriteLine statements. (If you are not sure, a namespace is a thing that contains classes, structures, and enumerations.)

Suppose, for example, that we are writing an application that employs differential equations to calculate missile trajectories. Before we start blowing things up, we will clearly want to test our code. We will definitely want to watch the behaviors unfold as the code is running to prevent things such as firing before aiming. Simplifying here, we could write methods to aim and fire, adding Trace statement to each method.

Listing 1: Instrumenting for Tracing.

Option Explicit On
Imports System.Diagnostics

Public Class FiringSystem

  Public Sub Aim(ByVal Elevation As Double, _
    ByVal Direction As Double, ByVal Distance As Double)

    Const Message As String = _
      "Aiming with Elevation={0}, Direction={1}, Distance={2}"
    Trace.WriteLine(String.Format(Message, Elevation, Direction, _

    'Aim here
  End Sub

  Private Function WasAimed() As Boolean
    Throw New NotImplementedException()
  End Function

  Public Sub Fire()
    Trace.WriteLine("Fire in the hole")
    ' Blow up bad guys
  End Sub

End Class

In the example, our stubbed out FiringSystem class provides an Aim and Fire method. The Aim method will send a string containing the Elevation, Direction, and Distance to a TraceListener. (More on TraceListeners in a moment.) The Fire method asserts that we did in fact aim and emits a trace statement that indicates that Fire was called.

When we run our FiringSystem, the Trace.WriteLine statements tells us what is going on.

Implementing a TraceListener

A TraceListener is a class that inherits from the abstract class TraceListener. To listen for Trace statements, TraceListeners are added to the Trace.Listener collection. Listener is a shared collection on the Trace class. By default, a debug TraceListeners has already been added to the Listeners collection and output is written to the Output window in Visual Studio .NET. However, if we aren't running VS.NET, we won't see these messages. Suppose we want to trace after we deploy the software or in another environment? Then, we can implement our own TraceListener and have it send trace messages to a log file or database.

To implement your own TraceListener, create a new class that inherits from System.Diagnostics.TraceListener, implement a Write and WriteLine method, and add an instance of your class to the Trace.Listeners collection. Listing 2 demonstrates a simple TraceListener and Listing 3 demonstrates how to start listening.

Listing 2: Implementing a stripped down TraceListener.

Imports System.IO

Public Class MyListener
  Inherits System.Diagnostics.TraceListener

  Public Overloads Overrides Sub Write(ByVal Message As String)
  End Sub

  Public Overloads Overrides Sub WriteLine(ByVal Message As String)
  End Sub
End Class

Listing 3: Listening to our FiringSystem class.

Public Class FiringSystem

  Private Shared Listener As MyListener = New MyListener()

  Shared Sub New()
    If (Not Trace.Listeners.Contains(Listener)) Then
    End If
  End Sub
'... Elided for clarity

MyListener provides a stripped-down TraceListener. Our listener will hear Trace.Write and Trace.WriteLine statements that are called with string arguments and send these to the Console. To begin listening, we add a shared constructor to the FiringSystem class. The shared constructor is called before any other code is run; the shared constructor stuffs exactly one instance of MyListener into the Trace.Listeners collection.

For more on TraceListeners, read the December 2002 codeguru.com article "Implementing a Custom TraceListener."

Page 1 of 2

This article was originally published on December 30, 2003

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date