This is probably the less useful mail ever, since it just goes over a
topic that has been explained over and over and still pops us in almost
every single meeting.

Let me say it again: 98% of the "undefined method `xxx' for
nil:NilClass" errors are NOT related AT ALL to Ruby being dynamically
typed and would NOT be prevented by the usage of a statically typed
language.

And the other side of the same recurring coin - we don't write unit
tests as a replacement for the compiler checks. That's not the point,
the goal or the intention of the unit tests.

This time I will try to explain it with an example (something that
already has been done, but I just felt impelled to do it one more time).

Let's say you have this Ruby method that returns an object of type
Device or nil if the device was not found

find_device_by_name(name)

And then you write this code

dev = find_device_by_name("/dev/sda")
puts dev.size

If there is no /dev/sda that will result in one of those "undefined
method `size` for nil:NilClass" that some people hate so much. Did it
happen because Ruby is dynamically typed? NOT AT ALL. It happened
because you didn't check for the situation in which the device is not
there with some code like this.

dev = find_device_by_name("/dev/sda")
if dev
  puts dev.size
else
  puts "No such device"
end

Let's do the same in an hypothetical typed Ruby in which there is
nothing like nil. Now your find_device_by_name method will raise a
NotFound exception instead of returning nil if the device is not there
(the approach we use in statically typed languages).

The first example will still fail, now with an uncaught NotFound
exception. The static type checking performed by the compiler didn't
save us from THE DEVELOPER ERROR and the result is pretty much the same
- an exception thrown in the user's face.

In this case, the correct solution is pretty similar to the real
(dynamic) Ruby one

begin
  dev = find_device_by_name("/dev/sda")
  puts dev.size
rescue NotFound
  puts "No such device"
end

Both errors are the same error, a programmer error. Both errors happen
during runtime, just the raised exception is different. In Ruby, the
error is revealed in a slightly different way that it would be revealed
in a static language. But that's the whole difference. Static type
checking would not save you in 98% of the cases.

What can save us in both cases? Comprehensive unit tests. Because they
have a completely different goal from the checks performed by the
compiler and they should spot a different kind of errors. Of course,
that implies that whoever is writing the tests thinks in all possible
situations (like the device not being there) and covers those situations
with tests. That's why unit tests are a must in both dynamically and
statically typed languages.

If you think in your unit tests as a replacement of the static type
checking... you will very likely not write the right unit tests.

And please, stop assuming that every single "undefined method" error is
caused by a missing type check.

Cheers.
-- 
Ancor González Sosa
YaST Team at SUSE Linux GmbH
-- 
To unsubscribe, e-mail: [email protected]
To contact the owner, e-mail: [email protected]

Reply via email to