Wednesday, July 23, 2008

Save your Visual Studio window layouts

Before I had my nice new laptop I had a normal desktop for work. It had two monitors so when I worked, I spread the windows of Visual Studio to cover both screens and give me maximum working space. If I worked from home I would connect to my work desktop using Remote Desktop and work like that. The problem was that this only gave me one monitor so I had to readjust the window layout for single-monitor usage. If I then would go to the office the next day, Visual Studio would still be in single-monitor window layout from the day before and I would have to drag all the windows around to get my dual-monitor layout back.

Now I have a nice laptop, so whether I work from home or in the office, I use the same machine. But I still have two monitors at work and only one at home. So even though I drag my PC with me everywhere, I still have the window layout problem.

Two or so years ago I discovered the VSWindowManager. This is a plug-in for Visual Studio that allowed you to save up to three profiles of different window layouts. You could then add three buttons to your toolbar to access those profiles. It did exactly what I wanted, but I still had two minor issues with it. First I couldn't rename the buttons, so I had to remember which button mapped to which layout. This wasn't that big of a problem. Secondly, and this was much more annoying, if you clicked the button of the profile you had currently loaded, it would save the window layout into to profile. So if I would come at work after having worked from home and I accidentally clicked the wrong button while trying to restore my dual-monitor layout, I would overwrite that layout with the then current single-monitor layout and I would have layout all the windows by had again.

If you look at the VSWindowManager project, it was last updated in September 2006. Now I do most of my work in Visual Studio 2008 and the plug-in doesn't work on this newer version. Sure, someone downloaded the source and got it to work for VS2008, but it didn't feel good to me if the original author had abandoned the project. So it was back to doing stuff by hand.

Earlier tonight I got fed up with it and decided to find a solution (again). I hoped that maybe someone else had written a similar plug-in. Instead, I found something way better. After googling a little, I came upon this MSDN article titled: Visual Studio 2005 IDE Tips and Tricks. It has a section specially dedicated to saving window layout and it provided a very simple solution to my problem. It uses the possibility to export user settings, together with a small macro to achieve exactly what I need.

Basically it works like this. You start by laying out the windows the way you like it. Then you export your IDE settings using the "Import and Export settings wizard", but in this wizard you can specify exactly what settings you want to export. So you choose only to export your window layout. You save the settings file in a known and accessible location (like your profile or documents folder) and name it so you know what settings these are. Then you create a new macro using the built-in macro editor. This macro will simply import the settings file. And since you only exported your window layout, this is the only setting that will be changed. So I can make a macro for my single-monitor setup and another macro for my dual-monitor setup. I can then add these macros to my toolbar and give them any icon and name I want.

Multi-/single-monitor problem solved!

Saturday, July 12, 2008

Code reduction through generic methods

I've build and now maintain a webservice application at work. The application has around 40 webservice functions and earlier this week I had to dive into the application again because of some issues. It occurred to me how redundant all the code in the webservice functions was. I'm talking about the top-level code, the stuff in the *.asmx.cs files.

In this application the code there deals with input validation, authentication/authorization and sending back the results of the operation (success or error data). So most of the code in those ~40 functions is basically the same. The only thing that differs each time is the specific business logic that the function offers to the world, but that logic is nicely abstracted from the interface part of the application in the business logic part of the application so it's only a few lines of code in each top-level function to setup and call that specific handler. The main code of each function is stuff that each and every function needs to do. All copied and pasted. That can be done better.

I started off by creating a base class from which all webservices should inherit. This base class would provide the functions for input validation (each input object now implements an IValidating interface that is called so the object can basically validate itself) and authentication/authorization. This still left behind a large chunk of code (large chunk being relative here. It was no more then 18  lines of code, but for most functions that was still more then 50% of code in that function). The problem is that each separate webservice function returns a specific return type based on the function itself. A function called "CreateAccount" returns a "CreateAccountResult" object, a function called "SetOptions" returns a "SetOptionsResult" object, etc. So it's not possible to write a helper method, or a method in the base class like I could with validation code or the authentication/authorization code. But then I remembers generic methods.

I don't understand why I've never done these optimizations before. I've used generic methods years before in C++ and I know it was possible in C#. I just never thought about it. So with this new idea I mind I started coding.

We throw our own exceptions in the application. And we make a distinction between two kinds of errors: functional errors and technical errors. The main difference between the two being that function errors are logged as warnings and technical errors are logged as errors. Function errors come from business logic decisions (invalid input, creating an account that already exists, etc) and technical errors come from unexpected problems (SQL server unavailable, External webservice unavailable, etc). So all our own exceptions inherit from one of these two base exceptions. Also all exceptions have an error message and an error code.

The results we return in our webservice functions also inherit from a common base (the BaseResult class) that provides them with at least an error message and an error code (which get filled from the exception). With all that in mind I copied and changed the code that looked like:

1 string errorMessage = "CreateAccount error: " + e.Message; 2 if (e is TechnicalException) 3 { 4 TechnicalException technicalException = (TechnicalException)e; 5 ErrorLog.Error(errorMessage); 6 result = new CreateAccountResult(technicalException.ErrorCode, technicalException.Message); 7 } 8 else if (e is FunctionalException) 9 { 10 FunctionalException functionalException = (FunctionalException)e; 11 ErrorLog.Warn(errorMessage); 12 result = new CreateAccountResult(functionalException.ErrorCode, functionalException.Message); 13 } 14 else 15 { 16 ErrorLog.Error(errorMessage, e); 17 result = new CreateAccountResult(-1, "An unhandled exception occured: " + e.Message); 18 }

Into a function in the base class that looks like:

1 protected T HandleException<T>(Exception e, string functionName) where T : BaseResult, new() 2 { 3 T result = null; 4 string errorMessagePrefix = functionName + " "; 5 6 if(e is TechnicalException) 7 { 8 TechnicalException technicalException = (TechnicalException)e; 9 ErrorLog.Error(errorMessagePrefix + technicalException.Message); 10 result = new T { Code = technicalException.ErrorCode, Message = technicalException.Message }; 11 } 12 else if(e is FunctionalException) 13 { 14 FunctionalException functionalException = (FunctionalException)e; 15 ErrorLog.Warn(errorMessagePrefix + functionalException.LogErrorMessage); 16 result = new T { Code = functionalException.ErrorCode, Message = functionalException.Message }; 17 } 18 else 19 { 20 ErrorLog.Error(errorMessagePrefix + ": " + e.Message, e); 21 result = new T { Code = -1, Message = "An unhandled exception occured: " + e.Message }; 22 } 23 24 return result; 25 }

And replaced all code that is similar to the first code block with this one line:

1 result = HandleException<CreateAccountResult>(e, "CreateAccount");

A significant reduction as you can see. I definitely should have thought about this before.

Tuesday, July 8, 2008

Windows Server 2008 on a laptop

Last week I got a new laptop for work. It's a nice fast Dell Precision M6300. On my old workstation I had Windows Server 2003 R2 running. I'm a developer, so I want to develop on the platform my software will run on. So on my new laptop I wanted to run Windows Server 2008 the Vista Server version of Windows.

Using this very nice blog entry from Vijayshinva Karnure I was able to make Windows Server 2008 look and work almost like Vista. Almost, because I'm missing two things that I have noticed so far. First off is the Windows Sidebar and secondly is Bluetooth support.

Now if you google for these problems, you'll find solutions to both of them. To enable Bluetooth support you'll need to install your drivers as usual and then perform some INF magic to persuade Windows to use them. To enable the sidebar you'll need to copy some files from a Vista installation and copy some registry settings. From what I read this will then work just fine, but I'm not comfortable with it.

You see, these things aren't part of the supported Windows platform, so if there are any security issues, you are on your own. Microsoft won't provide sidebar patches for Windows Server 2008, because they never released a Windows Server 2008 with Windows Sidebar. So you'll have to keep an eye on all security updates and patch the files by hand, or (more likely) let the software run with all its security issues. And that's not something I'm willing to do.

I also discovered, that if you install the Hyper-V because you might want to run some virtual machines for testing, sleep and hibernate will be disabled. Sleep and hibernate are incompatible with Hyper-V so you won't be able to use them. That sucks, so I uninstalled the Hyper-V, but at least I have the option of installing it if I do need it some time in the future. I will just need to learn to live without hibernate then.

And then I just ran into another issue. For remote workers my organization uses Check Point VPN-1 software, but as it turns out they don't have 64-bit versions of their client software. Even though 64-bit versions of Windows have been available for (rough estimate) 3 years now, they never saw fit to make their software work. According to their forums they will release a 64-bit version of some new software in Q4 2008 and this will fall under the existing licenses for the time being. In other words, you'll have to pay extra for 64-bit versions of their client software eventually.

Other then that, I'm pretty happy with my flashy new laptop :-)

Tuesday, June 24, 2008

Working with others = my glass ceiling

I've never really worked on projects that involved more then 3 people on the development side of things. That is, until January this year. At the start of this year my department started working on the biggest, most important piece of software we have ever build. And almost everyone from my team is involved. It's currently a 10-man project. 6 of which are developers.

So now we're 6 months in and we in the phase where I get to dig around in other peoples code. Be it for fixing bugs, or just plain and simple code reviews. And now I've started to notice something negative about me. I've noticed that I regard code that has not been written by me as bad code, even before I've take the time to examine it. I didn't notice it immediately , but I've started noticing it this week and thinking about it it explains some of my feelings towards certain modules.

Since I think the code is bad, even if it is better then what I would have written, I always want to refactor it, change it. And that's not good. Well sometimes it is, but not always. And when I do a code review I should pay particular attention that I judge code on how it works and not how I feel about it.

As a programmer you can get only so far flying solo. To progress as an effective programmer you must also learn to work well with others and be part of a team. This is something I know, but my unconscious doesn't appear to want it. Now I know I can start working on it. And in the end it will make me a better programmer.

Wednesday, June 18, 2008

I've never liked DRM

This time nothing about programming, but about my other great hobby: video games.

I recently bought Mass Effect for the PC. And it truly is an awesome game, but even though I bought it and I have the 2 DVDs lying right here on my desk, I never installed it. Instead, I downloaded the illegal, cracked, version and installed that. I figured it's not illegal since I did in fact buy the game. I also registered the CD key on the Mass Effect web site, so they know the game I bought was bought by me.

Why did I install the cracked version and not retail version? DRM.

The retail version comes with the SecuROM copy protection. But I don't consider it protection of any kind. It's system crippling software, that creates security problems on your system, makes it slow and unstable and only because the big video game publishers consider you a pirate no matter what. Mass Effect takes it even further. It requires you to activate the game and you can activate it only 3 times. After that you must purchase (yes, you must buy a new copy of the software) a new CD key. They planned it even worse. They wanted the game to require re-activation every 10 days. But after public outcry they changed that to unlimited time, but only 3 activations.

So when do you need to reactivate? When you get a new system. And a new system in this case is when you reinstall Windows, or replace some hardware. From an article linked above it seems to consider a new video card to be equivalent to a new system. That's as brain dead as Windows Vista needing reactivation because replacing my WiFi card must mean I have a new system.

Normally people would "vote with their money". Not buying the game would send a clear signal, but I think that in this case it would only play on the paranoid minds of the publishers. If people didn't buy the game because of the DRM, they'd just figure people where pirating it and they'd need more DRM the next time around. Never even considering that the DRM is what made people not want to buy it in the first place!

When will these people get it into their fracking heads that DRM is a big burden for honest consumers who bought the product, while it's no problem at all for the pirates. The game is cracked, the DRM removed, as soon as the game is available. It's just pestering the people who pay your salary. And it should stop!

Sunday, June 8, 2008

Counter-intuitive optimisation

I've always been interested in game programming. I never actually managed to create a full, completed game, but from time to time I do start another project. Currently I'm messing around with the XNA Game Studio 3.0 CTP. When Googling for some answers on some game-programming-related problem, I ran into a developers journal on GameDev.net. The journal was pretty interesting and I started reading all the entries. It's about a developer who's creating a space MMO. This particular developer mainly focuses on the graphics engine, so while all the specific graphics lingo and math is lost to me, I do understand the more general programming bits and one bit really surprised me.

On November 7, 2007 he wrote a piece about optimising a noise function. His project uses a noise function coded in a high level programming language and it appeared too slow. So this developer decided, like many other developers would, to rewrite the function in low-level assembly to gain performance. This kind of manual optimisation is very hard, but generally yields pretty good results. But when he hand-optimised the function it wasn't faster. In fact it was 2 times slower then the implementation written in the high-level programming language. Programming in assembly language is hard. It's very low-level and you need a really good understanding of how the CPU architecture works to get the best out of it. So it's not surprising that a compiler written by a lot of very smart people will produce faster code then a single, simple developer can product on his own. But this didn't appear to be the problem. No, the problem was using a lookup table.

A lookup-table is a very simple (and usually very effective) optimisation technique. If the calculations are slow, but limited in volume, it's easy to just calculate all the possible values one time and store it so that later calculations don't need to be calculated, but can just be looked up. In a lot of game-programming books I read this was usually the first optimisation authors would recommend. It's easy and it just works. Not anymore it seems. After the developer had reprogrammed the noise function in assembly language the bottleneck didn't appear to be the calculations, but the memory accessing in the lookup-table. So by eliminating the lookup-table and just calculating each thing every time, he made the function faster. And that is not something I would have though of.

The funny thing is, this is actually something Steve McConnell warns about in Code Complete. In this excellent book he warns about optimising performance by 'guessing' what's faster. Things that 'feel' like they would be faster aren't necessarily faster. And things that where faster last year, won't necessarily be faster on this year's CPUs, compilers and operating systems. The only one true way to determine what is faster and what is not, is by measuring.

Saturday, May 31, 2008

Clouds for the masses

I've been hearing about "The Cloud" for some time now. Mostly from Microsoft engineers. There is 'Cloud Computing' and 'Cloud Storage'. Sending things to 'The Cloud'.
The cloud in this case is of course the internet. They use the term "cloud" because when you draw a network diagram you usually symbolize the internet with a cloud.

So as a developer I've been hearing about clouds for some time now. And now Valve (makers of Half-Life and Portal) have announced Steam Cloud. The Steam Cloud framework enables games to store settings and saved games on their servers on the internet (in the cloud). Aside from this being totally awesome, it's just funny they chose the 'cloud' name. Of course it fits perfectly with their 'Steam' brand name and it makes sense to most people because steam produces clouds. But to the developer it also makes sense, because it does something in "The Cloud".
I thought it was funny to see a developer-centric term go mainstream without losing its meaning (even though non-developers probably won't give it the same meaning developers do).