Sunday, February 22, 2009

Ten Things Caedmon Learned Today

  1. If you dig down under enough layers of leaves, you'll generally find dirt.
  2. Dad can still shinny up some trees.
  3. Dad can't shinny up other trees.
  4. It's entertaining to watch Dad try to shinny up any tree.
  5. Sometimes if you pull rotten logs apart, you can find a whole bunch of termites.
  6. Termites squish when you poke them.
  7. Dad will let you poke at coyote scat with a stick.
  8. Dad won't let you pick coyote scat up in your hands.
  9. The leaves sound funny when it rains.
  10. If you get far enough out in the woods, Dad will let you beat on almost anything with a stick.

Monday, February 16, 2009

More West Bank Settlements

Haaretz is reporting that the Israeli Civil Administration has approved an additional 2500 acres worth of settlement expansion into the West Bank. I'm a friend of Israel, make no mistake about it: but this is intolerable. I simply don't understand how Israel can claim to take the peace process seriously when it continues to violate its own promises to the United States, to the Palestinians, and to the world. This sort of behavior gives comfort and encouragement to the most radical of the Palestinian factions: it's what keeps Hamas and others of that ilk alive. I simply don't understand why Israel doesn't get that this is dramatically counter to its own interests.

Hopefully George Mitchell will deliver a loud and strong message to Israel that if Israel continues with these sorts of practices, they can expect much less cooperation and aid from the United States. We've got a big lever here, and we need to help Israel even when Israel doesn't want to be helped.

I've said before that Israel deals with the Palestinians like a chess player who can only think two moves ahead. Peace won't come to the region until Israel learns to think five, 10 or 20 moves ahead. (Lots of other things would also need to happen, like Hamas acknowledging Israel or being removed from power, but Israel learning to anticipate the consequences of its actions is a sine qua non.)

Saturday, February 14, 2009

My favorite gripes about .NET

I've been coding primarily in .NET (VB.NET and C#) ever since it first came out, back in 2002, and on the whole, I think it's amazing. Microsoft did a whole lot right when they created the .NET framework.

I recently just took the .NET 3.5 certification exam, and studying for it, after a few years away from coding, gave me a chance to realize that MS also got a number of details wrong along the way. Allow me to share my favorites:

Bizarre Side-effects

Much of the .NET framework was well-designed, with the poor coder who has to use it in mind. But there are occasional pieces that make me shake my head. For instance, imagine that you saw this code in someone's application:

CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "MyKeyContainer"; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams);

Unless you happened to know the CryptoAPI very well, would you realize that this is how you create and store a key-pair? In other words, creating and storing the key is a side-effect of calling the RSACryptoServiceProvider constructor, if you happen to pass a CspParams object that happens to have its KeyContainerName property set.

It should have been designed to work something like this, of course:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

rsa.Key = RSACryptoServiceProvider.CreateKey();

rsa.PersistKey("MyKeyContainer");

Bizarre Names

When you want to specify that it makes no sense for an assembly to run unless it has the permissions to open a file dialog box, you can flag that assembly with the following attribute:

[assembly: FileDialogPermission(SecurityAction.RequestMinimum)]

And that makes some reasonable sense: you're saying that it needs, at a minimum, to be able to show the file dialog box. Still, a better name would probably be something like "Require" than "RequestMinimum": it's less ambiguous.

But if you want to step your security up a notch, and tell the runtime to automatically deny all permissions other than the ones you're listing, you use the enumeration SecurityAction.RequestOptional:

[assembly: FileDialogPermission(SecurityAction.RequestOptional)]

To call required permissions "optional" makes absolutely no sense, and it makes it significantly more difficult for your average coder to figure out what's going on. It would be much easier to understand if MS had chosen to call it something like "RefuseAllExcept":

[assembly: FileDialogPermission(SecurityAction.RefuseAllExcept)]

(For what it's worth, it's called "Optional" because whoever came up with the name was thinking from the perspective of the runtime: "Do I need to throw an exception if the assembly doesn't have this permission? No? OK, then it's an optional permission." But you don't flag an assembly with this attribute because you're concerned to communicate that it might not need this permission: you add this attribute because you only get the permission you need, i.e., you want to make sure that the assembly is good and secure and only does things you're explicitly aware of, and that the runtime actively refuses to let it do anything you hadn't previously thought about.)

Screwy Parameter Orders

Certain methods and classes in the .NET framework typically take parameters in one order; but other methods and classes take them in a very different order. There are numerous examples of this, but to take just one: if you want to format a string according to a specific culture using the String.Format() method, you pass parameters in the order "CultureInfo", "FormatString".

String.Format(new CultureInfo("en-UK"), "c", 100)

But if you want to use the ToString() method of an object to format it, you pass them in the order "FormatString", "CultureInfo".

d.ToString("c", new CultureInfo("en-UK"))

Stupid things like that just make a framework harder to use than it needs to be: it's one more thing to remember in a world where I've already got too much going on.

Inconsistent Object Instantiation

In general, there are two different ways you can get an instance of a class: you can do it yourself, or you can get something else to do it for you. Either one works fine, though there are reasonably good arguments for preferring the second (known as a "Factory Pattern"). The problem is that the .NET framework is inconsistent throughout. Some classes can only be instantiated with their own constructor:

AppDomainSetup setup = new AppDomainSetup();

Other closely related classes can only be instantiated through a static factory method:

AppDomain domain = AppDomain.CreateDomain("My App Domain");

And others can be instantiated either way:

Process process1 = new Process(); Process process2 = Process.Start("cmd.exe");

Frankly, I probably wouldn't care that much: it's mostly a stylistic difference, and the MS documentation is handy and usually pretty good. But any number of questions in the 70-356 exam turn on knowing whether you use a static or an instance constructor, and remembering that you can only get an AppDomain object by calling a static constructor, but you can get a Process object either way, gets old after a while.

Event Handling in C#

I've been using VB since version 1.0, long before it was a commercially viable language, and long before it had anything like object-oriented features. VB.NET is arguably a completely different language, but one of the things that remains very much the same, and very easy to do, is the handling of events. The syntax for declaring them is simple and intuitive, and easy enough for nearly anyone to understand. To handle an event in the most basic fashion, you have to specify four different "elements": you declare (1) the event and (2) the event handler, (3) you connect them by instantiating the event class using "WithEvents", and then (4) you raise the event.

Class AlarmClock Public Event Ring()

Sub MakeMeRing() RaiseEvent Ring() End Sub

End Class

Class Sleeper

Public WithEvents Alarm As New AlarmClock

Sub WakeUp() Handles Alarm.Ring Console.WriteLine("I'm awake, already.") End Sub

End Class

In contrast, in C#, for the most basic event, you have to follow seven steps. You declare (1) the event (2) the event handler, and (3) instantiate the class holding the event. You then wire up the event by (4) instantiating the delegate, and (5) adding it to the event. You then raise the event by (6) checking if there are any handlers, and then finally (7) you raise the event.

class AlarmClock { public event EventHandler Ring; public void MakeMeRing() { if (Ring != null) { Ring(this, new EventArgs()); } } }

class Sleeper { public AlarmClock alarm = new AlarmClock();

public Sleeper() { alarm.Ring += new EventHandler(alarm_Ring); }

void alarm_Ring(object sender, EventArgs e) { Console.WriteLine("I'm awake, already."); } }

For only one of those steps (declaring the event) does the language itself provide any structure for you: you otherwise have to use other unrelated language elements, such as delegates, constructors, and operator overrides: and you have to understand each of these, and think about each of these, before you can raise and handle events. In contrast, with VB, you only have to think about events, and not about three or four other unrelated language elements.

I'll grant that the C# implementation is elegant and flexible: but if you want, you can do it the same way in VB. VB just provides an alternate, much simpler way of handling simple events. The C# team has implemented plenty of cool features like LINQ, anonymous methods, generics, extension methods, nullable value types, and all sorts of other cool things. It's a shame that they haven't figured out a simpler way of raising and handling events. ents.

I've got more gripes – of course J – but the rest will have to wait.

Interesting Recommendation

I received an email from Amazon today, with the following recommendation in it:

Dear Amazon.com Customer,

We've noticed that customers who have purchased or rated books by Aristotle have also purchased If You Got It, A Truck Brought It: Our First Adventure by Robin Smith. For this reason, you might like to know that If You Got It, A Truck Brought It: Our First Adventure is now available.  You can order yours for just $8.99 by following the link below.

Product Description
With bright colorful illustrations and adorable characters, Josie and her freewheeling friends take you on an adventure to learn how a book is made.Along the way we'll get a start on learning colors, numbers and the alphabet.

 

Notice the basis of the recommendation: because I'd purchased books by Aristotle, they recommended a particular children's book. I smell a statistical cluster in there somewhere.

Friday, February 13, 2009

Initial Thoughts on WPF

I've started work on a quick-and-dirty little application for our church treasurer, who wants to be able to email donation statements to members, rather than send them via increasingly expensive snail-mail each quarter. I've written more WinForms apps than I can count, so I thought I'd try this one using Microsoft's still fairly new Windows Presentation Foundation. What you read on the MSDN website is that WPF is the hottest thing ever, and they give sample shots like this to whet your appetite.

Granted that I'm still at the very beginning stages of learning WPF, I wanted to give my first impressions. So some thoughts:

  1. Technically, it sounds really cool. I like the fact that, unlike GDI+, it's able to use hardware acceleration, with all the cool 3D potential that implies.
  2. I'm not sure about XAML yet. I'm not a huge fan of having to learn a proprietary markup language. Still, declarative programming? Interesting. Inability to debug anything I write? Interesting in an entirely different sense.
  3. It's a huge change from WinForms. Learning WPF is like learning ASP.NET: it's a completely different model. Don't expect to be able to pick it up in a few days.
  4. The UI design tools in Visual Studio are regrettably slow and clunky. I've got a fairly beefy machine, and it still takes several seconds to load up a very basic window in design view, with almost no controls on it. About every other time I switch to the design window, it tells me that I need to click on a special ribbon for it to refresh, because something (I have no idea what) has changed.
  5. The bundled controls are uninspired and uninspiring. To take just one example, for some astonishing reason, WPF has gone through three iterations, and it still doesn't come with a datagrid – which is perhaps the most basic control required in any business app. There are several third-party grids available, and MS has just released a "WPF Toolkit", which does have a basic datagrid. But still. It doesn't give me a lot of confidence that MS actually expects anyone to use this yet.
  6. There's a ton of inconsistency between the different UI controls. For instance, if you want to specify the text of a menu item, you set the Header attribute, like this:

    <MenuItem Header="Menu Item 1"/>

    But if you want to specify the text of a button or of a textbox, you specify it in the content area of the tags:

    <Button>Sample Button</Button>
    <TextBox>asdfasdfasdf</TextBox>

    But then get this. If you want to set the text of the button in code, you set its Content property:

    sampleButton.Content = "Content for a button";

    But if you want to set the text of the textbox, you set its Text property.

    sampleTextBox.Text = "Text for a textbox";

    Was there really nobody inside Microsoft who thought, "WTF?" MS has boasted any number of times that since they started from a clean slate with WPF, they got the design right. I can't yet speak for the overall elegance of the design, but if they can't even get the simple stuff right – consistent names and property accessors, for instance – it doesn't give me a lot of hope that they nailed the big stuff.
  7. The documentation isn't up to Microsoft's standards. It's there, and it's technically correct, but it's not terribly helpful. A good example is the official documentation for the Hyperlink.RequestNavigate event. Take a look at the page. It has, well, all sorts of vaguely interesting information. But it's entirely useless for someone who wants to understand the context for this event. When is it fired? Why does it exist? How do you use it? (Or the question I'm trying to troubleshoot at the moment, why does it not seem to be firing for me?) Compare that page to the documentation for a similar topic in ASP.NET, the Button.Click event. That page has a brief explanation of the context in which the event occurs, sample code in two languages, and links to four different articles for more information. Presumably the improved documentation will come with time. But it's not there yet.

I'm glad that Microsoft continues to improve their technology. But Microsoft also has a tendency to hype a particular technology, only to abandon it more-or-less completely within a few years. Anybody remember DNA? Or DAO? Or RDO? I don't think WPF is the same: it's more like ASP.NET vs. ASP: the underlying technology change is that significant. But unlike the migration to ASP.NET, the initial benefits of migrating to WPF are less clear to me.

Monday, February 9, 2009

Cisco has removed the WRT100 1.0.0.2 firmware

A month or two back, I posted a solution to the highly problematic 1.0.0.4 firmware for the Linksys WRT 110 wireless-N router. (In brief: a wide range of folks, including yours truly, have reported that when the 1.0.0.4 firmware will cause the router to freeze up if a second computer attempts to join the network. The solution was to download and install the 1.0.0.2 firmware from the WRT 100 support page.)
Unfortunately, Cisco has now removed the 1.0.0.2 firmware link from the WRT 100 page: the only option they present is to download the 1.0.0.4 firmware, which, as I mentioned, is highly problematic. Color me unimpressed with Cisco.
For folks stopping by because they're experiencing problems with the 1.0.0.4 firmware, I don't have a lot of options. I couldn't find the copy of the 1.0.0.2 firmware, unfortunately, or I'd post it for download. My only real suggestion is to note that if one or more of your machines are Vista, some of the folks on the Cisco forums have suggested disabling IPv6 support. ("Start", right-click on "Networks", choose "Properties", "Manage Network Connections", right-click on your wireless network adapter, deselect "Internet Protocol Version 6".) I haven't tested this: YMMV: let me know if it works for anyone.
Do other folks out there still have a copy of the 1.0.0.2 version of the firmware? If so, I'm happy to throw it up on my website. I've continued poking around for open-source firmware, but none of the various options seem to support the Ralink RT2720L/RT2780 platform.
Other thoughts?
[Added 2/10/09: Other folks have reported that disabling IPv6 under Vista does in fact work for them. That doesn't exactly excuse Cisco -- nothing you send at a router should take it down, and if it does, that's really, really bad -- but it does seem like the best workaround, now that Cisco has removed the working copy of the firmware.]
[Added 2/16/09: It turns out that Linksys has an alternate version of their website, and on that alternate version, they've still got the working 1.0.0.2 firmware.  In case they remove that again at some point, I've also posted a copy on my own website.]

Thursday, February 5, 2009

Horrified

I don't understand our laws.

The AP is reporting that an 18-year old girl in a Florida abortion clinic accidentally gave birth to a live infant. One of the workers at that clinic allegedly then took the still-breathing child, stuffed it into a plastic bag, and threw it away to die. Not surprisingly, the local DA's office is investigating whether homicide charges should be filed.

What astonishes me, though, is not so much that someone could do that to a breathing infant, but that if the clinic had succeeded in killing the infant actively and intentionally, just a few minutes earlier, no charges would have been possible.

I'm a moderate when it comes to abortion: I think there's room for plenty of grey in the debate. I can't quite convince myself that a single fertilized cell should be treated, morally, as a full human being. But neither is a 23-week fetus merely a blob of tissue. It's not one thing when it's inside the womb and something else when it's outside: it's the same thing. It doesn't change from "lump of tissue" to "individual human being" because it moved eight inches.

It's also a huge category mistake, in my mind, for the argument to turn on whether and/or when a fetus is a human being. Something doesn't have to be a human being for it to have positive moral standing. We've pretty much all agreed that cruelty to animals is a bad thing, that it should be illegal to kill whales and other intelligent mammals, and that endangered species should be protected by law. A fetus doesn't have to be a full human being in the eyes of the law for the state to have a legitimate interest in its care and treatment: and that interest, quite frankly, usurps any individual right to privacy.

This is why I'm convinced that Roe v. Wade remains a horrible and incomprehensible decision. My right to swing my fist stops where my neighbor's nose begins; and any right to privacy stops where an infant's health and safety begins. The state can intrude on the privacy of neglectful or abusive parents, and take their children away from them; and the state should similarly have the right to legislate against abortion. This was an issue which should never have been taken out of the hands of the legislative branch. Incomprehensible laws, and barbaric acts, like the one currently being explored in Florida, are the result.