Friday, November 11, 2011

On Implicit Typing in C#

I pulled out a copy of ReSharper after not having used it for a little while and turned it on my code. It's still a great tool but it kept bugging me about something:

"Use implicitly typed local variable declaration."

I was bewildered for a moment because I thought that sounded like it wanted me to use a var instead of a type. After some research, I was more bewildered because I found out it truly was.

My first landing was this. The writer references a post by Ilya Ryzhenkov at JetBrains that defends it. I also read Microsoft's unopinionated write-up of untyped local variables. The short version is that when you declare a local variable inside a method, you use an untyped declaration -- var, instead of int, or whatever other type it is -- and let the compiler figure it out.

From what I can see of the argument, it's for two reasons:
  • this is supposedly easier to read, and,
  • if the type changes, the code will function.
For the first postulate, I don't understand the argument. In the trivial case, var is no less difficult to read than int. If your type is Dictionary<Group, Member>, using var shields you from this. I couldn't find any justification for this and I can't say I agree.

There's a related argument as well, that if you use an untyped variable, it teaches you to correctly name your variables. On this, I'd flat-out disagree. We switched away from Pascal-naming a long time ago, for a reason. Further, good practices teach single-responsibility methods, which means your method body should be short. Short methods should fit on one screen and the reader should always be able to see the declaration throughout the entire method. Since the beginning of C, we've been using i as the primary index in a for loop, because it works well and increases readability. If a programmer lacks discipline, either in variable naming or in writing lengthy methods, they should correct this issue. The compiler should not enforce style.

As for changing types, whatever happened to programming to an interface? When the interfaces changes, the code that consumes it needs to change as well. This is a highly useful feature, not a problem. If a method I use from an API gets a signature change, I want the compiler to show me everywhere that my code needs to change. When I wrote the code, I expected a particular return type and my code depends on that. Changing the return type is likely to make my code do a different and unexpected thing. There are times I write code that intentionally deals with multiple possible return types and C# has an extensive set of features for exactly this case, from abstraction and polymorphism, to delegates and reflection. All are written so that type safety is preserved, from the reader's point of view. I'm not programming to make the compiler happy and readability -- therefore maintainability -- is usually my second or third highest concern when coding.

This takes me to a final point, that there are implicitly-typed languages out there. Until the var keyword was introduced, C# was not one of these languages. I don't think there is a coincidence that var was introduced with LINQ and I still explicitly type my LINQ statements most of the time.

There are times when I don't want explicit typing, like when I'm writing a script to sort my photo collection. When they come along, I use an implicitly-typed language and I don't think it's strange that this is almost always scripting. When it's not, there are plenty of options like F#, Ruby, Perl and VBScript, to mention just a few. For enterprise applications, my goal isn't just to get software out the door, but rather to deliver something that the next person will be able to maintain and add to, or myself but two years later when I've forgotten why I wrote it that way.

Monday, July 19, 2010

MySQL 5.1 XML Support

A better title would be, "not really."

Once again, MySQL is way behind the rest of the database world in functionality. Reading through the manual for what is as of this posting the current version, 5.1, the creators proudly advertise XML support. Unfortunately, the implementation is sufficiently incomplete as to be mostly useless.

Here's the problem: good XML is namespaced. Unless you're creating one off XML for extremely short term use, your dataset should contain and be constrained by some sort of definition. I personally prefer XML Schema, but there are other options such as DTD or Relax-NG. I think XML Schema is the de facto standard because it's most used and supported in most implementations, but I've heard from people who use Relax-NG frequently that it's a better standard.

None of the MySQL 5.1 XML functions support namespacing. They claim to, but they don't. They support namespace prefixing, but a prefix is useless without a namespace URI behind it. Prefixing an element does not namespace it; prefixing an element is a shortcut to make it easier and less verbose to longhand namespace it. But the prefix must be tied to a namespace, in the current context. If you are querying an XML document with XPath, the current context is the query, not the original document. Therefore, the prefix must be tied to a namespace within the query itself. Any compliant XPath querying function must take three arguments (somehow): the XML listing to query, the query and a map of prefixes to namespace URIs. Without the third argument, the prefix-to-URI map, it is impossible to correctly query a namespace-qualified document, which, if you're doing XML correctly, is pretty much every document.

Re-using or borrowing prefix-to-URI mappings from the source document is invalid. The mapping in the document is applicable on a document basis, not on a schema basis. That is, the mapping can change across instances of the document and still be valid within the schema. Given that, if you wanted to query a document and only know the schema, which is almost always the case at design time, you'd have no way to know what prefix is mapped to what URI. Therefore, you'd have no way of constructing a valid query containing prefixes.

Unfortunately, the manual page does not namespace-qualify any nodes in their examples, which is fairly common in XML examples. The only documentation mentioning namespacing refers to the ability to use prefixes and points the reader to a defunct Apache project. I hope that this was an oversight on the part of the MySQL developer team, probably an indication that whoever wrote the XML support has never used XML in a real-world context.

For what it's worth, other RDBMS platforms do support real XML querying. Oracle 10g's EXTRACTVALUE does support a half-baked but functional namespace URI specification in calling. Microsoft SQL Server has supported a fully namespace-qualified query on the XML data type with the query T-SQL keyword since their 2005 version. Even Postgres -- "even" only because it's open source and a direct competitor to MySQL -- has a fully compliant xpath function that takes arbitrary prefix-to-URI mappings.