This blog contains reflections and thoughts on my work as a software engineer

onsdag den 7. oktober 2009

Stop whining!

This is a little out of the ordinary but what the heck... There has to be room for a little fun from time to time

You know Arnold Schwarzenegger? Of course you do... He has become famous for quotes like "I'll be back", "Aaaaargh" and various other sentences which primarily excels in containing words exceeding no more than two syllables. There's one quote in particular I like (and so does my fellow coworkers). It is "Stop whining" from Kindergarten Cop - when spoken McBain style nobody at our team can continue whining over bad code, cold coffee, stupid typos etc but inevitably start smiling because whining is such an easy trap to fall into when the right thing to do is just to get the job done and get going.

How does this relate to coding? Well, tonight I wondered how to play media files in C#... I never actually tried coding audio stuff in C# so I figured that I wanted to find a WAV file containing the infamous Arnold shouting "Stop whining"... And so I did and it turned out to be a very little deal getting it out. It was actually two lines of code:


var myPlayer = new System.Media.SoundPlayer("myfile.wav");
myPlayer.Play();


Then I figured that I wanted to play it using a keyboard stroke - to make some kind of Arnold soundboard just using keyboard shortcuts - how would that be possible? Capturing keyboard strokes isn't hard at all - if your program is in focus but I wanted to have some keyboard hook which would catch my keyboard strokes globally... I knew it had to be done invoking unmanaged code which isn't something I do on an everyday basis... so instead of doing all the WinAPI stuff myself (yes, I am a lazy bastard) I dug up this article on CodeProject which I could make use of. It basicly encapsulates the WinAPI goodies required to globally listen to whatever the user is doing with his keyboard. The hardest part was actually getting raw WAV-files with Arnold quotes - I managed to find some but it required me to save them in a different format as the .NET Sound API only allows PCM files. Enter Audacity, a load and a save later on each file and I was good to go. I needed to research a little getting the Windows Form to hide itself as a tray icon (yet another thing I've never tried before) but it was also a nobrainer.



So as of tonight I have whipped up a small application which can store itself in the tray and listen to keyboard events. If you press down S, T, O and P down, Arnold will in his informal voice speak out "Stop whining!". Try the following for yourself: LACK and COP... The implementation is here (I won't cover the GlobalKeyboardHook as it is covered in the CodeProject article):



    public partial class ArnoldForm : Form
{
private GlobalKeyboardHook _gkh;
private List _pressedKeys = new List();
public ArnoldForm()
{
InitializeComponent();

_gkh = new GlobalKeyboardHook();
_gkh.HookedKeys.Add(Keys.S);
_gkh.HookedKeys.Add(Keys.T);
_gkh.HookedKeys.Add(Keys.O);
_gkh.HookedKeys.Add(Keys.P);

_gkh.HookedKeys.Add(Keys.C);
_gkh.HookedKeys.Add(Keys.P);

_gkh.HookedKeys.Add(Keys.L);
_gkh.HookedKeys.Add(Keys.A);
_gkh.HookedKeys.Add(Keys.K);



_gkh.KeyDown += gkh_KeyDown;
_gkh.KeyUp += gkh_KeyUp;
}

private void gkh_KeyUp(object sender, KeyEventArgs e)
{
if (_pressedKeys.Contains(e.KeyCode))
_pressedKeys.Remove(e.KeyCode);
}

private void gkh_KeyDown(object sender, KeyEventArgs e)
{
_pressedKeys.Add(e.KeyCode);
var arnold = new Arnold();
arnold.Speak(_pressedKeys);
}

private void Form1_Resize(object sender, EventArgs e)
{
if (FormWindowState.Minimized == WindowState)
Hide();
}

private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
Show();
WindowState = FormWindowState.Normal;
}
}

public class Arnold
{
public void Speak(List keys)
{
string voiceFile = GetVoiceFile(keys);

if (!string.IsNullOrEmpty(voiceFile))
{
var asm = Assembly.GetExecutingAssembly();
var file = asm.GetManifestResourceStream(voiceFile);

var myPlayer = new System.Media.SoundPlayer(file);
myPlayer.Play();
}
}

private static string GetVoiceFile(ICollection keys)
{

if (keys.Contains(Keys.S) &&
keys.Contains(Keys.T) &&
keys.Contains(Keys.O) &&
keys.Contains(Keys.P))
{
return "ArnoldQuotesForm.media.stop_whining.wav";
}

if (keys.Contains(Keys.C) &&
keys.Contains(Keys.O) &&
keys.Contains(Keys.P))
{
return "ArnoldQuotesForm.media.cop.wav";
}

if (keys.Contains(Keys.L) &&
keys.Contains(Keys.A) &&
keys.Contains(Keys.C) &&
keys.Contains(Keys.K))
{
return "ArnoldQuotesForm.media.lack_discipline.wav";
}

return null;
}
}


Download the entire project here


It's not exactly rocket science but I had a few hours of fun building the thing. Comments are welcome - until next time...  :o)

søndag den 27. september 2009

Throwing valuable time after wasted time

Ayende just wrote an interesting post about the cost of maintaining fragile code:

http://ayende.com/Blog/archive/2009/09/25/i-wrote-it-and-it-was-horrible.aspx

You and I - I'm not pretending to be any better than everybody else on the subject - should fight the urge to keep unmaintainable code and never fear a rewrite even though it seems like wasted time. It's just so freakin' hard holding on to such a set of core values because it might cost features not being implemented in the short run... Know the feeling?

Anyway: What I wanted to really say was that I'm looking forward to hearing Ayende himself in at JAOO in Aarhus, Denmark. It's not every day you get to see one of the most influential people in the Open Source community in person so I'm quite excited about it   :o)

mandag den 3. august 2009

The most overlooked risk in software engineering

 

5 weeks of vacation has ended – while browsing through the posts written during those weeks on Coding Horror I stumbled across a quote by David Parnas from the post Nobody Hates Software More Than Software Developers - quite a catching title, don’t you think?

“Q: What is the most often-overlooked risk in software engineering?

A: Incompetent programmers. There are estimates that the number of programmers needed in the U.S. exceeds 200,000. This is entirely misleading. It is not a quantity problem; we have a quality problem. One bad programmer can easily create two new jobs a year. Hiring more bad programmers will just increase our perceived need for them. If we had more good programmers, and could easily identify them, we would need fewer, not more. “

Click here to get a transcript of the entire interview

tirsdag den 23. juni 2009

Followup…

I have figured out a workaround to the problem regarding CruiseControl.NET having to run in Console-mode… There obviously wasn’t any elegant way to handle this so I decided to at least try and hide the console window outputting CruiseControl debugging info. so you can hide a console window and keep the process running. Instead of firing up CruiseControl.NET directly I created a small consoleapp which fires up CruiseControl.NET in console mode and then uses Windows API to hide the console window from the screen and was pretty amazed that I pulled it off within an hour. So I ended up with this - all credits to Brendan Grant:

class Program

{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);


static void Main(string[] args)
{
var fi = new FileInfo(string.Format("{0}/CruiseControl.NET/server/ccnet.exe", Environment.GetEnvironmentVariable("PROGRAMFILES")));
if (!File.Exists(fi.FullName))
{
Console.WriteLine("ccnet.exe not found in " + fi.FullName);
Console.Read();
Environment.Exit(0);
}

var p = new Process {StartInfo = new ProcessStartInfo(fi.FullName)};
p.StartInfo.WorkingDirectory = fi.DirectoryName;
p.Start();
Thread.Sleep(3000);

SetConsoleWindowVisibility(false, fi.FullName);
}

public static void SetConsoleWindowVisibility(bool visible, string title)
{
// below is Brandon's code
//Sometimes System.Windows.Forms.Application.ExecutablePath works for the caption depending on the system you are running under.
var hWnd = FindWindow(null, title);

if (hWnd != IntPtr.Zero)
{
if (!visible)
//Hide the window
ShowWindow(hWnd, 0); // 0 = SW_HIDE
else
//Show window again
ShowWindow(hWnd, 1); //1 = SW_SHOWNORMA
}
}
}


Now I’m exactly where I was a few days ago except I don’t have a console window on my server… I still have to remember not to log off when remoting to my buildserver and if something crashes I haven’t got any context running CruiseControl which writes stuff into the Eventlog etc. At best this is – well, pretty bad coding style actually... but again: It’ll do for now  :o)

fredag den 19. juni 2009

Testing Javascript in a Continuous Integration environment

Ever since I started doing TDD I've been looking around to find a solution for testing UI and Javascript which would enable me to develop UI having unittest-style feedback and integrate my UI testing in a Continuous Integration setup. A few months ago we tried using QUnit at work for testing clientside scripts which relies on 3rd party vendors (Google Maps) to provide us with data for our application. I always wanted to find time to try and mainstream our experiences a bit because we never got much past "let's-try-this-thing-out" and spend a few hours seeing what could and could not be accomplished.

So - I decided a few days ago to sit down and spend a few evenings setting up a Continuous Integration environment which would

  • A) Run clientside tests in a Continuous Integration server
  • B) Provide TDD-stylish feedback on both NUnittests and clientside tests

Disclaimer: If you don't have experience with Continuous Integration environments you might find this to go a bit over your head - I strongly recommend this article written my Martin Fowler and if you really want to dig deep into the subject "Continuous Integration - Improving Software Quality and Reducing Risk" is a must-read.

How it was done

I decided to use QUnit due to the fact that it is the clientside scripting library used to test JQuery. If it good enough for those people I guess it's as good as it gets - I didn't want to even try and dig up some arbitrary, halfbaked library when QUnit was such an obvious choice. I won't go into details about the "what" and "how" of QUnit - what it does is that it provides you with feedback on a webpage which exercises your tests written in Javascript - like this: 

image image

So - you write a test in a script and execute it in a browser and get a list of failing and completed tests. If everything is OK the top banner is green (left). If one or more tests fail the banner is red (right). This is controlled by CSS-class called "pass" and "fail". With that in mind and with a little knowledge of Watin I decided to just use write a unittest in Watin because it would allow me to write an test resembling the following:

[Test]       
public void ExerciseQUnitTests()
{
    using (var ie = new IE("http://(website)/UITest/QUnitTests.aspx"))
    {
        Assert.AreEqual("pass", ie.Element("banner").ClassName, "QUnittest(s) have failed");
    }
}



...where QUnitTests.aspx should be the page exercising my QUnit tests. The test itself should check for a specific class in the top banner - if "fail" would be active one or more tests would have failed and the unittest should fail and cause a red build. There is at least one obvious gotcha to this approach: You only get to know that one or more clientside-tests have failed. You don't get to know which one and why it failed. Not very TDD'yish but it'll do for now.



Here's a list of the things I needed to do once I had my Watin-test written:




  • I created a new project on my private CruiseControl.NET server which would download the sourcecode from my VS project, compile it using MSBuild and execute the unittests in my testproject. I battled for an hour or so with Watin because it needs to have ApartementState explicitly set. You won't have any problem when running your test in Visual Studio only but whenever you try to run the Watin test outside Visual Studio you get - well, funny errors basicly.


  • I pointed the the website to the build output folder in Internet Information Server


  • Then I ran into another problem - QUnit appearenly didn't seem to work very well with Internet Explorer 7 (or so I thought) - the website simply didn't output any testresults on my build server. It wasn't a 404 error or so - the page was just plain blank - so I had working tests on my laptop and failing tests on my buildserver. Without thinking much about it I upgraded to Internet Explorer 8 on my buildserver. Not much of deal so I did it - just to find out that the webpage still didn't output any results in IE 8 either. After a while of "What the f*** is going on" I started thinking again and vaguely remembered a similar problem I had about halft a year ago... The problem back then was that scripting in IE7 is disabled per default on Windows 2008 - which of course was the problem here as well. So I enabled scripting and finally got my ExerciseQUnitTests test to pass. Guess what happened when I forced a rebuild: GREEN LIGHTS EVERYWHERE. Yeeeehaaaaaaaa  :o)


  • Last, but not least I found out that CruiseControl.NET from now on will have to run in Console-mode in order to interact with the desktop in a timely fashion - because it needs to fire up a web browser - oh dear... I need to look into that one because I define having console apps running in a server environment as heavy technical debt you need to work your way around somehow. But again: It'll do for now even though I find it a little akward.




Conclusion: After a good nights work I got the A part solved - and another two nights I cranked the B part open as well. I'm now able to write QUnittests testing code in my custom JavaScript files, exercise the tests locally in a browser, check everything in and let a buildserver exercise the tests for me just like my client-code tests were first class citizens in TDD. Sweeeeeet....  The sourcecode is available for download here  - please provide feedback to this solution and share experiences on the subject with me in the comments   :o)



Links:



Continuous Integration article by Martin Fowler



QUnit - unit testrunner for the jQuery project



CruiseControl.NET - an opensource Continuous Integration server for Windows



Watin - web test automating tool for .NET

torsdag den 11. juni 2009

Testing software quality – open your mind

I recently attended a two day course called “Softwaretest – when it’s best” in Copenhagen. The reason I found it worth going to was that we recently had a major breakdown in our production environment because we pushed a bugfix into production without having properly testing what we were actually releasing. Thus having a new refactored decoupling of of our AspNetEmail component released without it being properly tested… You can imagine what people think of the guys in the IT departement when they either don’t get their mails or get them multiple times at random… Luckily we didn’t send anybody an email that they shouldn’t have recieved but we sustained major damage to our reputation within the organization because it’s not the first time we committed crimes like these before. So – we definately need improvement in our testing phase. We’re a team of developers – 5, to be exact. We know our TDD-drill and Continuous Integration is a first class citizen in our office so testing our own software isn’t totally unknown to us. I just feel we need to fill in the gaps to get to the next level - ideally without having to build and maintain an extensive and bureaucratic testing process nobody buys into 110 percent.

So I went there with a collegue to learn about this testing stuff - and I feel I am a little wiser now. Here's the eye-openers I have decided to share with you:

  • Developers live and breathe to make things work. Testers live and breathe to make things break. It’s a state of mind you need to be aware of as a developer. You can’t sit down and develop – and then test your doings without having said to yourself “I’m not a developer right now – I’m now a tester and want to break stuff”. I tried it today and WHAM!!! I found 3 critical bugs in a piece of software I recently wrote on one of my hobby projects. Each of them could have been found if I sat down and reviewed the code - but I found them nevertheless by simply WANTING to find errors.
  • Evolution is better than revolution. Nobody likes to be hazzled into something if they don't believe it provides value. Don't start out with preaching about "the god-awesome Testing Maturity Model (TMM)" and your visions about reaching level 5 before the end of the year. Get everybody involved before making any decisions - something about people and interactions over processes and tools... You know the drill for sure but it's easy to forget.
  • If you don't understand the product you won't find the error! How often have you reviewed code and signed off on it just to find out a month later that it had bugs in it - functional as well as nonfunctional? I have more times than I actually would like to think of... If you don't know what the code is supposed to do - you can only verify what it actually does. You'll never get to the point where you realize what's missing in the code if you don't know what the customer expects from it.
  • Test the deliverables not the specifications! If you have a clear set of specifications and a testplan for those you should of course use that testplan. But - your focus must always be on what is being delivered. You should as a tester try to gain as much understanding of the domain you're testing as possible - because who knows if the testplan (if one exists) is adequate? If you during development find out that performance is critical for a specific part of the software it is your responsibility to take this into account when testing even if performance is not an issue in the specifications. If the customer percieves the software as buggy it IS buggy regardless of whatever tests you've completed and signed during development and accepttesting.
  • ...plus a number of other related goodies such as "How to write a test plan", equivalence numbers, conflict handling between testers and developers, the difference between Blackbox and Whitebox testing etc.

The very vital issue while testing is that testers have a different mindset. Their best days at work is when they find themselves "in the zone" registering bugs like maniacs while developers think success and failure in terms of solving problems and implementing features. If you’re a developer you will never become much better than poor (at best) in a testing phase if you don't acknowledge that you need to change some things in your head in order to improve your testing capabilities. That's probably the biggest eyeopener I've had since I wrote my first unittests and after an hour or two of "Why am I writing so much code for nothing" suddenly got a failing test totally unexpected...

Tomorrow, before you contact your Product Owner because you have released something to your staging environment - say to yourself: “The next hour I'm a success ONLY if I can find bugs in what I just released”. Sit down, seek - and you will find. Promise :o)

torsdag den 14. maj 2009

Release planning with only one SCRUM team servicing multiple Product Owners

In real life, SCRUM usually requires some adjustments to fit into the organization in which you are working. One of the issues I have come across in my daily work as a ScrumMaster is having to work for multiple ProductOwners but the only ressource available is a single team. SCRUM applied with the green band around your arm says that a ProductOwner has a dedicated team throughout the entire project. In real life – that’s hardly ever so. I tried both ways – working on a dedicated team with a single PO and at my current job we are serving no less than seven ProductOwners with a single team of 4 developers – and everybody is generally happy about it. How is that possible?

We have decided on a model in which we do SCRUM by the book. Whenever we break away from the beaten path we do it because it enhances transparency and maintains visibility in contradition to following the “rules” of SCRUM. We try to do things because they make sense to us – individuals and interactions over processes and tools, we say. Having seven ProductOwners aren’t exactly SCRUM by the book but nevertheless it is the world we live in and things aren’t going to change on that particular issue. How to apply SCRUM under these conditions?

What we’ve tried to accomplish now is a more thorough plannning process – we’ve introduced release planning in our process. We have introduced what we call Pre-sprint planning. It is a meeting held about the 10. in every month. Participants are ScrumMaster (me), our IT Manager and a role we’ve invented called ProductOwner Coordinator. The IT manager is in charge and decides which backlogs gets a time slot in the forthcoming sprints. Every ProductOwner writes the IT manager an Email prior to our Pre-Sprint plannings and argue his or her case for having time in the forthcoming sprints. Some backlogs get time and some don’t. The very important thing here is that there is only one single person who decides – call it dictatorship but it’s the easiest for all parties involved.

At the meeting we collect the necessary data needed to prioritize. These data inclue all requests from ProductOwner, the content of our Team Backlog (the team’s list of technical debt issues prioritized by business value and estimated just like a normal backlog) and the contents of all Must-Haves on every backlog aggregated into a single Excel spreadsheet. We base our discussion on the data before us and the IT manager decides on a release plan for the next 3-4 months.

An example: Backlog A gets perhaps 50% of the next sprint. Backlog B and C gets 25% each in the next sprint. Backlog D gets 100% in the sprint after the next one. This release plan of course isn’t carved in stone – nothing is until Sprint Planning 1 where the team commits to a list of stories for the upcoming sprint. The release plan is being published on a blog which every ProductOwner subscribes to – and if a ProductOwner disagrees with our IT managers decisions after reading the updated releaseplan because he thinks there is more business value in getting his backlog stories implemented - he is required to go to our IT manager and argue his case and make a new request. A month later we meet again to another round of Pre-sprint planning and the current release plan is discussed, requests are taken into consideration and an updated releaseplan is published on our blog.

The advantages by having a long-term goal are numerous:

  • Visibilty is evident. The entire business knows what’s going on and who get’s precious timeslots next.
  • The team knows in advance which backlogs to estimate stories from. No more estimation meetings on backlogs which never make it to Sprint Planning.
  • Our many ProductOwners have a single person to go to in order to get stories implemented by the team.

The main advantage is that it is clear to everybody who’s in charge. This person must be empowered to prioritize between multiple requests and wishes. This person must not be an active participant in the process of implementing stories – no ProductOwner, ScrumMaster or Team member should attend this role. Our IT manager is the right choice in our organization. It depends heavily on the culture and organization structure which person is the right for this job.

We’ve tried this approach for the first time at our last Pre-sprint planning because we needed to get a clear picture of which backlogs we could focus on during the summer because our vacations are very wide spread this year. If nobody disagrees with it - well – we call in for estimation meetings on the backlogs we know are in the pipeline and will be much better prepared for Sprint Planning 1 than we’ve ever been even with the limited ressources available to us during vacation season    :o)