Monday, June 20, 2011

How Powerful is Your Language?

Most mainstream programming languages today are basically the same.  I mean, they are all Turing complete, they can all access databases, the web, and so on.  What else is there?

Well, my comparative languages class in college said there were four factors for evaluating programming languages:
  1. Readability
  2. Writability
  3. Reliability
  4. Cost
I would add a 5th, which is maintainability.  The argument I'm going to attempt to make today is that Dynamic Languages, and Ruby in particular, score better in these factors than static languages, and therefore are more powerful languages.

The first thing you might think of is syntax, and there is certainly something to be said for that.  Clean syntax makes for enhanced readability and writability.  And the ability to create DSLs in your language is another major plus to readability and writability.  So right off the bat Ruby is off to a pretty good start.

But I think the argument actually goes deeper than that.  Consider the SOLID design principles:
  • SRP: Single Responsibility Principle
  • OCP: Open Closed Principle
  • LSP: Liskov Substitution Principle
  • ISP: Interface Segregation Principle
  • DIP: Dependency Inversion Principle
These are principles we use to describe good code.  That is, more readable code, more reliable code, more maintainable code, and less costly code.  And I believe that Ruby, as a language, has many of these principles built right in.  And that means that it scores higher on the comparative ladder, and therefore is a better, more powerful, language!

Lets start with SRP.  So Ruby has Modules, which are pretty great.  And I would argue that they are a helpful tool for SRP.  I've had some awesome conversations on this point, but I land on the side of saying that Modules and MixIns are totally useful for SRP.  But that's about as far as we go for language support for SRP, so lets move on!

OCP is a bit more interesting, though still straight forward.  Dynamic languages like Ruby allow you to open up any class from a distance and add new methods to them, or change the definitions of existing methods.   So you can change anything in the class without having to open up the actual class definition. That's some pretty serious built in OCP support.  Of course, to be fair, this isn't a feature you're likely to depend on when you're implementing a class you want to follow OCP...  Its more of a last resort really, but we'll find its very useful for mocking which we'll talk about later.

When talking about LSP Wikipedia has this to say: "Behavioral subtyping is a stronger notion than typical subtyping of functions defined in type theory."  This is a super-wonderful sentence for my purposes here!  LSP is all about the behavior of subclasses matching their parent classes, and the beauty of this is that dynamic languages are ALL about behavior, you tend not to get to hung up with "types".  So, you still have to be careful that your derived classes' behavior is consistent with that of their parent's, but since you're already thinking about behavior instead of types, you are off to a much better start.

Interface Segregation seems simple at first glance, dynamic languages don't have interfaces, end of story right?  Not quite, because while ISP is about interfaces, what's its saying is that your interfaces should be highly cohesive so that you cannot divide the methods of an interface into discrete sets based on who calls them.  This is because we don't want to be coupled to methods we don't care about.  But in a dynamic language, the caller just sends whatever "messages" it wants to the object it is calling, so by default our "interfaces" are as segregated as they could ever possibly be!  We have perfect, automatic ISP in dynamic languages.

Dependency Inversion is sort of the crowning jewel of built in principles in dynamic languages.  Most of the time in static languages our main reason for caring about Dependency Inversion is for unit testing.  We invert our dependencies so that we can mock them out in our tests.  This is outrageously annoying because it means we can never ever ever call a constructor.  So we are forced to either a) make all our dependencies stateless or b) wrap all our constructors with factories.  It also means we have to introduce interfaces to describe a huge number of our classes. In Ruby, we don't have to think about this.  At all.  We can stub out the calls to constructors and return our own mock versions.  It's so easy it's totally stunning the first time you do it.

So there you have it!  Dynamic languages are awesome, in part, because they have the SOLID design principles built in, which makes them score better on the comparative language scale.

Monday, June 13, 2011

Code As Practical Art

One of the bands I play with, The Prime Time Big Band, had the lucky opportunity to have Sean Jones run one of our rehearsals.  It was awesome.  He was full of wonderful metaphors, and phrases, and energy.  One of his phrases was "the humanity of the music," referring to emphasizing the emotion of the lines and phrases of the music.  Another was "playing a ballad is like holding a baby."  You don't hold a baby tentatively or nervously.  You have to cradle it lovingly and softly.  But at the same time, you must HOLD it, firmly, and not drop it!

Cool stuff, but why am I writing about it on my tech blog?  Because a lot of what he said, and the passion in the way he said it, made me relate it to my job and my code.  For example, he said the difference between a great band and a good band was small, but it was in the attention to detail.

Sean Jones didn't speak to it directly, but I started to think about how much of what he was describing was very specific to artistic disciplines.  And yet it had a similar ring to programming.  And ultimately it has to do with the freedom of creation.  Art, music, and programming all deal with the creation of something via a controlled but very flexible medium.  Paint and canvas, 12-tone scales and instruments, or code and CPUs.

Tons of people have equated programming to art because of this creative aspect.  But the interesting difference is programming must serve a practical purpose.  Art and music don't have a practical purpose, past being pleasing, or challenging, or making money.  The practical aspect of programming is what can cause us to forget about, or trivialize, the creative joy of programming.

It is possible to deliver practical but crappy software.  That is, the software works, but the code or the UI or the architecture or the performance is for shit.  No one wants to spend their precious time building crappy software, but when the clock is ticking and the boss is getting impatient you can get swept away.

I got into programming because I loved the creative side of it.  Solving problems in clean, elegant, organized, understandable, and dare I say clever ways is what I love doing.  And this requires immense creativity!  It is no coincidence that these things are also what leads to better software applications.

So don't forget what you loved about programming!  Don't shun the creative aspect of your craft.  Apply the attention to detail it deserves and create awesome software!

Monday, June 6, 2011

Should You TDD Controllers?

If you use Selenium to test your website should you TDD your controllers?

My default stance is to TDD everything, so why would I even ask this question?  Because controller tests are just a mess of mocks and therefore tend to be time consuming to write, brittle, and mostly just verify that you called things in the right order...  This is especially true if you write thin controllers by pushing logic into "service" classes and your models.

Controller is one of the Object Stereotypes which is defined as "Controls and directs the actions of other objects.  Decides what other objects should do."  So this is an object that just deals with other objects.  That's why it's so mock heavy to unit test.

If you have Selenium (or whatever) tests that drive your website, then you have integration tests on your controllers, and, indeed, your full stack.  So at least the "happy paths" of your controller are covered.  And arguably covered in a more useful way than unit tests.

So, for argument's sake, lets say you agree with me that controller unit tests are mock heavy, expensive to write, and of limited value.  So what value do they provide?  One thing stands out above all others: error handling.  Especially errors from "services" which may depend on infrastructure concerns like file systems and web services or whatever.  Its difficult to test failures in these types of things without mocks and its difficult to mock in a Selenium test.

So, should you TDD controllers?  I think, only when it provides you enough benefit to out weigh the costs (imagine that).  For me, that means I don't test controllers that just do standard CRUD operations and handle 404 errors.  Those are trivial, fully covered by selenium tests, and take too long to mock.  But anything more complicated than that, I test.