Wednesday, June 02, 2004 - Posts

C-Omega, extensions to C#

Microsoft Research is publishing some white papers about C-Omega, a research programming language (actually an extension to C#). It contains a "control flow extension for asynchronous wide-area concurrency (formerly known as Polyphonic C#)" and "a data type extension for XML and table manipulation (formerly known as Xen and as X#)".

It looks intriguing. Especially if you remember that Whidbey's Generics also started out as a Microsoft Research extension to C#...

with 0 Comments

Assert Yourself (Part I)

Asserting yourself is a best practice. Especially when you write code. Or rather, you should assert that your code is correct.

What I'm talking about, of course, is not psychology or assertiveness, but correct and abundant use of Debug.Assert. This wonderful method, which dates back to the old C days, is executed in Debug versions of our code and verifies whether given assumptions are true. If not, the code exits and writes an error message to the Debug output, which we can read in Visual Studio.Net or which we can log to a text file, for example, using a TraceListener.

Misconceptions about Debug.Assert?

Misconception: Debug.Assert is for input parameter validation only

Hold on, hold on. Yes, I'm sure most of us know Debug.Assert and that many developers use it, maybe all the time, for input parameter validation on non-public methods. It's excellent for that, as is illustrated in this example:

Example 1

   1:  protected static double OptimizedLength(string text, int start, int end) {
   2:      Debug.Assert((text != null) && (text.Length > 0), "OptimizedLength: Input 'text' is empty.");
   3:      Debug.Assert(start > 0, "OptimizedLength: start is out of range.");
   4:      Debug.Assert(end >= start, "OptimizedLength: end is not after or equal to start.");
   5:   
   6:      //Rest of code here
   7:  }
 
But it can help us even better! Debug.Assert, in my humble opinion, is the most underused tool available in the .Net world, while it should, in fact, litter all code. Even in Microsoft's own example code, there's hardly any trace of it (pun unintended). It seems that us developers have some misconceptions about it, or fail to see the full range of its applicability.
Example 2

Consider this simple piece of code:

   1:  XmlNode pathNode = node.Attributes["HintPath"];
   2:  string xmlPath = pathNode.Value.Replace(".dll", ".xml");
   3:  Console.WriteLine("XML Path: " + xmlPath); 

What's wrong here?

If anything goes wrong during execution of this code, it's hard to tell why exactly. The author assumes that the XmlNode called node exists, is non-null and contains an attribute called HintPath. There's no doubt. If, due to a bug somewhere, one of these assumptions is wrong, the code above fails and it's hard to figure out which assumption was wrong.

Unless the author uses our friend:

   1:  Debug.Assert(node != null, "Node is empty before reading HintPath.");
   2:  Debug.Assert(node.Attributes != null, "Node Attributes are empty before reading HintPath.");
   3:  XmlNode pathNode = node.Attributes["HintPath"];
   4:   
   5:  Debug.Assert(pathNode != null, "Path Node is empty before determining XML Path.");
   6:  Debug.Assert((pathNode.Value != null) && (pathNode.Value.Length > 0), "Path Node is empty string.");
   7:  string xmlPath = pathNode.Value.Replace(".dll", ".xml");
   8:   
   9:  Console.WriteLine("XML Path: " + xmlPath);

Now, if something causes any of the assumptions to be off, whoever has to debug this code knows about it as soon as it happens. And of course, the cause of the error will show up on the test report. This is a tremendous help when debugging.

Misconception: This is too much work!

Ouch--the old argument that quality assurance is too much work. I agree that it's no fun, and that it seems to bog down developer functionality (just like that other thingy that's too much work: unit testing), but the fact is that it doesn't. Smart developers (that is, those who write unit tests and asserts) spend much less time debugging their code than others simply because they know where to look when something goes awry. An informed developer is worth two, you could say.

Adding asserts doesn't add much work to the load of development. It's not like adding an assert is as complex as figuring out a new sorting algorithm, and it doesn't take much time to type, especially with IntelliSense.

Misconception: Debug.Assert slows down my code

This is and is not a misconception. Debug.Assert statements only show up in the Debug version of your assemblies, so they don't slow down your Release code. But, of course, they do slow down Debug code.

There's nothing really wrong with that, unless your code is extremely time-sensitive. But if it is, probably you're not doing much logging, if any. Time-sensitive code is hard to debug, but that's another story. In most cases, the slowdown caused by ubiquitous Debug.Asserts doesn't matter much--especially considering the benefits. And if you're ready to stress-test your app, simply stress-test the Release version.

Incidentally, if you don't believe Debug.Assert only shows up in Debug assemblies, disassemble your Debug and Release assemblies and see for yourself!

with 0 Comments

About Smart Development

Hi everyone, and welcome to my blog. Here you'll regularly find new short pieces about Smart Development with .Net.

Smart Development isn't some new methodology or framework such as Extreme Programming (XP) or Microsoft Solutions Framework (MSF). It's just the name I give to a set of best practices, combined from XP and MSF, and some own observations added in. Moreover, it differs from XP in the way it looks at planning and teaming, to name a few. More will become clear in the time to come, on these pages.

The goal of Smart Development is simple: to give development teams the guidance to develop the best possible software, in the shortest time possible. Time is money, as they say, and that is certainly true in the software business. Many projects get canceled simply because they run out of money, or because of very poor planning. XP, MSF etc. try to minimize such risks. For example, XP says "don't do any planning more than 2 iterations ahead." I almost agree with that, but I think the very first phase of a project should include at least good guesstimation of the costs and features of a project -- and good guesstimation is derived from some form of plan.

Basic principles of Smart Development are:

  1. Iterative development: projects are developed in short iterations (1 to 3 weeks, tops), and iterations alternate between "new features" iterations and "bug-fixing/optimization" iterations;
  2. Quality comes first: for every decision to be made, always put the quality of the output first. One direct result of this principle: you don't add new features to your project if there are still known bugs that have not been labeled "acceptable". Another one: automate as much of the build and development processes as you can, as long as it's (pragmatically) justifiable, because nothing is as common and expensive as human error;
  3. Build process: with daily or multiple-daily builds as the heartbeat of the project, teams know that their software builds and integrates correctly. I personally don't like the idea of XP's Continuous Integration very much because I think it is applicable only to smaller projects, but a twice-daily build, for example, makes perfect sense even with larger projects. One of these builds is the full build, including all unit tests, complexity metrics, FxCop tests and what have you, whereas the second build runs less tests and can be considered merely a "smoke test" before the real "daily" build is started;
  4. Focus on provable correctness: unit testing is super-important. It is necessary to test the quality of new features, for regression testing (making sure new features don't break existing ones), quick-fix engineering and progress tracking;
  5. Progress tracking: progress needs to be tracked; not just the measurement of which features have been added etc., but also the number of new vs resolved bugs, the complexity of the software produced etc. need to be measured continuously. Especially for project leaders: never let the question "so how's your project going?" surprise you -- instead, answer with hard facts;
  6. Documentation: as part of progress tracking as well as making sure users will know how to use the software, and developers will be able to maintain the software in the future, documentation takes a primary position. Yes, we programmers hate to write documentation, but we hate to maintain undocumented code even more. Included in the documentation principle is, of course, the central availability of information and documentation to all: easy to find and complete;
  7. Know what you do, and do what you know: all work should be divided up into small, individual tasks that are either complete or not counted (i.e., they are never "90% done", but 0% or 100% done), and work should be done by those who are most qualified to do it. XP states, for example, that everyone should be able to tackle any task and assume any role in the team. I respectfully disagree. I think that, especially for larger projects with larger teams, specialization is an important benefit. Not everyone is as good a DBA or as good a low-level coder as their neighbor, and I think pragmatic teams should recognize that and benefit from it.

We'll get into detail in the coming months and years on this blog, on every one of these subjects.

Of course, comments and suggestions are always welcome. You can leave them here, straight on-site, or you can mail them to roy@u2u.be.

Many thanks,

Roy

with 0 Comments