Thoughts from the office by Ed Ball
Friday, January 11, 2008

For my latest technical blogging, check out http://code.logos.com/blog/. Specifically, check out my introductory post and my first technical post.

1/11/2008 3:20:40 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, September 21, 2005

I'm still waiting to find a good introduction to Windows Communication Foundation (aka WCF aka “Indigo”). I want an article or book that explains even the simplest foundational concepts; something for a client application developer like myself who is realizing that his code will eventually have to talk to that newfangled “Internet” he keeps hearing about.

A recently published MSDN article comes close, but it still uses too many big words. What little I understand sounds compelling, though, so I'll keep waiting...

9/21/2005 8:00:30 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, April 19, 2005

This is hopefully the first of a series of posts about object-oriented programming in JavaScript. You can’t get far in JavaScript without learning about functions and the built-in object types, but the mechanisms for defining your own object types aren’t quite as obvious. Let’s start as simple as we can – we’ll create an object that represents a two-dimensional point:

var pt = {};
pt.X = 3;
pt.Y = 4;

No surprises there. The pt object has two properties, X and Y. We can write functions that manipulate points; for example:

function MovePoint(pt, dx, dy)
{
  pt.X += dx;
  pt.Y += dy;
}
MovePoint(pt, 1, 2);

Of course, we’d rather have a Move method on the pt object itself.

pt.Move = function (dx, dy) { this.X += dx; this.Y += dy; };
pt.Move(1, 2);

When a function is assigned to a property of an object, and that function is called using the syntax shown, the special this variable references that object, so that when pt.Move is called, this.X refers to the X property of pt.

Now, it would be rather inconvenient to type all of that every time we need a new point, so we can write a function that creates a point.

function CreatePoint(x, y)
{
  return { X : x, Y : y, Move : Point_Move };
}
function Point_Move(dx, dy)
{
  this.X += dx;
  this.Y += dy;
}
var pt = CreatePoint(3, 4);
pt.Move(1, 2);

I’ve also taken the liberty of creating a Point_Move function so that a new anonymous function isn’t created every time a new point is created. (The actual name of the Point_Move function isn’t relevant; I could have called it Krebf, but the Point_Move naming convention helps me remember that I’m using it as the Move method for a Point.)

This actually works quite well, but it would be more natural if we could use the new operator, as with built-in objects. Fortunately, this is easy enough to do – we just create a function that will serve as the constructor.

function Point(x, y)
{
  this.X = x;
  this.Y = y;
  this.Move = Point_Move;
}
var pt = new Point (3, 4);
pt.Move(1, 2);

The two approaches do almost exactly the same thing; new Point creates a new object and immediately calls the Point function as if it were a member of the new object. There are subtle (and useful) differences that I’ll describe in my next post.

4/19/2005 3:44:13 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | JavaScript#
Monday, April 11, 2005

Be sure to read the revised Dispose, Finalization, and Resource Management Design Guideline, if only for Herb Sutter's annotations, in which he shamelessly demonstrates the superiority of C++/CLI in its handling of these issues.

4/11/2005 7:47:21 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, April 07, 2005

If you are as eagerly anticipating C++/CLI as I am, you will have no trouble sitting through 90 minutes of Herb Sutter at OOPSLA 2004. He does an outstanding job of explaining why we should bother with C++ when we already have such great languages as C# and Java. Be sure to stay for the questions; it seems not everyone is enthralled with C++ and .NET…

4/7/2005 8:43:58 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, April 06, 2005

Have you ever wanted to determine programmatically the name of the function represented by a function object? There’s no direct way to get it, but there is an indirect way. The toString method of a function object returns the function declaration, from the function keyword at the start all the way to the last closing brace. Even “native” functions support the toString method in this fashion, though the implementation is omitted. This means that a simple regular expression can be used to determine the name of any function.

function GetFunctionName(fn)
{
  var m = fn.toString().match(/^\s*function\s+([^\s\(]+)/);
  return m ? m[1] : "";
}

The regular expression simply finds the identifier after the function keyword. If it isn’t there (as can be the case with anonymous functions) GetFunctionName returns the empty string.

4/6/2005 3:22:20 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | JavaScript#
Tuesday, April 05, 2005

My last post described the BindArguments function – it returns an anonymous function that, when called, calls another function with the arguments originally specified in the call to BindArguments. Put another way, BindArguments converts a function that takes n arguments into a function that takes 0 arguments. But what if we need a function that takes 1 argument?

Imagine we have a Transform function that transforms an array of numbers in place:

function Transform(array, fn)
{
  ForEach(array, function (x, n) { array[n] = fn(x); });
}

We want to use this Divide function to do the transformation.

function Divide(n1, n2)
{
  return n1 / n2;
}

If we want to invert the numbers in the array:

Transform(array, function (x) { return Divide(1, x); });

Can we write a binding function like BindArguments that allows us to avoid the explicit anonymous function? BindArguments won’t work, because it returns a function that takes 0 arguments. If the returned function is called with any arguments, those arguments are ignored. We need the returned function to accept an argument and call Divide with 1 and that argument. We’ll call it BindFirst, because it accepts a function that takes two arguments and binds the first one.

Transform(array, BindFirst(Divide, 1));

In other words,

BindFirst(fn, x)(y) === fn(x, y)

Can we write such a function? Of course!

function BindFirst(fn, arg)
{
  return function (x) { return fn.call(this, arg, x); };
}

We can do better and create a function that will bind any number of arguments before any number of additional arguments.

// BindFirst(fn, x1, x2, …, xn)(y1, y2, …, yn) === fn(x1, x2, …, xn, y1, y2, …, yn)
function BindFirst(fn)
{
  var args = [];
  for (var n = 1; n < arguments.length; n++)
    args.push(arguments[n]);
  return function ()
    {
      var myargs = [];
      for (var m = 0; m < arguments.length; m++)
        myargs.push(arguments[m]);
      return fn.apply(this, args.concat(myargs));
    };
}

Outstanding. But wait; what if we want to divide the numbers in our array by 2?

Transform(array, function (x) { return Divide(x, 2); });

What we need here is a BindSecond function.

// BindSecond(fn, x)(y) === fn(y, x)
function BindSecond(fn, arg)
{
  return function (x) { return fn.call(this, x, arg); };
}
Transform(array, BindSecond(Divide, 2));

Better yet, BindLast, whose implementation I leave as an exercise for the reader. (It is very similar to that of BindFirst.)

// BindLast(fn, x1, x2, …, xn)(y1, y2, …, yn) === fn(y1, y2, …, yn, x1, x2, …, xn)

Is it possible to write a truly generic Bind function that can be used in place of both BindFirst and BindLast and support even more complex binding scenarios? It is, and I hope to show it to you… in a future post.

4/5/2005 12:31:44 PM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code | JavaScript#
Thursday, March 31, 2005

When you start passing functions around, you often end up creating anonymous functions that call other functions with specific arguments.

For example, let’s suppose that we’re writing a DHTML calculator, and we have a function WriteDigit that writes the specified digit to the display. To set the onclick handlers of the calculator buttons, we could do something like this:

btnOne.onclick = function () { WriteDigit(1); };
btnTwo.onclick = function () { WriteDigit(2); };

That will work just fine, but there is another way. We can write a function that takes an integer as its argument and returns the anonymous function.

function BindWriteDigit(n)
{
  return function () { WriteDigit(n); };
}
btnOne.onclick = BindWriteDigit(1);
btnTwo.onclick = BindWriteDigit(2);

Why would we do such a thing? Well, one good reason is to avoid unwanted closures. Whenever you create an anonymous function, you’ve got to pay attention to the local variables that will be kept alive, particularly under Internet Explorer, as I alluded to in a previous post. In general, when you are creating anonymous functions that will outlive the function that is creating them, you should minimize the number of local variables in that surrounding function to prevent unwanted closures, accidental modification of local variables used by the anonymous function, and other surprises.

It would be a pain to write a separate binding function for every function that we want to bind; fortunately, we can write a function that takes a function as its first argument and returns an anonymous function that calls that function with its second argument.

function BindArgument(fn, arg)
{
  return function () { return fn(arg); };
}
btnOne.onclick = BindArgument(WriteDigit, 1);
btnTwo.onclick = BindArgument(WriteDigit, 2);

No need to stop with one argument, though; with a little more effort, we can write a function that will bind to any number of arguments by using the apply method.

function BindArguments(fn)
{
  var args = [];
  for (var n = 1; n < arguments.length; n++)
    args.push(arguments[n]);
  return function () { return fn.apply(this, args); };
}
btnOne.onclick = BindArguments(WriteDigit, 1);
btnTwo.onclick = BindArguments(WriteDigit, 2);

This technique comes in very handy, particularly in problems that are less contrived than this one. You can do a lot more than this with a sufficiently complex binding function; more on that in a future post.

Update: Fixed a bug in BindArguments. (Thanks, Bradley!)

3/31/2005 1:50:13 PM (Pacific Standard Time, UTC-08:00) | Comments [8] | Code | JavaScript#
Wednesday, March 30, 2005

As I mentioned before, for...in would be a convenient way to enumerate arrays, if it actually worked the way you’d expect it to. Fortunately, anonymous functions make it possible to write a ForEach method that’s almost as easy to use as a proper foreach.

function ForEach(array, fn)
{
  for (var n = 0; n < array.length; n++)
    fn(array[n]);
}

As you can see, ForEach calls the specified function for each element of the array. So if you’d like to calculate the sum of the items in an array:

function SumArray(array)
{
  var nSum = 0;
  ForEach(array, function (n) { nSum += n; });
  return nSum;
}

I hope you agree that this syntax is not only more compact than an explicit loop, but that it is also easier to understand. It is also less efficient, of course, but not significantly so, except in special cases where you would certainly measure to determine its impact; you could easily unravel it into a standard loop if necessary.

My preferred implementation of ForEach is slightly more complicated.

function ForEach(array, fn, objThis)
{
  objThis = objThis || this;
  var len = array.length;
  for (var n = 0; n < len; n++)
  {
    var r = fn.call(objThis, array[n], n);
    if (r !== undefined)
      return r;
  }
}

Let me explain:

  • Calculating the array length outside the loop can be slightly faster.
  • I pass the item index as the second argument to the called function, since that can often be useful. (The called function doesn’t need to declare it as an explicit argument if it doesn’t need it.)
  • If the called function returns anything but undefined, the loop is terminated. This allows us to simulate what would be a break statement in a normal for loop. The ForEach method returns the value returned by the called function.
  • If the called function returns undefined, the loop continues. (A function returns undefined if it gets to the end without hitting a return statement, if it hits a return statement without an expression, or if it hits a return undefined (naturally).) An explicit return statement without an expression thus simulates what would be a continue statement in a normal for loop.
  • Using the call method allows us to specify this for the called function, which can be useful when calling ForEach from an object method.
  • The objThis argument is optional, but I make sure that it is never undefined, because under Internet Explorer, the call method is slightly faster when the first argument is a valid object (passing undefined forces it to determine the “global” object itself).

For example, we can use ForEach to find an item in an array, returning the index of that item, or -1 if the item is not found.

function FindInArray(array, find)
{
  var index = ForEach(array,
    function (item, n)
    {
      if (item == find)
        return n;
    });
  return index === undefined ? -1 : index;
}

In many cases (but not all) I have found that using ForEach is easier to write and more natural than an explicit loop. YMMV.

Update: Explicitly described how to simulate a continue; thanks to Eli for his comment.

3/30/2005 8:53:48 AM (Pacific Standard Time, UTC-08:00) | Comments [3] | Code | JavaScript#
Monday, March 28, 2005

Let’s say you want to sort an array of integers.

var array = [ 3, 14, 15, 9, 26 ];

You might think that you could just use the sort method of the Array. You’d be wrong.

array.sort(); // [ 14, 15, 26, 3, 9 ]

The sort method of an Array always sorts strings, which produces the unexpected result shown above. However, you can pass a function to the sort method.

function CompareIntegers(x, y) { return x - y; }
array.sort(CompareIntegers); // [ 3, 9, 14, 15, 26 ]

Now we’re talking. The CompareIntegers function returns a positive integer if x > y, a negative integer if x < y, and zero if x == y, which is what we needed for the sort method.

What if we wanted to sort the numbers in reverse order? Well, we could define a CompareIntegersDescending function, but it’s easier to use an anonymous function.

array.sort(function (x, y) { return y - x; }); // [ 26, 15, 14, 9, 3 ]

Very convenient. Here’s a function that can be used to find an item in an array.

function Find(array, fn)
{
  for (var n = 0; n < array.length; n++)
    if (fn(array[n]))
      return n;
  return -1;
}

The first argument is the array to search; the second argument is a function that returns true when the item has been found. We can use the Find function to find the index of the first item greater than 10:

function FindGreaterThanTen(array)
{
  return Find(array, function (x) { return x > 10; });
}

But what if you want to find the first item greater than an arbitrary number? Remarkably, this works fine:

function FindGreaterThan(array, n)
{
  return Find(array, function (x) { return x > n; });
}

This demonstrates the true power of anonymous functions. The definition of an anonymous function has access to any and every variable that was visible where the function was defined, including local variables. Furthermore, it retains access to those variables as long as the anonymous function lives, even after the calling function has returned! An anonymous function used in this way is called a “closure.”

Whenever you create an anonymous function that is stored in such a way that it will outlive the function call that created it (which is not the case in the example above) you need to keep in mind that every local variable of that function call will live as long as the anonymous function lives. (That’s right – every local variable, not just the variables that the anonymous function happens to use.) If any of the local variables are references to objects that aren’t needed by the anonymous function, this could prevent garbage collection from freeing otherwise unused memory; if the objects reference large amounts of memory, this can quickly become a serious performance problem. If you’re working with Internet Explorer, you should also be aware of a serious memory leak that occurs when reference cycles are created that involve DOM nodes; these cycles are easy to create inadvertently when using anonymous functions as event handlers.

Occasionally, you’ll want an anonymous function to support recursion, in which case you can use arguments.callee to reference the otherwise unnamed function.

var fnClearAll = function (obj)
  {
    for (var key in obj)
      arguments.callee(obj[key]);
    Clear(obj);
  };

Now that I’ve talked about anonymous functions, I can describe my favorite way to enumerate an array – see my next post for a description of the ForEach function.

3/28/2005 12:42:10 PM (Pacific Standard Time, UTC-08:00) | Comments [2] | Code | JavaScript#
Friday, March 18, 2005

Normally you access function arguments by name.

function WriteAll(a, b)
{
  Write(a);
  Write(b);
}

However, you can also access function arguments by index using the special arguments object. This technique is particularly useful when implementing a function that takes an arbitrary number of arguments.

function WriteAll()
{
  for (var n = 0; n < arguments.length; n++)
    Write(arguments[n]);
}

The arguments object has a length property and one integer property for each argument (starting with 0, of course), but its similarity to Array ends there – it has none of the other methods of an Array. It is easy enough to convert an arguments object to an array; I use SliceArguments:

function SliceArguments(args, nStart, nEnd)
{
  if (nStart === undefined)
    nStart = 0;
  if (nEnd === undefined)
    nEnd = args.length;
  var aResult = [];
  while (nStart < nEnd)
    aResult.push(args[nStart++]);
  return aResult;
}

The arguments object has another useful property; the callee property returns the Function object that is being executed. This is primarily useful for recursion in anonymous functions, since there’s no function name to use. (I’ll talk more about anonymous functions in a future post.)

The arguments object has one more property: caller. It returns the Function object that called the currently executing function. However, the caller property has limited use, and has been deprecated in the most recent versions of JavaScript.

One more item of interest – each Function object has a length property that indicates the number of named arguments of that function.

function Blorb(a, b, c) {}
// Blorb.length == 3
3/18/2005 12:58:31 PM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code | JavaScript#
Tuesday, March 15, 2005

The nicest way to enumerate an array would be to use the for...in operator:

for (var obj in array)
  ...

Don’t do it. The biggest surprise to the uninitiated is that this enumerates the indexes into the array, not the elements of the array itself. You’ll also find that the enumerated indexes are strings rather than integers. Worst of all, you’ll find that the indexes aren’t enumerated in numerical order, but in arbitrary order. You’ve probably figured out by now that what you’re actually doing is enumerating the properties of the array object, which happen to include the properties whose names are non-negative integers, but would also include any other custom properties you had assigned to the array.

So, how to enumerate an array? Well, the best approach is the most obvious – walk through the indexes of the array with a simple for loop:

for (var n = 0; n < array.length; n++)
  DoSomething(array[n]);

For a small speed increase, pull the length out of the loop.

var len = array.length;
for (var n = 0; n < len; n++)
  DoSomething(array[n]);

However, my favorite way to enumerate an array is to call a ForEach function that does all this for me – more on that in a future post...

3/15/2005 9:05:23 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | JavaScript#
Friday, March 04, 2005

Arrays in JavaScript are really just Objects with properties whose names happen to be non-negative integers. They also have one very special property: length.

A new array has a length of zero.

var a = []; // a.length == 0

Whenever a property whose name happens to be a non-negative integer is set, the length is automatically set to one more than that integer (unless the length is already greater than that integer).

a[3] = true; // a.length == 4
a[9] = false; // a.length == 10
a[6] = false; // a.length == 10

JavaScript Arrays are “sparse” – no space is allocated for unused elements.

// a[2] === undefined, (2 in a) === false

Deleting an item in the array has no effect on the length.

delete a[9]; // a.length == 10

Explicitly enlarging the length of the array has no effect on the items in the array.

a.length = 12; // a[11] === undefined, (11 in a) === false

Explicitly reducing the length of the array automatically deletes any items in the array whose index is greater than or equal to the length.

a.length = 5; // a[6] === undefined, (6 in a) === false

You can use the length to add an item to an array (but prefer the push method).

a[a.length] = true; // a[5] === true, a.length == 6

Arrays support a number of useful methods that treat the object like a traditional array:

  • push, pop: Adds or removes items from the end of the array.
  • unshift, shift: Adds or removes items from the beginning of the array.
  • slice: Returns a range of array items as a new array.
  • splice: Inserts and/or removes items to/from the array.
  • concat: Combines one or more arrays to form a new, concatenated array.
  • join: Joins the string forms of the array items into one string.
  • sort: Sorts the items in the array.
  • reverse: Reverses the items in the array.

There’s no clone method, but you can clone an array by calling either slice or concat with no arguments.

3/4/2005 3:08:09 PM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code | JavaScript#
Thursday, March 03, 2005

Since new object properties can be created at will, a plain old Object is quite useful in JavaScript.

One common use of an Object is as a simple data structure. For example, if you want to return multiple values from a function, you can return an object with multiple properties:

function SplitAt(str, n)
{
  var obj = new Object;
  obj.Before = str.substring(0, n);
  obj.After = str.substring(n + 1);
  return obj;
}

Or, using the abbreviated syntax:

function SplitAt(str, n)
{
  return { Before : str.substring(0, n), After : str.substring(n + 1) };
}

Another common use of an Object is as an associative array; specifically, a mapping from strings to objects.

var map = {};
map["George Washington"] = 1789;
map["John Adams"] = 1797;

Or:

var map = { "George Washington" : 1789, "John Adams" : 1797 };

To see if a string is represented by an associative array, you could simply check that it isn’t undefined (e.g., map["Ed Ball"] !== undefined), but a property can be explicitly set to undefined, so you should use the in statement (e.g., "Ed Ball" in map).

To remove a string from an associative array, use delete (e.g., delete map["Ed Ball"]).

To see all of the strings represented by an associative array, use for...in:

for (var str in map)
  write(str + " (" + map[str] + ")");

When using an Object as an associative array, make sure that your strings will never be the same as the name of a built-in property of Object, e.g., "toString" or "prototype". Why? Well, for example, unless it has been overwritten, map["toString"] evaluates to a Function object instead of undefined. Furthermore, "toString" in map will always return true, but for...in will never enumerate "toString", and delete map["toString"] will always fail.

Also keep in mind that future versions of JavaScript could add new built-in properties; for example, version 5.5 added "hasOwnProperty". When I want to make absolutely sure that I won’t have any conflicts with built-in properties, I prefix the string with a space character – no built-in property will ever start with a space, after all.

function Get(map, str) { return map[" " + str]; }
function Set(map, str, obj) { map[" " + str] = obj; }
function Has(map, str) { return (" " + str) in map; }
function Erase(map, str) { delete map[" " + str]; }
function Find(map, obj)
{
  for (var str in map)
    if (map[str] == obj)
      return str.substring(1); // remove space
}
3/3/2005 1:23:58 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | JavaScript#
Friday, February 18, 2005

In JavaScript, the “Boolean” operators && and || aren’t very Boolean at all. In most C-style languages, a || b returns a Boolean – true if either a or b are “true,” and false otherwise. (Remember that lots of things are “true” in JavaScript – in fact, the only things that are “false” are the false Boolean, the numbers 0 and NaN, the empty string, null, and undefined.)

Actually, that’s a somewhat simplified view, because the && and || operators of C-style languages short-circuit, meaning that b is not evaluated if a is “false.” Thus it is safe to have an expression like a == null || a.isEmpty() – the isEmpty method will not be called if a is null.

Where was I? Ah, yes, in most C-style languages, a || b returns a Boolean, so it’s the same as

a ? true : (b ? true : false)

But in JavaScript, a || b doesn’t necessarily return a Boolean, because it is really the same as

a ? a : b

How does this work? Well, if a is “true,” then a || b returns a, which is “true.” If a is “false” but b is “true,” then a || b returns b, which is “true.” If both a and b are “false”, then a || b returns b, which is “false.”

The danger is in assuming that a || b returns a Boolean when a and b are not Booleans themselves. For example:

var hasItems = a && a.getCount();
if (hasItems == true) // should be: if (hasItems)
  ...

Now, you shouldn’t be comparing Booleans to true or false anyway, but if you did, you’d find that hasItems equals true only when a.getCount() returns 1 (and then only because 1 equals true in JavaScript). Furthermore, hasItems equals false only when a.getCount() returns 0 (because 0 equals false). If a is null, hasItems will be null, which equals neither true nor false. If a.getCount() returns 2, hasItems equals 2, which, again, equals neither true nor false.

Be aware that the MSDN documentation is stunningly inaccurate here; it suggests that && and || always return true or false. (The JScript.NET documentation is more accurate, thankfully.)

Why does JavaScript evaluates the binary Boolean operators this way? Well, a || b provides a great shortcut for a ? a : b that only evaluates a once. Similarly, a && b provides a nice shortcut for a ? b : a. For example, instead of

var pane = null;
if (view != null)
  pane = view.getPane();

or

var pane = view == null ? null : view.getPane();

you can use

var pane = view && view.getPane();

You could argue that it’s not as clear, of course, particularly to anyone that doesn’t know about this feature of JavaScript, so take advantage of it at your own discretion.

I should also mention the unary Boolean operator of JavaScript. The “not” operator (!) is quite Boolean, because it always returns true or false. That is, !a evaluates to true if a is false, 0, NaN, "", null, or undefined; otherwise, !a evaluates to false. To explicitly convert a value to a Boolean, you could use a ? true : false, or you can simply use a double-not: !!a.

2/18/2005 4:45:39 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | JavaScript#
Wednesday, February 16, 2005

The this statement in JavaScript is important, particularly when writing “object oriented” code. What this is depends on when you ask.

Outside of a function call, this is the global object. If your code is being hosted by a browser, this is the window object. Other script hosts provide their own global object.

Inside of a function call, what this is depends on how the function was called. A function can be called in one of four ways:

  • F(arg1, arg2)
  • obj.F(arg1, arg2)
  • F.call(obj, arg1, arg2)
  • F.apply(obj, args)

In the first case, any reference to this in the function definition will evaluate to the global object. In the second case, references to this evaluate to the specified object (obj), which is why this is so important to “object oriented” JavaScript code. In the third and fourth cases, references to this also evaluate to the object, unless obj is set to undefined, in which case this will evaluate to the global object, as with the first case.

It’s interesting to consider the relative speed of each of the four ways to call a function. Unsurprisingly, the last is generally the slowest. Quite surprisingly, to me at least, under Internet Explorer, the second case is faster than the third. That’s right – calling a function property of a global object is faster than calling a global function. Only the Great Implementor would know for sure, but it looks like the extra time in the first case is spent determining what this should be. In fact, the third case is also faster than the first case when the first argument to call is anything but undefined. (Thus, when performance is an issue, and I’ve got a function variable, I call it with the call method and specify an explicit this.)

Update: I forgot to mention another useful use of this. When an HTML element raises an event, the event handler function can use this to access the element to which the event handler was attached. window.event.srcElement provides access to the element that raised the event. There's no difference between the two unless the event has bubbled to the element. For example, if you handle onclick in document.body, window.event.srcElement will be the actual descendant element that was clicked, but this will always be document.body.

2/16/2005 9:23:08 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | JavaScript#
Tuesday, February 15, 2005

What is true in JavaScript? It depends on how you ask.

X === true is true only if and only if X is a Boolean variable set to true.

(What, you’ve never heard of the “triple-equals” operator? It’s actually called the “identity” operator, and X === Y when typeof(X) == typeof(Y) && X == Y. There’s also X !== Y, which is the same as !(X === Y). You’re probably familiar with the typeof operator – it returns “number”, “string”, “boolean”, “object”, “function”, or “undefined”. Notice that there’s no “integer” or “real”, so it is unsurprising (but dangerous, given the unpredictability of floating-point math) that 1 + 1 === 0.5 + 1.5. Anyway, back to what is true…)

X ? true : false is true most of the time. It’s only false when X is the number 0, or the number NaN, or the empty string, or the false Boolean, or the null object, or undefined. (This is the same logic used by the if and while statements.)

Now, equality gets really confusing. X == true whenever X can be directly converted to the Boolean true. The following meet that criteria: the true Boolean, the number 1, and strings that convert to the number 1, such as “1”, “1.0”, “1E0”, “0.1E1”, “ +1.0 ”, etc. Note that leading and trailing whitespace is ignored! Surprisingly, strings like “true” or “True” do not meet the criteria – so "1" == true, but "true" != true.

In the case of equality, we must also talk about what is false. X == false whenever X can be directly converted to the Boolean false: the false Boolean, the number 0, and strings that convert to the number 0, such as “0”, “0.0”, “ -0E1”, etc. But wait; there’s more! The empty string (“”) is also “equal to” false, as well as any string that contains only whitespace! So " \n\t\r\u2002" == false! Who knew? However, a few things that you’d think might be “equal to” false aren’t: "false" != false, NaN != false, null != false, and undefined != false.

What's particularly confusing is considering which of the following similar statements are true for any given X:

  • X == true
  • X != false
  • X ? true : false

If X is "1", they are all true. If X is "", none are true. But if X is null, only the second is true. If X is " ", only the last is true. And if X is "2", the last two are true. The funny thing is that it really does work as you’d expect, most of the time. The subtleties of JavaScript…

Disclaimer: My experience is actually with Microsoft’s JScript, particularly as it is implemented inside Internet Explorer. I presume that this is all true for all JavaScript engines, but I haven’t actually tested it.

Update: I replaced the second to last paragraph with something that is hopefully more interesting and more accurate. (Thanks, Bradley!)

2/15/2005 9:16:02 AM (Pacific Standard Time, UTC-08:00) | Comments [2] | Code | JavaScript#
Tuesday, December 14, 2004

We're encouraged to believe that CRT data conversion functions are going to execute faster than anything we might write by hand. Unfortunately, this is not always the case. It certainly isn't the case for wcstoul, which converts a Unicode string to an unsigned long integer.

Granted, wcstoul does a lot. The documentation describes some of the stuff that it supports. And when you're using the CRT from the multi-threaded DLL, you've got to expect a little overhead. But I was calling wcstoul inside a tight loop, and was surprised to find that a simple homegrown converter took 5% of the time that wcstoul takes. That's right – not 5% less time, i.e., slightly faster, but 95% less time, i.e., unbelievably faster.

Of course, I determined the bottleneck by profiling the code, so the real message here is that you don't know what needs to be optimized, and you don't know if your optimization is actually helping, until you measure.

In case you're curious, here's the code, with radix support removed for simplicity:

template <typename TChar, typename TInteger>
inline bool ConvertDigitToInteger(TChar chDigit, TInteger & rnInteger)
{
if (chDigit < static_cast<TChar>('0') ||
chDigit > static_cast<TChar>('9'))
return false;
rnInteger = rnInteger * 10 +
static_cast<TInteger>(chDigit) - static_cast<TChar>('0');
return true;
}
template <typename TInteger, typename TInputIter>
inline TInteger ConvertDigitsToInteger(TInputIter itInput,
TInputIter itInputEnd, TInputIter * pitInputStop = NULL)
{
TInteger nResult = 0;
while (itInput != itInputEnd &&
ConvertDigitToInteger(*itInput, nResult))
++itInput;
if (pitInputStop != NULL)
*pitInputStop = itInput;
return nResult;
}
12/14/2004 12:48:11 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, October 12, 2004

I thought that Multi-threading in .NET was a great article, particularly if you're new to the subject. (Thanks to Ian Griffiths for the link.)

10/12/2004 1:25:27 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, July 19, 2004

I really enjoyed this short article from MSDN Magazine on What Makes Good Code Good (by Paul DiLascia). It matches quite nicely with my own views on the subject.

  • Simplicity
  • Readability
  • Modularity
  • Layering
  • Design
  • Efficiency
  • Elegance
  • Clarity

Now get out there and write some good code!

7/19/2004 2:45:17 PM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code#
Tuesday, May 11, 2004

I'm a weed puller, too. Glad to know I'm not the only one.

5/11/2004 8:07:38 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, May 03, 2004

Herb Sutter on C++/CLI (also from the April 2004 C/C++ Users Journal) [emphasis mine]:

“C++ and C++/CLI are actively collaborating to respect C++ evolution and craft high-quality C++ language extensions that will help to ensure C++'s continued relevance, nay supremacy, on important platforms.” And earlier in the article: “They [the C++/CLI revised extensions] make developing for the CLI/.NET platform in C++ a first-class experience, just as easy as in Those Other Languages you may have heard about that might sometimes claim to be the Last Word on that platform.”

I can't wait.

5/3/2004 4:23:14 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#

I still try to read trade magazines on occasion, and I thought I'd share this great programmer's blessing I found at the end of Alexandrescu and Held's article in the April 2004 C/C++ Users Journal:

May you be referenced for a long, long time.

5/3/2004 3:58:22 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, April 29, 2004

Ian Griffiths' article on preferring Monitor to ReaderWriterLock is a great reminder to avoid complex solutions when simpler solutions will do nicely. My natural tendency would be to use a ReaderWriterLock rather than a Monitor any time I had data that would support multiple reader threads, but Ian reminds me that there's another factor at play here – contention. If contention is unlikely – that is, if multiple threads reading the same data would be a rare occurrence – a Monitor is better because it is faster and simpler than a ReaderWriterLock. Premature optimization strikes again...

Far more disturbing was this little tidbit: “Also, remember that most of the classes in the .NET Framework aren't written to be safe even for read-only use – most of them are documented as being safe only for access on one thread at a time.” I must confess that I had assumed that most classes in the .NET Framework had been written to be safe for read-only use among multiple threads. Fortunately, things are not as grim as Ian makes them sound, at least from my perspective; from the MSDN documentation (emphasis mine): “By default, Collections classes are generally not thread safe. Multiple readers can read the collection with confidence; however, any modification to the collection produces undefined results for all threads that access the collection, including the reader threads.” Whew! Still, it is a good reminder to check the thread safety of any classes I'm using for data storage before making any assumptions...

4/29/2004 8:23:56 AM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code#
Wednesday, April 28, 2004

I have a coworker that was burned twice in one day by surprises while using text encodings with the .NET Framework. He was working with files that were meant to be encoded as UTF-8, but were accidentally encoded in code page 1252.

First, he wanted to decode a text document as UTF-8, knowing that there might be invalid UTF-8 characters and hoping to detect that fact somehow. Logically, he used Encoding.UTF8; unfortunately, that seemed to quietly remove invalid characters. Nor did creating a new instance of UTF8Encoding work – until he discovered the constructor with two Booleans, the second of which causes an exception to be thrown if an invalid character is found... (Let me take this opportunity to express my dislike of Boolean parameters to methods and constructors. I hope that the .NET Framework API designers discontinue this practice in the future; an enumerated type would be far more appropriate.)

Second, he wanted to use StreamReader to decode a text document with code page 1252, knowing that it might look like UTF-8. Logically, he created a StreamReader with the constructor that takes a file name and an Encoding object – he used Encoding.GetEncoding("windows-1252") as the encoding, but eventually he realized that the documents were actually being decoded as UTF-8. Ultimately, he discovered the StreamReader constructor with an additional Boolean parameter, which specifies whether or not to allow a byte order mark to override the encoding.

Things like this can take a while to track down, so I post them here in the hopes that readers will avoid similar confusion.

4/28/2004 3:51:52 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Friday, April 23, 2004

The latest article in MSDN Magazine on the new C++/CLR syntax and support explains in great detail why I'm so looking forward to Visual Studio 2005. I love the .NET Framework, I love C++, and the new stuff looks to provide me a beautiful integration of the two. Question is, once it is released, will I ever code in C# again?

4/23/2004 1:25:47 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Friday, March 26, 2004

If you're interested in the new rendering engine used by Longhorn, you should read Chris Anderson's latest article on Avalon, “The Blinking Lights Division”. It greatly assisted my understanding of the subject. It seems that the focus is always on XAML markup, and you probably know that it's possible to add shapes (elements, visuals) with plain old code, but did you know that Avalon also has an equivalent to the GDI device context called the DrawingContext, with methods like DrawRectangle()? Great stuff; it's all starting to make sense...

3/26/2004 1:20:24 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, March 24, 2004

I've never been very comfortable with third-party components – mostly for the typical ego-driven reasons, e.g., they don't do things exactly how I would do them, etc. However, I've had enough trouble with third-party components that I feel some of my hesitance is justifiable. In fact, I'm ready to give up on “closed source” third-party components altogether, primarily because fixing critical bugs or adding missing features can be difficult (you have to convince the company that the change needs to be made, and then you have to wait for them to make the change, and test the change, and hope that they didn't break something else) or impossible (the company is no longer actively developing that product, or the company is no longer in business).

In the future, I'll be looking for component vendors that provide source code to their customers; Dan Appleman makes a good argument for this. Not only is this the “ultimate security blanket,” but seeing out how the component works is often quite useful when you're trying to use a component. Furthermore, when something breaks, and you're trying to figure out if it is your fault or that of the component, being able to debug their source code can be invaluable.

3/24/2004 3:53:33 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, March 22, 2004

When an XmlDocument of the .NET Framework is used to load an XML file that references a DTD, that DTD (and supporting files) are parsed, even if they must be downloaded over the Internet! This, in my humble opinion, is an unexpected thing, and thus a bad thing. A coworker of mine wondered why simple manipulation of an XHTML document with the correct document type declaration was taking seconds instead of milliseconds – this was why. Every element insertion seemed to be delayed by a second or so!

The problem, as documented in this blog post, is that the default XmlResolver is an instance of XmlUrlResolver. If you want to ensure that your XML document manipulation is not hampered by the downloading and/or parsing of external entities such as DTD's, be sure to set the XmlResolver property of your XmlDocument instance to null before using it.

    XmlDocument doc = new XmlDocument ();
    doc.XmlResolver = null;
3/22/2004 3:59:16 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, March 18, 2004

If you're eager to see how the use of generics is going to actually play out in the base class library of the .NET Framework – not to mention how you'll be using generics in your own libraries – the Design Guidelines for Generics are a must-read. I found them quite fascinating and altogether reasonable. Nice work!

3/18/2004 11:40:12 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, March 10, 2004

From the Namespace Naming Guidelines of the Design Guidelines for Class Library Developers:

Do not use the same name for a namespace and a class. For example, do not provide both a Debug namespace and a Debug class.

If you want to avoid bizarre C# compiler errors, you would do well to follow this rule. In fact, don't give classes the same name as any part of any nested namespace. For example, if there's a MyCompany.MyFeature.MyLibrary namespace, you should avoid defining a MyCompany, MyFeature, or MyLibrary class, in that namespace or any other.

It ultimately comes down to conflicts with the using-namespace statements that you'll probably try to use. I've played around with it a bit and have been unable to put my finger on the method to the madness. When writing libraries, it is often tempting to create a class with the same name as the last part of the namespace; don't do it.

3/10/2004 4:17:05 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, March 09, 2004

I struggled for a while with a bizarre .NET assembly problem last night – I was getting a runtime exception when trying to access a new type in a strong-named library from a strong-named executable. Compilation was succeeding, and the assemblies were in the same directory, so I couldn't figure it out.

My first instinct was that the assembly must be in the global assembly cache (GAC), since I remembered that the GAC is checked even before assemblies in the same directory when everything is strong-named. But it wasn't there. So I finally ended up using the Assembly Binding Log Viewer (Fuslogvw.exe) for the first time. The executable wasn't having any trouble locating the library, so I had to set the ForceLog registry value to get more information. As it turns out, it was getting the assembly from the “download cache.” I didn't really know much about the download cache, presuming that it would never affect local assemblies, but somehow, though I haven't figured it out yet, I managed to get my assembly into the download cache, and the .NET Framework was using the old assembly without the new type from there.

Of course, I could have avoided this trouble altogether if I'd made sure that I was advancing the assembly version with every build. I've read arguments for and against the asterisk-syntax for assembly versions (e.g., “1.0.*”) – this seems like a pretty good argument for...

3/9/2004 10:11:46 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, February 26, 2004

I'm really looking forward to the next release of the .NET Framework. There is so much cool stuff coming, it hardly seems worth writing .NET code that targets the current version... Generics is far and away what I'm looking forward to the most. I'm also looking forward to the complete redesign of Managed C++; C# is a great language, but I want the best of both worlds!

Anyway, it sounds like there will be some improvements to Windows Forms as well, which is great news, considering how long we're going to have to wait for Longhorn...

2/26/2004 10:01:50 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, January 27, 2004

Be sure to read Ian Griffiths' article on casting in C#. C# uses a C-style cast for two quite different operations -- to unbox a boxed value type, and to coerce a value from one type to another. One cast can't do both jobs, so, for example, if you have an object with an Int64 in it, you can't cast it directly to an Int32; you'll have to first cast it from an object to an Int64 and then to an Int32.

object longVal = 42L;
int intVal = (int) ((long) longVal);

His last point resonates with me the most. Why did they choose to use the C-style cast? I've been well-trained by C++ gurus that the C-style cast is evil, and I cringe every time I have to use it in C#. Besides, it's horribly ugly, and produces far too many parentheses. The as keyword is far more beautiful, and I find myself wanting to use it even when I should use a cast (for one thing, as is slightly less efficient than a cast when you know that the object is the desired type).

Console.WriteLine(((Derived)(myArray[i])).DoSomething());
// vs.
Console.WriteLine((myArray[i] as Derived).DoSomething());

So, how about a new keyword that works like as, but throws an exception if the cast fails? Separate keywords for casting and boxing? Any ideas?

Console.WriteLine((myArray[i] cast Derived).DoSomething());
1/27/2004 3:21:16 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, November 26, 2003

These two paragraphs from Aero User Experience Guidelines > Picking the Right Degree of Control for User Interfaces are good to keep in mind:

You must also watch for fringe cases—the person who uses some obscure feature twenty times a day, or the person who uses a complex application once a year and expects to produce great results. It can be hard to willingly turn away a potential customer, but attempts to include fringe cases in your target users can compromise the interface's design, to the detriment of the majority of your users.

Every product has one category of users who are so far beyond the fringe that they don't belong in the usage profile at all. These users are the product's creators. If the developers of a software product have to click hundreds of times through a screen that their actual users will see only once, they may be tempted to apply design techniques appropriate for regular activities to what are in fact infrequent tasks. You must recognize this temptation and hold your ground against it.

11/26/2003 1:46:16 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, November 25, 2003

The one where Chris Sells reflects on the difficulty of writing cool apps without graphic designers at your disposal, especially in the new world of Avalon/Longhorn. I like to think that I'm capable of writing usable UI, but UI thats both cool and usable is beyond me. I'd much rather design under the "requirements and restrictions" imposed by an application that needs to run on a 180x180 monochrome PDA than have to design a cool-looking application for a 1600x1200 true color desktop with easy-to-use tools and APIs that make anything possible. Where do you find affordable people that are good at that sort of design work?

11/25/2003 9:38:48 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, October 27, 2003

Since Ed-at-work is mainly still in the land of C++, COM, DHTML, and JScript, it is primarily Ed-at-home's responsibility to keep me as current as possible on the cool new programming technologies from Microsoft, i.e., .NET. To that end, I recently created my first GotDotNet workspace, DocExtensions.

I love the idea of supplying object library documentation in special C# comments, but don't love the bulky XML syntax that is required. So, I wrote a console application that allows me to use a more pleasant Wiki-style syntax in my documentation comments. Check it out, and please let me know if you like the idea!

10/27/2003 12:15:51 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, October 22, 2003

A coworker of mine found a bug in my code that was basically a result of a typo -- brain thinks one thing, fingers type something else -- and it got me to wondering if a really good compiler could have warned me about it. The offending statement:

if (nSelectedIndex == 0 && strColor == "other" && strColor != "")

Wouldn't it be cool if a compiler could notice that there's probably a bug here? The third comparison is pointless, since if the second comparison is true, the third comparison will always be true, and if the second comparison is false, the third comparison won't even be evaluated.

10/22/2003 8:53:27 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, October 14, 2003

In .NET, strings are immutable, so string concatenation always creates a new string. If you perform many such concatenations, in a loop, for example, such that the string gets very long, this can become very inefficient. Hence the StringBuilder class in System.Text, which allows, among other things, more efficient concatenation of strings.

Since JScript (JavaScript, ECMAScript) strings are also immutable, the scripting language has the same efficiency problems. While there's no StringBuilder object defined for JScript, you can use an array of strings as a poor man's StringBuilder. Instead of concatentating to a string, push to a string array. Then, when you need the big string, call join("") on the string array, which is considerably faster than the traditional approach.

// very slow
var strSlowText = "";
for (var nSlow = 1; nSlow < 10000; nSlow++)
  strSlowText += nSlow + " ";
 
// very fast
var astrFastText = [];
for (var nFast = 1; nFast < 10000; nFast++)
  astrFastText.push(nFast + " ");
var strFastText = astrFastText.join("");

I didn't invent this technique, of course, though I don't remember where I first read about it.

10/14/2003 3:38:00 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, October 08, 2003

Instinctively,

  if (strGnusto != "")

is going to be less efficient than

  if (strGnusto.Length != 0)

when checking for an empty string, though I think the former is probably easier to read.

I decided that I'd do some rudimentary timing comparisons using JScript and C#. (Thanks to Jeff Key for Snippet Compiler!) The comparison using Length does seem to be more efficient than the comparison to "" -- about 1/5th the time in the (again, rudimentary) timing that I did.

No surprise, really, but I was hoping that the performance difference would be a bit less dramatic. As it is, I should probably start using the later syntax. The performance isn't going to matter in most cases, but consistency is best.

10/8/2003 9:42:05 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Friday, September 19, 2003

Call me crazy, but I'm actually getting excited reading about all the new stuff for developers coming from Microsoft. Remember how exciting it was when Windows development was going to 32-bit? I can't wait for Whidbey... Longhorn could be really cool... Oh, to be registered for PDC 2003... (My third child is due that week, so there's never been any hope for me...)

9/19/2003 11:53:03 AM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code#
Thursday, September 11, 2003

I'm a lot more fluent in C# than UML, so this C# design patterns site is a great way for me to brush up on my GOF patterns. [via Matt Berther via Jeremy Kercheval]

9/11/2003 9:36:35 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, September 08, 2003

"I think that one of an architect's most important tasks is to remove architecture by finding ways to eliminate irreversibility in software designs." [Martin Fowler] This is something I strive for, but is it too hard to do? How do you make things easy to change? The quote by Ralph Johnson at the end of the linked article seems to point out the difficulty -- making things easier to change tends to increase their complexity, and complexity is what makes things hard to change...

9/8/2003 12:31:07 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Friday, September 05, 2003

"Indeed, the ability to represent characters in nearly all of the world's languages means that you have more things to worry about, not less." Ain't that the truth. At least displaying Unicode isn't as bad as it used to be, now that so many fonts are Unicode-compatible.

9/5/2003 9:38:32 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#

A funny reminder to avoid copy-paste programming.

9/5/2003 7:44:47 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Wednesday, September 03, 2003

We're married to Microsoft's XML APIs, so most of the Conversation with Elliotte Rusty Harold probably isn't that interesting to me, but Part VII (!) has an interesting premise: "Having one clear vision for an API is better than compromising between many competing visions."

9/3/2003 6:03:51 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#

The Conversation with Anders Hejlsberg has been an interesting read, and Part III is no exception. I'm going to have to add "simplexity" to my vocabulary. Interesting tidbit: "So not only can delegates be more efficient than interface dispatch, they can be more efficient than regular method dispatch."

9/3/2003 5:56:18 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, August 28, 2003

The C# Source Code Generator for .NET has already been linked to by many, many blogs out there, but I thought I'd link to it as well, just because it seems so potentially useful. Some of the potential uses will be eliminated when C# templates arrive on the scene, of course, but this seems like a good tool to have at your disposal. I wonder if it could be integrated into the build process somehow...

8/28/2003 9:26:45 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, August 25, 2003

Okay, I'm familiar with the use of the javascript: protocol for executing code in response to a hyperlink. What I didn't know is that if the code in question evaluates to anything but undefined, the content of the page gets replaced with that value! How I've gotten this far without knowing that simple fact is beyond me. For example:

<a href="javascript:DoSomething()">click here</a>

calls the DoSomething function, which is fine if DoSomething doesn't actually return something. If DoSomething returned true, for example, the page gets replaced by the text "true", which is almost certainly undesirable.

In any case, if you want to make sure that a javascript: link doesn't ever replace the content of the page, use the void operator like so:

<a href="javascript:void DoSomething()">click here</a>

Seems like a good habit to get into.

8/25/2003 2:29:33 PM (Pacific Standard Time, UTC-08:00) | Comments [1] | Code#
Friday, August 22, 2003

Glad to see that the next revision of the C# compiler makes it a bit easier to use delegates, generic and otherwise.

8/22/2003 7:50:11 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, August 21, 2003

I recently read Code Reading: The Open Source Perspective by Diomidis Spinellis. I can see how it could be of use to someone trying to contribute to a software project if they didn't have much experience in the language or tools that it used, especially if it was an open source project. I've learned "the hard way" more than I need to know about building and using open source projects, and I've got reasonable experience in a good number of languages and tools, so this book didn't have that much new material for me.

If you'd like to skim a condensed version of the book, you're in luck; flip to the back of the book and check out Appendix E: Maxims for Reading Code, which summarizes the main points of the book in a dozen or so pages. Here's a good one from chapter 1:

You can successfully modify large well-structured systems with only a minimum understanding of their complete functionality. I've always resisted this maxim -- it's more fun to rewrite than modify -- but over the years I've learned that it's true, and modifying existing projects almost always gets the job done faster than starting from scratch, even if the latter seems like more fun.

In fact, all of the maxims from chapter 1 are pretty good, so even if you don't read the whole book, chapter 1 is probably worth it. Chapters 2 through 5 read more like An Introduction to C. The rest of the book seemed pretty intuitive to me -- not many surprises there -- but again, you might find them interesting, so don't avoid the book on my account.

The last chapter is A Complete Example, and shows some of his code reading maxims in practice. If you read that chapter and think you could have done better, maybe this book isn't for you. If you read that chapter and aren't sure you would have thought to do what he did, perhaps the book is worth a closer look.

8/21/2003 1:16:17 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code | Books#

Is there a really good reason that the try statement (in C++, C#, JavaScript, etc.) and its friends catch and finally require a brace-enclosed block? What's wrong with this?

try
DoSomething();
catch (x)
LogError(x);

I know that the grammar doesn't allow it; I just wonder why. I suppose I could scour the newsgroups for the answer. Maybe I should ask on the proposed comp.std.csharp newsgroup.

8/21/2003 12:32:13 PM (Pacific Standard Time, UTC-08:00) | Comments [2] | Code#

I've not been able to find any XML parsers out there that preserve whitespace between XML attributes. A Google search for "whitespace between attributes" comes up with people looking but not finding. Why would one ever want to preserve whitespace between attributes? Well, the most obvious reason is if you want to modify an XML document without messing with line-based difference algorithms too much; if the original document has line feeds between attribute values and you want to use a DOM to modify that document, it's going to look a lot different after you save it.

I really do understand why it doesn't exist; not that many people care, but they do want fast XML parsers, and worrying about this sort of thing certainly wouldn't speed them up any. Seems like they could at least provide an option, though...

8/21/2003 10:50:43 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#

I'm really looking forward to getting generics in C#. (That's "templates" for you C++ programmers.) C# is already a terribly fun language to program in; once I get generics, will C++ ever tempt me again?

8/21/2003 9:33:50 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#

The next time I write an application or library that isn't mostly just user interface fluff, I'm going to have to find the discipline to give unit testing and test-driven development a try. I've done more than enough reading about it, and both methodologies sound like great ideas, but I've not had the opportunity to give them a test run.

8/21/2003 9:29:15 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Tuesday, August 19, 2003

Brad Abrams has posted a series of entries "On Designing Good Libraries" for .NET. Great stuff that I'll have to return to when I start writing .NET. I love designing good libraries, probably even more than writing good applications... Here's what he's posted so far:

Part I, Part II (Comments), Part III (Comments), Part IV, Subclassing, Interfaces, IEnumerable

8/19/2003 8:03:58 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Monday, August 18, 2003

Brad Abrams wants to know where best to put sample code. The majority of the comments support the most energy going into individual property/method documentation examples, and I tend to agree. I generally just want a concrete example on how to use the method I'm trying to use.

8/18/2003 12:12:09 PM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#

Notification messages in "classic" Win32 programming drive me crazy. Why? Because they're always sent to the parent window. So if you're writing an enhanced edit control and want to know when the content changes, or if you're writing an enhanced combo box and want to know when the selection changes, you've got to notice when the _parent_ gets the EN_CHANGE or CB_SELCHANGE message. Both MFC and ATL have standard mechanisms for "reflecting" these sorts of messages back to the control, but if you don't control the parent, this can be easier said than done.

Anyway, if you're writing interesting controls in .NET or DHTML, just be glad that you can just catch simple events, and don't have to deal with notification messages. I'm off to put a rich edit control in an otherwise needless container window just so I can reliably reflect the notification messages back to the rich edit control... (I was previously dynamically subclassing the parent window, but it turns out that windows don't like to be subclassed twice, as this causes a bizarre crash that one must spend hours trying to track down until you finally figure it out.)

8/18/2003 8:16:21 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Thursday, August 14, 2003

I just helped one of our esteemed interns with this, so I thought I'd make it a matter of public record.

Basically, if you're going to be drawing text in GDI+, read MSDN KB 307208: http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q307208

In summary, you'll probably want to avoid the 1/6 em of space that's measured and displayed before and after a string, so you'll probably want to use the GenericTypopgraphic StringFormat object.

Incidentally, I didn't end up ever using this information personally, since our PDF driver actually uses FreeType with GDI+ to display text.

8/14/2003 10:16:30 AM (Pacific Standard Time, UTC-08:00) | Comments [0] | Code#
Search
Archive
Links
Categories
Administration
Blogroll