Saturday, October 23, 2010

.Net Debug Class (3)

Implementation Class: DianosticsDurationHelper

To calculation duration between two debug calls, I created an implementation class: DianosticsDurationHelper. In addition to two public properties in the base class, the implementation class provides a few public methods.


As you can see, the duration helper class has very simple APIs. One method Indent() is used for indentation or un-indentation, and one method for debug a message. The duration calculation is done within the class.

As discussed above, the calculation is done through delegates. Two private methods are defined here. One is for obtaining the current date time value, and another for calculating the duration value. Those methods are used as delegates to the base class calls.

private DateTime GetDateTime()
{
return DateTime.Now;
}

private string CalculateDuration(DateTime dt, DateTime poppedValue)
{
float duration = (float)((new TimeSpan(dt.Ticks - poppedValue.Ticks)).Hours) * 3600.0f +
(float)((new TimeSpan(dt.Ticks - poppedValue.Ticks)).Minutes) * 60.0f +
(float)((new TimeSpan(dt.Ticks - poppedValue.Ticks)).Seconds) +
(float)((new TimeSpan(dt.Ticks - poppedValue.Ticks)).Milliseconds) / 1000.0f;
return string.Format(" duration: {0:N2}", duration);
}

The remaining part of the duration helper class is as followings:

internal class DianosticsDurationHelper : DianosticsHelperBase<DateTime>
{
public DianosticsDurationHelper(string className) : base(className)
{
}

public DianosticsDurationHelper DebugMessage(string message)
{
base.debugMessageBase(message);
return this;
}

public DianosticsDurationHelper Indent()
{
return DebugIndent(true);
}

public DianosticsDurationHelper UnIndent()
{
return DebugIndent(false);
}

private DianosticsDurationHelper DebugIndent(bool indent)
{
if (indent)
{
base.debugIndent(GetDateTime);
}
else
{
base.debugUnindent(GetDateTime, CalculateDuration);
}
return this;
}
...// private methods used as delegates, see above.
}

Usage Examples

In many of projects, I used this duration class to get duration time between the begging and end of each call. Here are some example codes.

[STAThread]
static void Main() {
// customize indent string to --
DiagnosticsDurationHelper.IndentString = "--";
MyForm mainForm = new MyForm();
Application.Run(mainForm);
// ...
}

// MyForm.cs
class MyForm : Form {
// some helper methods using duration helper class
private DianosticsDurationHelper _debugHelper =
new DianosticsDurationHelper("MyForm");
// other data members
// helper methods to use the debug instance
private void DebugMessage(string message) {
_debugHelper.DebugMessage(message);
}

private void DebugMessage(string message, bool indent) {
if (indent) {
_debugHelper.DebugMessage(message).Indent();
}
else {
_debugHelper.UnIndent().DebugMessage(message);
}
}
// use debug helper methods to log duration...
private void MyForm_Load(object sender, EventArgs e) {
DebugMessage("MyForm_Load", true);
// ...
DebugMessage("Some information...");
// ...
DebugMessage("MyForm_Load", false);
}
// ...
}


By the way, in my helper class and base class, I tried to use fluent interface pattern for APIs. As you can see, the usage of those APIs is much fluent and clean.

To get the debug result in my Visual Studio's output console, I run my application in debug mode. Alle debug strings will be in the output console. Here are some results:

--[ 10/18/2010 11:21:58 AM ] MyForm::MyForm_Load
----[ 10/18/2010 11:23:58 AM ] DBGateway::DBGateway
...
----[ 10/18/2010 11:23:58 AM duration: 0.02 ] DBGateway::DBGateway
--[ 10/18/2010 11:22:58 AM ] MyForm::Some information ...
...
--[ 10/18/2010 11:21:58 AM duration: 0.22 ] MyForm:: MyForm_Load

Here is the source codes with an example.

Read More...

Sunday, October 17, 2010

.Net Debug Class (2)

My debug class contains one base class. Let's see the structure of the base class.

DianosticsHelperBase Class

My debug class is a simple base class, DianosticsHelperBase:


The above class picture shows all the public properties and protected helper methods for derived classes. Let's discuss the design of the base class.

Layout Format of Debug Message

The main purpose of the debug class is to print or log messages. The message consists two key parts: timestamp and message, with additional optional parts: context, indent, and calculated value.

The context is used as a convenience to identify message's context, for example, a class or module name could be used to mark debugged messages within the context.

Indentation is a nice feature to layout debug messages. The indentation and un-indentation are done through two method calls. DebugIndent() and DebugUnindent(). The indentation string can be set by the static property InentString. Null or empty string can be set to IndentString to disable indentation, or other strings to customize an indentation string, such as "—". The default indent string is a string of two spaces:

private static string _indentStr = "  ";

The base class provides another nice feature to calculate a value between two points. This is done by providing delegates to method calls: DebugIndent() and DebugUnindent(). If null delegates are passed to the calls (parameters), no calculation will be donem, thus disable the calculated value feature.

The layout format of debug messages is set by the static property Format of the base class. The default layout is:

//indent, timestamp, calculatedValue, context, message
private static string _format = "{0}[ {1}{2} ] {3}::{4}";

Constructor

Typically, an instance of the debug class is a member of a class where debug messages will be logged by the instance within its internal codes. A context string for the instance is set through the base class CTOR. The context of the debug instance is set in its creation time.

private string _context;
private string _calculatedValue;

public DiagnosticsHelperBase(string context) {
if (context != null) {
_context = context;
}
else {
_context = "";
}
_calculatedValue = "";
}

Helper Methods

A message is logged or output by the protected method debugMessage. In this method, a message is formatted as a string and output to a media. In the following codes, the output is passed to Output console in the Microsoft Visual Studio.

private string _context;
private string _calculatedValue;
private static bool _logMessage = System.Diagnostics.Debugger.IsAttached;

protected DiagnosticsHelperBase<T> debugMessage(string message) {
if (_logMessage)
{
System.Diagnostics.Debug.Print(
string.Format(_format, getIndent(), DateTime.Now,
_calculatedValue, _context, message));
_calculatedValue = "";
}
return this;
}

private string getIndent() {
string sVal = "";
if (_indent > 0)
{
int i = 0;
do
{
sVal = string.Format("{0}{1}", sVal, _indentStr);
i++;
} while (i < _indent);
}
return sVal;
}

The method checks _logMessage before further logging messages. This flag is set by Syste.Diagnostics.Debugger.IsAttached. If the build is in release mode, this flag will be False, as a result, no calls to log messages.

The concept of a calculated value is based on the consideration of calculating a value between two debug points, for example, a duration time value between the beginning and the end of a method call. This is done within the base class by two method calls: debugIndent() and debugUnindent(). How a value is obtained and how the calculated value is done are provided by passing delegates as parameters to those method calls. This provides a flexible way to generate calculated values such as duration, memory usage, disk free spaces and so on.

protected DiagnosticsHelperBase<T> debugIndent(GetValue<T> pushedValueDelegate) {
if (_logMessage)
{
if (pushedValueDelegate != null)
{
T value = pushedValueDelegate();
_debugDts.Push(value);
}
_calculatedValue = "";
_indent++;
}
return this;
}

protected DiagnosticsHelperBase<T> debugUnindent(GetValue<T> fromValueDelegate, GetCalculatedValue<T> calculatedValueDelegate) {
if (_logMessage)
{
if (calculatedValueDelegate != null && fromValueDelegate != null)
{
T value2 = _debugDts.Pop();
T value1 = fromValueDelegate();
_calculatedValue = calculatedValueDelegate(value1, value2);
}
if (_indent > 0)
{
_indent--;
}
}
return this;
}

All the methods in the base class are protected. They are only available for a derived class to implement specific debug usages. For example, the following duration helper class is an example for logging messages with duration information.

Read More...

Monday, October 11, 2010

.Net Debug Class (1)

I wrote a blog on debug or logger class in Objective-C about couple months ago. Actually, that class was based on my prevous .net debug class. It has a feature to print debug information in a nice indention layout, which was extended to my Objective-C class. I think my .Net is very useful, at least for me, and it is more generic, with an additional feature to calculate a value between paired messages(indent and un-indent).

Background Story

I was assigned to a task to resolve a painful slow performance issue of a .Net Windows application project. I did not spend much time to understand the complete business logic of the application. I went to the issue directly. What I did was to create a debug class to print out time and duration of each method or event call. Based on that information, I then focused on the longest duration calls to find out ways to improve the performance issue. The task was finished in very short period of time and the performance was greatly improved. My debug class is a very generic and useful tool. I have used this in my other projects with great success. With this experience and design, I created a similar logger class in Objective-C when I started iPhone development.

The intension to create this debug class is mainly based on three considerations. First is to generate debug message with duration information for each method or event call. This is the main reason and it is very easy to do. This could be done without a class. However, I would like to have debug message in a consistent format or indention. A class can encapsulate the implementation and provide unified interface. This second consideration actually was trigged by System.Diagnostics.Debug class, which has a nice property IndentLevel and a method Indent.

The third consideration is the maintenance. Since the debug calls are spread out all over the places in a project, it will be really hard to clean up them when the project is finally released. I would like to keep the debug feature or codes in my project without removing them, but also have least impact on its performance. As you will see, I have introduced delegates and early checks to avoid unnecessary calls if debug is disabled.

Delegates Used in the class

I like to use delegates as a way to pass custom implementation to my class. The first advantage is that it follows Open/closed-principle. It opens for extension or plug-in, but close my class for any modifications. The second advantage is to improve performance. Delegates normally used as parameters. They are pointers to functions or methods. If a delegate is not called for execution, its internal codes will never be evaluated. The following delegates are defined:

public delegate T GetValue<T>();
public delegate string GetCalculatedValue<T>(T value1, T value2);

The first one is a delegate to get a value. The delegate provides a way to let client to define his/her implementation to get a value. For example, for duration case, a delegate can be defined just returning a value of DateTime.Now.

The second delegate is for calculate a value based two parameter values, from value1 to value2.

Read More...

Friday, October 01, 2010

XCode 3.2.4 and iOS 4.1

Today I checked the Apple Development web site to see if there is any new Xcode and iOS available. Then I found that Xcode 3.2.4 and iOS 4.1 are available for download. I remember that when I just finished watching WWDC10 videos, I could not get the new iOS 4.1. It was only available for registered developers. I am very glad that now it is open for all developers.

My current XCode is 3.2.1 and iPhone SDK is 3.1.3. The new package is in download progress. The size of the package is 2.94GB. Like I have recorded the space compassion my iMac updates, here is the difference of free space between before and after.

Command: df -lakUsed(Kilobytes in 1024-blocks)
Before ...1,609,459
After...2,428,476
Difference (A-B)819,017


Issues After the Update

After the update, I tried to open the project I am working on. The first issue is that I lost my Framework references. For example, my UIKit.framework item in Frameworks became red. iPhone 3.1.3 frameworks were all gone.

That issue actually was not hard to fix. I opened the project Get Info window, and changed the Base SDK for All the configurations to iOS 3.2. Then select a format for my project.


The second issue was not so straightforward. I saw an error when I tried to build the project. It is code signing issue with key chains.


After I googled the web for solutions, I found this answer from SO. Basically, default device for my build was set to iPhone, instead of Simulator. For device build, I do need to be a registered developer.

After I fixed those two issues, I am now back to my progress of development. XCode and iOS updates are very well back-compatible. The updates do not like Visual Studio update with a lots of changes or conversions. Maybe my project is just too simple?

Read More...