I Can't Change Your Mind. And I Don't Want To

... and I said as much yesterday on my Tumblog. There's no point in my trying to convince you that LanguageX is better than Y - and I'm not going to. Languages are a tool - if you pick sides and go with only one then you're being ridiculous

. However I know a lot of people are curious, and they find by understand what I like, it helps them to form their own opinion. I think that's a bit co-dependent, but I can also see the merits of it.

I like the way Miguel put it to me today on Twitter:

A better C#. Let's start right there.

C#, Microsoft's Leatherman Language

I like the whole Razor/WebMatrix idea, believe it or not (read: the idea, not what was pushed out). I was wandering the halls at MS when the idea was being tossed around - but all I ever heard were small mentions and so on - I was never looped into the discussions. I think it's generally understood that Microsoft sees PHP's ability to get people to up speed quickly as a great "vector" for platform adoption. There are a ton of resources out there on PHP, and the language is fairly simple (at first). The tooling, also, is rather simplistic (Notepad).

That seems to be where the WebMatrix team stopped: "Let's make a tool that looks and acts like a scripting experience and we'll make it free!" Great idea! But then... "we'll leverage ASP.NET and C# - building out an additional abstraction layer that we'll say is 'concept-light'".

I'm not alone in being confused (Tweet from David Hayden):>If WebForms and MVC were more productive, intuitive, and convention-based out of the box, would we need WebMatrix?

The thing that struck me sideways is that it's sort of like WebForms 2.0 - you have the same stack underneath it (C#, ASP.NET, and .NET in general) but now you have "Scripter Components", which are modeled after PHP's snarled mess of core functions. The concept is interesting, but masking the language and framework - essentially dressing it up like a college kid - seems like sleight of hand.

A bit of a buildup - but here's the core point:>It's clear that C# isn't the best language to use for Web Development. Just ask the guys who are writing the frameworks with it.

ASP.NET is built on abstraction - "backing [the framework] baby into the corner". Companies have made millions on components designed to seal away and "black box" web functionality. And now we have Razor, which all but buries C# under a funky DSL that, all in all, is pretty functional.

It's just confusing to the existing community. Which is OK - it's not designed for them. It's designed for people who need to get in and out fast - the people who fall backwards into becoming web developers because they have to support their company/department intranet (or blog, or commerce site... whatever) which uses Joomla or Drupal (or Wordpress). These people just need to know enough Razor to create plugins for these platforms - and if they're naturally interested in the process... well a web developer is born.

So it makes sense -

except for the whole PHP part. Maybe when DotNetNuke switches over to Razor... But this post isn't about Razor... let's get back on track...

C# is an atomic powerhouse of a language - the power of the .NET framework clearly shows that. The web, however, is a pretty simple system that really doesn't need all the jargon and patterns we throw at it from day to day.

In response to Miguel the only thing I can say is:>C# is just fine. I just don't like building websites with it all that much.

Why I Like Ruby

Update

Geoffrey Grosenbach was kind enough to drop me a line about some better ways of handling Ruby. Specifically - while mocking is possible with Ruby (below) - it's not reliable. Please read the example as an ability with Ruby - not the way to accomplish mocking.

Geoff also mentioned that the methodmissing way of building out a query is rather expensive perf-wise. Ruby has to scan all methods before falling back to methodmissing. It's still a good example RE what Ruby is capable of - but it's not something you should do every day.

Before I jump into this - you're going to think "Oh Rob's left the MS stack... whatever this is ranting". You're free to think what you like - but I haven't. I need to bring this up every time I talk about something that's not mainstream MS - which is actually a bit sad. Ruby is supported by the DLR; many people (including myself) would love to see it become a bit more mainstream.

I really

love this article from Ben Griswold (aka JohnnyCoder) who really tries to capture the essence of working with Ruby. You've heard it before, Ruby is a very malleable, forgiving and fun language that is a treat to work with.

I'm going to show you some code now - and I'd really appreciate it if you could not get defensive (if you're a C# person). Recognize that I am too - and also recognize the context: Web Development. So put your geek hat on and take a trip with me...

Case 1: Expressiveness

You've heard it - but what does it mean? Let's consider a few examples - the first is handling a NULL value. In C# it would be something like this:

if(myVariable != null){ //handle it }

Rubyists hate this "machine-like" way of thinking about variables and their "assignments". They think in terms of interrogation, rather than process-flow, so they would write the above like this:

unless(my_variable.nil?) #do whatever end

Something to consider about the Ruby syntax above is just how readable it is - right down to the question mark. For some developers this is silliness - what amounts to putting stickers on your computer. For others - it's instantly readable and the microsecond you didn't have to go back and read over the machine syntax of C# you can put to use reading the rest of the code.

Let's jump to another example: exceptions. In C# the normal flow might be something like this:if(myVariable != null){ //handle it }else{ throw new InvalidOperationException("Hey dude! Where's My Variable Assignment!") }

With Ruby you can do this slightly cleaner:raise "Hey dude! Where's My Variable Assignment" if my_variable.nil?

The goal of the above is to get to something that a lot of people appreciate: The aesthetic of Ruby and its expressiveness. But there's more you can do as well.

Case 2: Packaged Code Distribution: Aka "Gems"

No doubt you've heard of Ruby gems. These things are about as close to DLLs as is possible - but it's so much more. The gem system is a package manager all by itself - and it handles versioning and dependencies quite nicely.

Imagine it this way: you want to use NHibernate on your next project. You've heard there's a new release, so you decide to head over to the project site to download it. You're greeted at Sourceforge with an obtuse download page that you stare at for a bit - ultimately figuring out what it is you need to click on.

Once you have NHibernate and it's army of supporting DLLs, you manually drop them into your project - making sure that you put them in a "lib" directory so they can go under source control - with your web project completely incapable of managing which version the app requires. And if it's in the GAC, you're screwed. Finally you manually add the references and off you go.

Imagine now that NHibernate was ported to Ruby: RHibernate - and is available as a gem. Your installation becomes:gem install rhibernate

(Rubyist Note: yes I finally know about RVM - that's for another post). The gem manager heads on out and pulls down all the lovely bits you'll need - as well as the appropriate dependencies, and pops them in your gem files. If you're using Rails or Sinatra you can dictate the specific version required by your project - and your project can actually go and get them for you (using Rake, a task runner).

I've heard a few people say they dislike the gem system, and Ruby's openness in general - stating that you end up managing gems and debugging the code a lot, and that this is a hassle. This is reasonable - but I like to look at it the other way: at least I can debug it! Moreover, just because Microsoft writes and distributes code doesn't mean it's bug-free.

Case 3: The Simple Things

I was watching a Railscast the other day on seeding data in Rails, and Ryan Bates showed some code which made me do a double-take. It's an interesting thing to ponder - how the various frameworks would handle such a thing.

Let's imagine that

there's a text file online with a list of all the countries in the world. I want you to import them into your web app and pop them into a table.

Let's assume for fun that you already have a table and an ORM with an object called "Country" - that part doesn't count. Neither does the mechanism - let's just pretend you have a console app kicked up. The only restriction is that you have to use the core language/platform features...

Here's the Ruby code (from Ryan Bates)require 'open-uri'

Country.deleteall
open("http://openconcept.ca/sites/openconcept.ca/files/country
codedrupal0.txt") do |countries|
countries.read.each_line do |country|
code, name = country.chomp.split("|")
Country.create!(:name => name, :code => code)
end
end

A couple of things here: open-uri is part of Ruby, not some external gem I pulled in. It allows you to call "open" which returns the contents of the page. You open a block against that return and loop over the values. Notice the second line of the loop - the one with "chomp.split", showing off Ruby's ability to assign variables in succession...

It's safe to say that with C# and System.Net it's just a bit longer. Not that much longer - but you'd have to have a pretty practiced hand to get through the "machine noise" that begins to creep in. Again - this is an aesthetic, a preference that a lot of people won't value and that's just hot buttery flavah. It's OK to have an opinion and if you don't share mine, I really don't care :).

Working with enumerations in Ruby is pretty nice - once you get used to code blocks and what they do. I'll write more about those later - for now take a look at this code - assume we have an object Address with typical Address-y properties:def actioninvoker(controller, methodname) controller.send(methodname) if controller.respondto? method_name end

class PayPalLibrary def validate true end end

myaddresses = Address.findby_state("HI")

def Address def self.#method_missing(meth, *args) #parse meth to build the query, use args to build parameters end end

def myaddress.formataddress #this is sort of like an Extension Method - but it's assigned to an actual instance, not a type end

"eyes".scan /thedarkness/ catch( :inthewind ) { ?a.round; "breath" \ or "a".slice /ofmoon/ }