Saturday, August 29, 2015

Fail Early and Loudly

One of the things I learned the hard way is that a software should fail loudly. If you fail silently, it becomes very difficult to find the cause of the problem and fix it quickly. Raise exception as close as possible to the failure so that we can quickly figure out the issue. The exception should contain all the relevant data, the location and the likely cause of failure.

The concept of failing loudly is discussed in the Code Complete 2 book by Steve McConnell. If you just read the theory, you need to expose yourself to that theory repeatedly so that you will be able to apply it in practice. If you learn by experience it becomes easier to grasp that theory quickly and you will never forget it.

Example 1:

One of the gems that I developed requires Ruby 2.2.2 or above. When I did:

$ gem install merlot
Fetching: posix-spawn-0.3.11.gem (100%)
Building native extensions.  This could take a while...
Successfully installed posix-spawn-0.3.11
Fetching: pdf-core-0.6.0.gem (100%)
Successfully installed pdf-core-0.6.0
Fetching: ttfunk-1.4.0.gem (100%)
Successfully installed ttfunk-1.4.0
Fetching: prawn-2.0.2.gem (100%)
Successfully installed prawn-2.0.2
Fetching: merlot-0.1.0.gem (100%)t.1.0.gem
ERROR:  Error installing merlot:
merlot requires Ruby version >= 2.2.2.

Boom! The command fails at the very last step. It does not fail early. The precondition must be checked before wasting time by installing all the dependent gems.

Example 2 :

I turned off my WiFi and did:

$ gem install bacardi
ERROR:  Could not find a valid gem 'bacardi' (>= 0), here is why:
          Unable to download data from https://rubygems.org/ - no such name (https://rubygems.org/specs.4.8.gz)

The error message I receive has no indication on how the user can recover from this problem. Ideally, we want our software to check for the precondition to be satisfied. In this case, a valid Internet connection. This also happens when I am at Starbucks and I have connected to the WiFi but I have not agreed to the terms and conditions. Wouldn't it be better to catch this particular exception and provide a clear message to the user like:

'We have detected a problem with your Internet connection. Please check your connection and try again.'.

The software we develop following this principle would be user friendly and robust under abnormal conditions.

Example 3 :

I worked on a Rails project where one of the gems in the Gemfile used a private gem repository on github. The Gemfile used :github to specify the private gem location, when I ran bundle install, I got the error:

Fetching gem metadata from https://rubygems.org/.Retrying dependency api due to error (2/4): Bundler::HTTPError Network error while fetching 

https://bundler.rubygems.org/api/v1/dependencies?gems=rack-netscaler,rack-timeout,sprockets-rails,rails,rainbow,rdoc,ref,rspec-support,rspec-expectations,rspec-collection_matchers,rspec-core,rspec-example_steps,rspec-mocks,rspec-rails,ruby-progressbar,rubocop,rubyzip,sass-rails,sdoc,websocket,selenium-webdriver,simplecov-html,simplecov,spring,therubyracer,typhoeus,uglifier,vcr,vcr-helper,web-console,webmock

The actual error message has nothing to do with the cause. It turns out that I did not have access to that repository and the admin had to add me as one of the contributor to that repository. Wouldn't it be nice, if either the Bundler or the Github API provided a clear message stating the cause and how to fix it by providing a link for reference? 

No comments:

Post a Comment