Summary:
Bruce Eckel talks with Bill Venners about why he prefers Python's latent type checking and techie control of language evolution.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: January 11, 2006 6:58 AM by
|
Bruce Eckel says, "Once I get the program running, I feed it real data. Then I'm going to find some interesting errors. So the sooner I can do that, the sooner I can find those errors." Read this Artima.com interview with Bruce Eckel: http://www.artima.com/intv/typing.htmlWhat do you think of Bruce's comments?
|
|
|
I missed one point in the discussion about runtime vs. compiletime type-checking and that is the self-documenting effect when I explicitly specify the types I use.
I think this is much more communicating:
public Configuration getConfiguration(File file) throws IOException
than
def getConfiguration(file)
|
|
|
I started using Python three weeks ago and I like it very much. I tried to convince my colleagues to switch to Python, but the biggest problem is the "type checking" issue. Runtime type checking just scared them away. Bruce Eckel's arguments are not so convincing to them(even not to me myself, and I like Python and Thinking in XXX). Hope somebody could make a top ten list about why runtime type checking is GOOD(or not that BAD).
|
|
|
> I missed one point in the discussion about runtime vs. > compiletime > type-checking and that is the self-documenting effect when > I explicitly specify the types I use. > > I think this is much more communicating: > > > public Configuration getConfiguration(File file) throws > IOException >
Hmm... looks kind of redundant to me... Also, to increase the redundancy further, you may want to write several versions of this same method in Java; one that takes a BufferedReader, one that takes a String filename, etc. > than > > def getConfiguration(file) >
What about this? def getConfiguration(configFile): 'Reads the specified file and returns a Configuration object; throws IOException.'
|
|
|
> Hope somebody could make a top ten list about why runtime > type checking is GOOD(or not that BAD).
I don't know about a top ten list, but when I first started learning Python, I was concerned about this issue, as well. The thing you learn as you begin to use it more, is that it is really a non-issue. Later, when using Java or C#, you realize how much a pain always working static types can be.
I think both static and dynamic typing have their merits and are not mutually exclusive. I'd like to see a language that has both.
As it is now, there are many tasks where Python is clearly superior to Java and many where the reverse is true.
Until the perfect super language arrives (i.e. never), it is probably useful to know at least one scripting/dynamically typed language (Python, Ruby, Perl, etc.), one VM-based strongly typed language (Java, C#, Smalltalk, etc.) and C/C++ for the low-level stuff (via JNI and extensions, or just by building stand-alone tools).
|
|
|
> > I missed one point in the discussion about runtime vs. > > compiletime > > type-checking and that is the self-documenting effect > when > > I explicitly specify the types I use. > > > > I think this is much more communicating: > > > > > > public Configuration getConfiguration(File file) throws > > IOException > >
> > Hmm... looks kind of redundant to me... Also, to > increase the redundancy further, you may want to write > several versions of this same method in Java; one that > takes a BufferedReader, one that takes a > String filename, etc. To achieve the same thing in Python you would have only one method (wich accepts several types), with dispatching code at the beginning of the method. I think this is much worse. > > than > > > > def getConfiguration(file) > >
> > What about this? > def getConfiguration(configFile): > 'Reads the specified file and returns a > rns a Configuration object; throws IOException.'
This is exactly the problem I see with runtime-typed languages. Instead of specifying the types in the normal sourcecode, you begin specifying those things in informal comments!
|
|
|
Having looked at Python several times, the lack of runtime type checking has always been a show-stopper. All developers who have been in the business awhile know how difficult it is to develop robust, error-free code so the sooner bugs are caught the better. This idea of "wait until runtime" to catch errors is unacceptable. The rule of thumb is to catch as many errors, as early in the process, as possible. The "saving finger-typing" argument holds no weight when compared to catching bugs. For mission critical and safety-conscious systems, run-time type checking catches errors *before* serious consequences occur.
When productivity squares off against reliability, productivity should lose.
- Mike
|
|
|
> Having looked at Python several times, the lack of runtime > type checking has always been a show-stopper. All > developers who have been in the business awhile know how > difficult it is to develop robust, error-free code so the > sooner bugs are caught the better. This idea of "wait > until runtime" to catch errors is unacceptable. The rule > of thumb is to catch as many errors, as early in the > process, as possible. The "saving finger-typing" argument > holds no weight when compared to catching bugs. For > mission critical and safety-conscious systems, run-time > type checking catches errors *before* serious consequences > occur. > > When productivity squares off against reliability, > productivity should lose.
It seems that there is this very popular implicit assertion that compile time type-checking finds and eliminates (or prevents) a large number of programming errors.
I agree with your final conclusion, for some cases, but I haven't seen any convincing data to show that runtime type-checking really eliminates that many bugs. Like any programmer, I make plenty of mistakes in the process of writing software. I don't think that type-checking would save me from any of them. I don't think my Python code is any more buggy than my C++, Java or C# code.
That is, I think using a type incorrectly, or using the wrong type is a relatively rare mistake. Even in C, where it is most dangerous and easiest to do, I don't imagine that is the source of a significant number of programming errors.
This is the same reason I began to hate the Hungarian notation convention with such a passion. If you are so ignorant of your code that you don't even know what type of variables you are using, then you are probably better off not touching the code. In many cases I've seen, the Hungarian notation usage is carried to such an idiotic extreme that all you know is the type of the variable and you are hard pressed to figure out what its purpose is.
Incidentally, the ubiquity of editors with code-completion features (for statically and dynamically typed languages alike) further lowers the already slim chances of misusing types.
Maybe there are some studies of this subject somewhere that show conclusively that programs written with compile time type-checking are overwhelmingly more reliable and of higher quality than those with runtime type-checking only? If so, please point me to them and I will capitulate.
Finally I'll repeat my usual point that these programming tools are not mutually exclusive. (Yes, it is actually possible to run Python and Java on the same machine (really!) -- heck, it is even possible to run them both in the same virtual machine!).
|
|
|
I used to think that static type checking was a life-saving programming tool. I've been gradually changing my mind about this.
First, the first big program I wrote (many years back now), was written in Perl. It started out as a few scripts on a Web server, and over time grow into a full-fledged enterprise application for a finance company. It had a huge uptime (better than 99.999%), and had been used non-stop by several 100 people for years. Perl's weak typing was never an issue in writing that app, because I made very small changes to the system over several years (mainly because the system was constantly in use), and each small iteration brought to fore the biggest bugs during testing. So we could just fix those bugs right away, and type-mismatch bugs never found their way into the production system.
I think static typing is important when developers use tools that exploit them. With many IDEs, such as IDEA, I can just click on a variable that refers to a customer, and up pop all the methods I can invoke on that customer. I don't have to remember those methods, their parameters, or return types. I think it's a huge productivity booster, because I get to stay in one spot of the program and don't have to interrupt my flow looking at docs, etc (something Bruce had talked about in an earlier interview). I can just keep typing (pun intended).
Static typing becomes even more important when we access network-based resources. However, few systems provide a strongly typed network object model (Jini is one exception). With static typing, if I want to access a inventory management system, I can just write code that says, in effect, "OK, at this point just find an object that implements the Inventory type." Since I know the methods of that type, I can continue programming to that interface without having to know how someone implemented that inventory system. In reality, I might not even be able to find out the implementation, even if I wanted to, since we're talking about an object that comes across the network from some remote location. So a strongly typed system allows me to have the object's type be the only prior agreement with whoever implemented that Inventory object. On the other hand, progamming in an untyped network environment is often a complete nightmare - having remember protocol messages, message order and content, etc., are a very unproductive experience.
About Bruce's remarks on feeding real data into a program: I found that dynamic typing often breaks down during data loading. When I consume a text file, for instance, to feed someone's database into my program, I can use Python or Perl to read that text file. That Python program is going to parse the file, and give a variable that corresponds to, say, position 6 in the database file, which would, say, represent the sale price of an inventory item (e.g., a float). But a lot of databases out there are really often corrupt - position 6, for instance, might be blank, or represent some mistaken value. And that means that now *I* have write my own type checker. But I wouldn't have to do that if I could feed typed data into my program, i.e., a SaleItem. Because that object presumably conforms to all the contracts of what it means to be a SaleItem, I can take those guarantees for granted.
In fact, one of the biggest productivity boosters I came across lately is to put a strongly typed service layer on top of data sources that my program has to rely on.
|
|
|
> > > > > > public Configuration getConfiguration(File file) > throws > > > IOException > > >
> > > > Hmm... looks kind of redundant to me... Also, to > > increase the redundancy further, you may want to write > > several versions of this same method in Java; one that > > takes a BufferedReader, one that takes a > > String filename, etc. > > To achieve the same thing in Python you would have only > one method (wich accepts several types), with dispatching > code at the beginning of the method. I think this is much > worse. >
In the getConfiguration method:
Either, 1. you would accept an ancestor common to BufferedReader, String, File that you use for sequential reading, or
2 will write overloaded versions of getConfiguration.
Both things can be worked out in Python:
add 1. fine, Python has virtual methods add 2. getConfigurationFromBufferedReader, getConfigurationFromString, getConfigurationFromFile, etc.
Jiri
|
|
|
in Java we've also found out that we check things at both compile time and runtime Strange to have a discussion of static vs. dynamic typing without mentioning that some type systems are much more powerful than others.
Haskell, Clean, OCaml (and potentially Nice) have type systems that are powerful enough to infer the types of functions and variables at compile time. The programmer simply doesn't need to do finger-typing. Let's not confuse the inadequacies of Java's type system with the capabilities of modern static typing.
|
|
|
one VM-based strongly typed language (Java, C#, Smalltalk, etc.) Smalltalk is strongly typed, but at run-time not at compile-time - it's a dynamically typed language.
|
|
|
For mission critical and safety-conscious systems... reliabilityThe important thing here is what reliability means for each specific system. Dynamically-typed Smalltalk has been used to develop mission critical, reliable systems for many investment banks. What made the systems reliable is that they didn't crash & burn when there was a runtime error. They halted, paged a developer; and allowed the developer to debug the problem, correct data, and crucially resume from where the error occured. They were reliable because Smalltalk can be hot-fixed. How about 99.999% availability in dynamically typed Erlang? Ericsson AXD 301 ATM Switch control system, 1 million lines of Erlang source code 400,000 lines of C/C++ code 13,000 lines of Java code 200 person project http://www.erlang.se/publications/Ulf_Wiger.pdf
|
|
|
> > When productivity squares off against reliability, > > productivity should lose. > > It seems that there is this very popular implicit > assertion that compile time type-checking finds and > eliminates (or prevents) a large number of programming > errors. > > I agree with your final conclusion, for some cases, but I > haven't seen any convincing data to show that runtime > type-checking really eliminates that many bugs. Like any > programmer, I make plenty of mistakes in the process of > writing software. I don't think that type-checking would > save me from any of them. I don't think my Python code > is any more buggy than my C++, Java or C# code. > > That is, I think using a type incorrectly, or using the > wrong type is a relatively rare mistake. Even in C, > where it is most dangerous and easiest to do, I don't > imagine that is the source of a significant number of > programming errors. It is not necessary to try and quantify how many bugs are caused by the lack-of type-checking for three reasons: 1. It may not matter based on the type of application or system your are building. 2. The answer is greater than 0. 3. I can program in languages with strong typing. I don't consider this overly burdensome. In fact, I would love it if Python included this as an optional feature. As an illustrative example, there has certainly been widely publicized bugs relating to bad data and mismatched types. One in particular in the Mars Lander -- see http://mars.jpl.nasa.gov/msp98/news/mco990930.html. Best wishes, - Mike
|
|
|
> As an illustrative example, there has certainly been > widely publicized bugs relating to bad data and > mismatched types.
There are also many widely publicized bugs regarding bad data and perfectly matched types. Pick your favorite buffer overflow error. One can argue this all day either way. While interesting, it doesn't really get anyone anywhere.
I figure that it doesn't pay quantify how many bugs are caused by lack of type checking because regardless of whether the language is strongly typed, there are bugs.
Although, some (finger) type checking would have picked up this one :-) > 1. It may not matter based on the type of application > or system your are building.
|
|