Saturday, December 16, 2006

switches and jump tables

In my last post I had discussed about how only constants can be used with C# switches. From the post's comments and later discussing with other folks I learnt something that came to me as a surprise. A lot of people working on managed code consider switch-case to be a stylistic variant of if-else, and that is all.

However, in the C/C++ world switch is not just a variant of if-else (neither is it in .NET), it's a fast (O(1)) variant of if-else (O(n)). Stating that switch is just a better way to express multiple comparison against the same variable is stating Dictionary<T> is just another form of List<T>. They are not (Dictionary can give you O(1) lookup results).

For example C restricts the case to have constant-expression. This is done so that the compiler can generate optimized jump-table for its execution. Let's consider the following code.


switch(i) {
case 4:...
case 5:...
case 6:...
case 7:...
// many more cases...
default:...
}

For this code the machine code generated is similar to the steps below.


  1. Compile time jump table creation: For each case statement a fixed block of memory is reserved. Say 8 bytes. These 8 bytes contain a jump (jmp) instruction to the location where the actual code for the case resides. The base address of this table is labeled as say JMPTABLEBASE.
  2. Normalizes the value of i as i = i - 4 (the first value of the case)
  3. Boundary check: For the i it sees if the value is larger than the largest case (7-4 = 3), in case it is the execution flows to default.
  4. Jump to address JMPTABLEBASE + (i * 8)

As you can see from above the whole thing happens at constant time.

Some embedded C compilers (like the TI C-compiler) generates separate code section named .switch for the jumptable. Later this section can be targetted to the high-speed internal DARAM for faster execution in case the switch needs such special treatment.

Obviously compilers vary a lot in this manner .

Why can we only use constants in a switch-case statement?

Why can we only use constants in a switch-case statement? The following code fails to compile with the error “A constant value is needed” for someStr as it is not a constant string.


static void func(string str)
{
switch(str)
{
case "Zaphod": Console.WriteLine("The king"); break;
case someStr: Console.WriteLine("The coder"); break;
default: Console.WriteLine("None"); break;
}
}
string someStr = "Noo";

Here goes a long answer to this short question.



The reason is simple and yet involved. Let’s take the following valid code which only has constants and see how it works.


static void func(string str)
{
switch(str)
{
case "Zaphod": Console.WriteLine("The king"); break;
case "Abhinab": Console.WriteLine("The coder"); break;
default: Console.WriteLine("None"); break;
}
}

If we open see the code in IL it looks something like this


      L_0007: ldstr "Zaphod"
L_000c: call bool string::op_Equality(string, string)
L_0011: brtrue.s L_0022
L_0013: ldloc.0
L_0014: ldstr "Abhinab"
L_0019: call bool string::op_Equality(string, string)
L_001e: brtrue.s L_002f
L_0020: br.s L_003c
L_0022: ldstr "The king"
L_0027: call void [mscorlib]System.Console::WriteLine(string)
L_002c: nop
L_002d: br.s L_0049
L_002f: ldstr "The coder"
L_0034: call void [mscorlib]System.Console::WriteLine(string)
L_0039: nop
L_003a: br.s L_0049
L_003c: ldstr "None"

See the usage of op_Equality in L_000C and L_0019. This indicates that even though we are using switch-case, ultimately the code is converted to multiple if-then-else by the compiler. So the switch-case is converted by the compiler to something like


if (str == "Zaphod")
Console.WriteLine("The king");
else if (str == "Abhinab")
Console.WriteLine("The coder");
else
Console.WriteLine("None");

If this is the case then what is stopping the case statements from having non-constants? In case of a non-constant the code generated could be something like if (str == someNonConstantStr) which is valid code.



The answer is simple. When the numbers of cases are larger, the generated code is very different and is not constituted of if-then-else. Isn’t that obvious? Otherwise why would anyone ever use switch-case and why would we call switch case to be faster??



Lets see when we have a large number of case’s as follows what happens.


switch(str)
{
case "Zaphod": Console.WriteLine("The king"); break;
case "Abhinab": Console.WriteLine("The coder"); break;
case "Ford": Console.WriteLine("The Hitchhiker"); break;
case "Trilian": Console.WriteLine("The traveler"); break;
case "Marvin": Console.WriteLine("The Robot"); break;
case "Agrajag": Console.WriteLine("The Dead"); break;
default: Console.WriteLine("None"); break;
}

For this first a class is generated by the compiler which looks like


Internal class CompilerGeneratedClass
{
internal static Dictionary CompilerGenDict;
}

And then for the switch case the following code is generated.


if (CompilerGeneratedClass.CompilerGenDict == null)
{
Dictionary dictionary1 = new Dictionary(6);
dictionary1.Add("Zaphod", 0);
dictionary1.Add("Abhinab", 1);
...
CompilerGeneratedClass.CompilerGenDict = dictionary1;
}
if (CompilerGeneratedClass.CompilerGenDict.TryGetValue(
str, out num1))
{
switch (num1)
{
case 0: Console.WriteLine("The king"); return
case 1: Console.WriteLine("The coder"); return;
case 2: Console.WriteLine("The Hitchhiker"); return;
...
}
}
Console.WriteLine("None");

What this means is that first time the function is called a Dictionary of strings (key) and int (value) is created and all the cases are stored in this dictionary as the key and an integer as a value is stored against it. Then for the switch statement the string is taken and is queried in the dictionary and if it is present the number value for the string is returned. Using this number the compiler creates an efficient jump table and it jumps to the target Console.Writeline string.



Now the answer :). The strings are pre-stored in the dictionary. If the strings in the case statement were not constants, changes in them won’t reflect in the dictionary and hence you’d land up comparing against stale value. To avoid this inconsistency the non-constant values are not supported at all.



Obviously for dynamic values the dictionary cannot be used and hence there is no optimization possible for switch-case so one should anyway use if-then-else.

Test Driven Development

A lot have already been said about Test Driven Development (TDD) by a lot of people, but I'd still like to add my 0.02paisa.

We have an internal requirement of checking in UnitTests along with the product code and the code coverage for the unit tests needs to be high. Most of our developers have over 85% code coverage.

In my sources I decided to try out TDD. I used the following steps

  1. Write the method's prototype so that it matches the design doc and throw a NotImplementedException in it.
  2. Write unit-tests in Visual Studio Team System unit-test framework. I try to cover all the requirements, even the ones required for negative testing like pass an invalid handle and catch an ArgumentNullException and verify that the correct argument is mentioned in ArgumentNullException.Param.
  3. After that I run the tests. All the tests obviously fail with lots of X marks.
  4. Then I go about fixing each of the test failures by adding the functionality in the code.
  5. After each fix (or couple of them) I run the tests and the red marks keep changing into test passed green ticks.
  6. Once I'm done, I run with code coverage and then add more tests if required to cover the blocks which were not touched by the tests.

Even though the system looks simple it has helped me enormously by catching multiple bugs at the beginning. Even trivial tests like tests for GetHashCode and operator overloads found issues :) The fun in seeing all those X marks disappear one after the other brings in a childish zeal to get them done even faster.

The other goodness is that after every code change later I can easily fire these tests for sanity check.

Conditional Text

We have moved to a new Satellite TV provider some time back. It is time to pay the quarterly bill, so I dug up their manual to look for online payment options. Sure enough there was a section on "Internet payments". I opened the section and it had one line. "For Internet payment options click here"!! How the hell am I supposed to click on a paper?

The reason for the line is simple enough, they are just distributing printed copies of their online documentation.

I shared this with couple of friends and the discussion soon turned to the issues with maintaining multiple versions of the same document. I figured out soon enough that they have not heard about conditional text supported in most DTP software. I was in the Dev team for Adobe FrameMaker and it was one of the features in the product. It works very much like the following C* kind of code


#if Web
Console.WriteLine("Click <a href=\"http://www.abhinaba.com\">Here</a>");
#elif Doc
Console.WriteLine("Visit http://www.abhinaba.com");
#endif

If the symbol WEB is defined then the fancy Click Here is printed else the URL is printed out. Conditional Content works very much like this. You can define document wide variables and associate text, images (any supported content) with these variables. Later you switch on/off one or more of these variables to print out various versions of the same doc. So all your common content remains common and you have the ability to pick/select from the rest.

No idea if Office supports this. But with the powerful collaboration features supported in Word, I highly suspect that this is indeed supported.

Change the world or go home

Saw this via Steve Clayton's blog. This is going to be my new wallpaper...


Funny messages are not always funny

I used to work in a Company where Easter Eggs used to be considered a feature and there used to be a official maintainer for it (I used to maintain both the Easters listed here and more). I used to feel that Microsoft shouldn't have moved away from inserting Easter eggs and should've stuck with funny messages in its Software. Microsoft Max (now canned) use to give really funny messages like suggesting that I get coffee as the installation may take some time.

However, with time I have realized that funny messages are not always funny (even though I still believe Easter eggs are). If you look up the demographic usage data of Orkut it is mostly used in Brazil (60%) and the 3rd highest usage is in India (12%) and growing astronomically. Server failures in Orkut is given out as a "Bad, Bad Server. No donut for you" message. Now the problem is in India we do not eat Donut and I have a ton of non-geek friends who've never been to the US and have no idea what a donut is. One of them got majorly irritated with the message.

I guess for free services where there is no paying customers it's OK to have these kind of funny light-hearted messages, but still you need to target your jokes well. Lets hope in the Future we have India servers throwing up "Bad Bad server, no Vada for you" messages :)

Monday, December 04, 2006

Binary Banner

Cross posted from http://blogs.msdn.com/abhinaba/archive/2006/12/04/binary-banner.aspx

BoingBoing has a story of a store that sells t-shirts with offensive messages spelled out in binary. I think its a nice way to generate email signature or web-page banner where you can really say offensive stuff and get away with it. I wrote the following code in Ruby which takes any word and spits out the binary ASCII representation.


ARGV.each do str
def PrintBin(ch)
mask = 0x80
while mask != 0
print (if (ch & mask) == 0 then "0" else "1" end)
mask >>= 1
end
end

str.each_byte do ch
PrintBin ch
end
print "\n"
end

My Ruby is completely rusted so it took me some time to get this done. Later I tried writing the same code in C#. It took me over 3 times the LOC it took me to do it up in Ruby. I'm sure a experinced Ruby programmer can make this even more simpler and concise.


C:\MyStuff\Code\Ruby>BinaryBan.rb Krikkit
01001011011100100110100101101011011010110110100101110100


I have already started using it on my web-site

Tuesday, November 28, 2006

Using m_ prefix

Cross posted from http://blogs.msdn.com/abhinaba/archive/2006/11/28/m.aspx

We all know that Hungarian notation is bad. That has been debated a thousand times and closed upon. It has been proven that having type information as the variable name can lead to trouble. Some nice examples are here and here.

However, though most developers agree with the issues with type information in the variable name, there is some lack of clarity on the other aspects of variable naming. Like the m_ prefix. Many developers believe that it's ok to use m_ for non-public variables, especially because it can be easy to get confused between local and instance variables. Some even prefer just an underscore prefix.

The .NET Fx guidelines and MS internal coding guidelines clearly calls out against it and so does tools like FxCop and StyleCop. The reason is simple; it looks ugly and has other repercussions. For example if one uses m_ for instance variables, then he might want to call out static variables with s_ and global variables (yea C# is exempt) with g_. So one falls into the same trap while changing a static to an instance variable or vice-versa.

Moreover, these prefixes are simply not needed. The guidelines suggested way of using a this. prefix works much better, as you clearly use the this pointer indicating that the reference is to an instance variable. Topics like these turn into religious war during code-reviews or reviews of team wide coding guidelines. I personally believe that things like prefixes has no place in todays world of coding…

Tuesday, November 21, 2006

Actually that should be one of the first zunes in India, but hey what the ....

Our dear AmitChat the resident gadget maniac got himself a Zune (nah, not the Brown one). This is sure to be one of the first Zune's to come into India. He got it from Redmond and costed about $260.

That's me holding it with its smaller bro in the other hand ;). As they say bigger the better (I'm referring to the screen size :)



Sunday, November 19, 2006

Is it for him or her??

I accompanied one of my friend to the Central mall in Hyderabad. He wanted to buy a present for his fiancee. I was acting as the experienced consultant :)

We approached the watch salesman and my friend told him "I'm looking for a present for my would be" the salesman asks him back "is it for a him or her". We were stunned. This is India, I thought we don't talk in these lines :)

Friday, November 17, 2006

Program performed illegal operation. Let's call the police

Cross posted from http://blogs.msdn.com/abhinaba/archive/2006/11/17/program-performed-illegal-operation-let-s-call-the-police.aspx

One of our Colleague's young kids were working on a computer when it popped up a message "Program has performed illegal operation and will be shut down". He got a urgent call from his 9 year old daughter "Dad, does this mean that the police will come?".

So next time you ignore a UX guideline think thrice.

And yes this is a true story and I didn't cook it up.
IE 7 menu bar

Cross posted from http://blogs.msdn.com/abhinaba/archive/2006/11/17/ie-7-menu-bar.aspx

I'm using IE 7 for some time and lovin it.

I had believed that IE has done away with the menu. Whatever functionality I needed were available through the Tools and Page split buttons in the toolbar and I always printed using Ctrl+P so I never felt the need of the Menu. However, I just found out some time back from Amit that when you hit the alt button the menu magically appears and then magically disappears!!!

I have no idea what made the IE team come up with such a weird non-discoverable feature! Its so non-standard design. I understand the need of minimal UI and that WinForm enumerates the Alt key as System.Windows.Form.Keys.Menu but would've never figured out the association :)

Thursday, November 16, 2006

Scheme of things

Programming in Static OO languages for a long time numbs the brain. These languages are designed to be simple and efficient. These criteria not necessary create beautiful languages. In the world of C++, C# our imagination get severely restricted.

Take for example the expression x + y. In scheme you can code this as

(define (addAbs x y)
((if (> y 0) + -) x y))

(addAbs 4 -5)

The if expression is very interesting. It actually compares y with 0 and returns a operator (+ or -). Its simply beautiful :)

Tuesday, November 14, 2006

Black day for Indian SW industry and NCR

Today we got the shocking news of the kidnap of Adobe India head's son. Being a father I can imagine the trauma the family is going through. Its a disgrace for NCR (National Capital Region). It's high time police acted up and brought these element under control.

I pray for early recovery of Naresh's child...

I had worked in Adobe India and had known Naresh personally. I had also met Naresh's baby, then only about a year old. Naresh is one of the most amazing people I have ever met in my life. He used to know each and everyone working in Adobe and what they worked on. In a party he actually asked my wife how she's finding NOIDA and whether she plans to start teaching again. We were amazed how he remebered that she used to be a teacher back in Bangalore.

Monday, November 13, 2006

Tea-Shots

When I visited USA for the first time I was surprised by the size of the servings. Specially the sizes of drinks (Starbucks starting from Tall :) ). I remember asking for a large Coke in a Panda Express outlet and was handed over a bucket of coke. In contrast here in India you get miniature size drinks, like the one I'm holding. It's a cup (??) of Chai

Get Indian Rope Trick

Cross posted from my MSDN Blog

Even though Wikipedia expresses doubts over the validity of the great Indian rope trick I saw a variant of it in MS India. I call it the great indian ladder trick.

Monday, July 31, 2006

The CLR Nullable DCR works!!!!!

Cross posted from http://blogs.msdn.com/abhinaba/archive/2005/08/24/455765.aspx

CLR took a DCR some time back on how nullable types are implemented. See here and here to find out more about the DCR. I found from one of the internal DLs that the fix was already in the RTM bits.


I wrote a small piece of code which should work only with the DCR changes and kept it aside so once this DCR gets implemented I'd try it out. So each time I upgraded to a new build of VS/CLR I built/ran this code to see if it works. And it just did, with my todays upgrade to about 10 day old build in our lab. The new nullable type after becoming a basic runtime intrinsic just rocks. I have put in comment all the failures that used to happen previously with the same piece of code....


// this code works only with the latest bits of
// Visual Studio 2005 (C#2.0) and will fail to
// compile/run with older Beta2 bits

static
void Main(string[] args)
{
int
? val = 1;
int? nullval = null;


// this always worked
if (nullval == null
)
Console.WriteLine("It worked"
);

// this used to fail before and I think one of
// the biggest issue with the previous implementation
object
nullobj = nullval;
if(nullobj == null
)
Console.WriteLine("It worked"
);


// previously required
// box = Nullable.ToObject<int>(val); argh!!!!
object
box = val;


// If you do not need exceptional code
// (that's code that throws exception)
//
you needed to do int? unbox = Nullable.FromObject<int>(box);
int? unbox = (int
?)box;
if
(unbox == val)
Console.WriteLine("It worked again"
);


int intval = (int)box;
if
(intval == val.Value)
Console.WriteLine("attained Nullable Nirvana"
);


int x = 10;
object
y = x;
// Previously Exception!!! cast is not valid
int? z = (int
?)y;


IComparable c = val;
// Previously Exception!!! : object type cannot be
// converted to target type
if
(c.CompareTo(box) == 0)
Console.WriteLine("I have seen it all"
);


// compilation failure
IComparable<int
> ic = val;
if(ic.CompareTo((int
)box) == 0)
Console.WriteLine("Wow there is even more to see"
);
}


The output of the program is


It worked
It worked
It worked again
attained Nullable Nirvana
I have seen it all
Wow there is even more to see

Frame Arrangement in image strips used for animation

Cross posted from http://blogs.msdn.com/abhinaba/archive/2005/08/16/452080.aspx

Sometimes we get so used to things being the way they are we stop questioning them. We always have the perception in mind that individual frames of animated logo in a Bitmap strip is always horizontally arranged. I remember writing code to extract icons from a image lists that store individual frames of an animation sequence one after the other horizontally using something like


animationIcons = new Icon[bitmapStrip.Width / 16];
for (int
i = 0; i < m_animationIcons.Length; i++)
{
Rectangle rect =
new
Rectangle(i*16, 0, 16, 16);
Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat);
animationIcons[i] = Icon.FromHandle(bmp.GetHicon());
}


Even winforms ImageList works on this assumption that the AddStrip method of the ImageCollection in the control has the images placed side-by-side. However this is not at all the optimal placement of images. Read it on Raymond Chen's blog .....

Function generator in C++

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/08/12/450868.aspx

Some of us were just chatting about my previous post about function generators and we wondered about whether it can be done in C++ without using function pointers.... Most of my C++ knowledge has been rusted beyond repair but I thought even though its not possible to do directly, one can overload the ( ) operator to simulate this. So it should be possible to code so that the following is valid

FuncGen(Adder)(p1, p2)


Here the part in red semantically behaves like a function generator returning different functions based on the flag you pass. So here's some code in C++ that does it. Again I want to stress that this is not a function generator in C++, it just simulates something like it so that a statement like FuncGen(Adder)(p1, p2) will actually work....


#include <iostream>
#include
<string>
using namespace std;


enum FuncType
{
Adder,
Subtractor,
Multiplicator,
};


class CFunc
{
public
:
FuncType m_funcType;
template <typename
T>
T
operator
()(T p1, T p2)
{
if
(m_funcType == Adder)
return
FuncAdder(p1, p2);
else if
(m_funcType == Subtractor)
return
FuncSub(p1, p2);
else if
(m_funcType == Multiplicator)
return
FuncMult(p1, p2);
}


private:
template <typename
T>
T FuncAdder(T p1, T p2)
{
return
p1 + p2;
}
template <typename
T>
T FuncSub(T p1, T p2)
{
return
p1 - p2;
}
template <typename T>
T FuncMult(T p1, T p2)
{
return
p1 * p2;
}
};


CFunc cfunc;
CFunc& FuncGen(FuncType ftype)
{
cfunc.m_funcType = ftype;
return
cfunc;
};


int main(int argc, char* argv[])
{
int
p1 = 5, p2 = 1;
cout << FuncGen(Adder)(p1, p2) << endl;
cout << FuncGen(Subtractor)(p1, p2) << endl;
cout << FuncGen(Multiplicator)(p1, p2) << endl;
return
0;
}


Instead of using a global variable like cfunc I could have also created a object on the heap in FuncGen and later deleted it but since I have been coding in C# so long that I felt too lazy to write a delete statement.

My Experiments with continuation in C#

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/08/11/450785.aspx

The blogs are buzzing with continuation support in C# 2.0 and what cool things can be done with it. http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons explains the concept of continuation extremely well. I also found Don Box's posting http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx very interesting.


Traditionally in languages like C/C++ functions works off the stack. Each function call creates a new frame on the stack in which current context is stored (return address, current stack pointer) and then any arguments to the function is pushed in. The function also creates all its local variables on the stack and pops them off before the function returns. So when the function returns, all information regarding the functions execution is lost. So in case you call the function again it starts from the beginning.


However in continuation this is not what happens. Here the state of the function is preserved and when you call back on the function it starts off from where it left off. All the function locals are allocated on the heap so that their values are preserved when the function is called again. In C# we have a *very* restricted version of continuation using the yield return statement. Even though its restrictive it allows some very cool way of programming.


Here a sample of code where I have a container containing my friends names and I enumerate them.


public class MyContainer
{
string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
public IEnumerator<string> GetEnumerator()
{
for (int index = 0; index < m_friends.Length; index++ )
yield return m_friends[index];
}
}


class Program
{
static void Main(string[] args)
{
MyContainer myContainer = new MyContainer();
foreach
(string str in myContainer)
Console.WriteLine(str);
}
}


You can have multiple enumerators too as in


public class CoolContainer
{
string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
public IEnumerable<string> straight
{
get {
for (int index = 0; index < m_friends.Length; index++ )
yield return m_friends[index];
}
}
public IEnumerable<string> Reverse
{
get{
for (int index = m_friends.Length - 1; index >= 0; index--)
yield return m_friends[index];
}
}
}


class Program
{
static void Main(string[] args)
{
CoolContainer cc = new CoolContainer();

foreach
(string str in cc.Reverse)
Console.WriteLine(str);

Console.WriteLine("----------------");

foreach
(string str in cc.straight)
Console.WriteLine(str);
}
}


Seeing all these work I got carried away and tried to do the enumeration without the foreach as in



IEnumerator<string> enumerator = myContainer.GetEnumerator();



enumerator.MoveNext();


Console.WriteLine(enumerator.Current);


enumerator.MoveNext();


Console.WriteLine(enumerator.Current);


enumerator.Reset();



enumerator.MoveNext();


Console.WriteLine(enumerator.Current);



My idea was that after the call to Reset internally I would be able to reach the first element in the list as the index variable will be reset. That’s where I got the surprise in the form of a NotSupportedException in the call to Reset. I send emails to the CSharp user group and found out that its indeed not supported and you need to create new enumerator to go back or if the enumerator once runs till end (i.e. one return is executed) then you’ll automatically get the reset you wanted. This means that iterating twice or more using the same iterator works as in



MyContainer myContainer = new MyContainer();
foreach
(string str in myContainer)
Console.WriteLine(str);
foreach (string str in myContainer)


Console.WriteLine(str);

Anonymous methods and closures in C#

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/08/08/448939.aspx

Anonymous Method

One of the new features in C#2.0 being shipped in with Whidbey is anonymous methods. Though this at first glance looks like an easy way of creating delegates, where instead of having to create a new function which the delegate will call you can pass the code inline.

Before C#2.0

class MyClass
{
delegate void MyDelegate
();
static public void
Function()
{
Console.WriteLine("I'm called"
);
}

static void Main()
{
MyDelegate writeMessage = new MyDelegate
(Function);
writeMessage();
}
}


With C#2.0 and anonymous methods: the Function is eliminated and the same piece of code can be written more elegantly as follows


class MyClass
{
delegate void MyDelegate();
static void Main()
{
MyDelegate writeMessage = delegate ()
{
Console.WriteLine("I'm called"
);
};
writeMessage();
}
}


For more details on Anonymous methods check out http://msdn.microsoft.com/msdnmag/issues/04/05/c20/default.aspx.


However, there is more to it than just getting a short hand way of writing code. With anonymous methods you can now do a lot of things in C# which are commonly done in Functional languages. Consider the code below which is actually a function generator.


class Program
{
delegate void MyDelegate
<T>(T t);
enum
FunctionType
{
WithPrefix,
WithoutPrefix
}
static MyDelegate<T> FunctionGenerator<T>(FunctionType
fType)
{
int i = 0;

if (fType == FunctionType
.WithPrefix)
{
return delegate(T t)
{
Console.WriteLine(i.ToString() + ": "
+ t.ToString());
i++;

};
}
else
{
return delegate
(T t)
{
Console.WriteLine(
t.ToString());
};
}
}


static void Main(string[] args)
{
MyDelegate<int> mdWith = FunctionGenerator<int>(FunctionType
.WithPrefix);
mdWith(5);
mdWith(5);

MyDelegate<string> mdWithout = FunctionGenerator<string>(FunctionType
.WithoutPrefix);
mdWithout(
"Hello"
);
}
}


The output is
0 : 5
1 : 5
Hello


As in the above piece of code you can create Function Generator that actually return different implementations based on requirement. For another interesting sample see Don Box's blog http://pluralsight.com/blogs/dbox/archive/2005/04/17/7467.aspx


Closure


For any languages which allow passing around functions as arguments or functions returning another function the Closure abstraction is very important. For more info on Closure see http://en.wikipedia.org/wiki/Closure_(computer_science. C#2.0 supports closure by the use of anonymous methods.


Closure is a function along with its lexical environment (available variables and their values) when the function is created.


int i = 10;
return delegate(T t)
{
Console.WriteLine(i.ToString() + ": "
+ t.ToString());
};


Since the variable i was available with the value 0 when the Anonymous method was created, inside the method, i will be available with the same value when the method is called via the delegate.


From the definition of Closure it can be inferred that Closure remembers the values of the variables during its creation. However in C# the outer local variable (i in this case) is shared with the anonymous method by creating it on the heap. This means any change to it in the anonymous method changes the original value and when the method is called the second time it gets the modified value of i as 1 (see second line of output). This leads many to argue that anonymous method is not actually a Closure as by its definition the value of a variable at the time of creation of the Closure should be remembered and not modifiable.


Check out the link http://blogs.msdn.com/brada/archive/2004/08/03/207164.aspx on how the implementation of Anonymous methods in C# have led to interesting issues.

marking required fields on forms/UI
Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/06/26/432832.aspx
How do you communicate to users which fields on a UI is required and which is optional? This was the questions I was trying to answer while implmenting the Team Build Type creation wizard. Though there exists some common conventions in Web forms like marking the fields with asterix and putting something like "Fields marked with an asterix * are required" somewhere on top, there seems to exist no convention to do this on Windows user interfaces.
In team system the work item tracking UI does this by making the background color of the required fields with the same color as tooltip (yellow) and then as soon as the user types in some thing in them the color changes back to window backgorund color (white). So the user can quckly review the form and can locate fields that are left to be filled as they are marked with a different color (yellow).



I liked this idea a lot and wanted to do the same thing with our wizard and Start build forms. But could'nt get that approved by the User Experience team becuase they think that on wizards the visual cue should come from the enabling of the Next button. The idea is that once the user has filled in all the required fields in the page Next should get enabled so that he can move to the next page. I think this works well only when the number of controls on the Wizard page is less, other wise the user will keep trying to guess why the next button in not getting enabled. Since wizard guideline clearly calls out against crowding too many things in one page, I guess this is fine but still think we should move towards a common guideline on marking required fields and I think the background color change is a fine way of doing just that.

Command line tool syntax

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2005/01/20/357058.aspx

Command line interface (CUI) designs for many of the tools found with VS or in Windows were to include a bunch of individual commands or exe with options or flags.

To get a directory listing: dir <options> as in dir c:\temp /w
To create a directory: md c:\temp\foo
To delete a directory: rd /s c:\temp\foo

So even though all the tasks pertain to directory or path handling , you need to know three command to do the task. This design is slowly changing to the format of command <action> [</options:attributes>]

For example if we change the above commands to this format with the common command called dir, we will be getting
To get a directory listing: DIR list c:\temp /w
To create a directory: DIR make c:\temp\foo
To delete a directory: DIR rem c:\temp\foo /s

So effectively user learning is reduced. One can argue that he still needs to remember the names of the actions. But in the previous case he needs to remember rd, md, dir. Now he knows everything to do with path handling is to be done with DIR. So he can run DIR /? to get the list of actions and then do a DIR list /? to know the options for listing. The other advantage is namespace pollution in terms of the names of the executables also reduces.

This new format has also been adopted in the VS as in the source control tool. So to get the listing of all workspaces on MyServer you run the command
h.exe workspaces /s:MyServer
To create a new workspace you run the command
h.exe workspace /new MySpace /s:abhinab-test
I guess going forward we will see more and more of the standard OS commands also taking up this format. A very common example is the NET command
Error Messages

Cross posted from http://blogs.msdn.com/abhinaba/archive/2005/01/12/351201.aspx

Frequently we are presented with error message pop-ups with messages like "Unable to open file". Error messages are popped up when something has gone wrong. If SW cannot convey to the user what went wrong and what he can try to fix the problem, it might as well not show the error message at all.
So all errors messages must have three components
  • Notification
  • Explanation
  • Solution
A good example for a Team Build scenario would be
Unable to connect to the build machine "BuildServer01"
Make sure that the machine is connected to the network and the TeamBuild Service is running on it.
So all error messages that have one sentence in them are most probably not as helpful as it states what happened and not what can be done to rectify it.
Another important thing to note is that the user is never to be blamed for any error. If the action he did was dumb then we are at fault that we did not restrict him from committing a dumb action.

Cross-posted from http://blogs.msdn.com/abhinaba/archive/2004/11/16/258046.aspx

I always tried to figure out that in spite of the fact that India will become one of the largest PC markets in the future and that India SW engineers are everywhere, why is there no mainstream software in Indian languages. Yea there is Windows Hindi, and I read somewhere that Windows Bengali is also coming up, but thats after years of existance of Windows in other not so prevalent languages. I always got the answer that this is mainly due to SW piracy. Its so prevalent here that almost no one pays for software and hence the SW companies do not have revenue motive to localize their software for India. A further study revealed that 63% of al PCs in India ship with pirated Windows!!!! A person who is ready to use a pirated OS, will surely not pay for any other software he installs on that box. So this can lead to millions of dollars lost in revenue for the SW companies.

Its so bad here that frankly till date I have rarely seen a home user using a legitimate copy of Windows. Even when I have seen that, it was in branded PCs which came pre-installed with the OS. The moment I congratulated someone for using a legitimate OS, within a minute he figures out that he was made to pay for the OS by the PC vendor, and he felt bad that he could have got the pc for less if he had a way for not opting for the OS.

This issue is not only with home users, its every where, its in cyber cafe's, in SOHO, even in mid size organization and colleges. PC vendors are adding fuel to fire by shipping PCs with Linux pre-inslalled on them. This serves as a simple solution to buy a branded PC at a lower cost. People buy this PC, goes home and installs Windows from pirated CDs which cost them around Rs.100, thats a little more than $2. So now you have a branded PC running Windows sans the price.

Many have suggested that low cost software is a solution to this. I absolutely do not agree with this. It may be a part of a solution but not the solution in itself. SW piracy has become so prevalent that no one feels like paying for it. You are considered a fool if you pay. What is required is a change in the way of thinking, user education and pride of ownership. People need to know that its equivalent to stealing, and is a punishable offense. This is a bad thought though, with 63% of all PCs shipping with pirated OS, it brings most my friends and relatives who own a PC in this category...

Saturday, July 29, 2006

The CEO of Microsoft Corporation, Steve Balmer is visiting Hyderabad on the 15th (next Monday). There's a lot of excitement around this. He is supposed to inaugurate a part of the new Microsoft Campus and also to lay foundation stone for the second phase.

Hyderabad is very proud to house the MS IDC, a race it won by defeating several other cities. This visit is raising lot of rumors and some sites have gone as far as to predict that the new center will slowly grow and employ 5000 developers and will be the largest outside US. Check out http://economictimes.indiatimes.com/articleshow/915404.cms. This appears to be a very distant reality. Personally I’m eager to hear what he has to say.

MS was working out of rented facilities that spread across multiple floors in different buildings. Since these building are part of Software Parks, some additional benefits come with it. You get banks, ATMs, florists, travel agents, restaurants all at the same place.

However, like most people I prefer the company having its own campus. You get a feel of unity and get to meet a lot more people from your own company. Casual chats over a cup of coffee can give amazing insight into a different technology domain which the other guy sharing your table works in. I just can’t wait to get into the new building once it start functioning…