August 2007 Archives
From President Bush's speech to the Veterans of Foreign Wars today:
One unmistakable legacy of Vietnam is that the price of America's withdrawal was paid by millions of innocent citizens whose agonies would add to our vocabulary new terms like "boat people," "re-education camps," and "killing fields."
The killing fields were not a "price of America's withdrawal." What brought the Khmer Rouge to power, and made the killing fields possible, was the secret bombing of Cambodia.
American forces, with the approval of Prince Norodom Sihanouk (who wanted the NLF out of his country), conducted a four-year-long strategic bombing campaign on the Ho Chi Minh trail and the NLF's southern headquarters. This operation, in which over 11,000 bombing missions were flown, killed something on the order of 100,000 Cambodian peasants, though given what happened in its wake it's hard to assess the accuracy of that number.
What's not hard to assess is the campaign's result: the bombing drove the rural farmers of Cambodia directly into the arms of the Khmer Rouge. The Khmer Rouge's anti-urban ideology did not just come from the bits of Marx and Mao that Pol Pot picked up while he was at the Sorbonne, it came from the fact that urban Cambodia had, by proxy, declared war on rural Cambodia. The Khmer Rouge came to power because the Cambodian monarchy had delegitimized itself by allowing foreigners to kill tens of thousands of its subjects.
Not only did American withdrawal not cause the killing fields, it helped end them. When the Khmer Rouge were driven from power in 1979, it was not by the freedom-loving West, but by Communist Vietnam, who, no longer engaged in driving a foreign enemy out of their country, had the resources to put an end to the worst humanitarian crisis in the history of Southeast Asia.
The "killing fields" that Bush cites were not a consequence of American withdrawal from Vietnam. They were a consequence of the American presidency circumventing Congress. The Nixon administration lied to the House and Senate Foreign Relations Committees and falsified Air Force records to conceal the campaign from Congress.
It was, in fact, the secret bombing of Cambodia, and not the war in Vietnam, that motivated Congress to pass the War Powers Act. The War Powers Act is what galvanized young Republican staffers and attorneys like Richard Cheney, Donald Rumsfeld, and David Addington. The guiding philosophy of the Bush administration, from before it even took office, has been to undo the constraints on the Presidency that this law imposed.
So it is deeply ironic that the President of the United States should make a speech justifying his actions in Iraq by pointing to the killing fields of Cambodia. The killing fields of Cambodia were a direct result of the central policy of his presidency.
So, let's suppose you're a C# developer who's built a pretty extensive class library in support of a pretty complicated application, and you finally have to take a whack at giving it a UI. And the natural idiom for presenting one of your collections of objects is in a DataGridView. It's simplicity itself to hook up your KeyedCollection to a BindingSource, attach the BindingSource to the DataGridView, create some columns, and in minutes - really, minutes, especially if you've done this once or twice before - you have something that resembles a UI.
But there are a lot of objects in your collection. The UI's really only going to be usable if you can sort them. No problem, right? Just click on the column header and...nothing happens.
And now, friend, you are in a world of pain. Because while anything that implements IList can be iterated by a BindingSource, if you want to sort, or filter, your collection needs to implement IBindingList.
And my god, is IBindingList elaborate. Because it has to provide all of the services whose implementation details BindingSource is hiding from you: adding new items, sorting, filtering, raising events when items change...
And when you start browsing around the interwebs, you find things like open-source projects to produce a BindingList<T>, which is kind of a cool thing if you a) want to incorporate a lot of other people's code in your project and b) figure out how BindingList<T> implements IBindingList and c) implement IComparers and d) well, spend a whole lot of time debugging and testing.
And there's a book you can buy that has a whole chapter devoted to the exciting ways that generic templates and interfaces can eat a week of your life so that your DataGridView can, as the Ruby on Rails folks like to say, just work.
Although, man, it's gonna be sweet that you can create an instance of BindingList<T> and hook up its PropertyDescriptors (once you figure out how PropertyDescriptor works) up with IComparers (once you've written them) to make your collection sortable alphabetically any way you want!
No. Stop. Step away from the architecture.
Do not get seduced by the appeal of spending a week making sure your widget implements all the right methods the right way, raises the right events, works with any type T, in short, getting every last detail of the IBindingList implementation right and then some. You'll feel very smart that you've built a piece of software that Microsoft should have in the first place, but you'll be left with this nagging feeling:
Why didn't they?
Why, in the enormous thicket of code that is the .Net framework, isn't there a class that you can put your objects into and bind to a DataGridView and have it just work?
If you ask the question the right way, the answer's obvious: there is such a class. It's the one that the BindingSource (and DataGridView) has clearly been designed from the ground up to interoperate with: the DataTable.
Create an unbound DataSource, add a DataTable to it, write a little method to read through your collection and create a row for each object and populate its columns with properties.
Look how you now have something that implements IBindingList! You can sort! You can filter! You can insert and delete rows! Why, it's almost like a table that contains data!
Yes, it's true that if your collection has ten thousand objects in it, copying their properties into a DataTable is going to be less than instantaneous, and use up twice as much memory (or more) than your tidy little collection did. And while you don't have to implement any methods to deal with insertion and deletion, since the DataTable already knows a thing or two about that, you're going to have to write event handlers on the BindingSource that update your collection (since the BindingSource isn't bound to it).
On the other hand, that just took you thirty minutes, not forty hours.
("But wait," you say, "what if I derive a class from DataTable and overload its NewRow method?" Step away from the keyboard.)