OOP Conference is the longest running conferences I’ve ever presented at. This year was it’s 21st year of running, and although coming from Object-Oriented programming roots, the contents of OOPConference have evolved with the times to represent so much more – just like JAOO has over the years.
This is the second conference I’ve presented at where the talks were in a mix of languages – obviously German, since the conference is based in Munich, and the other language being English. As a result, the number of sessions I attended was much lower than I normally would and I was able to catch up with a number of other speakers such as Johanna Rothman, Michael Nygard (author of Release it!), Kevlin Henney (97 Things curator) as well as meeting many new speakers.
I was also surprised at how many German speakers I’d met previously and got to practice a little bit of German. I did try sitting in on one session with a former colleague, Gregor Hohpe where he talked about (auf Deutsch) the Near-Field Communication technology the Japanese have. He talks pretty fast in English, let alone in German. I thought I was doing pretty well understanding the gist, but at probably half an hour into the talk, I think my brain seemed to explode and couldn’t take any more. A good way to test your limits
Fortunately he also used lots of photos in the slides so I could follow along.
I attended a number of other talks in English, one on the latest going on in the NoSQL space (reminding me of a news commentary on what was going on) as well as one of the keynotes by David Parnas. I’ll admit that none of the keynotes blew me away. They all had good solid points they wanted to get across but the message not really new to me. I appreciated listening to Parnas’ talk because of his significant impact to the way OO-Programming is done, although his focus on documenting and enforcing contracts meticulously (whilst having its place) isn’t necessarily as relevant in the internet applications of today (but highly relevant in embedded systems that last for 25 years!).
Something I learned from his keynote was a new tool for better thinking about object oriented design, providing a table to help people classify what sort of information they want to hide and some recommendations to do so. Although probably not a very new tool, I think it has been forgotten through the passage of time and I know plenty of developers who could learn more about real encapsulation who’d benefit from it.
I had two sessions presented at OOP Conference. The first, “Learning to see, A Systems Thinking Primer” gave people a focused introduction to systems thinking concepts, the ideas of archetypes and applying it to situations in software. I’m really glad that a German audience proved much more interactive than I’d hope and I think it proved some interesting insights into topics such as Mental Models and such.
The other sesison was working with my Hamburg-based colleague, Ken Fassone on a “Night School” lecture/workshop Pair Programming: Good, Bad and Ugly (which I have to give credit to another colleague, Rachel Laycock for). I’m not sure some some people anticipated a workshop, but I’m pleased at how some people enjoyed it. We swapped exercises after a mishap with some supplies and shipment, but afterwards, realised how difficult it was for some attendees to do some sentence writing, with a new group, in a language that is not their mother tongue. They did way better than I ever could, and from the enthusiastic thanks from some of the participants at the end of the workshop, proved to be an enjoyable exercise as well.
TLDR Version: This book is incredibly well researched and covers pretty much everything in the Ruby world. While it does have a very good introductory section I think the main benefit to this book is as a reference guide.
Programming Ruby is probably the most well-known book in the Ruby world. I guess I’m a little unsure as to the target audience for this book, but based on the amount of recognition it has received it seems to be aimed at pretty much anyone who codes in Ruby.
There are several points in the book where the author gives you the option of skipping past a particularly difficult section, which would be very helpful to newcomers to Ruby will still making it useful to more experienced developers.
The GoodI started reading this book to learn Ruby. I already knew a bit of Ruby at that point, but I wanted to really understand the different concepts and functions of the language. This book does work pretty well for that approach – new concepts are introduced in an order that makes it easy to understand and the explanations are straightforward and backed up by good examples. The first section of the book serves pretty much as a tutorial to the Ruby language.
After reading the first 100 pages or so I abandoned the book and started coding a few simple examples. I then moved on to Project Euler and solved a fair number of the problems with my new Ruby skills. This is probably the approach I would recommend – you can try to read the whole book cover to cover, but you’re probably better off writing more code as soon as you feel comfortable.
All the sections in this book are incredibly detailed and well-written. The amount of research that must have gone into this is very impressive. I only read the latest version (aimed at Ruby 1.9), but from what I read online almost 50% of the book was modified from the previous version.
The BadSimilar to The Rails 3 Way, this book is long – more than 900 pages in all! I don’t think anyone will read this cover-to-cover, but even reading everything up to the reference section is more 400 pages. While this makes the book great from a reference point of view, I did find everything past the first (tutorial) section to be a bit long-winded. For example, I don’t really see the need to know all 8 aliases for the exit command in IRB (the Interactive Ruby Shell).
I also found some of the examples to be a bit confusing – especially some of the examples around testing could probably be improved. (I’ve found this to be the case for quite a few books, so maybe I’m just overly fussy)
ConclusionThis book is incredibly well researched and covers pretty much everything in the Ruby world. While it does have a very good introductory section I think the main benefit to this book is as a reference guide.
I’m a bit in two minds about using a book as a reference guide in today’s world where most reference material is simply a Google search away, but from what I’ve seen this book would work very well in complementing online reference material. It’s simply a matter of all the topics being very detailed and well researched.
One the most undervalued roles in a web or software development team is that of a Copy Writer/Content Strategist. Having a skilled specialist on a team who is able to set the tone of the conversation with users and ensure that it is consistent across the site can make the difference between a mediocre or great product.
Unfortunately, it’s rare to have a dedicated Copy Writer on a team unless the product is either content heavy or marketing driven. Largely the duty of authoring all those small but important bits of text tends to fall to the User Experience Designer and Product Manager/client when creating and reviewing wireframes.
In the worst-case scenario it gets left with the Devs to do when they are building pages. In this case instructional text, error messages, field labels, etc. end up sounding like the have been written by an emotionless robot. This is not a slight aimed at the English skills of my technically minded colleagues, but more a reality of what happens when copy is produced as a by-product of writing functional code.
Recently a colleague of mine, Meaghan Waters, shared a set of content writing guidelines, which had previously been shared with her by an old colleague, Amy Teshio.
It has some great tips and reminders on how to write compelling content. I found it so valuable and helpful that I had to share it here as well:
Like most things in life, good writing is about thinking and feeling:
Some tips:
Trusts its value. Let it speak for itself. Tell stories. Know when to move from information, to story, to visual rendition, back to information, etc. (or consult with others).
Let the flurry happen. Put it aside and come back with fresher eyes. Consult with our editorial team. Give yourself enough time to draft, consult, revise. Writing is different from editing. Don’t try to do them simultaneously.
Remember, just because you are reluctant to give up a particularly nice word, sentence or paragraph doesn’t mean the reader will miss it. If you are having trouble giving it up, copy it to a separate file and make it your own buried treasure.
“Vigorous writing is concise. A sentence should contain no unnecessary word, a paragraph no unnecessary sentence, for the same reason that a drawing should have no unnecessary lines and a machine no unnecessary parts.”
William Strunk, Jr., The Elements of Style
Mix up the rhythm. It keeps it interesting and sounds less robotic.
If you have another idea to convey, start a fresh sentence.
Know your audience.
Voice should reflect subject matter.
Use the appropriate tone:
No: The white iPhone is preferred by generation Xers.
Yes: Generation Xers prefer the white iPhone.
Don’t put too many qualifiers between you and your message. This attempt to be conscientious will only confuse the reader. Readers don’t retain ideas that are in remote locations.
Avoid jargon. Use the simple, reliable work. Good writing is not so much a matter of using unfamiliar words, as using familiar ones in unfamiliar ways.
Three factors of influence versus three influences.
When talking to different participants, paper copy remains a critical component of the way they manage day-to-day information.
But note: paper copy didn’t do the talking to the different participants.
Avoid passive voice/double gerunds.
No: The e-binder concept form was seen as a way to provide a format for organizing sharing.
Yes: Participants see the e-binder as a way to organize the sharing of information.
Why learnings instead of lessons? Why around instead of about?
We ran into an interesting problem when trying to start up an Oracle instance using dbstart whereby we were getting the following error:
-bash-3.2$ dbstart ORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listener Usage: /u01/app/oracle/product/11.2.0/dbhome_1/bin/dbstart ORACLE_HOME Processing Database instance "orcl": log file /u01/app/oracle/product/11.2.0/dbhome_1/startup.log
Ignoring the usage message we thought that setting the environment variable was what we needed to do, but…
-bash-3.2$ export ORACLE_HOME_LISTNER=$ORACLE_HOME -bash-3.2$ dbstart ORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listener Usage: /u01/app/oracle/product/11.2.0/dbhome_1/bin/dbstart ORACLE_HOME Processing Database instance "orcl": log file /u01/app/oracle/product/11.2.0/dbhome_1/startup.log
We ended up looking at the source of dbstart to see what was going on:
# First argument is used to bring up Oracle Net Listener ORACLE_HOME_LISTNER=$1 if [ ! $ORACLE_HOME_LISTNER ] ; then echo "ORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listener" echo "Usage: $0 ORACLE_HOME"
The usage message does explain that you’re supposed to call it like this:
-bash-3.2$ dbstart $ORACLE_HOME
But it still seems a bit weird/misleading to me that you’d override the value of a global variable from inside a script which doesn’t suggest that it’s going to do that!
Such is life in Oracle land..

QCon invited Rebecca and I to do a keynote at QCon London (March 7). Over the last year or so we’ve been seeing more and more of a change in how organizations think about data, so that seems a natural choice to talk about. Our clients are seeing larger volumes of data, that they need to analyze more quickly and more cleverly. We’re seeing different technologies for data storage that have loosened the vice-like grip of relational databases. And we find our profession needs to start thinking about what our responsibilities are in managing all of this information.
While reading the Ruby Pickaxe book I realized that while JavaScript and Ruby are both dynamic languages, they handle method resolution in very different ways. I often use JavaScript as a reference since it’s the dynamic language I’m most familiar with.
A Simple Example in JavaScriptLet’s first look at a simple JavaScript example.
var widget = {}
widget.name = "Wobble"
alert(widget.name)
widget.surname = "Bobble"
alert(widget.surname)
This will run without any problems. If you try to get the value of a property that doesn’t exist JavaScript will simply return undefined. If you try to set a property that doesn’t exist JavaScript will create that property and set the value. JavaScript will complain when you try to invoke a method that doesn’t exist.
If I recall correctly, dynamic objects in C# 4.0 will function the same way – you can add properties to a dynamic object without problems, but invoking a method will raise an error. (It’s been a while since I worked in C#, so don’t quote me on that)
Ruby doesn’t have the concept of properties, so in the following snippet of Ruby code,
widget.name = "Wobble"
Ruby is actually looking for a method called name= and passing the string “Wobble” as a parameter.
A Simple Example in RubyLet’s try the same example in Ruby.
class Widget end widget = Widget.new widget.name = "Wobble" puts widget.name

As you might expect, Ruby raises an error saying there is no name= method on this object.
There are a couple of ways we can get around this limitation. The simplest is probably to add a name accessor to the class.
class Widget end widget = Widget.new class Widget attr_accessor :name end widget.name = "Wobble" puts widget.name
As you can see from the example, Ruby allows us to add accessors for a @name instance variable to the class. The attr_accessor method (also called a Macro) will add the necessary methods to access this attribute – in other words, it’s similar to adding the following two methods:
def name @name end def name=(val) @name = val end
It’s important to know that the attr_accessor method doesn’t actually create the @name instance variable – it will be created the first time we access it.
Using method_missingRuby also allows us to define a method_missing method (also called a Hook) which will be invoked when a method is not found (as you might deduce from the name). It has a pretty simple signature:
def method_missing(name, *args, &block)
So we have the name of the method being called (passed as a symbol), the arguments passed as a splat array, and a block.
We can now put this to use to allow us to dynamically access any instance variable.
class Widget
def method_missing(name, *args, &block)
if name =~ /.*=$/
instance_variable_set("@" + name.to_s.chop, args[0])
return args[0]
end
if name =~ /.*[^=]$/
return instance_variable_get("@" + name.to_s)
end
raise "I can't figure out what you're trying to do"
end
end
widget.surname = "Bobble"
puts widget.surname
Conclusion
I definitely wouldn’t advocate using this type of code in a real project, but it’s interesting to see what’s possible.
If you want to play around with my example you can find it here. Happy coding.
I’ve long been a fan of the podcast series Software Engineering Radio. The team there have built an excellent series of podcasts on various aspects of software development and I often listen to them while taking my afternoon walk. So I’m glad to get a spot on there myself. In this episode I’m on the program with Rebecca Parsons, my colleague and co-author of my DSL book to talk about DSLs. We talk about what DSLs are, the differences between internal and external DSLs, and when you should (and shouldn’t use DSLs). The episode is hosted by Markus Völter, who, of course, is a considerable expert on DSLs too - so it’s really a three way conversation on the topic.
Just a decade ago the amount of memory for a typical desktop was in the lower 3 digits of MB. 15 years before it was in 2 digits of MB. Yet we had email clients, browsers, word processors, spread sheets, image processors. I read about one financial analyst’s perspective about the inflation and taxation in America. It is such that the purchasing power of money in your hand after taxes is significantly lower than the inflation adjusted money’s purchasing power in 1950. For example; if someone sells her house for in 1950 and then the amount of purchasing power that money had after the tax was significantly higher than what it could do in 2012. The direct and indirect taxes have risen and the inflation has masked the effects of it.
While writing this, I am doing so in a machine which has 8GB RAM, 500GB hard disk and i7 processor. That is a 250 times increase in my computing power than 15 years ago. Though the frequency of the crashes I encounter has reduced to a great deal, there are still crashes and non responding apps which annoys at times. I have observed that the thought “memory has become cheaper than efficient programs” is prevalent for most of the applications barring a few which demand performance. Take a look at the hardware of the Apollo Guidance Computer. We were able to land on the moon with that piece of hardware, but right now even with such excellent hardware we many times end up with non responsive websites. With a workload of just above 1000 concurrent users some web sites can easily choke the best hardware they are running in.
Is there a way that the generous doses of memory and computing power could be used effectively or will be waiting for something like water scarcity or environment pollution to happen to learn to use the hardwares efficiently?
Continuous delivery is a software development strategy that optimizes your delivery process to get high-quality, valuable software delivered as quickly as possible. This approach allows you to validate your business hypothesis fast and then rapidly iterate by testing new ideas on users. Although Continuous Delivery focuses on engineering practices, the concept of continuous delivery has implications for the whole product-delivery process, including the “fuzzy front end” and the design and analysis of features.
Read the rest of this article on InformIT (free, no registration required)
While I was reading the Ruby Pickaxe book I came across an example of Unit Testing which – in my opinion – is testing implementation rather than behavior. This particular example was used to explain Duck Typing in Ruby, but I think it illustrates that it’s pretty easy to write tests which end up testing the wrong thing.
A Simple ExampleIn this example we have a simple Customer class.
class Customer
def initialize(first_name, last_name)
@first_name, @last_name = first_name, last_name
end
def append_name_to_file(file)
file << @first_name << " " << @last_name
end
end
Let’s go ahead and write a test for the append_name_to_file method. (I’m not a fan of doing testing this way – we really should write the test first, but let’s ignore that for a moment)
One way to test this would be to create an actual temporary file and pass that to the Customer object.
class TestCustomer < Test::Unit::TestCase
def test_customer_writes_full_name_to_file
customer = Customer.new("Mark","Twain")
File.open("Output.txt","w") do |file|
customer.append_name_to_file(file)
end
File.open("Output.txt") do |file|
assert_equal(file.read, "Mark Twain")
end
File.delete("Output.txt")
end
end
If I run the test I get the familiar success output. Hurrah!

Ok, so this test isn’t all that pretty. For one thing, there’s quite a lot of work going on just in order to get the test to run and to make sure the file we create is removed at the end. Even worse, when the test fails the final line of the test will not get executed and the temporary file is never removed! Using my knowledge of Exceptions I can fix that easily enough:
class TestCustomer < Test::Unit::TestCase
def test_customer_writes_full_name_to_file
begin
customer = Customer.new("Mark","Twain")
File.open("Output.txt","w") do |file|
customer.append_name_to_file(file)
end
File.open("Output.txt") do |file|
assert_equal(file.read, "Mark Twain")
end
ensure
File.delete("Output.txt")
end
end
end
I’ve taken care of the file being left behind when the test fails, but my test code is still pretty ugly. The author of the Pickaxe book now argues that we don’t really need to pass a file to the append_name_to_file method – we simply need to pass something which acts like a file. How about using a simple array?
class TestCustomer < Test::Unit::TestCase
def test_customer_writes_full_name_to_file
customer = Customer.new("Charles", "Dickens")
fake_file = []
customer.append_name_to_file(fake_file)
assert_equal(["Charles", " ", "Dickens"], fake_file)
end
end
The test passes, and the code is much simpler. Are we done?
The Implementation changesNot quite. Let’s say I’m working on the Customer class and I decide that I don’t really this C++ syntax – I would prefer to do a simple formatted string.
def append_name_to_file(file)
file << "#{@first_name} #{@last_name}"
end
Notice that I didn’t change the behavior, but when I run the test…

Uh-oh. The problem stems from the fact that we were testing the underlying implementation details, not the behavior. I didn’t check that the Customer object can write to a file, I tested that the Customer object uses the << method to write 3 different strings to the file object I pass to it.
One way to fix this would be to stop using an array and pass in a string. Let’s try that.
class TestCustomer < Test::Unit::TestCase
def test_customer_writes_full_name_to_file
customer = Customer.new("Jane", "Austen")
fake_file = ""
customer.append_name_to_file(fake_file)
assert_equal("Jane Austen", fake_file)
end
end
Once again our test passes, and the code is even simpler. Are we done? Well, let’s see – another developer is now working on the code and he/she is of the strong opinion that the only correct way to write to a file is to use the File#write method.
def append_name_to_file(file)
file.write "#{@first_name} #{@last_name}"
end
And we’re back to square one. Once again, I didn’t change the behavior of the method, but changing the implementation has broken the test. This is an example of fragile unit tests – tests which break when the code under test is still functionally correct. This is often a symptom of poorly designed tests.
What’s the Answer?So what’s the answer? Should we go back to using a temporary file? (Using a temporary file worked for all three implementations) Not really. I think in this case the problem is actually poor design and we’re struggling to test the code as a result. From an object-orientated perspective it doesn’t really make sense for a Customer object to have an append_name_to_file method. Any time you see a method taking an object and then doing something to it, it’s usually a code smell.
Let’s try and refactor this code. Instead of the Customer writing something to a file, I think it makes more sense for a Customer to have a method that returns their full name.
class Customer
def initialize(first_name, last_name)
@first_name, @last_name = first_name, last_name
end
def full_name
"#{@first_name} #{@last_name}"
end
end
Now it’s straightforward to write a test.
class TestCustomer < Test::Unit::TestCase
def test_customer_has_full_name
customer = Customer.new("John", "Milton")
assert_equal("John Milton", customer.full_name)
end
end
That’s only ONE solution
Ok, what should we do when we really do need to test interaction with a file?
Unfortunately, there is no silver bullet or golden rule here. If there was, this wouldn’t be an issue. We could possibly mock the behavior or maybe we really do need to use a temporary file. The only golden rule (in my opinion) is that we need to make sure we’re testing the right thing – behavior, not implementation. This leads to better, more maintainable tests – which will pay massive dividends in the long run.
If you want to play around with my example you can find it here. Happy coding.
Over the last couple of years several of my colleagues have been organizing code jam[1] events where developers get together to write software for charitable causes. A good example is a regular code-jam in New York that works on RapidFTR. Chris George, a ThoughtWorker based in New York, helped organize a one-off event in New York in August 2010. The group didn't get as much done on the day as they had hoped, but in a bar afterwards decided to try to get together more regularly. Since then they've been meeting every week. It's a small group, still mostly ThoughtWorkers and friends, with a core of 3-4 people rising to a dozen when we've had a big project in town.[2]. (Chris is happy to have more people join the group, so if you are interested drop him an email.)
Many people have found these events to an enjoyable way to use our skills for purposes that we find rather more fulfilling than many day jobs, and a way both to learn new skills and learn from a different group of people. So I thought I should share our thoughts on how to set one up.
The first thing is to find a suitable effort to contribute to. We look to contribute to projects producing open-source software for NGOs - the open source model fits well for such organizations. The two that we've built up most of a relationship are RapidFTR and OpenMRS. RapidFTR is a system designed to help reunite families after a natural disaster or other calamity. It allows people to quickly input information about either a lost child, or a child found without parents - then provide search facilities to match them up. OpenMRS is an open source medical records system, designed to support various forms of health care delivery work. It's used by many health care groups all over the world (and not just in the developing world).
Like New York, most of our code-jams begin as one-off events, a single evening or all day event. These days we advertise heavily, and hope to get a good sample of local developers to come along and take part. One-off code jams like this don't usually produce much useful software, since they are too short to really accomplish much. But they still have value. Firstly they generate awareness, exposing the local development community both to the specific project and the notion of working on open-source efforts for NGOs. More directly they can be the seed for an regular code jam, so it's useful to put together activities that will encourage getting back together later.
A regular code jam gets together on a schedule, with core of people who come most weeks. Such a group can make some significant contributions to a code base. People come because they get to work on some different technologies, with a different group of co-developers, to an audience that (unlike most open-source projects) isn't just other developers.
To make meaningful progress, you need someone to prepare for each code jam by breaking down work-items into something small enough that people will be able to finish them during the time at the jam. Whatever people may say and hope, they'll rarely work on the project outside code jam hours, and the schedule is too infrequent to want half-done things hanging over. Small tasks allow teams to make perceptible progress each jam - which helps keep motivation high. We like to put these tasks online before each event so people can prepare if they want to, or just get a feel for what we're working on. We also set up a mailing list to keep up regular communication on the jam and support anyone who does contribute outside of the jam.
Our regular code-jams succeed best when the group has a couple of champions who take the lead in organizing the event. It's best to have more than one champion, to cope with the work load and provide some resilience if they are absent for a while.
We try to ensure the development environment is set up to allow people to come in quickly and become productive. Much of this is the same kind of thing that we do on projects anyway to enable continuous integration - make sure that installation and build are automated so people can quickly install the code base and get it working. It's important to mention this in the advertisements for the event - people are often put off from coming due to a concern that they'll never get started due to these issues. Even so, make sure that each event has at least one person who is familiar with the code base and build environment, she can then help others find their way around. Often someone will give a short overview of what the system does and how it works for new people at the start of the jam.
We usually provide food to each event - that's an easy thing for us to do as a corporate contribution. As any XPer knows, sharing food when working is an important part of gelling a team.
So, if the idea of a code-jam appeals to you, why not give it a try? Find a suitable project to contribute to, a group of a few people to act as a core, and spend a few sessions to get things going. (There are developer guides for both OpenMRS and RapidFTR to help you get started if those projects appeal to you.) If you get going on a stable basis - post in a blog somewhere so we see what code-jams are avaialable and learn more about how to get them going.
1: "Code-jam" is a problematic name for these events. As far as I can determine, the term "code-jam" was originally used for competitive events where programmers would try to best their peers in some programming challenge. The events I describe here are the utter opposite of this, on many levels, but have attracted the same name.
2: When one of the team went down to our Porto Alegre office, he got a group contributing there too.
Ruby 1.8.7, Rails 2.3.8
I made a rookie mistake a few days ago but thanks to a colleague of mine who smacked me on the hand, I had a chance to correct it. Consider the following model:
class Order < ActiveRecord::Base belongs_to :account end
class Account < ActiveRecord::Base has_many :orders end
If you are retrieving a group of accounts and accessing each of its orders, you would be encountering an N + 1 query problem. Meaning you would be firing 1 query to retrieve 1 account, and if that account has N orders, N + 1 queries would be executed.
accounts = Account.find(:all, :limit => 10) accounts.each do |a| puts a.orders end
ActiveRecord uses default_scope to avoid the N + 1 situation.
class Account < ActiveRecord::Base default_scope :include => :order has_many :orders end
This will execute just 2 queries:
SELECT "accounts".* FROM "accounts" LIMIT 10 SELECT "orders".* FROM "orders" WHERE "orders"."account_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
The :include option can be used in a named scope as well. Long running queries are bad (of course), especially when you are dealing with tens of thousands of records.
Lesson well learnt (and remembered). Thanks Blake.
Generally when we are writing our automation test in Selenium or any other driver , the first thing we tend to do is start looking for object Id. Thought we have multiple ways of getting the hold of the object on a webpage like:
Id or name is the most simplest and easy to use locators. Advantages with them is it increases the readability of your test code. It’s also better than other locators in terms of test performance. If you are using lot of Id’s and your test code is becoming too clumsy then one suggested way of using Id’s would be to have a separate file and then probably you can rename them if they are not properly named in the page source (Google page “q” as their search box Id).
Link Text is mostly used with links and limited to that. They are easy to use. However they are a little problematic to maintain because of often changing link texts.
Next is the famous XPath, simple to use (if you are using Firebug or any other add-in to get it) but makes your test code look ugly. XPath should generally be used when the object is having neither Id nor name. Problem with XPath is when we run the test, browser runs it XPath processor to check if it can find any object, which actually impacts the performance. One important thing which we tend to forget while using XPath is, it ensures the order of elements. So it should be used to verify some object with respect to certain other object. One example could be to verify if “Today’s Deal” appears with in the header section of the Amazon home page.
DOM I haven’t used much so can’t comment on that.
As I mentioned in a post last week we’ve been automating the setup of our developer machines with puppet over the last week and one thing that we’ve learnt is that you need to be careful about how you define dependencies.
The aim is to get your scripts to the point where the outcome is reasonably deterministic so that we can have confidence they’re going to work the next we run them.
We noticed two ways in which we haven’t quite achieved determinism yet:
Accidental DependenciesThe first few times that we ran the scripts on top of a vanilla image we were doing it on a virtual machine which had VMware tools installed on it.
We’d forgotten that VMware tools had been installed on those VMs and ran into a problem with Oracle dependencies not being satisfied when we ran puppet on some machines which had CentOS installed directly (i.e. not on a virtual machine).
Those dependencies had been satisfied by our VMware tools installation on the VMs so we didn’t realise that we hadn’t explicitly stated those dependencies, something which we have done now.
External DependenciesWe couldn’t find the Firefox version that we wanted install on the default yum repositories so we created a puppet task which linked to a Firefox RPM on an external server and then installed it.
It worked originally but at some stage over the last couple of weeks the URI was changed as a minor version had been upgraded, breaking our script.
We also came across another way that external dependencies can fail today – if a corporate proxy blocks access to the URL!
We’re trying to get to the stage where we’re only relying on artifacts either coming from a yum repository or an internal repository where we can store any libraries which aren’t available through yum.
Don’t assume determinismWhile trying to solve these dependency problems in our puppet scripts I made the mistake of assuming that if the script runs through once and works that it’s always going to be that way in the future.
Since we had achieved that previously in my mind it was impossible for it to fail in future which stopped me from properly investigating why it had stopped working.
This past month I was on a 1000km door-to-door drive from Bangalore to Pune. On the way, I was able to photograph two beautiful raptors - a black shouldered kite and a white-eyed buzzard. Note this - I wasn't on a photography trip and most people won't be looking for photography opportunities on Indian highways. All said and done though, the opportunities did present themselves and I have some decent photos to show for. Photography is quite like that - readiness is a big strength. They say that luck is when preparation meets opportunity and this couldn't be truer for photography. If you want great photographs you need to have a camera with you. If your camera is always at home, you'll miss a lot of photo worthy moments. And mind you, it doesn't always need to be your entire camera kit. Even a phone camera is often a great tool to have for photo-journalism. Just remember to carry it with you; so when the momen presents itself, you're always ready. As an elearning developer or an instructional designer, you'll perhaps notice a lot of photo-worthy moments in the office that are worth preserving. I can't tell you how many candid photographs that I've randomly taken in the office came out to be useful in presentations, courses and in-person training sessions.
(Click for a larger image)Take a look at the before and after on this picture. Remember that not every photo opportunity will give you brilliant light in the right direction, with a very cooperative subject. This barn owl is my neighbour. I see the family every evening when I'm out for a run with my dog. The big problem though, is they're owls - they're nocturnal. In particular, I've never seen this family during the day or even in the twilight hours. I only see them at times when the light is poor. Now what should I do if I see this owl come and sit in the light of the street lamp, on a fairly good perch? Not take the shot? So well, I took the shot but as you can see, it wasn't much to write home about. Thankfully I was shooting in RAW. Before I tell you what I did, let me tell you what a RAW file is.In my last post I had a look at handling exceptions in Ruby and the functionality around that. In this post I’m going to look at how Ruby also allows us to unwind a single block of code without raising an exception. I’ve said before that exceptions should be exceptional – the functionality in Ruby offers a lightweight version of this within a single scope.
Let’s see some codeThis is much easier to explain with an example.
def get_number
rand(100)
end
random_numbers = catch (:random_numbers) do
result = []
10.times do
num = get_number
throw :random_numbers if num < 10
result << num
end
result
end
p random_numbers
The catch keyword defines a block with a given name. The block is processed normally until a throw statement is encountered.
When a throw statement is encountered Ruby will look up the call stack for a catch statement with the corresponding symbol. It will then unwind the call stack up to that point and terminate the block.
In this example the block will have two possible return values. If no number under 10 is generated the throw statement will never execute and the array of random numbers will be returned. If the throw statement does execute the block will simply return nil. Ruby also allows us to override this behavior – for example, instead of returning nil I might choose to return an empty array. We can do this by specifying a second parameter to the throw statement.
random_numbers = catch (:random_numbers) do
result = []
10.times do
num = get_number
throw(:random_numbers, []) if num < 10
result << num
end
result
end
Performance
One of the reasons why it’s possibly not a good idea to overuse exceptions in your code is performance. Every time you raise an exception Ruby has to build a stack trace. If your exceptions are exceptional (as they should be) this won’t be a problem. However, if you’re using a large number of exceptions in a tight loop it could have a negative impact on performance. I’m assuming that a catch-throw block doesn’t need to create a stack trace – let’s see if we can get a rough idea of the performance impact.
start = Time.now
10_000_000.times do |i|
begin
raise StandardError, "Error #{i}"
rescue StandardError => error
error.inspect
end
end
puts "Raise&Rescue Operation took #{Time.now - start} seconds"
start = Time.now
10_000_000.times do |i|
catch (:the_loop) do
throw :the_loop
end
end
puts "Catch&Throw Operation took #{Time.now - start} seconds"

As I mentioned, these are very rough performance estimates, but there does seem to be a significant performance difference between using exceptions and using a catch-throw block.
ConclusionThe catch-throw block seems to be a lightweight error handling mechanism – useful when you want to jump out of a nested construct during normal processing. The performance figures point to the same conclusion.
If you want to play around with my example you can find it here. Happy coding.
I like Exceptions. They’re a very useful concept for raising and handling errors at the correct level without cluttering our code. Coming from C# the way Exceptions work in Ruby are intuitive to me, but there are actually a few extra features which aren’t available in the .NET world.
Basics FirstTo illustrate Exceptions, I’ve created a very simple class that simulates interaction with a remote resource.
class RemoteResource
def initialize
@users = Hash.new
@users["Malcolm"] = "password1"
@users["Angus"] = "password1"
@users["Phil"] = "password1"
@users["Cliff"] = "password1"
@users["Brian"] = "password1"
end
def create_connection(username,password,secure=false)
unless @users[username] && @users[username] == password
raise ArgumentError.new("Invalid username or password")
end
raise SecurityError.new("Secure connections are unavailable") if secure
@connection_initialized = true
end
def get_resource
unless @connection_initialized
raise SecurityError.new("A connection has not been established")
end
raise StandardError.new("An unknown error has occurred") if rand(3) == 0
"Widget #{rand(11)}"
end
end
Let’s see what happens when we raise a simple exception.
remote_resource = RemoteResource.new
remote_resource.create_connection("Kurt","password1")

As you would probably expect, our little application exits immediately and reports the type and message of the exception that was raised. So far so good.
Handling ExceptionsLet’s see how we handle an exception.
remote_resource = RemoteResource.new
begin
remote_resource.create_connection("Kurt","password1")
rescue Exception => error
print "Could not create connection: #{error}\n"
end
Pretty neat. This is probably not very good code, since we’re handling the global Exception class which is bad practice – we should try to handle only specific Exception classes.
remote_resource = RemoteResource.new
begin
remote_resource.create_connection("Malcolm","password1", true)
rescue ArgumentError => argument_error
print "Could not create connection: #{argument_error}\n"
rescue SecurityError => security_error
print "Could not create secure connection: #{security_error}\n"
end

We can also handle multiple Exception classes in one block.
remote_resource = RemoteResource.new
begin
remote_resource.create_connection("Malcolm","password1", true)
rescue ArgumentError, SecurityError => error
print "Could not create connection: #{error}\n"
end
Ensure code is executed
We can also ensure that a block of code is executed – for example, we might want to add some logging code around the accessing of the remote resource.
remote_resource = RemoteResource.new
remote_resource.create_connection("Malcolm","password1")
print "Connection created at #{Time.now}\n"
begin
result = remote_resource.get_resource
rescue SecurityError => error
print "Error using connection: #{error}\n"
ensure
print "Resource released at #{Time.now}\n"
end

As the name implies, ensure ensures that a certain block of code is executed – as you can see from the output. C# users will immediately recognize a strong similarity to the finally keyword in .NET.
Ruby also introduces the else clause – this will only execute if no errors were encountered. The else clause must go before the ensure clause and after any rescue clauses.
remote_resource = RemoteResource.new
remote_resource.create_connection("Angus","password1")
print "Connection created at #{Time.now}\n"
begin
result = remote_resource.get_resource
rescue SecurityError => error
print "Error using connection: #{error}\n"
else
print "The connection was accessed without any errors\n"
ensure
print "Resource released at #{Time.now}\n"
end
This is probably quite useful in certain scenarios.
Retry the blockRuby also allows us to correct the cause of the exception and retry the block. For example, since my remote resource is a little unstable I might choose to retry the block until the resource is returned.
remote_resource = RemoteResource.new
remote_resource.create_connection("Angus","password1")
begin
result = remote_resource.get_resource
print "#{result}\n"
rescue SecurityError => error
print "Error using connection: #{error}\n"
rescue StandardError => error
print "Error accessing remote resource - #{error}\n"
retry
end

As you might imagine, it’s one of the easiest ways of creating an infinite loop so use with care. In fact, I actually managed to create an infinite loop while writing this post!
ConclusionAs someone coming from C# the Exception handling in Ruby seems very intuitive to me. The additional functionality (else and retry) could also be very useful in certain scenarios.
If you want to play around with my example you can find it here. Happy coding.
As part of the Test Automation Bazaar minesweeper challenge, a colleague and I developed a CoffeeScript implementation of minesweeper. We wanted to use a test first approach to writing our CoffeeScript, so we decided to use Jasmine.
Setting up a development environment
Even though we were developing the application in CoffeeScript, which generates JavaScript, we found it easy to use a simple ruby environment to boostrap these tools. Our environment therefore looked something like this:
Specifying a Guardfile
A Guardfile consists of a bunch of guards that perform actions whenever a file is modified in that location. Our Guardfile looked like:
guard 'coffeescript', :output => 'javascripts' do watch /^coffeescripts\/.*[.]coffee/ end guard 'coffeescript', :output => 'spec/javascripts' do watch /^spec\/coffeescripts\/.*[.]coffee/ end guard 'sass', :input => 'stylesheets'
Writing a Jasmine specification in CoffeeScript
A Jasmine spec in CoffeeScript looked something like this:
describe 'GameState', ->
game_state = null
field = Field.new mineCount: 1, rows: 1, cols: 3
beforeEach ->
game_state = GameState.new field
it 'should initialise lost to false', ->
expect(game_state.lost()).toEqual false
it 'should initialise won to false', ->
expect(game_state.won()).toEqual false
it 'should initialise remaining_mines to mine_count', ->
expect(game_state.remaining_mines()).toEqual 1
it 'should initialise remaining_mines to mine_count', ->
expect(game_state.remaining_cells()).toEqual 2
Running Jasmine tests
The jasmine gem makes it very easy to run your jasmine tests. There’s a rake task called ‘jasmine’ which you can run to launch a jasmine server locally on port 8888. If you browse to that page, you’ll see something like this:

Test First CoffeeScript development
Now that you have Jasmine running, and Guard generating the CoffeeScript, it’s easy to write a new spec, refresh the Jasmine browser page to run all your tests (in our case in a third of a second) and then write the code to make it pass.
Automatically running Jasmine tests on Travis CI
If you’ve got your CoffeeScript and Jasmine on github, it’s trivial to automatically run all your Jasmine tests using the Jasmine::Ci rake task on Travis CI. All you need is a .travis.yml file like:
language: ruby rvm: - 1.9.2 env: - DISPLAY=:99.0 before_install: sh -e /etc/init.d/xvfb start
Once you add the project to travis, it’ll automatically run whenever you push. Magic.
Lessons Learned
I hope you enjoy your CoffeeScript test driven development with Jasmine.
ThoughtWorks embraces the individuality of the people in the organization and hence the opinions expressed in the blogs may contradict each other and also may not represent the opinions of ThoughtWorks.