back to listing index

5-2-03 Strong Typing vs. Strong Testing - Google Docs

[web search]
Original source (docs.google.com)
Tags: types bruce-eckel technical-reading
Clipped on: 2014-12-27

To enable screen reader support, press shortcut ⌘+Option+Z. To learn about keyboard shortcuts, press shortcut ⌘slash.
5-2-03 Strong Typing vs. Strong Testing 
(A more accurate title would be "Static Checking vs. Strong Testing"). 
 
In recent years my primary interest has become programmer productivity. 
Programmer cycles are expensive, CPU cycles are cheap, and I believe that 
we should no longer pay for the latter with the former. 
 
How can we get maximal leverage on the problems we try to solve? 
Whenever a new tool (especially a programming language) appears, that 
tool provides some kind of abstraction that may or may not hide needless 
detail from the programmer. I have come, however, to always be on watch 
for a Faustian bargain, especially one that tries to convince me to ignore all 
the hoops I must jump through in order to achieve this abstraction. Perl is 
an excellent example of this — the immediacy of the language hides the 
meaningless details of building a program, but the unreadable syntax 
(based, I know, on backwards-compatibility with Unix tools like awk, sed and 
grep) is a counterproductive price to pay. 
 
The last several years have clarified this Faustian bargain in terms of more 
traditional programming languages and their orientation towards strong type 
checking. This began with a 2-month love affair with Perl, which gave me 
productivity through rapid turnaround. (The affair was terminated because of 
Perl's reprehensible treatment of references and classes; only later did I see 
the real problems with the syntax.) Issues of strong-vs-weak typing were 
not visible with Perl, since you can't build projects large enough to see these 
issues and the syntax obscures everything in smaller programs. 
 
After I had worked with Python (free at www.Python.org) for awhile — a 
language which can build large, complex systems — I began noticing that 
despite an apparent carelessness about type checking, Python programs 
seemed to work quite well without much effort, and without the kinds of 
problems you would expect from a language that doesn't have the strong, 
static type checking that we've all come to "know" is the only correct way of 
solving the programming problem. 
This became a puzzle to me: if strong static type checking is so important, 
why are people able to build big, complex Python programs (with much 
shorter time and effort than the strong static counterparts) without the 
disaster that I was so sure would ensue? 
 
This shook my unquestioning acceptance of strong type checking (acquired 
when moving from C to C++, where the improvement was dramatic) enough 
that the next time I examined the issue of checked exceptions in Java, I 
asked "why"? which produced a big discussion wherin I was told that if I 
kept advocating unchecked exceptions, cities would fall and civilization as we 
know it would cease to exist. In Thinking in Java, 3rd edition, I went ahead 
and advocated the use of RuntimeException as a wrapper class to "turn 
off" checked exceptions. Every time I do it now, it seems right (I note that 
Martin Fowler came up with the same idea at roughly the same time), but I 
still get the occasional email that warns me that I am violating all that is 
right and true and probably the USA Patriot act, as well (hi, all you guys 
from the FBI! Welcome to my weblog!). 
 
But deciding that checked exceptions seem like more trouble than they're 
worth (the checking, not the exception. I believe that a single, consistent 
error reporting mechanism is essential) did not answer the question "why 
does Python work so well, when conventional wisdom says it should produce 
massive failures?" Python and similar "weak" or "latently" typed languages 
are very lazy about type checking. Instead of putting the strongest possible 
constraints upon the type of objects, as early as possible (as C++ and Java 
do), languages like Ruby, Smalltalk and Python put the loosestpossible 
constraints on types, and evaluate types only if they have to. That is, you 
can send any message to any object, and the language only cares that the 
object can accept the message — it doesn't require that the object be a 
particular type, as Java and C++ do. For example, if you have pets that can 
speak in Java, the code looks like this: 
 
// Speaking pets in Java: 
interface Pet { 
  void speak(); 
} 
 
class Cat implements Pet { 
  public void speak() { System.out.println("meow!"); } 
} 
 
class Dog implements Pet { 
  public void speak() { System.out.println("woof!"); } 
} 
 
public class PetSpeak { 
  static void command(Pet p) { p.speak(); } 
  public static void main(String[] args) { 
Pet[] pets = { new Cat(), new Dog() }; 
for(int i = 0; i < pets.length; i++) 
  command(pets[i]); 
  } 
} 
 
Toggle screen reader support