Typo-checking instead of static typing

B

Ben Giddings

Once again, static typing reared its head on the mailing list, and once
again, the knights of the Ruby table slayed the beast... but it will
return. The wheel of time continues to turn and the beast will return
again.

But really, when people talk about "static typing", what is it they
*really* want. What does static typing buy you? I'd argue it's simple.

Static typing tends to find typos and brainos in code before it's executed.

It's as simple as that. I don't need to talk about the various down sides
to static typing here, but that upside is particularly important when
there are bits of code that might very rarely be executed.

So the real question is: in a dynamic, strongly typed language like Ruby,
how do you find typos and brainos in code that your app may very rarely
use?

The stock answer here is "unit tests", but honestly, I never bought that
answer. Maybe it's because too often I deal with things that are
incredibly difficult to unit test, i.e. GUIs, external data sources,
unreliable networks, opaque 3rd-party interfaces and other things which
are very difficult to mock out. It isn't to say they aren't testable,
just that they're really hard to test well.

My open question is then: how do you find typos and brainos in seldom-run
code in a dynamic language like Ruby?

(And maybe we can use the answers next time the monster rears its head)

Ben
 
C

Curt Hibbs

Ben said:
Once again, static typing reared its head on the mailing list, and once
again, the knights of the Ruby table slayed the beast... but it will
return. The wheel of time continues to turn and the beast will return
again.

But really, when people talk about "static typing", what is it they
*really* want. What does static typing buy you? I'd argue it's simple.

Static typing tends to find typos and brainos in code before it's executed.

It's as simple as that. I don't need to talk about the various down sides
to static typing here, but that upside is particularly important when
there are bits of code that might very rarely be executed.

So the real question is: in a dynamic, strongly typed language like Ruby,
how do you find typos and brainos in code that your app may very rarely
use?

The stock answer here is "unit tests", but honestly, I never bought that
answer. Maybe it's because too often I deal with things that are
incredibly difficult to unit test, i.e. GUIs, external data sources,
unreliable networks, opaque 3rd-party interfaces and other things which
are very difficult to mock out. It isn't to say they aren't testable,
just that they're really hard to test well.

My open question is then: how do you find typos and brainos in seldom-run
code in a dynamic language like Ruby?

(And maybe we can use the answers next time the monster rears its head)

As I read this, I immediately imagined parsing all the individual tokens
in a set of Ruby programs, and counting the number of occurrences of
each. Tokens that appear infrequently (like once) are likely to be typos.

This idea, with a little more smarts added, could be used to detect
potential typos.

Curt
 
S

SER

Once again, static typing reared its head on the mailing list, and
once
again, the knights of the Ruby table slayed the beast...

It would be more accurate to say that the Knights claimed the beast
was:

1) impossible to implement
2) insignificant
3) not really a beast

largely in that order.

--- SER
 
J

James Britt

Ben said:
Once again, static typing reared its head on the mailing list, and once
again, the knights of the Ruby table slayed the beast... but it will
return. The wheel of time continues to turn and the beast will return
again.

But really, when people talk about "static typing", what is it they
*really* want. What does static typing buy you? I'd argue it's simple.

Static typing tends to find typos and brainos in code before it's executed.

It's as simple as that. I don't need to talk about the various down sides
to static typing here, but that upside is particularly important when
there are bits of code that might very rarely be executed.

The arguments I've heard for static typing rarely focus on catching
finger farts. Yes, that's a part of it, but the essence seems to be a
desire for some assurance that not only does code compile and that
objects respond to specific messages, but that the resulting behavior
will match certain expectations.

(Oh, and speed is another argument.)
So the real question is: in a dynamic, strongly typed language like Ruby,
how do you find typos and brainos in code that your app may very rarely
use?

-w ?
-c ?

Comprehensive unit tests?

James
 
E

Eric Hodel

The stock answer here is "unit tests", but honestly, I never bought
that
answer. Maybe it's because too often I deal with things that are
incredibly difficult to unit test, i.e. GUIs, external data sources,
unreliable networks, opaque 3rd-party interfaces and other things which
are very difficult to mock out. It isn't to say they aren't testable,
just that they're really hard to test well.

My open question is then: how do you find typos and brainos in
seldom-run
code in a dynamic language like Ruby?

Yes, unit tests and ruby -w. I wrote the thing in the 'I Rock.' post
between midnight and 4am. As you can imagine, writing code tired is
fraught with crazy typos, but the unit tests found them all.

When I was almost done, I spent 15 minutes on a 1 character typo (rrc
in one spot, rcc in another). I didn't have a unit test for that case.
 
J

John Carter

It would be more accurate to say that the Knights claimed the beast
was:

1) impossible to implement


http://rubyforge.org/snippet/detail.php?type=snippet&id=47

Description:
Searches through all defined symbols for near misses in namespace.
Hopefully some of those listed will be mispelling bugs.

Usage :-
ruby -w Mispel.rb

Will run its unit tests.

ruby -rmodule1 -rmodule2 -rmodule... Mispel.rb --cache

Will create ~/.mispel_ignore, a list of known near misses in the
system and in those modules.

If you add into your script, after all require statements...

require 'Mispel'
Mispel::problem_cases
exit(1)

It will (after a long time) print out all near misses in namespace
that are not in ~/.mispel_ignore


John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand


Somewhere on the edge of a Galaxy, one of literally billions of such
galaxies, is a sun, one of literally billions of suns in that
galaxy.

Orbiting that sun is a small rock 330000 times smaller than that
sun.

This rock is covered by a very very thin scum of life. (Think 6000km
of rock followed by a meter or so of biomass.)

Amongst the millions of species in that scum are many hundreds of
thousands of types beetle and a mere handful of primates.

Surprisingly enough, this email does not originate from a beetle.

It originates from just one of the 6 billion vastly outnumbered humans.

I trust you will keep this perspective and context in mind when
reacting to this email.
 
H

Hal Fulton

Eric said:
Yes, unit tests and ruby -w. I wrote the thing in the 'I Rock.' post
between midnight and 4am. As you can imagine, writing code tired is
fraught with crazy typos, but the unit tests found them all.

When I was almost done, I spent 15 minutes on a 1 character typo (rrc in
one spot, rcc in another). I didn't have a unit test for that case.

Let me put in a plug for code coverage tools in general.
Combined with good unit tests, these are truly invaluable.

There's a good one out there, but I forget what it's called --
<admission>I don't use it much, I've only played with it.</admission>


Hal
 
E

Eric Hodel

Let me put in a plug for code coverage tools in general.
Combined with good unit tests, these are truly invaluable.

There's a good one out there, but I forget what it's called --
<admission>I don't use it much, I've only played with it.</admission>

ZenTest?

PS: ZenTest comes, free of charge, with unit_diff, which is the
spiffiest test running helper tool ever. It runs your actual/expected
outputs through diff helping you spot the differences in massive
structures. Or even small ones of one or two lines.
 
H

Hal Fulton

Eric said:
ZenTest?

PS: ZenTest comes, free of charge, with unit_diff, which is the
spiffiest test running helper tool ever. It runs your actual/expected
outputs through diff helping you spot the differences in massive
structures. Or even small ones of one or two lines.

I don't know ZenTest. I was thinking of rcov or whatever
it is called. Was it Simon S who took that over??


Hal
 
P

pat eyler

PS: ZenTest comes, free of charge, with unit_diff, which is the
spiffiest test running helper tool ever. It runs your actual/expected
outputs through diff helping you spot the differences in massive
structures. Or even small ones of one or two lines.

unit_test is awesome! Here's an example from an article I wrote
recently (to be published soon) -- first without unit_test, then the
same thing with unit_test.

$ ruby ts_long.rb
Loaded suite ts_long
Started
F
Finished in 0.02506 seconds.

1) Failure:
test_long(TestLong) [ts_long.rb:33]:
&lt;"If you use open source software, you're sure to brush up against
some of its rough edges. It may be a bug, or a place where the
documentation isn't clear (or doesn't exist), or maybe it's not
available in your language.\n\nIf you want to give back to the
community, you can work on any of these problems, even if you're not a
programmer.\n\nYou could write a bug report for the developers (and
submit a patch if you're a programmer).\n\nYou could write or extend
existing documentation.\n\nIf you're really up for a challenge, you
could even work on translating the application and/or
documentation.\n\nHowever you choose to get involved, you should start
by contacting the developers."&gt; expected but was
&lt;"If you use open source software, you're sure to brush up against
some of its rough edges. It may be a bug, or a place where the
documentation isn't clear (or doesn't exist), or maybe it's not
available in your language.\n\nIf you want to give back to the
community you can work on any of these problems, even if you're not a
programmer.\n\nYou could write a bug report for the developers (and
submit a patch if you're a programmer).\n\nYou could write or extend
existing documentation.\n\nIf you're really up for a challenge, you
could even work on translating the application and/or
documentation.\n\nHowever you choose to get involved, you should start
by contacting the developers."&gt;.

1 tests, 1 assertions, 1 failures, 0 errors
$ ruby ts_long.rb | unit_diff.rb
Loaded suite ts_long
Started
F
Finished in 0.017676 seconds.

1) Failure:
test_long(TestLong) [ts_long.rb:33]:
3c3
&lt; If you want to give back to the community, you can work on any of
these problems, even if you're not a programmer.
 
P

pat eyler

unit_test is awesome! Here's an example from an article I wrote
recently (to be published soon) -- first without unit_test, then the
same thing with unit_test.
[lots of test result stuff snipped]
oops, all that was all prepped for xml, so replace the &gt; and &lt;
characters as needed :)
 
N

Nick Woolley

Ben said:
My open question is then: how do you find typos and brainos in seldom-run
code in a dynamic language like Ruby?

At the risk of being jeered: I have found perl's 'use strict' with 'my'
declarations have helped keep my feet unshot in the past. It won't get
everything, but misspelt variables won't pop into existance behind your
back. Conversely, javascript has always spent me to deadline hell with
just this sort diabolical mischief (grr).

I've always wondered why ruby doesn't have somthing similar. Presumably
there's some flaw/objection to the idea of having this? But! surely
this is exactly what Ben is asking for?

Also, conceivably, couldn't (optional) implicit run-time checks be added
which match the declared 'type' of an assignee variable to the current
type of the assigned object? No type inference, just a little extra
runtime overhead (which could be switched off). And/or similar optional
preconditions on method arguments?

e.g.

Fruit var1 = Banana.new # ok
Flesh var2 = Sausage.new # ok
Object var3 = Hamster.new # no checks on this var
var3 = var2 # so, Sausages are okay here
var3 = var1 # so are Bananas
var1 = var2 # but not here, cos Sausages aren't Fruit - bang!
var4 = 0 # var4 isn't predeclared - bang!

Um, this seems so obvious I am expecting someone to reveal my
cluelessness imminently.

Nick
 
H

Hal Fulton

Nick said:
Also, conceivably, couldn't (optional) implicit run-time checks be added
which match the declared 'type' of an assignee variable to the current
type of the assigned object? No type inference, just a little extra
runtime overhead (which could be switched off). And/or similar optional
preconditions on method arguments?

e.g.

Fruit var1 = Banana.new # ok
Flesh var2 = Sausage.new # ok
Object var3 = Hamster.new # no checks on this var
var3 = var2 # so, Sausages are okay here
var3 = var1 # so are Bananas
var1 = var2 # but not here, cos Sausages aren't Fruit - bang!
var4 = 0 # var4 isn't predeclared - bang!

Um, this seems so obvious I am expecting someone to reveal my
cluelessness imminently.

It's not a question of cluelessness, but I would state it
this way: Absence of explicit typing and variable declarations
are two of Ruby's best features, and they are foundational in
its design.


Hal
 
R

Robert Klemme

SER said:
It would be more accurate to say that the Knights claimed the beast
was:

1) impossible to implement
2) insignificant
3) not really a beast

largely in that order.

Thanks for that comprehensive summary. However I don't fully agree: in
Ruby land it *is* a beast - although it's not in Eiffel land. Note:
context matters. :)

Kind regards

robert
 
J

Joost Diepenmaat

http://rubyforge.org/snippet/detail.php?type=snippet&id=47

Description:
Searches through all defined symbols for near misses in namespace.
Hopefully some of those listed will be mispelling bugs.

It's also interesting to note that perl does a simpler (but surprisingly
effective) check if you enable warnings:

code:

#!/usr/bin/perl -w

$a = 1;

print $aa + 3;



output:

Name "main::a" used only once: possible typo at test.pl line 3.
Name "main::aa" used only once: possible typo at test.pl line 5.
Use of uninitialized value in addition (+) at test.pl line 5.
3


Joost.
 
J

Jon A. Lambert

Ben said:
Static typing tends to find typos and brainos in code before it's
executed.

My most frequent Ruby error:
"NoMethodError: undefined method `foo' for nil:NilClass"

Not a typo, and arguably anything is a braino.

Fixed by asking oneself two questions
1) How in sam hill did that get set to nil?
2) Can method bar can return nil, if blah blah foozle wimble?
 
C

Charles Mills

Hal said:
case.

Let me put in a plug for code coverage tools in general.
Combined with good unit tests, these are truly invaluable.

There's a good one out there, but I forget what it's called --
<admission>I don't use it much, I've only played with it.</admission>


Hal

Are there any code coverage tools for Ruby?

-Charlie
 
J

Joe Van Dyk

My most frequent Ruby error:
"NoMethodError: undefined method `foo' for nil:NilClass"

Not a typo, and arguably anything is a braino.

Fixed by asking oneself two questions
1) How in sam hill did that get set to nil?
2) Can method bar can return nil, if blah blah foozle wimble?

That's about my most common error too (it ties with a parse error due
to a missing 'end' statement).
 
H

Hal Fulton

Joe said:
That's about my most common error too (it ties with a parse error due
to a missing 'end' statement).

Yes. Most languages just shift this "boundary problem" into
different paradigms and terminology.

In Java, the "pointerless language," the most common runtime
error is "NULL pointer exception."

Or in Pascal, "Attempt to dereference nil pointer."

Or in C, "Segmentation fault."


Hal
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top