SWeko's .net ramblings

1 Comment

The constructor that wasn’t there

Breaking changes are bad, and often it’s hard to convince ourselves that we really need them. However, it’s even worse when we do something innocent, that should not affect anything and we see that two hundred unit tests fail. Or even more fun for everyone, when everything seems fine, but a few days later, another developer comes, frothing at the mouth, yelling that he just wasted half a day because of our, obviously not-so-innocent, change.

A whole class of these problems, especially in object-oriented languages is connected to the “brittle base class” problem. Essentially it means that it’s never ever safe to change not only the interface, but even the behavior of the base class, because, someone, somewhere, depends on that behavior.
An example of this problem, specific to C# is connected with the default class constructor.

In general, the process of constructing an instance in .net consists of two steps, allocation of memory for the new object, and running a construction method on it. By definition, in order for a instance of any class to be constructed, it must have a constructor method.
The first step is done automatically for us, by the framework, and the second one is where we can do our work. In fact, the specification of the CLI, section I. in particular, insists that some constructor must be called.
In contrast to this, the C# language allows us to define a class without a constructor, i.e. the following are perfectly valid class definitions:

class Base {} // a class with no fields, properties, methods, or constructors
class Derived:Base {} // a derived class with no constructors
//and I can make new instances from those classes in the regular way
Base binstance = new Base();
Derived dinstance = new Derived();

So I can use those classes just like if I defined a constructor that takes no parameters. Actually, this is exactly what happens under the covers. The C# compiler detects that we have not provided a constructor for our class, so it provides a constructor for us. If we decompile the generated IL code, our base class will look somewhat like this:

class Base{
  public Base(){} //this constructor is generated automatically

And this is a great feature of C#, that we can just code away at the important stuff, without writing unnecessary code that can be inserted automatically by a machine.

However, the minute we add an instance constructor to our class, the compiler will not add any generated constructors to our class.1 This is a bit counter-intuitive, and in certain scenarios this could lead to unexpected errors, as usually adding independent code to a class should not break it, but it’s a design decision of the C# team, and we should live with it.

When we throw derived classes in the mix, the situation gets a little more complicated. According to section III. of the CLI specification, a constructor for a derived class must eventually call a constructor for the base class, i.e. no object can be constructed, without constructing a base class object2. Again, the C# standard makes is less cumbersome, by doing some of the plumbing work for us, in this case, injecting a call to the default (parameterless) base constructor. E.g. these two derived classes

class Derived1 : Base {}
class Derived2 : Base
  public Derived2 (int value){}

will be transformed to:

class Derived1 : Base
  //automatically generated constructor with an automatic base class constructor call
  public Derived1() : base() {} 

class Derived2 : Base
  //automatically added base class constructor call
  public Derived2 (int value) : base() {} 

This is great, as it ensures that the object will be properly constructed, and the compiler will not pester us with errors. That is, until we go in and add an explicit constructor to the base class.

class Base {
  public Base(string name){}

When we do that, the compiler does not automatically create a parameterless constructor, and the derived classes end up calling a non-existent constructor. The whole thing fails with the error: ‘Base’ does not contain a constructor that takes 0 arguments

The interesting part is that this error is issued on the line where the derived class is defined, because, as far as the base class is concerned, there are no errors. So, if the hierarchy is more than a couple of classes long, this message is very confusing to see.

There are two ways out of this. One is to explicitly call the new constructor from the derived classes – maybe adding a parameter to it’s constructor, maybe hard-coding a meaningful value, and the other is to add an explicit parameterless constructor to the base class. It’s either this:

class Derived1 : Base {
  //hard–coded and hopefully meaningful value
  public Derived1 : base(string.Empty) {}
class Derived2 : Base {
  //additional constructor parameters = more changes in code that uses this class
  public Derived2 (int value, string name) : base(name) {}

or this:

class Base {
  public Base(string name){}
  //calls the parameterful constructor with a hard-coded value
  public Base() : this(string.Empty) {}

The first solution is most likely the one we need, because if we added a parameter, its value is obviously needed by the class.

However, this will most likely be a breaking change not only to the derived classes themselves, but to the code that actually uses, or maybe even derives, the derived classes. So, if we do not have complete control of the derivation, i.e. if they are developed by another team, or if our base class is part of some library, we’ll have to take the second route, even if it means that some value is hardcoded to (hopefully) a sane default.

The lesson to draw from this is that designing a class hierarchy is hard. When we define a class that can be derived from, we are making a promise on both its contract (members and method signatures etc) and its behavior. We should always be vary when we introduce changes, and we should always make sure what and how they can break. If we do not want to make such a promise, we should declare the class as sealed, and then we know that the behavior we define is the behavior the consumer will get.

– inspired by http://stackoverflow.com/questions/12138221/does-not-contain-a-constructor-that-takes-0-arguments, feel free to upvote my answer 🙂

Leave a comment

Hello TypeScript

It’s no secret that I’ve never been a fan of JavaScript. The “anything goes” approach just seemed wrong to me, and the abysmal debugging experience in the early 2000’s didn’t help. In fact, in one of my first major battles with JavaScript, I remember losing an entire day hunting down a bug that at the end, turned out to be a stray = when a == was needed. I’ve never turned down an opportunity to bash JavaScript, and to point out what is wrong and fundamentally flawed about it.

But, the reality is that JavaScript is the lingua franca of the web. For better or for worse, one simply cannot write a web-application without using JavaScript, and that fact is not going to change soon. There are bajillions of web-sites that use it heavily, and, for the foreseeable future, it’s the only language that will be natively supported in all the browsers and on all platforms.

Thankfully, not everything is so bleak. There are lots and lots of beautiful frameworks and tools that make living in the land of the JavaScript manageable. With jQuery I can tell JavaScript what to do in a saner manner, and with Firebug I can even debug it. There are also tools that enable you to write in some another, arguably better structured language, which is that translated to a browser-runnable JavaScript.

Still, developing large JavaScript applications with teams greater that one, is harder than it should be, especially to developers like me, that are a bit spoiled by some excellent tooling. There is still no way to make sure that a commit from a colleague did not horribly break my code, except to run it, and see what happens, and there’s no easy way to discover if some specified functionality exists or not.

That was the situation, at least up to a month ago, when Anders Hejlsberg introduced TypeScript – an extension to JavaScript, that more or less has everything that I wished for. Those who know me know that I have a huge geek crush on Hejlsberg, and, through twists of fate, have worked with almost everything that he was involved with, starting with Turbo Pascal, through Delphi, finishing with C#. Once again, Hejlsberg delivered a succinct presentation of the possibilities of TypeScript, and why it will help us write better code faster.

In short, here are some of the announced (and delivered) features and characteristics of TypeScript, and why I think it’s the greatest idea since sliced bread (sorry, no code this time, I’ll turn practical in the next post):

First and foremost, it’s an extension to JavaScript, so it’s entirely optional. Every valid JavaScript code is valid TypeScript code, so it has zero start-up cost. You can just take an existing JavaScript file, change it’s extension to .ts, and – bam –  you have now a TypeScript file. When the TypeScript compiler compiles that file, you’ll get back the exact same JavaScript you started with. Nobody is gonna mess up your precious existing code.

Of course, this scenario does not make a lot of sense, so once you have your TypeScript file, you can start adding type notifications, extracting some interfaces, maybe even organizing some code into modules… If you use Visual Studio with the Web Essentials Extension, just hit save in the TypeScript editor, and again – bam – you have your compiled JavaScript file, that you can use in absolutely any way that you can use any other JavaScript file. And since TypeScript is just JavaScript on steroids, the generated file is essentially the code you would have written if you had to code it in plain JavaScript.

So, the second good thing about TypeScript I’d like to point out is that it also has a zero “changed-my-mind-this-sucks” cost. If TypeScript doesn’t work for a specific scenario, or if you just plain find the syntax icky, just leave it, and take your JavaScript files with you.

The third thing I love about TypeScript so far, is it’s optional nature, code-wise. I can add a little or a lot of static check code, and it will just work. This enabled me to create an interface definition file for an internal existing library in literally minutes. And it worked on the first try, with full Intellisense in Visual Studio. This also enabled a lot of people to create a lot of definiton files for a lot of existing frameworks, so if you want to use an existing library with TypeScript, knock yourself out. The experience of using jQuery with typed Intellisense is incredibly rewarding, even if you do know  all possible overloads of a method call by heart.

And the fourth and last thing I’m gonna go into this time is that TypeScript, in a smart move by Microsoft, is completely open-sourced. You can check out the sources and it is announced that the repository will accept code contributions in the near future.

IMHO, this time Microsoft hit the nail on the head, and more importantly, with the right amount of force. This is not an incompatible and proprietary extension that will only work somewhere, and if you say the right prayer. This is an open and honest solution to a real world problem.

Application scale JavaScript development is hard. TypeScript makes it easier.