Saturday, 6 February 2010

Quack!


Since I am prancing through the playground that is Objective-C at the moment, I'm having to face concepts that have been pushed to the back of my C#'nd mind. Of course, I'm talking pre-C# 4.0 so assume the CLR and compiler are not collaborating to allow any form of duck typing, which is primarily what I'm interested in right now. I also don't count the C# libraries out there that work around the language and sealed classes because IMHO if the language doesn't let me do it then it's all just too much work on top of what I'm already writing. Yes, this even applies to assisted automated testing. Bring on C# 4.0 but until then, let's look at a language that complies... Objective-C.

This came up while looking at mocking in Objective-C and how the language makes it easy, whether you choose to use a mocking framework or implement something quickly yourself (as for how to do that, you'll have to wait until another post). Duck typing makes testing delightful in dynamically typed languages and I want to make sure that the tricks learned while testing in Ruby are not lost to me.

Take a look at some clear and concise code examples of Duck Typing on Wikipedia.

Over a conversation on IM with an ex-colleague, I had to spend quite a lot of time making it clear that a dynamic language does not mean the same thing as dynamic typing in a language. This is an error often made and voiced as if the terms are interchangeable. They are not.

Dynamic typing is when type checking is done at run-time, meaning while the program is executing and not at the time of compilation. The implication is that types are associated with values rather than variables. Run-time dynamism is different to dynamic typing, in that the language does a lot of things at run-time that other languages might do at compile time like adding code, optimising decision paths, extending objects and type checking (dynamic type checking). A dynamic language can have dynamic types but it does not have to.

Now one of the bonuses of this is that the type of an object can be used to make a decision while the program is running, to decide what code should be executed next. This is Duck Typing. The term comes from the idea that if something looks like a duck and quacks like a duck then it is probably a duck. That assumption allows for an instance of an object with the correct accessors or methods to be used without checking first if the object actually is of the right type. Of course, if the object does not have the right characteristics then is will throw a run-time error.

Run-time errors seem to scare people a lot more than I first realised. In a static world, a run-time error usually means that something very bad has happened in your compiled code with respect to resource management or the compiler corrupting the intent of your code. That is scary. Thing is that testing is a great way to check that your code isn't going to blow up unexpectedly, whether your typing is checked statically or not.

If you don't understand duck typing and are from a statically type checked world then you can end up hamstringing yourself by adding meta data to an object that is set and checked to indicate the type of an object. Explicit type checking in this case means you have missed the point and the advantages of the type system you are using. You must unlearn these habits and understand your language to use it correctly. Changing languages is not as simple as changing development environments. It's a mindset change. You as a developer have a responsibility to use your tools in the right way. You can always hammer a screw in to place but it's not necessarily the right way to do it. Maybe use a screwdriver and learn how it works. Many times, you will see a language that is written with the accent of another language and it works and looks almost right but simply isn't. Engineers who go from C# to Java and back will see themselves doing this and smack themselves on the hand when they realise. This is a habit to break.

While playing with Objective-C, I have seen compiler warnings given that won't stop you from running your code but will highlight that the compiler isn't sure that you are sure what you are doing. Explicit type casting will remove these warnings if you have the kind of OCD that doesn't allow you any warnings at all in what will ultimately become production code. For me, the majority of this is in my testing code so I'm more 'laxed than I might usually be.

C# has what is called nominative typing. In other words, you use the name of the object's type to determine what it is. To handle the type you use explicit naming to deal with what is expected. Duck typing allows part of an object's structure to be accessed at run-time to check compatibility. Before C# 4.0, any attempt to duck type sealed classes was shut down by the CLR. There are ways around that involve inheriting from your own interfaces that look similar to other interfaces but this is not sincere enough for me. If you must add these tricks to your code then maybe you are at the point of considering using another language that is more suitable for the job. Luckily for us .NET'ers, we can use a lovely language like C# for our glue and integrate a lot of other funky technologies to do cool stuff. I can't wait to see the next version of the language. Hopefully, the changes are real and not just work-arounds.

In summary, Duck Typing allows a method to use an object as long as the object it expects supports the methods or properties that the method is looking to call. The given object doesn't even have to inherit from the same base or interface. The object does not have to support all methods and properties to be passed into a method.

There is no actual point to this post. It's more a bunch of realisations as I journey from one language to another.

There is much space for misuse and making stuff go bang but that can be said about a lot of dynamic features of languages. You can't take all the power to create beauty away from developers simply because some may shoot themselves in the foot with it.

Dynamism doesn't kill people, people kill people.

1 comment:

Michael Foord said...

So, if dynamic typing and dynamic languages are orthogonal (and I'm not convinced I think the terms are more-or-less interchangeable) can you give an example of a dynamic language that doesn't use dynamic typing and also a dynamically typed language that isn't dynamic?