#Google Analytic Tracker

Pages

May 21, 2008

Customizing a Base Class Static Members thought its Derived Class

In my programming experience, it usually doesn't make sense to customize a static member. In short, implementing a static member is not part of the object orientated programing technique.

In C#, at least as far as I know, you cannot override a static member. For example:

   public class MyClass
   {
        //Compiling error: Overridable method cannot be static
        public static virtual void Do(){// Do something}
   }
   public class DerivedClass : MyClass
   {
        public override void Do(){// Do something else}
   }

A static method is like a global method that can be called anywhere in your code without instantiate an object. Therefore, it doesn't make sense you can override a base static method.

A Situation when Customizing a Static Method is Needed.

Last year, I needed to create a brunch of data access classes. A data access class's primary purpose is to retrieve and transfer data between an application and a database. In design, you would expect you to see something like this:

MyVehicleData vehicle = new MyVehicleData();
//...
//... Do something with vehicle object
//...

//Save to database
vehicle.Save();
However, what if you want to write Select()? Does it make sense that you need to instantiate an object and then call the Select()?
MyVehicleData vehicle = new MyVehicleData(); 
vehicle.SelectByKey("somekey");
Instead, you probably want to do something like:
MyVehicleData vehicle = MyVehicleData.SelectBykey("somekey");

The above SelectByKey() method is a static method. In the code, most likely you can hardcode your select SQL.

What if you want to 100 data access classes?

As a smart lazy programmer, you don't want to hardcode your SQL statements for every business objects. You want to write a base class to save you time from repetitive coding. Even better, you can write a code generator to create your data access class. However, code generation is outside of my discussion.

This is what we would like:

// We want to do something like this:
// NOTE: This is just an idea, you will get compiling error
public abstract class BaseDataAccess<TDataAccess>{
    protected static string selectSQL;

    // Returns an instance of Data Access object of type TDataAccess
    public static TDataAccess SelectByKey(string key)
    {
        // note: RunSQL get column data based on the select SQL and the parameter
        string[] retrievedData = RunSQL(selectSQL, key);
        
        T result = TDataAccess.CreateData(retrievedData);
        return result;
    }
    
    // Creates a new instance of TDataAccess based on database values
    // Note: Compiling error: you can't have static method in with abstract declaration
    public abstract static TDataAccess CreateData(string[] values);
}

Solution

In the above example, it won't compile because abstract static is not allowed.  From the start, it doesn't make sense you can decorate the base class though its derived classes. This is time when Generic come into rescue. The solution is to create an instance of the derived class within the generic base class static constructor.  Please take a look at the following example:

// Don't get confused by the following declaration. What it said is that when you deriving // from this base class, you have to pass in a type that is also a // based from BaseDataAccess<TDataAccess>.public abstract class BaseDataAccess<TDataAccess> : where TDataAccess : BaseDataAccess<TDataAccess>, new()
{
    protected static string selectSQL;
    protected static BaseDataAccess<T> instance;
    
    // This is a static, it only run once!
    static BaseDataAccess()
    {
        instance = new T();
        selectSQL = instance.GetSelectSQL(); // virtual method call
    }

    // Return a instance of TDataAcess from database
    public static TDataAccess SelectByKey(string key)
    {
        // note: DataManager.RunSQL get data based on the select SQL and the parameter
        string[] retrievedData = DataManager.RunSQL(selectSQL, key);
        
        T result = instance.CreateData(retrievedData);
        return result;
    }
    
    // Create a new instance of TDataAccess based on database values
    // Note: Compiling error: you can't have static method in with abstract declaration
    protected abstract TDataAccess CreateData(string[] values);
    
    protected abstract string GetSelectSQL();
}

public class DerivedDataAccess : BaseDataAccess<DerivedDataAccess>
{
    // Parameterless constructor, this allow the base class to create an instance of its derived class.
    public DerivedDataAccess()
    {
    }
    
    public DerivedDataAccess(string[] values)
    {
        //Initialize your object;
    }
    
    // override the CreateData, this is how you customize the behaviour of your base class
    protected override DerivedDataAccess CreateData(string[] values)
    {
        DerivedDataAccess result = new DerivedDataAccess(values);
        return result;
    }
    
    protected override GetSelecteSQL()
    {
        // This virtual method will be called by base constructor, it should only use constant data
        return "select x, y, z from someTable";
    }
}

By using generic, the compiler create many type of base class for you. In addition, you instantiate a derived object so that you can get the information from the derided class.

Note that your base class static constructor only execute once, it won't re-initialize the base static constructor when you call "instance = new T()", hence, there is no infinite loop.

Also, you need to specify the where TDataAccess : BaseDataAccess<TDataAccess>, new() so that you can call the base class method. By specifying the generic type to be the BaseDataAccess, you can call the derived class virtual methods.  Just a side note, be careful when you call a virtual method in the constructor, because your object is not initialized, therefore any dynamic data will not be setup for your implemented virtual method to use.  The new() tells the compiler that your class support parameter-less constructor. Therefore you can instantiate a generic type though new T();

As a result, you can no do the following:

DerviedDataAccess myDataAccess = DerviedDataAccess.SelectByKey("someKey");

Final Thought

When I did this program, I was still using C# 2.0. However, in C# 3.0, the above idea can also be achieve by partial method.  In any case, it is still a neat technique.


 

May 9, 2008

Python Design Patterns

Design Patterns, one of the must known tool set for software developer, there is a very good video that talks about design pattern.

http://www.catonmat.net/blog/learning-python-design-patterns-through-video-lectures/

Even though the example is presented in Python, but the concept is the same, and it applies to other OO programming languages.

Also, for those who want a introduction of Design Pattern.  I recommend you get the First Head Design Patterns.  This is a very good introductory book for design pattern. Don't get scared if you don't know Java, it is very easy to understand.  I used it whenever I need ideas for solving architecture problem, or it is simply something to discuss with your colleges when you are bored at work! :)

May 8, 2008

No files were found to look in. use Ctrl+Scroll Lock!

 

Credit goes to: http://blogs.ugidotnet.org/franny/archive/2005/12/08/31303.aspx

Today, one of my colleges ran into a problem. He click on "Ctrl + Shift + F" to open the Find and Replace dialogue, and he tried to find a string in his solution.

image 

The text that he wants to search is right in front of his eyes, yet clicking on the Find All button only returns: "No files were found to look in.Find was stopped in progress."

He thought that he must be tired today.  Double check his spelling, his cap lock, and all other options. There it goes his 1/2 hr of work.  So, he came over to me to make sure that ensure that he is not hallucinating.  I said no, surely something is wrong with VS.

Another one of my colleges overheard our conversation, and said, "Try Ctrl + Scroll Lock".  WT..., how does Ctrl + Scroll Lock helps to solve this issue? Surprisingly, it worked!

The annoying part is that there is no explanation on how you get into to this state and how to fix it.  Obviously, no one will spend time continue investigate into this, because your main job is to develop your product and not debugging your development tools.

I suspect this maybe due some incorrect interaction between Visual Studio and the OS layer. The Scroll Lock button is rarely being used in modern software. In the past, when people still uses text-based UI, this button is used to make the arrow key to scroll the contents of the text window instead of moving the cursor.