Saturday, 22 October 2011

Ahoy matey, let's plunder 'tis camp

Friday Oktober 7th I visited Arrrrcamp in Gent, Belgium. Arrrrcamp is a conference about Ruby, Rails, Radiant and Rum with a pirate theme, yarrr. The conference offerred a broad spectrum of topics and some well known speakers, like Jonas Nicklas and Corey Haines. A celebration of open source Ruby development with a serious hint of craftsmanship. Here the outline of my day.


First up was Jim Gay, the lead developer for Radiant CMS. Most of his talk was about the new features of Radiant CMS. Since I've never used Radiant, most of his talk was wasted on me. The features he showed were quite impressive. Radiant is a CMS created in Ruby on Rails (of course) and you can use cool RoR features like Sass, Scss or Coffeescript in Radiant. You can create pages and define your CSS and javascript seperately. What's really nice is that they created different editors for this, like an IDE which supports different languages. Jim talked a lot about their upcoming 1.0 release and their struggle to migrate to Rails 3. Migrating a product which has many open source plugins is quite a challenge, since most plugins will not work in Rails 3. Jim explained they cannot just convert to Rails 3: you will have to give users and plugin makers a clear path to migrate along with you. This is why the 1.0 version will not be a Rails 3 version, but will remain on Rails 2.3. However, they are already working hard on the Rails 3 version and in the future, it will be possible to add Radiant as a Rails engine to your project. Wow.

A speaker which I really looked forward to seeing, was Jonas Nicklas, and he certainly didn't disappoint. Jonas is the creator of Capybara (an acceptance test framework for webapplications), Carrierwave (a solution for file uploads in Rails) and during his talk he introduced Evergreen, which integrates Jasmine javascript tests into Rails applications.
Here some of Jonas' quotes:
  • Rubyists love testing. Rubyists love programming. Rubyists love Ruby.
  • We want beautiful, well structured and tested code.
  • More and more code moves to front-end. Backend is more and more a CRUD application with JSON responses.
  • jQuery is the PHP of javascript.
Jonas demonstrated testing javascript using Evergreen, which integrates Jasmine javascript testing into your Rails application. This has some advantages: a route is mounted in your application where you can see if your Jasmine tests succeed and you can use Coffeescript to write your Jasmine tests.

He also offered some advice on using Capybara. Capybara is not an integration test framework, it's a tool to simulate user behaviour which you can use to create automated acceptance tests. His advice was:
  1. add your own selectors
  2. avoid asserting on URL, session state, cookies or application state (!!)
  3. avoid too specific selectors
  4. make generic asserts
Sound advice, if you ask me. To summarize: use Capybara to test what a user can do and can see, not what the application does. You should test that elsewhere in your test suite.

After a great lunch, I joined Julian Fischer's talk about "three ways to scale towards happiness". Julian had a disadvantage, since the room was next another one where they cranked up the sound so loud we could almost follow that talk instead of Julian's. Beforehand, I was afraid of having to listen to a commercial promotion of Railshoster.de, since he is involved in that company. But Julian's talk was incredibly informative and educational. He started talking about the high hosting prices in the U.S. and the legal issues you face when you host your webapp at a U.S. company. I've never realized that hosting my data in the U.S. can mean that the U.S. government might be allowed to demand access to that data. Do we really want to risk that?

The three ways he compared to scale towards happiness were:
  1. cloud hosting
  2. cheap datacenter hosting
  3. high end datacenter hosting
For each way, he made a detailed comparison of the advantages and disadvantages. Did you know that cloud hosting costs upto 20 times more than other hosting solutions?
At the end of his talk, he explained how to choose between the three options. Each application has it's own characteristics, which, when examined properly, will lead to a logical choice of one the options. You should do a requirement analysis of budget, load (normal and peak load), response time, availability, geographic targeting, estimation of growth rate, legal constraints, technical constraints and competence of inhouse support.Check out his presentation here on how to choose the correct Ruby on Rails hosting.

Next up was Andrew Nesbitt, who showed how to do A/B testing with Split, a Rack based A/B testing framework. He asked us the question: are you testing your users? (eehm, no...) How do you know that you are succeeding, then?
He demonstrated how to do A/B testing using the Split gem. Split uses Redis to save test data, which of course is very fast and scalable. It uses cookies to differentiate users and you can test almost anything, you can swap css, render different templates or partials, set different controller variables or even hack up your javascript.
Using Split looks easy, you can just create an experiment with alternatives and view via a CRUD controller how the experiment is doing. Split also has a dashboard to show results and you can even combine this with Google analytics to get a more detailed view. Disadvantage is that you will code the A/B tests in your product's release code. Andrew also had two memorable quotes:
  • Be a good Ruby citizen and contribute to your community!
  • If you're not prepared to fail, you're never going to be original.

A pretty long break followed, in which the organisation served free mojito's (yarrrr). To wrap up this enjoyable day, Corey Haines did a talk about fast Rails tests. A phenomenon which most of us only hear about, but never experience. I've heard Corey last year on the RubyAndRails conference in Amsterdam. He talked about software craftsmanship and that was the most insipiring talk I've ever seen. Corey has a great stage appearance, he's relaxed, funny, provocative, opinionated and inspiring.
He showed his way to get fast tests for Rails projects and why you should bother. You should bother, because slow tests will finally stop your developers running tests and it distracts them from the work they should be focussing on. To get faster tests, his main point is to NOT load Rails in your test unless it's absolutely necessary. You can create seperate modules or classes to defer behaviour from the Rails context and use stubs or mocks to test the behaviour outside of Rails.

Corey talked about Test Driven Development, here a summary of some of his statements:
  • The fundamental difference between test first and test driven development is, that in test-first you change your tests until workable, where with test-driven, if you discover that something's hard to test, you change your design.
  • TESTABILITY = GOOD DESIGN
  • Better design is one that is easy to change
  • The 3 A's of testing: Arrange, Act and Assert. Use 1 assert per test. Try it out for a while and you'll discover when to use it and when not to.
Especially Corey's opinion on how to create your Rails test suite and his opinion on integration testing led to much discussion. Which for me, actually continued until we were almost back home. Thanks to Corey for another inspiring talk.

When all was said and done: the Arrrrcamp conference is a properly organized event. The venue is small and has small disadvantages, but the pirate theme and excellent food and drinks more than made up for those disadvantages. I haven't seen an uninteresting talk all day, so I will return next year without a doubt. Yarrr!

Friday, 21 October 2011

Talk about TDD @ Coolblue

Today I did a talk about Test Driven Development @ Coolblue in Capelle. They invited me because they are continuously improving their development process (yes, they are doing Scrum!) and wanted to know more about Test Driven Development.

Coolblue has 4 shops and 99 specialized webshops. I was impressed by their order system, especially by how they were able to handle an enormous increase in sales volume and still maintain real-time services. And maintaining 99 webshops with just a few Scrum teams, hats off to these guys. I really enjoyed a peek into their kitchen and it was nice to be able to speak to other developers about stuff that I am really passionate about. You can view the presentation here: Note: the presentation is in Dutch!

Friday, 14 October 2011

Ruby on Rails surprise: conditional active_record callbacks

Sometimes you discover hidden features in Rails by trial and error. This week I was refactoring a method into an after_create callback. The method would create an empty user profile when a user was created, thus using an after_create callback would simplify this code. Using the handy create_ method which active_record provides when a belongs_to or has_one relationship is used I've managed to refactor this (quite horrible) piece of code:
class User < ActiveRecord::Base
  has_one :profile

  def create_from_ldap(login)
    #some code left out
    create_personal_belongings
    save
  end

  def create_personal_belongings
    profile = Personal::Profile.new
    profile.id = self.id
    profile.save!
  end
end
into these lines of code:
class User < ActiveRecord::Base
  has_one :profile

  after_create :create_profile

  def create_from_ldap(login)
    #some code left out
    save
  end  
end
Consequence of this change was that a user profile is always created when a user is created. Which is great, because users without a profile should not exist anyway. But it broke some specs, because some specs relied on specifying a certain profile for a user, so we can test some aspects of the user / profile relationship properly.

So what I actually wanted to do, is create a profile after creating a user, but only if the user hasn't got a profile yet.
When using active_record validations I've discovered you can do a conditional validation like this:
class User < ActiveRecord::Base
  validates :email, :presence => true, :email => true, :if => :has_email_enabled?
end
This validates the user's email attribute only if the has_email_enabled? method returns true for the specific user object. (see the active_record_validations documentation for more info) I couldn't find if I can also use conditionals on active_record lifecycle callbacks, so I just tried:
class User < ActiveRecord::Base
  has_one :profile

  after_create :create_profile, :unless => :profile

  def create_from_ldap(login)
    #some code left out
    save
  end  
end
Hey, that works! I believe it's not a documented feature, but it's really nice. I love Rails' adagium "use convention over configuration", because once you know how some stuff works in Rails, you can deduct how the other stuff works. And even better, the chosen conventions usually make sense. To me, at least.