Ruby:
FileUtils.copy('myfile.txt', 'myfile2.txt')
c#
File.Copy("myfile.txt", "myfile2.txt")
Now I can see it. The Ruby way is so much better!

This raises a few interesting points. First, a usable API is possible in most languages and platforms, which is encouraging for those of us that work primarily in C# and .NET. Just because we work in a static language doesn’t mean we should settle for verbose, unintuitive APIs.

The second point, and the topic of this post, is the idea of essence versus ceremony. Both lines of code above clearly show the essence of what we are trying to achieve: create a copy of myfile.txt in a file called myfile2.txt. Of course these two lines of code do not quite tell the entire story; there is a certain amount of ceremony we need to go through to get them to run. Let’s see how many incantations we need to mutter to get these things to work.

C# is for ceremony?

Until C# 5.0 and compiler-as-a-service (or a few weeks ago for Mono users ;)), we need to do some work to get our C# line of code to satisfy the compiler. This means wrapping the line in a class with a static Main entry point that will be called when we compile it into an EXE.

So our single line of code takes around 6 ceremonial lines/operations (plus some brace noise) to make work. We need to reference the IO library to access the API we need; we need a class declaration that for this code is completely useless, and we need to utter ye olde "public static void Main(…)" incantation before we get to the essence of our program. We’ve got access modifiers and a plethora of punctuation. We then need to compile and run the resulting EXE. Of these, only the required library and executing the program bears any relation to the problem at hand.

Note: Yes, I could ditch the using statement, but I want to keep the original lines of code intact, and I want to show referencing the library as a separate logical operation. I’ll give Ruby the same treatment.

Expressing essence with Ruby

As Ruby is interpretted it has a pretty unfair advantage here. We just need to tell Ruby where to find the library we need for our single line of code, then execute it using the Ruby interpretter.

require 'FileUtils'
FileUtils.copy 'sample/src/1.txt', 'sample/dest/'

> ruby file_copy.rb

Here pretty much everything relates to the essence of our code. True, this is a silly little example, but it does show that the two single lines of code posted in the original comment don’t tell the whole story, and that the single line of Ruby code takes less work to get going than the equivalent C#.

But wait! There’s more…

How many times do you actually compile .NET code in anything other than an IDE? I used Vim to write both the C# and Ruby, but let’s pretend for a moment I’m normal rather than the insane, rambling lunatic I actually am and code this in Visual Studio. :)

That’s over 120 lines across 4 files and a couple of directories. True, there are many great advantages to using VS, but lack of ceremony isn’t one of them. ;)

But this is a ridiculous example!

Yes, I agree! So why bother pointing out obvious differences between compiled and interpreted languages? Because it’s important to understand the difference between essence and ceremony so we can emphasise the essence of our code as much as possible, and it’s hard to find a simpler, more obvious example than this. Once looking for it, it becomes very obvious that satisfying the compiler isn’t the only form of ceremony C#/VB.NET devs (et al.) go through.

Consider this: with Ruby (and many other languages), you don’t really need an IoC container. You don’t really need factories. Explicit interface files for extensibility? Don’t need them for a dynamic language; you’re programming to an implicit interface. And say goodbye to code noise like public / static / virtual / abstract / override etc. Ruby doesn’t want any of that mumbo-jumbo thanks very much! Then there’s Ruby’s meta-programming which lends itself to coding via conventions, and the loose syntax which makes some very expressive, internal DSLs possible. (Have a look at Design Patterns in Ruby for some great examples of how common design patterns can become much simpler with Ruby.)

None of this means C# is bad. It’s not. It’s an awesome language. Static typing provides a number of advantages, as does compilation. But it is very important to consider the ceremony you need to go through to get your job done. It is definitely worth looking at other languages and platforms like Ruby, Python, Rails and Django to help find ways of reducing the amount of ceremony you need for your C# code, but also to help you pick the right tool for the right job.

Comments

All code and advice is provided without warranty -- use at your own risk! This is just a blog! Don't take it too seriously!
Despite not being too serious, this blog has a Privacy Policy, because it uses Google Analytics to see if anyone drops by.