soeren says

Unique Fail

March 2nd, 2008

I haven’t fully moved to CoRD yet, largely because of various quirks in its UI. (I see that a new beta is out that may address most of my issues, but I haven’t had a chance to test that.) As a result, I mostly use Microsoft’s ‘official’ Remote Desktop Connection client 2.0.0b2. Plus, I’ve always loved its icon (props to Iconfactory on that, I believe).

This morning, it crashed. [Not a] big deal; crashes happen. I was curious why, though, and while the crash report didn’t help me figure that out (the topmost call in the stacktrace is MBUMutex::Acquire(unsigned long), which tells me absolutely nilch about the actual intent), I did find something else.

Here’s a portion of the Binary Images section from the crash log:

Binary Images:
    0x1000 -    0x23fef +com.microsoft.rdc 2.0.0 Beta2 (2.0.0 Beta2) <0775a7210cb4454ea17af3dfdec33e2c> /Applications/Remote Desktop Connection.app/Contents/MacOS/Remote Desktop Connection
   0x92000 -   0x108fe6 +com.microsoft.netlib 12.0.0 (12.0.0) <9fac28ca22ff49bf9185194497585126> /Applications/Remote Desktop Connection.app/Contents/Frameworks/Netlib.framework/Versions/12/Netlib
  0x436000 -   0x5bafc7 +com.microsoft.rdc 2.0.0 (2.0.0) <ad448d7a974d4d90ad5b89b5dfa08bc1> /Applications/Remote Desktop Connection.app/Contents/Frameworks/RDCPAL.framework/Versions/12/RDCPAL
  0x86c000 -   0x94dff7  libxml2.2.dylib ??? (???) <ccd6e2cb514fcd0b541bf153aae13481> /usr/lib/libxml2.2.dylib
  0x9c8000 -   0x9e6fe7  com.apple.OpenTransport 3.0 (3.0) /System/Library/PrivateFrameworks/OpenTransport.framework/OpenTransport
[..]

Notice something? That they still use OpenTransport strikes me as weird, that they use the same bundle identifier com.microsoft.rdc for the two distinct bundles RDCPAL.framework and Remote Desktop Connection.app, which furthermore run simultaneously, is even stranger, but oddest yet? This explosive combination actually works.

After all, a bundle identifier is supposed to be globally unique. There are several API calls that let you launch and otherwise access a bundle through its identifier. How would that ever work when two bundles which clearly, while related, are distinct in their nature and purpose, have the same identifier? Should Xcode prevent you from building a project whose identifier matches one that already exists? Probably impossible to do on a reliable basis. Should dyld refuse to link or XNU refuse to launch a bundle when one with the same identifier is already running? Or should Microsoft simply have someone smack the CFBundle documentation over developers’ heads?

Tagged , , , , ,
Posted in Rants

Share | No Comments

A Matter of Honor

March 1st, 2008

So you write a piece of code.

It doesn’t have to be excellent. Realistically, given constraints in time and budget, and not knowing entirely right from the start just what the implementation is supposed to accomplish, including every single edge case, your code may very well end a mess.

Does that embarrass you? Or do you not care, because, after all, “it works”, right?

Me, I’m embarrassed. Code efficiency is frequently not a concern to me (which I would argue is okay, since I don’t tend to write performance-critical things). But trying as hard as possible to make code readable and ‘elegant’ certainly is. I always know I’ll never quite achieve that goal, for customers want solutions fast and cheap, and virtually never can even tell the difference between what’s well-written and what’s not. But to me, the difference matters nonetheless, and when I spot something that obviously can be solved in a nicer way, I do so.

Oftentimes, you can call that process ‘refactoring’. Whether it’s making symbol (variable, function, etc.) names more comprehensible and organized (hey, can we settle on a single style?), or merging multiple blocks of code in different source code files into one unique function because they happen to accomplish the exact same thing, it helps. It’s a little step, but the next time I come across the same lines, I think to myself ‘good thing I cleaned that mess up, for this time, everyone else will understand it better, and I will be less bothered by it’.

From my point of you, if all of the above seems agreeable, non-disagreeable, perhaps even obvious, you’ve got what it takes to be a good teamwork programmer. You understand that committing code to the shared repository is not generous, but essential, and that doing so frequently, split up into atomic, self-contained pieces of resolved micro-tasks helps everyone.

Unfortunately, this isn’t true for everyone. Some developers apparently feel that applying a devil-may-care attitude to what they’ve written is acceptable. I don’t blame them for wanting to spend their spare time differently than constantly having think about what they’ve worked on. But when their commit consists of badly-written code, is delivered a day after I need it (rather than simply the moment it was done), is incomplete, and meshes solutions to multiple unrelated problems together, it drags down my efficiency, my motivation, and my honor.

When I create something, I want to maximize how much others can benefit from it. Otherwise, why bother?

Tagged , ,
Posted in Rants

Share | No Comments

System.Windows.Forms.Convoluted

December 23rd, 2007

Perhaps there is a hidden rule about the System.Windows.Forms namespace that its classes ought to have as many properties as possible, as to come across as powerful and flexible. Probably not, but nonetheless, that’s what it feels like.

In the pre-OOP days, this may have been unavoidable: without inheritance, you essentially have all or nothing. But with .NET, Microsoft had the opportunity for a fresh start, and so this does not make much sense for me.

Consider LinkLabel.

I was not alone in my expectations (nay, convictions) that it ought to have some property that sets the URL, and that clicking anywhere inside the label will open a browser window and load the resource the URL points to:

When I first used this control, I thought the control should have a link property where I would add the URL of my Web site and it will work. But no. It doesn’t work that way.

Instead, it appears a LinkLabel effectively works like an image map, where you can define areas inside the control that respond to different URLs. Sure, you could have one area that covers the entire control. Also, the page describes an easy workaround of defining an event handler for LinkClicked. But why in the world would you make such a control deceptively simple and in actuality complex? Who thought this was a good idea?

Reasonably, LinkLabel inherits Label. But to me, the complexity of being able to define multiple links with rectangle areas they respond to belongs in a separate control: a subclass of LinkLabel. (And even then, the potential confusion of “this control actually represents multiple links” still hits the user.)

Or how about PropertyGrid?

I can only assume a lonely soul at Microsoft thought they were doing something really clever. That’s exactly what it seems to be at first, too: clever, convenient, cool.

The PropertyGrid control provides you with a highly flexible (if a little overengineered) interface to manipulate settings – or properties, if you will. Microsoft mostly appears to reserve its use for developer- and administrator-type applications rather than regular end user ones, and probably for good reason: the control is overwhelming, at least at first. It’s hardly impossible to understand how it works, but for every single thing it does, you cannot help but wonder if a more traditional approach may have been less confusing – at the expense of slightly more development time.

But it does suit our purposes, and once you hide its own toolbar (yes: by default, the control has its own toolbar – luckily, it can be turned off in code), it even becomes viable for a releasable application. Almost.

By default, the PropertyGrid control does not populate its contents in the traditional, active manner. You don’t, say, pass an array of categories, which in turn contain arrays of properties. Rather, you tell it what object is “selected”, and it fetches the properties from that using Reflection. This is where the clever part comes in: any object’s properties are automatically available to the PropertyGrid. It takes no effort on the developer’s part.

That is, until you realize that it really does. The properties of an object were defined by developers for developers, and not for end users, and the more you try to put finishing touches to whatever window you have a PropertyGrid in, the more you realize how much needlessly harder the simplest of things suddenly become.

The most obvious case is the naming of properties. Because properties are special kinds of variables and therefore symbols, there’s probably .NET-compatible language in the world that lets you use spaces in a property’s name. Now, some developers like CamelCase, or dromedarCase. Others use underscores_instead, and yet others may use different alternatives, such as dashes. Whatever they choose, nothing except for the space itself (which isn’t allowed) is what the end user should see. Have a property named ReadOnly? Sorry, but if you plan to ship that app, its property grid better show “Read-only”. Luckily, Microsoft provides a solution for this: the aptly-titled DisplayName attribute.

	<DisplayName("Read-only")> _
	Public Property ReadOnly() As Boolean
		' Lots of code…
	End Property

Theeeeere we go. But no, we’re not done here. As mentioned, the properties shown in the grid can have categories, and once you go beyond more than a handful, you will want to use those. Therefore:

	<DisplayName("Read-only"), _
	Category("Nifty Things")> _
	Public Property ReadOnly() As Boolean
		' Yet more code…
	End Property

Better! And when in doubt, you can even provide a description:

	<DisplayName("Read-only"), _
	Category("Nifty Things"), _
	Description("Prevents the user from editing the field, but still displays its current contents.")> _
	Public Property ReadOnly() As Boolean
		' Yet more code…
	End Property

See, that wasn’t so bad, was it? Unfortunately, we’re not done yet. The above may be a fine solution if two things can be assumed:

Yeah, good luck with that. Of course you’ll eventually have customers from abroad, and of course at some point properties can change not only based on the context of the object, but also within one and the same object. (No, you can’t use a function for localizing the DisplayName, Category or Description attributes: Visual Studio will immediately throw an error that they have to be constant.)

That’s not to say it’s impossible to localize the contents of a property grid, or impossible to have a dynamic list of displayed properties. But by the time you get there, you scratch your head and cannot imagine any more that this use of reflection made things easier. It didn’t save you any time because, instead of having to populate the properties by hand, you had to edit each and every property by hand. Moreover, it wasted you time because you had to learn a different way of doing things; reflection is normally rarely used, and I get the feeling this particular example of it isn’t a good one.

There are guides on localizing the DisplayName1 as well as the Category2, and perhaps there’s even one for the Description. Likewise, you can find various articles on dynamic properties.3 There’s even hacks to pretend that the PropertyGrid handles Booleans as checkboxes, rather than as dropdown menus with “False” and “True” options (*shudder*!), although in my mind, they only make toggling a setting even more confusing.

But in my experience, nothing you can find on the vast resources of the Web will squash the gut instinct that all of these workarounds would have been necessary at all if the grid had simply been manually filled with properties at runtime.

It wouldn’t have been as clever. At the same time, it also would have been more useful.

Other candidates.

Maybe Microsoft isn’t the worst offender in bizarre control class design decisions. Lately, that questionable honor seems to lie with Infragistics, whose controls are bought because they offer more flexibility. Still, the sheer amount worries me: ‘Why can I change the color of this side of the drop shadow of this particular menu item?’

Now, coming from mostly a Mac background, I assume I can populate a menu with items, and possibly with other controls, which should be avoided. I’d also assume submenus could be attached to items. Finally, between items, there could be separators.

With Infragistics, you don’t think in terms of menus at all. API-wise, menu items are actually “tools”, added to a “toolbar manager” as well as a “menu tool”, which in turn you have to set to display as a menu, if you so desire.

You also don’t add separators. Rather, you tell an item (a “tool”, remember?) that it’s the first within a group, and the API will then appropriately add a separator in front of that – or on top of it. What if you have dynamic items? No problem:

	Dim menuHasOptionsGroupAlready As Boolean = False

	If shouldAdd("SomeItem") Then
		someMenuTool.Tools.Add(Me.UltraToolbarsManager1.Tools("SomeItem"))

		If Not menuHasOptionsGroupAlready Then
			someMenuTool.Tools(someMenuTool.Tools.Count - 1).InstanceProps.IsFirstInGroup = True
			menuHasOptionsGroup = True
		End If
	End If

	If shouldAdd("AnotherItem") Then
		someMenuTool.Tools.Add(Me.UltraToolbarsManager1.Tools("AnotherItem"))

		If Not menuHasOptionsGroupAlready Then
			someMenuTool.Tools(someMenuTool.Tools.Count - 1).InstanceProps.IsFirstInGroup = True
			menuHasOptionsGroupAlready = True
		End If
	End If

And so on. That’s how I solve it naïvely, anyway – I don’t think there is a better alternative.

Finally, you don’t just attach a menu to a “tool”. Rather, you replace the ButtonTool with a PopupMenuTool, which then must have a menu, which in turn consists of ButtonTools – unless, of course, you want submenus.

Disclaimer

This is the first time I talk about everyday experiences at my job. As such, I feel I should state the following: The opinions expressed here are my own, and neither my employer nor any other party necessarily agrees with them.

Moreover, to everyone at Microsoft and Infragistics working hard on the .NET Framework / Visual Studio and NetAdvantage for Windows Forms, respectively, I ought to stress that, despite the occasional annoyances and weirdnesses, I obviously enjoy using the products more than enough, and while my above criticism is real, it only represents minor niggles.

  1. For instance: Gerd Klevesaat’s “Globalized property grid” or Anthony Trudeau’s “Localizing display properties in the PropertyGrid”
  2. Also by Gerd Klevesaat: “Globalized Property Grid - Revisited”.
  3. “Unleash PropertyGrid with Dynamic Properties and Globalization”, “Customized display of collection data in a PropertyGrid” and “Bending the .NET PropertyGrid to Your Will”.

Tagged , , ,
Posted in Rants

Share | 1 Comment