Sunday, September 28, 2008

Null-coalescing operator in .NET Framework

The post Declaring variables as nullable in c# describes how nullable value types can be declared used in C#.

.NET Framework also provides the ?? operator, called the null-coalescing operator, and its primary use is to define a default value for a nullable value types as well as reference types. It returns the left-hand operand if it is not null; otherwise it returns the right operand.

As an example, if the following code is run, the intValue will be 1, since nullInt is null.

Nullable<int> nullInt = null;

int intValue = nullInt ?? 1;

Thursday, September 25, 2008

Walkthrough EQATEC Tracer

1: Create application in .NET

I have written a simple test application, TestEqatecTracer, to play with the new tool EQATEC .NET Tracer (which I mentioned in the previous post). In the TestEqatecTracer application,

- names are populated in a list structure,
- list is then sorted using the List.Sort() ,
- finally, the list is sorted by the last character using SortByLastCharacter Comparer class.


using System;

using System.Collections.Generic;

using System.Text;

 

namespace TestEqatecTracer

{

   public class SortByLastCharacter : IComparer<string>

   {

        #region IComparer<string> Members

 

        public int Compare(string x, string y)

        {

            if (string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y))

               return 0;

            else

               return x[x.Length - 1].CompareTo(y[y.Length - 1]);

        }

 

        #endregion

   }

 

   public class Program

   {

        static void Main(string[] args)

        {

            List<string> names = new List<string>();

            names.Add("John");

            names.Add("Frank");

            names.Add("Andy");

            names.Add("Brain");

 

            Console.WriteLine("Initial names: ");

            PrintNames(names);

            Console.WriteLine();

 

            Console.WriteLine("Names sorted: ");

            names.Sort();

            PrintNames(names);

            Console.WriteLine();

 

            Console.WriteLine("Names sorted by last character: ");

            names.Sort(new SortByLastCharacter());

            PrintNames(names);

            Console.WriteLine();

 

            Console.ReadLine();

        }

 

        private static void PrintNames(List<string> names)

        {

            if (names != null)

            {

               foreach (string name in names)

                    Console.WriteLine(name);

            }

        }

   }

}



2. Instrumentation Process

Now open the EQATEC Tracer tool. In the Instrumentor tab, browse and locate the assemblies of the application. The drag and drop feature can also be used.

The list of all assemblies in the selected folder will be shown in the Assembly List.

Select the assemblies that will be analysed in the list shown, and start the instrumentation process by selecting the "Instrument currently selected assemblies" button and a modified version of the assemblies will be then generated. The instrumentation process injects trace statements in the assemblies.




3. Select methods to trace

Click the flash icon to launch the modified application. The application view will then change to the Viewer tab.

After connecting to the application, the Control tree is populated with the classes and methods of the assemblies. Select ones that needs to be traced by checking the boxes.

The LocalHost represents the local machine. If the application is a device application, then the IP address of the device should be entered.



4. View trace results

Now connect to the application using the "Play" button.

And the trace will be shown in the Trace Viewer.



25/09/2008 15:51:18 (1) enter Program.Main ( String[], )
25/09/2008 15:51:18 (1) enter+leave Program.PrintNames ( List`1[System.String], )
25/09/2008 15:51:18 (1) enter+leave Program.PrintNames ( List`1[System.String], )
25/09/2008 15:51:18 (1) enter+leave SortByLastCharacter..ctor ()
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Andy", "Brain", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Andy", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "Frank", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 3, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Brain", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Brain", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter+leave Program.PrintNames ( List`1[System.String], )

EQATEC Tracer

Another free developer tool has been released yesterday - the EQUATEC Tracer.

Here's the email extract from the EQATEC development team:

We're happy to announce the release of yet another development tool, the EQATEC Tracer.

In summary, the tracer will show how your .NET code is executed live. It's great for debugging and no source code changes are needed: just point the tracer to your app, run the modified code, and start watching the trace output. It's that simple.

The tracer is useful for all .NET developers, but especially for those doing embedded development in .NET Compact Framework: it allows you to enable in-target-debugging during development or at customer sites - a situation where a traditional debugger isn't an option. Letting the tracer add trace-instructions to all methods and turn them on/off at runtime can easily save many, many days of work, so you can spend your time on the fun and interesting parts instead of adding endless trace-messages.

Some functional highlights include:

- Add trace to any .NET apps - no source code changes needed
- Enable tracing at runtime for all method calls, parameters, exceptions etc
- Works with both .NET Compact Framework and the full .NET Framework
- Very low overhead when tracing is turned off
- View trace output from PC or device remotely over network connection
- On the fly enabling and disabling of trace instructions
- Trace each thread in a separate window


The EQATEC Tracer can be downloaded here under BSD license terms.

Tuesday, September 23, 2008

CommaDelimitedStringCollection class in .NET Framework

One simple but yet very interesting and useful class in .NET Framework that allows the creation of comma separated string from a list of string items is the CommaDelimitedStringCollection. This class is found in the System.Configuration namespace. So, we can stop reinventing the wheel each time we need such a collection, and instead, make use of this ready-made class.

Sample code...

CommaDelimitedStringCollection sites = new CommaDelimitedStringCollection();

sites.Add("www.yahoo.com");

sites.Add("www.google.com");

sites.AddRange(new string[] { "moiashvin-tech.blogspot.com", "www.lexpress.mu" });

Console.WriteLine(sites.ToString());


Output...
www.yahoo.com,www.google.com,moiashvin-tech.blogspot.com,www.lexpress.mu

Sunday, September 21, 2008

100% code coverage - good but not preeminent

I was configuring TestDriven.NET on my machine, and the idea of writing a few lines about code coverage popped in my mind. There have been continuous debates and discussions about this particular topic in the past years and thousands of words have already been written by experts in the field. Everyone can have a different opinion about testing, and more importantly code coverage (as this is what the post is all about), and so do I.

We, programmers (irrespective of the programming language that we use), have one common goal in our respective objectives - to write good quality code. And by good quality code, I mean code that implements correctly the desired functionality, is in line with industry (or corporate) standards while following the appropriate coding guidelines, uses constraint resources of the environment and infrastructures in an optimal way and is easily maintainable, just to mention a few. Last but not least, another feature of the good quality code is also 'bug free' code.

The testing phase in a software development life cycle ensures that the code is well-tested using an appropriate strategy. Different types of tests, such as unit tests, integration tests and system tests, just to name a few, are conducted. Once the tests are completed, code coverage reports are usually produced.

"Testing never proves the absence of faults, it only shows their presence." - Edsger Dijkstra

What is code coverage? Code coverage tells us how much of our code have we tested. It gives helpful information about the part of the code that has been exercised, and hence, a complete new perspective to the testing paradigms. However, the toughest task is to be able to correctly interpret the code coverage results (or say, reports). And that's where development teams and programmers often make their first mistake.

Many professionals in the software development field believe that a 100% code coverage means that the application is bug free. Hold on. Take a moment and give this a second thought. Are you indeed such a believer?

According to me, 100% code coverage is good but not preeminent. Not preeminent? Yes, I believe there is nothing extraordinary with a 100% code coverage. Does the 100% coverage guarantee that all the tests have been done in the right way? Does it guarantee that the selected test cases and test data are indeed correct? Does it guarantee that we haven't missed any corner case? What about a missing functionality in the code, will the 100% coverage identify it? The answers are a big NO. This is neither the Test Driven Development nor the code coverage fault. It's a failing of the way the results are interpreted. The focus should be more on the test strategies, scenarios and data rather than on the code coverage.

Let me give a very basic example. I have a static Divide() method in the Divider class that accepts a dividend and divisor and returns the quotient.

using System;
using System.Collections.Generic;
using System.Text;
 
namespace CodeCoverageTests
{
    public class Divider
    {
        public static double Divide(int divident, int divisor)
        {
            return dividend / divisor;
        }
    }
}


I will use the DividerTest class to test this Divide() method using the NUnit tool.

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
 
namespace CodeCoverageTests
{
    [TestFixture]
    public class DividerTest
    {
        [Test]
        public void TestDivide()
        {
            Assert.AreEqual(10.0, Divider.Divide(30, 3), "Incorrect division.");
        }
    }
}

When run, the test is passed successfully.


And more importantly, the code coverage shows a 100% figure.


With this figure, it gives the impression that this is really a good piece of work, with tests passed succesfully, and above all, a code coverage of 100%.

Ladies and Gentlemen: Don't be fooled by the coverage report. That's how Andrew Glover expressed himself in his article “In pursuit of code quality: Don’t be fooled by the coverage report”.

Call the method Divide() with 0 as the divisor and the program will throw a DivisionByZero exception. This is just a simple example to show how wrong one can be when assuming that a piece of code with 100% code coverage is bug free.

Code coverage is a very good indicator of how various sections of the code were tested. It is here to work as a complement, not the primarily indicator, for the overall code quality picture.

Thursday, September 18, 2008

Netbeans free DVD distribution program suspended indefinitely

Extract of the email from Netbeans Webmaster...

I regret to inform you that the DVD distribution program has been suspended indefinitely as we evaluate options to simplify the distribution of NetBeans software.

Since August 30th, 2005, NetBeans.org has shipped more than 225,000 CDs & DVDs to developers around the world through this initiative! During this period, NetBeans has experienced explosive growth as a download, media kit, and a community. To stay ahead of this encouraging trend we are looking into ways to effectively satisfy increasing demand for NetBeans software worldwide. Please bear with us.

In the interim, we are offering the same great contents of NetBeans IDE 6.1 ML DVD Starter Kit as an ISO image that you are free to download and burn. Alternatively, visit our download page for installer bundles as lightweight as 18MB. In the near future we also hope to offer our downloads via mirrors and bittorrent ...

Monday, September 15, 2008

Logon failed for user MACHINENAME/ASPNET

Some weeks back, everything was working fine with the login MYCOMPUTER/ASPNET on the SQL Express Server.

I formatted my machine recently and during 're-installation' of the operating system, I used a MACHINENAME instead of the default MYCOMPUTER.

Then, I run the aspnet_regiis command and it seems to me that the user MACHINENAME/ASPNET has been created and is also being used as login onto the database.

The client application throws the following exception:

System.Data.SqlClient.SqlException: Cannot open database "XXXDATABASEXXX.MDF" requested by the login. The login failed.
Login failed for user 'MACHINENAME\ASPNET'.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
... ... ... ...
... ... ... ...

The database should now be configured to recognise this new MACHINENAME/ASPNET user.

I tried to replace the MYCOMPUTER/ASPNET user with MACHINENAME/ASPNET user in the database properties but can't find the MACHINENAME/ASPNET user in the available list of users. Any reason for that???

Anyways, instead of losing precious time finding the right way, the following SQL statement will create the user on the database and allow successful login. Just you have to make sure that the appropriate permissions are set once the user has been created.

USE [XXXDATABASEXXX.MDF]
CREATE USER [MACHINENAME\ASPNET] FOR LOGIN [MACHINENAME\ASPNET]
GO

Don't forget to change XXXDATABASEXXX and MACHINENAME to the appropriate names on your machine...

Friday, September 12, 2008

Predicates: List.Find() method

When it comes to searching an element in a list in C#, it seems easier to write a for loop, and iterate over the elements until the desired element is found. In other words, a linear or sequential search.

As an example, a LocationVO has two members: Code and Description.
public class LocationVO
{
    private string code;
 
    /// <summary>
    /// Gets or sets the code.
    /// </summary>
    /// <value>The code.</value>
    public string Code
    {
        get { return code; }
        set { code = value; }
    }
 
    private string description;
 
    /// <summary>
    /// Gets or sets the description.
    /// </summary>
    /// <value>The description.</value>
    public string Description
    {
        get { return description; }
        set { description = value; }
    }
}

The list declaration would be as follows:
List<LocationVO> locations = new List<LocationVO>();

And the linear search would be:
/// <summary>
/// Finds the business location.
/// </summary>
/// <param name="code">The code.</param>
/// <returns></returns>
public LocationVO FindLocation(string code)
{
    if (locations != null)
    {
        for (int i = 0; i < locations.Count; i++)
        {
            if (locations[i].Code = code)
                return locations[i];
        }
    }
    return null;
}

Predicates
An more elegant way is to use the List.Find() method. This method uses a predicate that defines the search criteria. If an element has to be searched by using another criteria (e.g. using the description property rather than the code one), it would be better to write another predicate rather than duplicating the linear search algorithm in the source code.
/// <summary>
/// Finds the location using predicate.
/// </summary>
/// <param name="code">The code.</param>
/// <returns></returns>
public LocationVO FindLocationUsingPredicate(string code)
{
    LocationVO vo = locations.Find(delegate(LocationVO curr)
    {
        return curr.Code == code;
    });
 
    return vo;
}

The List.FindAll() method is yet another interesting method that returns all instances matching the search criteria.