Search

Monday, May 19, 2008

Model, View, Controller

Chocs

These days the whole world is abuzz with the Model, View, Controller (MVC) architecture. This is not something new and is known by computer scientists for close to 30 years. I guess the new found popularity is due to the fact that this has heavy application is web development and lot of main-stream web development platform are putting in support for this. Ruby-on-rails and ASP.NET MVC are classic examples.

Coding horror has a nice post on this topic. I liked the following statement it made

"Skinnability cuts to the very heart of the MVC pattern. If your app isn't "skinnable", that means you've probably gotten your model's chocolate in your view's peanut butter, quite by accident."

I actually use a very similar concept. The moment I see an application's architecture (be it an interview candidate or a friend showing off something) I ask the question "Can you write a console version of this easily?". If the answer is no or it needs a re-design it means that the separation of model, view and controller is not correct. You are going to have a nightmare if you write and maintain that software.

Saturday, May 17, 2008

You need to be careful about how you use count in for-loops

Negotiating

Lets consider the following code

 MyCollection myCol = new MyCollection();
myCol.AddRange(new int[] { 1, 2, 3, 4, 5, });
for (int i = 0; i < myCol.Count; ++i)
{
Console.WriteLine("{0}", i);
}


 


What most people forgets to consider is the condition check that happens for the for loop (in Red). In this case it is actually a call to a method get_Count. The compiler doesn't optimize this away (even when inlined)!! Since the condition is evaluated after each iteration, there's actually a method call happening each time. For most .NET code it is low-cost because ultimately it's just a small method with count being returned from an instance variable (if inlined the method call overhead also goes away). Something like this is typically written for count.

public int Count
{
get
{
return this.count;
}
}

Someone wrote something very similar in C, where in the for-loop he used strlen. Which means that the following code actually is O(n2) because each time you are re-calculating the length...

for(int i = 0; i < strlen(str); ++i) {...}

Why the compiler cannot optimize it is another question. For one it's a method call and it is difficult to predict whether there's going to be any side-effect. So optimizing the call away can have other disastrous effect.


So store the count and re-use it if you know that the count is not going to change...

Tuesday, May 13, 2008

Alternatives to XML

Halloween

Though not as much as the Jeff Atwood I don't like overuse of XML as well. In our last project we used XML in a bunch of places where it made sense and also planned to use it in bunch of other places where it didn't. For some strange reason some folks think its actually readable and suggested we use XML to dump the user actions we recorded because it's easy to parse and is human readable/editable. While I'm perfectly fine doing it in XML, but definitely not for that reason.

Anyways, sense prevailed and even though we do store it in XML we dump out automation source code in obviously more readable C#/VB.NET.

Before I completely get sidetracked let me state that this post is not about XML or about JSON but about the fact  that there exists many alternatives to both. Head on to here (via Coding Horror)...

What is the similarity between Windows and Textile Industry

...they both use threads and fibers :)

Pink....

Most people are aware of processes and threads. Windows offers an even finer granularity over execution. This is called Fiber. To quote MSDN

A fiber is a unit of execution that must be manually scheduled by the application. Fibers run in the context of the threads that schedule them.

The obvious question that should come to managed code developers is whether .NET supports Fibers? The answer is from 2.0, CLR does support fiber mode. This means that there are hosting APIs using which a host can make CLR use Fibers to run its threads. So in effect there's no requirement that a .NET thread be tied to the underlying OS's threads. A classic example is that of SQL Server which hosts .NET in fiber mode because it wants to take care of scheduling directly. Head over to here (scroll down to SQL Server section) for an excellent read about this topic.

There's also the book Customizing the Microsoft .NET Framework Common Language Runtime written by Steven Pratschner which has a chapter on customizing CLR to use Fibers. I have already ordered the book. Once it comes in and I get a chance to read it, I'll post more about this.

Monday, May 05, 2008

My workstation layout

Our team just moved to a new building in Microsoft India campus. A lot of people were going around checking out other people's office. I got asked couple of times about my workstation layout and thought I'll do a quick post on that.

Workstation

Like most people in our team I use a dual monitor setup. Last time I estimated I spend about 12% of my life looking for things (40% of it for my car keys). So even though there are people who use 7 monitors I'm never going to join that gang and bump that number to 30% by adding the time to search for my app window. And Microsoft will definitely not fund those many monitors either :). So for me 2 is enough.

Both monitors I have, are standard HP1965 (19" monitors) hooked on to ATI Radeon cards. One of the monitors (the one on the left) is looped through a KVM switch and I can rotate that among the other 2 machines that I have. The other I have rotated in portrait (vertical) mode and use it primarily for coding. The image below should explain why

Workstation

This provides a much better code view. In the font size I use (Consolas 9pt) I can see 74 lines of code vs 54 in the landscape mode. So this means 37% more!!! Since I have ATI card I use Catalyst Control Center to rotate the display.

I also prefer dark background and use white/light-color text on it. My eyes feel better with it. I keep both Visual Studio and GVim in dark color mode. You can download my vssettings from here and .vimrc from here.

That kind of rounds up the workstation layout that I use in office. I try my best not to work on the laptop directly.  I TS on to it in case I need to use it for any reason. When I took the picture it was quietly napping on the other side of my office :)

Friday, May 02, 2008

Struggling with email overload

It literally rains email at Microsoft (if you've been to Seattle/Redmond you know why :) )

I've always struggled to keep up with the email in Microsoft. When I joined I was stunned with the downpour. The number of email I got on the first day was more than what I got in a month in Adobe. The situation worsened when I went through team transition last month because for some time I had to listen to the email threads of both teams DLs (distribution list).

I have tried using various techniques to cope before. This included complex labyrinth of folders (I've met folks with 9 level deep folder nesting), rules, search folders, you name it!!

All of them failed until I saw this post from John Lam. This talks about reverse pimping outlook. Even though I didn't go to the extreme he did, I basically got the following done

  1. Removed all rules, toolbars, folders
  2. Created 3 simple folders Archive, Followup, Automated
  3. Created one big fat rule to move all emails from automated DLs (e.g. checkin notices) to the automated folder
  4. Copy pasted macros from Johns blog and setup toolbar buttons to launch these macros and also associated short-cuts with these. Go to John's blog for the macros or download from here
  5. Effectively all emails from human beings land up in my inbox.
  6. When an email comes I read it. After that I have only 3 options
    1. Delete it
    2. Hit Alt+R to archive it (this launches a macro to mark the email as read and moves it to the archive folder)
    3. Hit Alt+U for follow up (this launches a macro to flag the email to be replied by EOD and moves it to the follow up folder)

This ensures that I read all emails that come to me, I never miss an email now. I go on hitting zero emails in the inbox couple of time a day. Couple of times a day I scan the followup folder to ensure that I have replied/taken-action on all emails in the follow-up folder.

Even though the process sounds complex it's working miraculously for me for the last two months. I can finally forget about email overload.

My outlook looks as shown below. It's more cluttered than John's version because I need to see upcoming meetings in the right pane.

Thursday, May 01, 2008

Forcing a Garbage Collection is not a good idea

Our cars 

Someone asked on a DL about when to force a GC using GC.Collect. This has been answered by many experts before, but I wanted to re-iterate. The simple answer is

"extremely rarely from production code and if used ensure you have consulted the GC folks of your platform".

Lets dissect the response...

Production Code

The "production code" bit is key here. It is always fine to call GC.Collect from test/debug code when you want to ensure your application performs fine when a sudden GC comes up or you want to verify all your objects have been disposed properly or the finalizers behave correctly. All discussion below is relevant only to shipping production code.

Rarely

A lot of folks jumped into the thread giving examples of where they have done/seen GC.Collect being used successfully. I tried understanding each of the scenarios and explaining why in my opinion it is not required and doesn't qualify to make it to the rare scenario. I have copy pasted some of these scenarios with my response below (with some modifications).

  1. For example, your process has a class which wraps a native handle and implements Dispose pattern. And the handle will used in exclusive mode. The client of this class forgets to call Dispose/Close to release the native handle (they rely on Finalizer), then other process (suppose the native handle is inter-process resource) have to wait until next GC or even full GC to run Finalizer, since when Finalizer will run is not expected – other process will suffer from waiting such exclusive sharing resource…
    This is a program bug. You shouldn’t be covering a dispose pattern misuse with a GC call. You are essentially shipping buggy code or in case you provide the framework then allowing users to write buggy code. This should be fixed by ensuring that the clients call the dispose and not by forcing GC. I would suggest adding an Assert in the finalizer in your debug bits to ensure that you fail in the test scenario. In case of Fx write the right code and let performance issues surface so that users also writes the right code
  2. Robotics might be another example—you might want time-certain sampling and processing of data.
    .NET is not a Real time system. If you assume or try to simulate Real Time operations on it then I have only sympathy to offer :). Is the next suggestion to call all methods in advance so that they are already jitted?
  3. Another case I can think of is the program is either ill-designed or designed specially to have a lot of Finalizers (they wrap a lot of native resources in the design?). Objects with Finalizer cannot be collected in generation 0, at least generation 1, and have great chance to go to generation 2…
    This is not correct. The dispose pattern is there exactly for this reason. Any reason why you are not using dispose pattern and using GC suppress in the dispose method?
  4. Well, one “real world” scenario that I know of is in a source control file diff creation utility.  It loops through processing each file in the pack, and loads that entire file into memory in order to do so it calls GC.Collect when it’s finished with each file, so that the GC can reclaim the large strings that are allocated.
    Why cannot it just not do anything and is there a perf measurement to indicate otherwise? GC has per-run overhead. So incase nothing is done it may so happen that for a short diff creation the GC is never run or atleast run for every 10 files handled leading to less number of runs and hence better perf. For a batch system where there is no user interaction happening in the middle what is the issue if there is a system decided GC in the middle of the next file?
  5. A rare case in my mind is you allocate a lot of large objects > 85k bytes, and such size objects will be treated as generation 2 objects. You do not want to wait for next full GC to run (normally GC clears generation 0 or generation 1), you want to compact managed heap as soon as possible.
    Is it paranoia or some real reason? If it holds native resources then you are covered by dispose patterns and if you are considering memory pressure then isn’t GC there to figure out when to do it for you?

In effect most usage are redundant.

Question is then what qualifies as a rare scenario where you want to do a GC.Collect. This has been explained by Rico Mariani (here) and Patrick Dussud (here).

‘In a nutshell, don’t call it, unless your code is unloading large amounts of data at well-understood, non-repeating points (like at the end of a level in a game), where you need to discard large amounts of data that will no longer be used.”

Its almost always when you know for sure a GC run is coming ahead (which you completely understand and maybe confirmed with the GC guys of your framework) and you want to control the exact point when you want it to happen. E.g.in case of a game level end you have burned out all the data and you know that you can discard them and if you don’t GC will start after 6 frames of rendering in your next level and you are better off doing it now as the system is idle and you’d drop a frame of two if it happened in the middle of the next frame.

And obviously you call GC.Collect if you found an issue reported/discussed in the forums and you have figured out a GC bug which you want to work around.

I would highly recommend seeing this video where Patrick Dussud the father of .NET GC explains why apparent GC issues may actually be side-effect of other things (e.g finalizes stuck trying to delete behind the scene STA COM objects).

What is the problem with calling GC.Collect

So why are folks against calling GC.Collect? There are multiple reasons

  1. There's an inherent assumption that the user knows more about when the GC is run. This cannot be true because according to CLR spec there is no standard time. See here. Since GC is plugged into the execution engine it knows best of the system state and knows when to fire. With Silver Light and other cross-plat technologies being mainstream it will become harder and harder to predict where your app is run. There's already 3 separate GCs the desktop, server and compact framework. Silver light will bring in more and your assumptions can be totally wrong.
  2. GC has some cost (rather large):
    GC is run by first marking all the objects and then cleaning them. So whether garbage or not the objects will be touched and it takes awful amount of time to do that. I've seen folks measure the time to do GC.Collect and figure out the time taken. This is not correct because GC.Collect fires the collection and returns immediately. Later GC goes about freezing all the threads. So GC time is way more than what collect takes and you need to monitor performance counter to figure out what is going on,
  3. GC could be self tuning:
    The desktop GC for example tunes itself based on historical data. Lets assume that a large collection just happened which cleaned up 100mb of data. Incidentally exactly after that a forced GC happened which resulted in no data to be cleaned up. GC learns that collection is not helping and next time when a real collection is to be fired (low memory condition) it simply backs off based on the historical data. However, if the forced GC didn't occur it'd have remembered that 100mb got cleared and would've jumped in right away.

Both 2 and 3 are GC implementation specific (differs across desktop and Compact GC) stressing the first point which is most assumption are implementation details of the GC and may/will change jeopardizing the attempt to try out-guess the GC when to run.

Wednesday, April 30, 2008

Ensuring only one instance of an application can be run and then breaking that approach

Whidbey_2005_0409_131710

A question posted on a DL was as follows

"I have an application that allows only one instance on the desktop, how do I force it to open multiple instance for some testing purposes".

Disclaimer: Note that this is kinda hacky and only relevant if you are a tester trying to break something. This shouldn't be treated as a way to achieve anything productive.

Since the user didn't explain which approach is used to ensure only one instance is allowed I'll try listing down the methods I know off and how I can break them.

Using named Mutex:
This is the more resilient approach taken by applications like Windows Media player. Here the application tries to create a named Mutex with sufficiently complicated name to avoid collision. E.g. namespace.app.guid and then try to acquire the mutex. In case it fails to acquire it then an instance is already running and it closes itself. If it acquired the mutex it means it is the first instance and it continues normally. An approach is outlined here.

Even though this seems to be the most robust solution this can be made to fail as well. If an user has sufficient permission he can do a CloseHandle on a Mutex handle created by some other application as well. For this you don't even need to write code. Do the following

  1. Download and install Process Explorer.
  2. Launch it (might need elevation on Vista)
  3. Have an application that uses this approach like my application named SingleInstanceApp.exe. Try launching a second instance and it will fail to open it.
  4. Click on the app finder toolbar button in Process Explorer and drag it to SingleInstanceApp window. This will get this application selected in process explorer.
  5. Select View->Lower Pane View ->Handles or simply Ctrl+H
  6. This will show all the handles created by SingleInstanceApp.
  7. Scroll down looking for the mutexes. At the end the screen looks something as follows Capture
  8. Right click on the mutex and choose Close Handle.
  9. Now try creating the second instance and it will open fine.

Enumerate the names of applications running and see if the app is already running:
This uses a combination of Process.GetCurrentProcess and Process.GetProcessByName(), see an implementation here.

This is easy to break. To do a DOS (Deinal of Service or DOS) just  create another application with the name that the app expects and per-launch it. To open two instances copy the application to another name and open that first and then the original application.

Enumerate Windows

This involves iterating through all the open windows in the system using EnumWindows and then seeing if a Window with a given name or classname is already present. Since the system doesn't guarantee uniqueness in either of the text or class name this can be broken in a similar approach to the first one. However, there are some complications to it as it is difficult to change window text from outside. However, a combination of code injection and SetWindowText win32 API should work.

Tuesday, April 29, 2008

Trivia: How does CLR create a OutOfMemoryException

 

Bargaining

When the system goes out of memory a OutOfMemoryException is thrown. Similarly for stack overflow a StackOverFlorException is thrown. Now typically an exception is thrown as follows (or the corresponding native way)

throw new System.OutOfMemoryException();

But when the system is already out of memory there's a little chance that creating an exception object will succeed. So how does the CLR create these exception objects?


The answer is trivial and as expect, at the very application start it creates all these exception objects and stores them in a static list. In case these exceptions are to be thrown then it is fetched from this list and thrown.


The consequence of handling Stack overflow is even bigger because once the stack has overflown calling even a single method in that thread is equally dangerous and can cause further corruption. That is the material for another post :)

Monday, April 28, 2008

When does the .NET Compact Framework Garbage Collector run

 

Moon

Other than the exact when part this post applies equally for the desktop portion.

Disclaimer: This post is mainly indicative. When the GC runs is an implementation detail and shouldn't be relied on. This is not part of any contract or specification and may (most probably will) change.

The ECMA specification for Garbage Collection is intentionally vague about when an object will be collected (or freed up). The memory management cycle mentioned in the spec is as follows

1. When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
2. If no part of the object can be accessed by any possible continuation of execution, other than the running of finalizers, the object is considered no longer in use and it becomes eligible for finalization. [Note: Implementations might choose to analyze code to determine which references to an object can be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use. end note]
3. Once the object is eligible for finalization, at some unspecified later time the finalizer (§17.12) (if any) for the object is run. Unless overridden by explicit calls, the finalizer for the object is run once only.
4. Once the finalizer for an object is run, if that object, or any part of it, cannot be accessed by any possible continuation of execution, including the running of finalizers, the object is considered inaccessible and the object becomes eligible for collection.
5. Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with that object.

As you can see the specification doesn't even need an implementation to do code analysis to figure out garbage. It can simply use scoping rules (used anyway by the compiler to detect valid variable usage) for garbage detection. The specification also doesn't specify eventually when the objects are collected. The only need is that it is finalized and freed unspecified time later than the time when it goes out of use. This convenient open statement lets each GC implementers to choose whatever they deem fit for the purpose. Since even thread is not specified a concurrent GC or a non-concurrent GC can be used.

However, everyone wants to know exactly when their platform's GC is run. Here goes the non-exhaustive list for the .NET Compact Framework's Garbage Collector

  1. Out of memory condition:
    When the system fails to allocate or re-allocate memory a full GC is run to free up as much as possible and then allocation is re-attempted once more before giving up
  2. After some significant allocation:
    If one megabyte of memory is allocated since the last garbage collection then GC is fired.
  3. Failure of allocating some native resources:
    Internally .NET uses various native resources. Some native resource allocation can fail due to memory issues and GC is run before re-attempting
  4. Profiler:
    Profiler APIs build into the framework can force a GC
  5. Forced GC:
    System.GC class is provided in the BCL to force a collection

Obviously there can be small differences across various platforms on which .NET CF is implemented. However, the differences are small enough to ignore for this discussion.

Even though this list seems small it works pretty well across disparate systems like XBox and Windows Mobile. In the next post I'll try to get into why "production user code should never do a forced GC". I know that statement is a bit controversial (at least it got so in an internal thread).

Wednesday, April 16, 2008

Which end of the egg do you crack. Putting it differently, what is your Endianess

Mr.Egg

Few people seem to know that the word Endianess comes from Gullivers travels. In Gulliver's travel where there were two types of people, the Lilliputs who cracked the small side of their soft boiled eggs and the Blefuscu who used the big side (Big-Endian). Since I'm well networked these days (over Orkut/Facebook/LinkedIn) I make a conscious decision to be Big-Endian while cracking an egg as its the preferred network endianess.

I do not want to delve into the holy endianess war especially because most modern processors allow hardware/software methods to switch it (reminds me of some politicians though :))

However, I do use bit/byte questions as the acid test for fly/no-fly interviews as suggested by this guy. One of them involves asking about the whole endianess business and a code snippet to find out the endianess of the current system. I'm usually looking for something as below

short a = 1;
if (*((char *)&a) == 1)
printf("Little Endian\n");
else
printf("Big Endian\n");
The idea is not to look for an exact code but to ensure that there's no complete ignorance of this area...

Friday, April 11, 2008

Multi-threaded developer

Building....

Once upon a time a kick-ass developer I knew told me that a good developer needs to be multi-threaded and run the following threads

  1. The main worker thread: This is the one used to code up 3-tier applications for your employer. This pays for the rent and for that fancy big car.
  2. The core thread: This is the one that's used to read up data-structures, OS and other fundamental CS stuff which helps you to join into discussion when folks are discussing threaded BST. This also helps you to crack an interview in case you need a new job.
  3. The cool thread: This is the one you use to read up about Silver Light Mobile, ASP.NET MVC Framework, JSON, etc. This keeps you up to date and let's you hang around with other geeks like Scot Hanselman and Don Box

The same person also told me that real programmers do not blog, he asked me "Do you know about Dave Cutler or Linus Torvald's blog?". So I guess we can safely ignore him :)

Wednesday, March 26, 2008

Time for a change

I've been working for some time in Visual Studio Team System (first on the TFS server and then on the testing infrastructure). I was looking for a change and then I happened to talk with the GPM of the .NET COMPACT FRAMEWORK team. The following explains in brief what followed...

NetCF

... and so I landed a job in the .NETCF Garbage Collector and other parts of the execution engine. I'm sure I'll be super busy as the team is heads down into getting Silver Light onto mobile devices and going cross-plat (I guess most folks have heard about SL on Symbian/Nokia).

What this means is that I can (or rather I have to) muck more with .NET (both desktop and CF) without any guilt and can claim that blogging about them is actually a part of my job. So what this means for this blog is that there'll be more hardcore stuff about .NET and an additional Tag called NETCF when I post specifically about it.

In case you are in India and want to work in a Kick-ass team delivering one of the most key technologies for the industry then drop me a line at abhinaba.basu @ you know where. Bragging rights will come for free when you point to all those cool WinMobile/S60/XBox/Zune devices and claim how you coded .NET for it....

Wish me luck...

Monday, February 25, 2008

Coolest reception

 

chauffeur waiting for Google folks at the airport

Rental car chauffeurs waiting for some software company employees. No marks for guessing the name of the company :)

Wednesday, February 20, 2008

International Mother Language Day is back and being celebrated with a lunar eclipse

Interview - Delhi

For starters it doesn't include C++ or C#, even though your mom codes in it :) ...

A lot of people speaking English natively forget the importance of mother language due to its predominance. They take their language for granted. However, each year a bunch of languages become extinct, the latest being Eyak, which got extinct exactly a month ago with the death of Marie Smith Jones the last native Eyak speaking person.

To me this day (21st Feb) is even more special because on this day in 1952 people in Bangladesh laid down their lives while demanding the right to use their own (and mine) mother language, Bangla.

I believe that if we don't actively try to preserve our mother language they will slowly become extinct. One of the most important things to preserve a language is to ensure that they are better covered by technology. Until XP complex script handling was not enabled by default. This resulted in Bangla and other Indic language to be rendered completely wrong on XP. This was a serious deterrent to use Bangla on Windows. I used to have Bangla signature in my email and got countless replies indicating the spelling is wrong. I always replied back to them about how to turn the complex script handling on. Things are changing rapidly, Vista has this on by default and with better keyboard and font support I'm sure using Bangla on Computers will become really easy.

Tuesday, February 05, 2008

Linked on the msdn forum for all the wrong reasons

Flowers Rennaisance hotel - Mumbai

Someone saw a message in their Team Foundation Server history which was "Edited by God" and asked how is this possible on the msdn forum. Someone actual read my blog (or some other's but I tend to believe mine 'cause I'm linked in that page)  which shows exactly how to do that. So now I have a poor-joke (PJ) of mine being featured in msdn :)

Sunday, February 03, 2008

Rain in Lahari resort - hyderabad

For the last couple of days a vast majority of the movie that I'm seeing is somehow landing in Africa. Since I didn't choose any of them (Amit did), it wasn't a conscious decision. Example include The Interpreter, Blood Diamond, Duma.

In all of these movies African music is used in the background, and I've began to like them a lot. I have no idea about the tribe/nationality of these but the sound is just enchanting. Any idea where I can get some good original African music on the web? Buying is also an option if Indian stores/sites have them (which I heavily doubt).

Update: A comprehensive list from someone who obviously knows a lot more about this, link

Tuesday, January 22, 2008

Banana leaves - hyderabad

Sometime back I posted about variable parameters in Ruby. C# also supports methods that accepts variable number of arguments (e.g. Console.Writeline). In this post I'll try to cover what happens in the background. This is a long one and so bear with me :)

Consider the following two methods. Both prints out each argument passed to it. However, the first accepts variable arguments using the params keyword.

static void Print1(params int[] args)
{
foreach (int arg in args)
{
Console.WriteLine(arg);
}
}

static void Print2(int[] args)
{
foreach (int arg in args)
{
Console.WriteLine(arg);
}
}

The above methods can be called as follows

Print1(42, 84, 126); // variable argument passing
int[] a = new int[] { 42, 84, 126 };
Print2(a); // called with an array

Obviously in the case above, using variable number of parameters is easier.

If we see the generated IL for Print1 and Print2 using ILDASM or Reflector and then do a diff, we will get the following diff

.method private hidebysig static void Print2(object[] args) cil managed
.method private hidebysig static void Print1(object[] args) cil managed
{

.param [1]
.custom instance void [mscorlib]System.ParamArrayAttribute::.ctor()

.maxstack 2
.locals init (
[0] object arg,
[1] object[] CS$6$0000,
[2] int32 CS$7$0001,
[3] bool CS$4$0002)
L_0000: nop
L_0001: nop
L_0002: ldarg.0
L_0003: stloc.1
L_0004: ldc.i4.0
L_0005: stloc.2
L_0006: br.s L_0019
L_0008: ldloc.1
L_0009: ldloc.2
L_000a: ldelem.ref
L_000b: stloc.0
L_000c: nop
L_000d: ldloc.0
L_000e: call void [mscorlib]System.Console::WriteLine(object)
L_0013: nop
L_0014: nop
L_0015: ldloc.2
L_0016: ldc.i4.1
L_0017: add
L_0018: stloc.2
L_0019: ldloc.2
L_001a: ldloc.1
L_001b: ldlen
L_001c: conv.i4
L_001d: clt
L_001f: stloc.3
L_0020: ldloc.3
L_0021: brtrue.s L_0008
L_0023: ret
}

Only the lines in Green are additional in Print1 (which takes variable arguments) and otherwise both methods looks identical. In this context .param[1*] indicates that the first parameter of Print1 (args) is the variable argument. The ParamArrayAttribute is applied to the method to indicate that the method allows variable number of arguments.


Effectively all of the above means that the callee is not really bothered with being invoked with variable number of arguments. It receives an array parameter as it would even without the param keyword usage. The only difference is that the method is decorated with the some directive and attribute when param is used. Now it's the caller-code compiler's duty to read this attribute and generate the correct code so that variable number of parameters are put into a array and Print1 is called with that.

The generated IL for the call Print1(42, 84, 126); is as follows...

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] int32[] CS$0$0000)
L_0000: nop
L_0001: ldc.i4.3 ; <= Array of size 3 is created, int32[3]
L_0002: newarr int32 ; <=
L_0007: stloc.0 ; <= the array is stored in the var CS$0$0000
L_0008: ldloc.0
L_0009: ldc.i4.0 ; push 0
L_000a: ldc.i4.s 0x2a ; push 42
L_000c: stelem.i4 ; this makes 42 to be stored at index 0 **
L_000d: ldloc.0
L_000e: ldc.i4.1
L_000f: ldc.i4.s 0x54
L_0011: stelem.i4 ; similarly as above stores 84 at index 1
L_0012: ldloc.0
L_0013: ldc.i4.2
L_0014: ldc.i4.s 0x7e
L_0016: stelem.i4 ; stores 126 at index 2
L_0017: ldloc.0
L_0018: call void VariableArgs.Program::Print1(int32[]) ; call Print1 with array
L_001d: nop
L_001e: ret
}

This shows that for the call an array is created and all the parameters are placed in it. Then Print1 is called with that array.

Footnote:
*interestingly it starts at 1 and not 0 because 0 is used for the return value.
**stelem takes the stack [..arrayindexvalue] and replaces the value in array at index with value

Monday, January 14, 2008

The differences between int[,] and int[][]


Mumbai roadside drinks

A friend asked me the differences between the two. Here goes the answer

int[,]

This represents a two dimensional rectangular array. Let's take the following array definition

int[,] ar = new int[3, 3] { { 0, 1, 2}, 
{ 3, 4, 5},
{ 6, 7, 8}};

The array actually looks like the following



Which as we can see is rectangular. This kind of array is required when for every items represented in the rows there's exactly the same number of items represented in the column. E.g. a board game like chess.


int[][]


This is defined as array of arrays or as jagged arrays. They are created as follows

int[][] ar2 = new int[3][];
ar2[0] = new int[] { 0, 1, 2 };
ar2[1] = new int[] { 3, 4 };
ar2[2] = new int[] { 5, 6, 7, 8 };

The array looks like


Capture


Here the number columns is not the same for each row. A good example of this kind of usage is when we have a array of polygons where each row contains the coordinates of the vertices of the polygon. Since each polygon has different number of vertices (square, triangle, ...) this data-structure is useful in defining it.


Since it's jagged it has to be referenced carefully.

Console.WriteLine(ar2[0][2]); // Prints 2
Console.WriteLine(ar2[1][2]); // Crashes as row 1 has only 2 columns

The jagged array can be padded on the right to convert it to a rectangular array, but this will result in a lot of space wastage. In case of the jagged array the usage of space is sizeof(int) * 9 but if we pad it we will use sizeof(int) * max (column). This additional space can be significant.


Note:


int and 2D arrays were used only as example. This applied equally well to other data-types and higher dimensions.

Sunday, January 13, 2008

Expanding and compressing in Ruby Method calls


2007_0520_184605

One of the things I didn't like in Ruby at all is the support for method overloading. You have no ways to support it in a straight forward way other than to define a single method that takes a variable number of arguments.

def foo(*f)
f.each { |a|
puts a
}
end

foo("Hello", "world")

What the above does is that it converts the multiple parameters into a single array and passes it to the method call. I think this is really bad because method overloading is a very basic requirement.


However, Ruby seemed to support another really weird feature of expanding arrays in method calls. What this means is that if a method accepts a number of parameters and it's called with an array then the array is expanded such that the i'th element in the array is passed as the i'th argument.

def bar(name, address, age)
puts (name, address, age)
end

details = ["Abhinaba", "Hyderabad, India", 42]
bar(*details)

So details[0] is passed to the name parameter and details[1] is passed as address, and so on

Learn a new dynamic or functional language every year


2007_0501_091707

Specially for folks using the C* languages (C/C++/C#) and Java it's very important to learn dynamic/functional languages.

There are three reasons.

  1. With time we will see more and more high level dynamic languages and at the same time many languages like C# will take up dynamic/functional language attributes and hence it's good to be prepared
  2. It'll give a fresh perspective to do the mundane day to day coding. Lambda's in C# won't look alien any more :)
  3. It's fun and will help you survive going through gazillion bulleted lists like this ..

I think the fun part is the most important.

``I think that it's extraordinarily important that we in computer science keep fun in computing. When it started out, it was an awful lot of fun. Of course, the paying customers got shafted every now and then, and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful, error-free perfect use of these machines. I don't think we are. I think we're responsible for stretching them, setting them off in new directions, and keeping fun in the house. I hope the field of computer science never loses its sense of fun. Above all, I hope we don't become missionaries. Don't feel as if you're Bible salesmen. The world has too many of those already. What you know about computing other people will learn. Don't feel as if the key to successful computing is only in your hands. What's in your hands, I think and hope, is intelligence: the ability to see the machine as more than when you were first led up to it, that you can make it more.''

Alan J. Perlis (April 1, 1922-February 7, 1990)

Monday, December 31, 2007

Open a beer bottle with paper

 

If I knew this during my college years my teeth would've been in better shape now :)

For more life hacks head here.

Wednesday, December 19, 2007

Giving up on Ubuntu

Whidbey_2005_0409_131710

I have an old hp laptop (1.3 GHz, 512 mb RAM) lying around on which I'm trying to install Ubuntu. There's no reason for it, but I had just backed up all stuff on it to another machine and I thought I'll give Ubuntu a spin.

I downloaded Ubuntu 7.10 burned it onto a CD and booted it up. After that the experience so far has been real bad. I ran into all sorts of issue. Listed some of them below

  1. Initially I tried various languages in the installation screen, complex script was completely broken. I understand if an installer doesn't support Bengali or Hindi, but in that case the option shouldn't be in the screen, specially when it's not even readable. On top of it language switch wasn't painting the screen correctly
  2. Installer went on broadcasting some sort of weird garbled sound (I guess garbled due to CPU stress)
  3. It booted up into a brown screen without any option to do anything. I waited couple of hours and figured out something is wrong and rebooted again into some safe mode
  4. After a long time it did come up but the UI was sluggish to the point of not working
  5. I clicked on the install icon and nothing happened for a long time.
  6. Now I'm stairing at a fancy screen where the cursor is frozen and the CD is making sounds as if it wants to join F1 racing.

I know the Linux fanatics will sham me as a fool and point me to all sorts of hacks and stuff I can do. The problem is that I'm really not interested in tinkering with installation, I'm used to them just work. I'm not an admin and couldn't care less about these things. For me getting it up and running so that I can do the stuff I wanted to do is more important.

Right now I'm at the point of giving up and moving to some other Linux distro. I'm out of touch with Linux for a long time (~6 years) and I guess I need to look around. Hopefully Red-Hat and Mandrake will work for me.

Thursday, December 13, 2007

Bar Charts on the console

Golconda fort arches

I work on the UI action recorder and it has a strict performance requirement. The tool dumps the time it takes to record each action in it's log and that is compared against the maximum allowed value (otherwise the system will seem sluggish). To do this obviously we need fancy charts, as everyone likes them, other than of course the alpha-geeks :).

However, I like the console chart. Way back my mom used to work on Main-frames that ran COBOL on them and dumped out business data on paper at the end of the day. These reports had these printed bar charts.

I wrote a small ruby script to dump these charts on the console. The output looks like

D:\MyStuff\Code\Ruby>perf c:\logs\Recorder_20071118_144855.843.log
c:/logs/Recorder_20071118_144855.843.log ===============================>
640 ********************************************************************************
0 *
109 *************
0 *
46 *****
0 *


Serves the same purpose as their fancier counterpart but manages to look uber geeky.

Support for range in programming languages

DSCF2530

The .NET platform and the languages on top of it have limited or no support for range of values. Data ranges are one of the most common data-types and somehow it's not there. Funnily most programmers do not even seem to miss it (unless of course if you have used Ruby).

How would you specify a valid range of age and validate user data against it? If you know the maximum and minimum values, at max you'd define a MaxAge and MinAge consts and strew the code with if(age < MinAge|| age >MaxAge). Or maybe you'll define a class to encapsulate this and add a IsValid method.

However, in Ruby, Range is a standard DataType like say string. To do the above processing you'd do

age = 1..120

print age.include?(50)
print age.include?(130)


print age === (50) # more easier way to do include? test using the === operator


So intuitively you create a range using start..stop.


Creating a range of data is also very simple. Say you want to generate the column numbers for an excel sheet, you'd do the following

column = 'A'..'ZZ'

column.to_a # creates an array of all the values

column.each {|v| puts "#{v}\n"}

Similarly ranges can be easily created for any class by implementing some special methods. On ruby the support of Range is in the compiler and makes the code very easy to develop and intuitive.


>>Cross posted here

Wednesday, December 05, 2007

Fun Windows Home Server site

2006_1101_200024

Windows Home Server team has a nice light-hearted site up at http://www.stayathomeserver.com/. All of it was funny, until I reached the page http://www.stayathomeserver.com/book.aspx. It says "daddy wants to give mommy a special gift.... So he buys a stay-at-home server".  That's not funny, "Wife Acceptance Factor" would be reflecting nitrogen freezing point for a home server.

You can sneak one in, understate the price and show all the image streaming to kinda buy acceptance, but a gift, no way :)

Saturday, December 01, 2007

Choose your company name well

 

Picture 057

Sometime back Hutch phone in India got bought over by the international phone giant vodafone. They re-branded Hutch in India to Vodafone.

Now when I call up home and the phone is busy I get a recorded message in Bengali which means "The Vodafone number you're trying to call is busy". All that is good but the problem is that vodafone in Bengali exactly means foolish phone. So I just hang up and wait for the foolish-phone to get free.

Friday, November 30, 2007

Ravenous Bugblatter beast on Indian roads

From the HitchHiker's Guide to the Galaxy.

"The Ravenous Bugblatter Beast of Traal is a creature that hails from the planet of Traal, and will eat anything. If you are to encounter one, the Guide tells you that it's impossible to slay, so you should wrap a towel around your head. This creature is so mind-bogglingly stupid that it assumes that if you can't see it, then it can't see you."

I felt like one while on a road-trip to Visakhapatnam and surely you'll feel like one on Indian roads. We were going at high speed and suddenly we see someone crossing the highway. We honked hard and the person simply looked down. So the idea is that, if he can't see you, then you don't exist. Or maybe they were using the SEP field technology.

In the following video watch the first person crossing the road and next a cyclist goes in the wrong direction as we wiz past at 120kmph (75 miles/hour).

Newbie Question: How do I figure out the inheritance chain of a type

Redmond_2005_0417_010447

I got this question from someone just starting out on the .NET platform. He is used to hit F12 (go to definition) on types and then figure out the inheritance chain. However, he couldn't do that say on a number (int) or array.

The solution is to write a simple recursive routine as follows

static void Dump(Type t)
{
if (t != null)
{
Dump(t.BaseType);
Console.WriteLine(t.ToString());
}
}

The routine can be called as follows

Dump(typeof(int));
Dump("abc".GetType());
Dump(1.GetType());
Dump(typeof(EventAttributes));
No marks for guessing the output though :)

Wednesday, November 28, 2007

Woohoo - Rosario November CTP is out...

2006_0311_123604

...and I can finally talk about what I'm working on for the last so many months.

First things first, for more information on Microsoft Visual Studio Team System code name "Rosario" November CTP release head on to Jeff Beehler's blog

A small bullet in the list of features is Manual Test execution. What it means is that you can now record you manual tests and play them back. Yes, it means you have a UI record and playback feature in the Manual Test Runner!! It's not a full fledged UI automation solution for now. It is mainly targeted to speed up manual testing so that the manual tester can zip past the part which she is not interested in testing. E.g. the manual tester can record the login, purchase pages so that she can play them to directly land in the final checkout page and do manual actions/validations on it.

The solution works for web-UI (IE pages) and also has very limited support for Win32 applications.

I work as a part of the team that develops the record and playback (RnP) framework. It's been an excruciating working on a great technology but not being able to publicly talk about it. Thankfully that time has ended :)

How do you name your computer

2006_1101_200024

Windows gives examples of "Kitchen Computer" or "Mary's Computer" for setting the name of a computer (Computer Name tab in System Properties). But I'm sure that most people don't name their computers that way and show off a bit of creativity in it.

Previously I used to use names from Asterix like GetAFix for my main dev box. Now I exclusively use names from Hitchhiker's Guide to the Galaxy. Some of the machines I use are named as below

  1. traal: My test box
  2. Krikkit: My dev box
  3. Vogon: A old vintage machine I have at work which I use to test some perf scenarios (Vista on 512mb RAM :^) )
  4. Hooloovoo : My personal laptop
  5. Bugblatter: Another laptop

What name do you use?

Tuesday, November 20, 2007

True object oriented language

 

DSCF2530

Today I was spreading the goodness of Ruby and why I love it so much (and you can expect multiple posts on it). SmallTalk programmers can sneer at me, but hey I wasn't even born when SmallTalk came into being and hence I can be pardoned for pretending that Ruby invented this :)

Languages like Ruby are "truly" object oriented. So even a number like 2 is an instance of the FixNum class. So the following is valid Ruby code which returns the absolute value of the number.

-12345.abs

Taking this to an extreme is the iteration syntax. In C# to write something in a loop "n" time I'd be needed to get into for/foreach syntax, however in Ruby I can do the following

5.times { puts "Hello"}

Which prints Hello 5 times.


However, I actually lied about having to use for/foreach statement in C#. With the new extension-method/lambda goodness we can very well achieve something close in C#.


For that first we create the following extension method

public static class Extensions
{
public static void times(this int n, Action a)
{
for (int i = 0; i < n; i++)
{
a();
}
}
}

Then we can call "times" on an int as easily (well almost as I still need some lambda ugliness).

5.times(() => Console.WriteLine("Hello"));
// Or
6.times(delegate { Console.WriteLine("Hello"); });

All programming languages evolve towards Lisp

 

2007_01_28 120

In an internal DL people were debating what all should be included in the next version of C#. One of the things I suggested turned into an interesting thread.

Abhinaba: Add if as expression (like in Ruby) so that I can do the following

var ageGroup = if age < 2
                   "Infant"
               else if age < 19
                   "Teen";

SomeOne: Can't we do

var ageGroup = ((age < 2) ? "Infant" : ((age < 19) ? "Teen" : String.Empty));

Abhinaba: We can but put 4 more cases and it’ll start looking like Lisp :) with all the parenthesis.


SomeTwo: All programming languages evolve towards Lisp.


Yeah, right!!!

Monday, November 19, 2007

Lack of Aspect Oriented Programming support in .NET

I was preparing for a presentation on Aspect Oriented Programming and I started re-looking for the solutions in .NET.

I'm personally not interested about any of the dynamic methodologies, be it dynamic weaving or any other form of dynamic proxying. To me CLR is static-typed and I'd want any solution to be the same (on DLR I'd definitely accept a dynamic solution). Predictability, performance, debugability are  major concerns that are not well addressed in dynamic methodologies. Some of the Dynamic approaches also have special requirements like they can only support virtual methods as join-points.

To me the perfect AOP solution on .NET would either be an IL weaver which ships as a post-compilation tool or an extension language. AspectDNG and EOS are good example for the two approaches respectively.

Wikipedia had a bunch of links and I tried couple of them. It seemed like most of the tools uses dynamic approaches and had the same issues mentioned above. From the static tools I tried AspectDNG's IL weaver. Even though the weaving was good it didn't update the pdb files resulting in very poor (or no) debugging experience. I tried EOS and liked it a lot. However, the project seemed to have died with no updates for a long time.

I think something serious needs to happen in this space. Either Microsoft or some other large body (serious open source project ?) needs to pick AOP up to make it successful in .NET. To me the tool of choice would be extension to the C# language in the same lines as EOS (or AspectJ).

There seems to be already some work going on like the Policy Injection Application Block which works over .NET remoting.

Saturday, November 17, 2007

The WOW factor in software

 

I care a lot about the nice nifty features that takes a software from being just a good software to a great software. It makes me feel that the developer really cared. I know how features are cut and these making it to the product indicate a mature, well thought-out execution.

Joel in his How to demo software writes

"bump into all the nice little “fit and finish” features of your product. Oh look, that column is halfway off screen. No problem. I’ll just drag it over. (“Wha!” the audience gasps, “you dragged a column in HTML?”) Oh, look, this feature is supposed to be done by next Tuesday. I’ll type “next tuesday” in the due date box. (“OMG!” they squeal. You typed “next tuesday” and it was replaced with “11/20/2007”)."

I absolutely agree to this. I've seen Microsoft Office time and again do that. The first time I fired up a PowerPoint presentation on a dual screen I gave that same squeal "OMG! the slide show start on one and I get the presenter view on the other with full access to the notes!!!!". Even 3 days back I used the same mode for a presentation on Aspect Oriented Programming and felt happy about using the product.

However, there's the other category of software which doesn't work in first place and tries to be smart on top of it. There's nothing worse than this. You look at these in disgust and head over to the dumber but working competition.

Thursday, November 15, 2007

Don't forget to lock your Computer

So Amit pointed me to this post on Coding Horror (I didn't get time to read any of the feeds for the last 2 days!!). It's about colleagues playing pranks with folks who leave their computer un-locked. I myself have done couple of these stupid but amazingly successful ones like taking screen shot of the desktop and then making it the wallpaper. Then you hide all visible things on the desktop so that the user on retuning goes on clicking on them without any result.

However, these days at Microsoft the prank has changed. On returning you just get to see an email typed out, addressed to Bill Gates. I don't even want to get into the topic of what is typed. The effect is amazing and permanent. Win+L keys become etched in your reflexes.

Monday, April 23, 2007

I just heard from a friend that my ex-colleague Sachin Gaur has passed away. He comitted suicide unable to cope with the pressure of our profession. He used to work with me in Adobe. He left behind his wife and son.

Sachin was a very kind person. When I bought my car, he drove it back from the car showroom as I was a bit unsure of driving it. I still remember him advising me to driving slowly and safely on the way back.

This is me with Sachin sitting beside me at a office lunch at the Noida Radission. May his soul rest in peace.

Friday, December 15, 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 :)

Sunday, December 03, 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 :)



Saturday, November 18, 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 :)

Wednesday, November 15, 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 :)

Monday, November 13, 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.

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.