Archive for September, 2008

Racing to Failure

Friday, September 26th, 2008

Threading.? Deadlocks.? Race conditions.? These are such seemingly simple items, yet no one seems to have a good answer to how to handle them.? Instead we seem to have 2 categories of developers.? One category is the developers who understand the problem is hard and are careful in their design and approach to avoid the easy errors, and those who want to simply explain away a lack of rigor in their approach as an unavoidable outcome of the nature of the problem.? In my experience, you are far more likely to encounter problems caused by the second group than the first.? Fortunately, the type of errors created by the second group is usually easily identified in a code review and can be fixed by fairly simple means.?

Take, for example, the following code (C#):

List<string> duplicates = null;

System.Threading.ThreadPool.QueueUserWorkItem(

? new System.Threading.WaitCallback(delegate(object target)

? {

??? duplicates = new List<string>();

??? while(/* some condition */)

??? {

????? duplicates.Add(someMethod());

??? }

? }));

foreach(string name in names)

{

? if(isDuplicate(name))

? {

??? duplicates.Add(name);

? }

? //…

}

Can you find the problem?

Of course, this is greatly simplified, and in looking at this code it should be blatantly obvious to the most inexperienced among us that there is a race condition between the threaded work item and the foreach loop.? If the threaded work item does not execute immediately, the foreach will throw out a NullReference exception.? Of course, in this case, we can add an easy fix to the NullReference problem:

List<string> duplicates = null;

System.Threading.ThreadPool.QueueUserWorkItem(

? new System.Threading.WaitCallback(delegate(object target)

? {

??? duplicates = new List<string>();

??? while(/* some condition */)

??? {

????? duplicates.Add(someMethod());

??? }

? }));

while(null == duplicates)

{

? System.Threading.Thread.Sleep(0);

}

foreach(string name in names)

{

? if(isDuplicate(name))

? {

??? duplicates.Add(name);

? }

? //…

}

So all is well, right?

Actually, it sucks.

The immediate risk of failure is averted, but the design is still poor.? It may be that we are required to use this design for some external reason, but on the face of it, it simply sucks.? Why not simply do away with the selective threading entirely and thread the whole method as needed?? By thinking about the problem and the reasons that we wanted to thread, we should be able to come up with several different ways of implementing this that do not suffer from the same drawbacks as the current implementation.? By simply thinking about the problem and what we are trying to accomplish before writing any code, we can eliminate most of these types of errors before they even occur.? But doing that would put us firmly in the camp of the first category of developers, which is much harder than to simply admit defeat.

Separation of Concerns

Thursday, September 25th, 2008

I had an interesting discussion today at work over whether it was appropriate to include a progress bar inside an export class.? I am of the opinion that the export class should merely provide hooks to access progress information that the caller would be able to connect to and display any progress bar as appropriate.? The person I was working with disagreed, making the argument that it would complicate the code and was unnecessary since we didn't have any intention of supporting alternative callers in the foreseeable future (the export class is called from a single export form).

Of course, this person (we'll call him Mark) is absolutely correct.? As of right now there is no plan to access this export from anywhere other than a windows form from which it is absolutely permissible to pop up a progress window to be displayed to the user.? So why do I care?

Essentially, it boils down to this:? I have worked on a fair share of maintenance tasks and release-cycle bug fixes, and I am against anything that makes it more difficult to fix/change/maintain.? Now, you might be asking yourself (much as Mark asked me), why I thought maintaining this code would be any more difficult than if he had separated concerns (grossly simplified to illustrate my point):

System.Windows.Forms.ProgressBar _progressBar;

string _path;

public void Export(string[] lines)

{

? this._progressBar.Minimum = 0;

? this._progressBar.Maximum = lines.Length;

? this._progressBar.Value = 0;

?

? System.IO.TextWriter writer = null;

? try

? {

??? writer = new System.IO.StreamWriter(this._path);

??? foreach (string line in lines)

??? {

????? writer.WriteLine(line);

????? this._progressBar.Value++;

??? }

? }

? finally

? {

??? if (null != writer)

??? {

????? writer.Close();

??? }

? }

}

My problem is that this is mixing two unrelated items.? For a lot of applications the export is critical – you have to have a way to get the data out of the system, but displaying a progress bar is never critical.? It makes things much nicer for the user, but in a pinch they can survive without it because there are other cues they can use to determine whether the system is doing anything or not.? If there is a problem in the display code for the progress bar, and I am in a rush, the first thing I will do is disable the display code.? Unfortunately, in this situation, that means that I have to go through and rewrite part of the export code.? What if the code had instead been written in this fashion:

? try

? {

??? writer = new System.IO.StreamWriter(this._path);

??? for(this._progressBar.Value = 0,this._progressBar.Value < lines.Length;this._progressBar.Value++)

??? {

????? writer.WriteLine(lines[this._progressBar.Value]);

??? }

? }

? finally

? {

??? if (null != writer)

??? {

????? writer.Close();

??? }

? }

?

Now we are starting to see why it is important to separate our concerns. We have tightly integrated the presentation logic with the export logic.? Changing one will necessitate a change in the other.? Now imagine this wasn't the grossly oversimplified example I have created here, and was instead a complicated export involving transformations, conditional data checks and multiple files.? Now imagine that it is an hour before the big demonstration to your client that will determine whether the project continues and the export keeps crashing.? With that kind of time pressure, it sure would be nice to have a sharply separated control and presentation layer, wouldn't it?? Something that would let you modify/fix/disable each part independently of the other…? Of course when I started to mention this well known pattern, Mark immediately explained how this was different (since this wasn't data and it wasn't part of the model it didn't count).

Of course, in this case, the corresponding solution is almost as simple (again, grossly oversimplified, but you can see the point):

? public class ProgressEventArgs : EventArgs

? {

??? public int Minimum;

??? public int Maximum;

??? public int Value;

?

??? public ProgressEventArgs(int min, int max, int value)

??? {

????? this.Minimum = min;

????? this.Maximum = max;

????? this.Value = value;

??? }

? }

? public class ExportClass

? {

?

??? public event System.EventHandler<ProgressEventArgs> UpdateProgress;

?

??? public void Export(string[] lines)

??? {

????? System.IO.TextWriter writer = null;

????? try

????? {

??????? writer = new System.IO.StreamWriter(this._path);

??????? for(int i=0;i< lines.Length;i++)

??????? {

????????? writer.Write(lines[i]);

????????? this.UpdateProgress(this, new ProgressEventArgs(0, lines.Length, i));

??????? }

????? }

????? finally

????? {

??????? if (null != writer)

??????? {

????????? writer.Close();

??????? }

????? }

??? }

? }

But somehow as software engineers we seem intent on always re-learning these lessons for ourselves…? In the end, I simply gave up the point after making my suggestion and spending a couple of minutes defending it.? Sometimes it is just better to maintain relationships than code.

Using Properties in Constructors

Wednesday, September 24th, 2008

I ran across an interesting question on stackoverflow.com tonight concerning whether or not it is considered “best practice” to use properties to set private data members instead of setting the members themselves.? It is interesting because it is a fairly common practice – I've seen constructors sprinkled with method calls and properties, usually in the name of clarity.? The idea is to keep all the validation code and so forth in the same place and use it to validate the inputs to the constructor.? This is a good idea, but like all interesting problems, it is not as simple as it seems.? Of course, Microsoft has been kind enough to publish their own set of guidelines and best practices for constructors, which interestingly enough addresses almost this exact issue.? Essentially, it boils down to whether the properties/methods being called are virtual.? If they are, there is a chance that the method being called will be executed by a type that has not been constructed yet.? Check out the guidelines from Microsoft, and read through their code example.? Its a worthwhile illustration of the problem and can hopefully help you avoid a very subtle defect.

Developers vs Testers

Wednesday, September 24th, 2008

This is a post that has been a while in the making because I can't seem to quite get it right.? It is essentially the basis behind my recent post The Danger of Bad Tests, so I figured that now is the time.? Developers make bad testers.

There I said it.? Everyone knows it.? Some people even talk about it.? But somehow we still manage to ignore it.? Writing code does not qualify you to test code, in the same way that testing code does not qualify you to write it.? This does not mean that developers should never have to test, nor that all testers should be exempt from writing code.? Instead it means that it is time to stop pretending that we can save money by pressing developers into double duty.

A lot of times developers make bad testers simply because they don't want to test.? This is the same reason that no one wants to work on maintenance projects consisting of mostly bug fixes.? All developers want to be making the cool new feature, not reading someone else's code to figure out why it is broken or running through ten different variations of the same function to make sure it can handle all the edge cases.? So, they do the bare minimum they need to do to get by and still be able to claim that a feature was tested, and then they return to the more interesting work of writing new code.

Of course, not all developers are seeking to simply scrape by.? There are a number that genuinely want to release quality software, and they make sincere attempts to test new features to ensure they work.? The problem is that developers know how the code should work, and test to make sure that it works the way they think it should.? They continue refining their code until they achieve their desired result, then they try to hit a couple of outlier cases and claim completion.? Only a few times have I ever encountered a situation where someone knowingly claimed a feature was complete when it wasn't (and this was always due to management plans that set an arbitrary code-complete date and then allowed for as much bug-fixing and testing as needed – a horrible plan that simply encouraged the developers to submit sloppy code and then fix it during the much longer testing and bug-fixing phase).

Finally, most developers become very attached to the feature as they wrote it.? They simply don't conceive of a way in which someone could use their feature in a wrong or unexpected way, so it doesn't occur to them to test those cases.? It doesn't occur to them to test what happens when you try to save a large file to an external drive and yank out the cord halfway through it.? Not because they are dumb or otherwise unimaginative, but because they already know that if you pull the external drive out while a file is saving, the file will not get saved.? Since you are trying to save the file, there is no reason to disconnect the hard drive until you are done.? Developers will argue for hours about whether something is a bug or a user error because if it is a bug, it implies there is something wrong with their code.? So when they test, they assume a perfect user, because a perfect user would never do something as dumb as disconnect a hard drive during a save.? Unfortunately, we all know the perfect user does not exist, but somehow the myth persists on.?

Just like the mythical developer as tester.

Constants First

Tuesday, September 23rd, 2008

Yep, I'm one of those people.? The kind of person who always puts my constants first in conditionals.? This was a learned habit, and not something that always comes naturally, but there are a couple of situations where if find it tremendously useful.? The prototypical situation is the ubiquitous null check:

? if (null != var)

? {

??? // Do Something…

? }

?

I have always liked this check for the simple reason that I only need to read the first two words to figure out what it is doing.? Since I usually am skimming code looking for important bits, I can quickly discard this check unless I am looking specifically for NULL reference issues.? I find it much quicker to read since I only rarely care about which variable is actually being checked for NULL.

Of course, that construct pre-dates modern compilers and comes from “back in the day” when you could make assignments inside an if statement and have it still be a valid conditional:

? bool myFlag = false;

?

? if(myFlag = true)

? {

??? // I want to do something if myFlag is true

? }

? // myFlag now equals true.

This used to be a perfectly valid statement.? In this case, the if statement will always get executed (myFlag would be assigned true, which is then passed to the conditional, which would logically evaluate to true).? Of course, today's modern compilers will flag the original as a warning, and since we all compile with the Warnings as Errors flag set (you do, don't you?), these types of errors will never happen…? But still, many a long night was spent looking for “=” where we meant to write “==”…? So a number of developers learned to write it backwards:

? bool myFlag = false;

?

? if(true = myFlag)

? {

??? // I want to do something if myFlag is true

? }

Since you can't assign anything to a constant, the compiler caught this for us.? Not perfect, because you could still accidentally assign variables, but it was better.? This was why I originally began putting constants first in my conditionals.? I got bit by this error once, and my technical lead at the time introduced me to this pattern, for which I am eternally grateful.

Of course, for some reason, this always seems to annoy someone.? They claim that since the compiler will catch it, and it isn't a “natural” construction, that I should write it the “correct” way (which is always with the constant on the right).? In most cases, I am actually indifferent to coding style.? I am a firm believer that as a software professional you must learn to read a wide variety of coding styles because otherwise you will never be as productive as someone who can read any style (or at least the popular ones).? However, in this particular case, I much prefer my method.? The reason is simple…? It allows you to avoid needless NULL checks:

??? public bool IsMe(string name)

??? {

????? if (name != null)

????? {

??????? return name.Equals(“Brian”, System.StringComparison.CurrentCultureIgnoreCase);

????? }

????? else

????? {

??????? return false;

????? }

??? }

This method simply checks to see if a given name is mine.? Pretty simple right?? Return true if the name passed in equals mine.? Oh and since we don't know who is calling this, make sure that the name isn't NULL, and if it is return false, since my name isn't NULL.

Simple.? But wouldn't it be easier to just write it like this:

??? public bool IsMe(string name)

??? {

????? return “Brian”.Equals(name, System.StringComparison.CurrentCultureIgnoreCase);

??? }

It does the exact same thing, only we don't need to bother with that pesky NULL check anymore.? The constant will never be NULL, so we can just test if the constant equals name, instead of the other way around.? It seems a little unnatural at first, but it avoids all sorts of unintentional errors (for example, how many people would have forgotten to check for NULL in the first example – I did the first time around…)??

Naturally, there are other ways to handle this and avoid having to test for NULL (String.Equals can handle null values), but this requires no framework support.? It will always work, and it has the added bonus that if you ever have to use a compiler that won't flag conditional assignments, you already use a defensive style of coding that won't expose you to unintended assignment errors.

The Danger of Bad Tests

Monday, September 22nd, 2008

Bad tests are worse than no tests at all.? It is a simple fact that seems to go unstated or unnoticed on most projects.? Someone decides that there must be a certain number of tests (or a certain percentage of code must be tested), and so the developers (who are already overworked and not suited to write good tests anyway) throw together a set of tests that ostensibly navigates the required functionality.

I am convinced that this seemingly unwritten rule is the reason that developers avoid writing tests.? We have all been forced to spend hours wading through some test failure only to discover that whoever wrote it had obviously spent more time commenting the code than actually testing what was needed.? Take, for example, my experience today.? I had to fix a defect which allowed bad data to be written to our database, so I wrote some code to validate the data before it was written.? It was a pretty simple fix as the code was already written, we had just missed an entry point.? Satisfied that all was well, I checked in the code, and promptly broke the build.?

Now, to be honest, this is a fairly common occurrence with me.? We use an automated build system that detects check-ins and schedules builds immediately.? Unfortunately, I have a habit of checking the differences in all my files before checking them in and including comments on the check-in to indicate what I had intended to do.? This naturally takes some time, so I frequently end up spanning the automated build process.? By the time I have completed my check-in, the build has already started, and will usually fail because of a dependency on an item I have not checked in yet.? This has had the unfortunate side-effect of training me to ignore build errors.? Its a bad habit, but the system is setup such that I expect a failure during my check-ins, so I wait for the second build before I worry about it.

In this case, the error was due to a test failing.? Originally I had assumed the test was failing due to my slow check-in process.? The test was in a related area, but was testing our handling of duplicates.? After the second build failed, I realized that the test was failing because of my change.? After looking at the test, there was no reason for it to be failing due to the changes I had made.? It claimed to be testing how the system saved duplicates – perfectly valid data in our case.? I checked the validation code and sure enough, duplicates were not allowed.? Intrigued, I stepped into the debugger to see what was going on.? Imagine my surprise when the validation failed!

Now I was in trouble.? I had been relying on the existing validation code and if it was flagging valid data incorrectly, I would have to go back through all the validation rules and make sure it was written correctly.? Not a task I was looking forward to.? Fortunately, in addition to my bad habit of not trusting the build, I have also learned not to trust our automated tests.? They were written with the goal of meeting a certain percent code-coverage, and have been shown to be fairly useless in terms of correctly evaluating the behavior of the system.? So I started looking at the actual data that was being written, and as it turns out, the data was in fact invalid.? The test, which was attempting to ensure that valid data could be written to the database, was writing invalid data.? Not only that, but the test had been happily running and passing for over a year.?

False positives such as this cause two problems.? The first problem was that the system was telling everyone that there was no defect in the way in which we handled duplicate data.? In this case there was in fact an underlying problem that was being hidden by our use of invalid data.? The problem had already been discovered in a released version and had been fixed, but this test never indicated that the problem existed, despite that being its reason for existence.? The second problem is that it falsely indicated an error when there was none, causing a couple of hours of development time to be lost in a very tight schedule.? Lapses such as this cause the situation that we are currently in on this project, where we have simply turned off a number of our automated tests because they are failing and no one can explain why.?

Good tests are hard.? They are hard to write, and they are hard to automate.? Unfortunately, the dangers of writing bad tests far outweigh the cost of writing a good test, so most developers simply ignore writing tests unless they are forced to, and then development slows down as everyone spends their time chasing imaginary bugs.

Data-binding Fun

Thursday, September 18th, 2008

I work mostly in C# these days, writing desktop applications.? Unfortunately this means that I am exposed to the great evil that is Microsoft's data-binding framework.? Now don't get me wrong.? Data-binding has its place.? It is great for quick and dirty prototypes or to quickly throw something together.? It does a remarkable job of getting you 90% complete.? The problem is that frequently that last 10% is next to impossible to implement because of all magic that occurs behind the scenes with little documentation and no access to it.

Take, for example, the problem I have been wrestling with today.? I have a wrapper class that exposes a couple of properties to both a data grid, and a property grid.? The wrapper is not particularly complicated, it is basically a pass through to keep the data layer out of the presentation layer (standard Model-View design, nothing fancy) and to make things nice for data binding.? As part of the “making nice” effort, we use the various attributes to provide clean display names, descriptions, categories (for the property-grid), etc.? For the data-grid, we explicitly bind the columns to the properties we are interested in.? For the property grid, we use the “Browsable(false)” attribute to indicate whether a given property should be displayed.

Everything was working great until we decided to no longer display one of the properties we had bound to our data grid in the property grid.? Looking at the documentation for the “browsable” attribute, it was pretty explicit that it pertained to property grids and design-time editors, and had nothing about general data binding, so we marked the property as non-browsable.

Naturally, the property grid immediately stopped displaying that property.? Unfortunately, the data grid did not display it either.? The behavior was more complex though because if you edited the value in the column, it would then display the newly edited value.? It appeared to only ignore the initial values.? So now we have a problem.? We don't want this property showing up in the property grid, but we have to bind to it so it will display in the data grid.? It seems another wrapper class is in my future…

Arrggg.

Fortunately in this case I was able to use a similar property that was being displayed in the property grid and bind the data grid to it and achieve the same affect by tweaking the formatting and parsing code.? Unfortunately, that seems to be par for the course with data binding, you can always get it to work, it just never seems to be exactly what you want, and in the end, you seem to spend all of your time getting it to do *almost* exactly what you want…

Russian Roulette

Monday, September 8th, 2008

I have a confession to make.? I love code reviews.? Done correctly, they are a wonderful opportunity to learn and expand your coding style.? They can provide an excellent safety net and in the long run will increase productivity.? How many of us have had to step in to help with a feature because it is late or someone has left, or have had to fix a bug in someone else's code because that person is working on something else just as important?? How many of us have had a developer leave a project and wonder how on earth are we going to finish the release on time because nobody understood what that person had been doing?? Code reviews alleviate these problems because other members of the team are involved in all development on the project.? No one is “going dark” because reviews are required on incremental changes.? All the information is spread among multiple team members, and this is a good thing.

Of course, most of us have more experience with the bad reviews.? The ones where you spend three hours reformatting your code because Bill doesn't like it when your brackets are on a separate line.? Or where you have a continuous discussion about the best possible name for a one-line method.? Or where someone doesn't like the naming scheme you used for your private member variables.? The list goes on and on.? The number of hours a code review can cost you in time and effort far exceeds the number of hours you can save.? And yet, I still prefer bad reviews over no reviews at all.? Folks can argue over all the different benefits and drawbacks, but for me, it comes down to two things.

First, reviews let me see fairly quickly who knows what they are doing and who doesn't.? Reading code is hard.? I like to have every opportunity to see new styles and learn from them.? Conversely, I have never met a great developer who was not also a great reviewer.? These are the people who can look past the idiosyncrasies of your code and distill it down to something they can both understand and critique.? Seeking out these folks and squeezing them for every bit of knowledge they have time to give you is the quickest way to becoming a great developer yourself.

Second, some things are next to impossible to catch in testing.? The behavior may not manifest itself in an error, but instead in wrong output.? They may be edge cases or threading errors that may only manifest themselves once in a thousand runs.? There is no substitute for a quality code-review to catch and correct these errors while the code is fresh in your mind.? Even a bad review will cause at least one or two other people to look at and think about your code.? That may trigger a memory about a little-used utility method that can greatly enhance the code, or a hidden performance drain, or a memory hog, or any of the million other little mistakes that can creep into your code the longer you go without someone else looking at it.

Of course, the reason I write all this is because today is the first time in 6 months I participated in a real code-review on my current project.? The team does not believe reviews to be worthwhile, yet in the quick 15 minute review we performed today we found a serious logic error that would not have manifested itself except through careful analysis of thousands of data point for a subtle off-by-one error.? Instead, a simple change to a couple of lines of code and all is well.? The review easily saved us over a week of analysis and debugging time, and took a total of 1 man-hour to complete.? By my estimate, this review alone should buy us enough time to perform up to 39 other reviews, assuming we find no other problems…? But instead, we will continue to play Russian roulette, hoping that each of us is smarter than everyone else.? Eventually, it will catch up with us.? Hopefully, we will continue with the code reviews before it does.

The Singularity

Wednesday, September 3rd, 2008

So recently I have had the chance to catch up on some reading.? I subscribe to several different magazines and have been steadily accumulating unread issues for the past several months so I am making a concerted effort to read and clear them all out.? In doing so I ran across a fascinating issue from IEEE Spectrum that was published in June (Spectrum is one of my favorite magazines – its a nice easy read that covers a broad range of current technology topics).

The issue concerned the idea of the “Technological singularity” – in a nutshell it is a belief that one day humans will create a machine intelligence that will be able to spawn ever more intelligent machines.? The singularity will occur as the machine intelligence is improved at an exponentially faster rate until eventually the machine intelligence far surpasses our own.

The articles all present intelligent and well-described positions both for and against the singularity occurring, so I won't bother to go into their details here, instead I will simply suggest that you simply go straight to the source and browse through the articles available through their website.

While I found the articles all fascinating, I must admit to a healthy dose of disbelief when it comes to the idea of a singularity.? Essentially, I don't understand the leap in faith required to extrapolate the current technological progress to an ever increasing intelligence.? The idea seems to be that if we can create an artificial intelligence and if technology continues to advance that artificial intelligence will get smarted simply through the increased speed in which it can perform its computations.? While I don't have a problem believing that one day we will eventually be able to create an intelligent machine, I see no reason to believe that a faster machine is any more intelligent than its slower brethren.? Sure it may be able to calculate equations faster, but the end result will still be the same – its just a matter of the amount of time it takes to get there.

In addition, humans have a long history of creating intelligent “machines” – our educational system has been churning out intelligent humans for centuries, and yet we have yet to encounter the type of exponential growth in human intelligence that we seem so ready to ascribe to machines going through a similar process.? We still produce far more “average” humans than we do geniuses.? The idea that we can somehow invent the magical formula to do this for machines when we still don't know how to do it for humans seems far-fetched at best.?

I think that it is far more likely that we end up with machines with the same range of intelligence as we see in humans.? Some machines will be able to perform amazing feats of intelligence (depending on your definition of intelligence, we have already achieved some impressive feats of “intelligence”, especially in the realm of games), while others will range from the ordinary down to the current “dumb” machines we see today.? As our own intelligence increases, the intelligence of the machines will increase in tandem, so that as we understand more of our world, the machines we create will understand correspondingly larger portions of the world.

Of course, one of the geniuses I talk about above may invent a completely new type of machine or software that will invalidate all my experience and pre-conceived notions such that my concerns are no longer relevant.? In which case, I for one, will welcome our new robot overlords…