Before joining my current project I spent about 4 months working with Ruby every day, the first time I’d done so for a few years. It was a glorious time: uncluttered syntax, closures, internal iterators, and with open classes, the ability to extend the ‘core’ at will.
Today I’m working with C# and .NET, and I’ve noticed that those 4 months with Ruby have changed the way I’ve been writing code. Most noticeably, I’m using anonymous delegates a lot more. But that’s not all.
I’ve found myself aching to use the List<T>
’s ForEach
method; I’m now wired to use Ruby’s internal iterators where instead of
List people = FindAllPeople(); foreach (Person person in people) { ... }
I can instead do
List<Person> people = FindAllPeople(); people.ForEach(delegate(Person person) { Console.WriteLine(person.Name); });
But, frequently I’m put off by the surrounding guff that’s needed to express the same and have almost always gone back to the more traditional external iterator-based approach. It’s simply too high-a-price to pay.
One of the largest smells I’ve noticed recently (to my mind) appears driven out of not having open classes and external iterators. If they were there, I’m sure people would use them. The result: all across the codebase, whenever you need to convert from type to another you’ll see
List<Person> people = FindAllPeople(); List<String> firstNames = new List<String>(); foreach (Person person in people) { firstNames.Add(person.Name); }
This smells to me. But it really, really smells from having used Ruby where I would previously have written something as succinctly as this:
find_all_people.collect {|person| person.name}
(I’m sure other languages could do equally good things- but I’m familiar with Ruby, before the Pythonists pounce :p)
Well, turns out that you can get nearly there with C# 2.0 and .NET 2.0 with the almost certainly underused ConvertAll
method (also part of List<T>
).
List<Person> people = FindAllPeople(); List<String> names = people.ConvertAll(delegate(Person person) { return person.Name; });
There’s still a fair bit of accidental complexity remaining- lot’s of delegate
and type declarations.
C# 3.0 introduced lambda expressions and we can use that to bubble our soup down to a nice intentional broth even more. We can get rid of the delegate bumpf and let the compiler infer the type (we are still statically typed after all)
List<Person> people = FindAllPeople();List<String> names = people.ConvertAll(person => person.Name);
Next step, we can also infer the types for our local variables:
var people = FindAllPeople(); var names = people.ConvertAll(person => person.Name);
Pretty nice. Most of the code is focused on the task at hand, and on expressing the necessary complexity (what it means to convert people to names). Guess learning a new language each year has it’s benefits.
I’ve got another bit of Ruby influenced C# refactoring to cover (a somewhat declarative way of removing switch statements), hopefully I’ll get that posted tomorrow!