Sponsored Link •
|
Summary
If it is, maybe there's something we can do to decouple static types and the languages which use them.
Advertisement
|
The battle between static and dynamic typing enthusiasts rages on and on. Java "upped the ante" by introducing generics and increasing the amount of verbiage in our source files. The dynamicists have responded with Rails and various Python frameworks, showing the world that you can write powerful web applications with an extremely small number of keystrokes. Personally, I'm more in the dynamicists camp, but I do think that there are some problems in the dynamic language world and some of them are political.
Let's play out a scenario. You've just graduated from school. You and your best friend look at the landscape and you figure "hey, we're young, let's make a go at this Web 2.0 thing." You sell your bicycle and some aluminum scrap that you find on the side of the road and you have your seed money. You buy a server, a development machine and download Rails. You and your friend code something up and go live in a week. It's flimsy but it works. You have your first users. Now, you're the only programmer. Your friend is sleeping at the door with a shotgun to keep venture capitalists away from you. Your user community grows, and your first big shopper comes by.. a big public company, with people in suits. They want to buy you.. they start doing their diligence.. they walk in and they are amazed that you are running a 50,000 user system on a simple server using a dynamic language, and it's handling real money. Their technical guru turns around and says "We can't buy this! It could have all sorts of errors in it and we'd never know!" You point to your tests, but he's adamant. "They're hackers!!" he whispers, "you can't buy this!"
Far fetched? Probably. Dynamically typed languages are growing in acceptance, but there are many cautious people in this post-Sarbanes Oxley legislation world.
Now, let's put aside the static versus dynamic language debate.. I think everyone on both sides of it will admit that dynamic languages offer some advantages during development. And, most people would agree that there are some times when it would be nice to check some things at compile time. Can we have the best of both worlds?
It turns out we can. Some languages allow optional type declarations. Visual Basic is the most prominent example of this (not that I've seen anyone work with it this way), but you can type a variable as an Object and send it any message. At runtime a lookup function is called it will attempt to resolve the message against the object. If you like static typing, you simply use types when you declare your variables: ''Dim count as Integer''
The interesting thing is, this feature can move us to a different style of development: write your program using dynamic typing, and when things are stable, fill in the types afterward; I imagine it would be like doing a Sudoko puzzle.
But.. there is a problem.. once you fill in the types, they are everywhere. They annotate each variable declaration, all your method arguments.. changing them is a pain. They nail down your program. It's hard to refactor, it's hard to get tests in after the fact. Your program and its types are snarled together.
Let's go back to first principles.. software design principles and apply them to directly to language design. We should consider the idea that static typing, as we currently do it, may be bad coupling. When we litter a program with type annotations, we're tightly binding an error detection scheme to the form of the program. We can't work with the form of the program independently of that error detection scheme. What if we tried to decouple them? What would we end up with?
Take a look at this piece of Ruby code:
class Word attr_reader :text @@random_number_generator = Proc.new { | exc_upper_bound | (rand * exc_upper_bound).to_i } def initialize(words,text,successor) @text = text @words = words @successors = {} @words[text] = self unless @words.has_key? text @words[text].add_successor(successor) end def add_successor(successor) @successors[successor] = 0 unless @successors.has_key? successor @successors[successor] += 1 end def sum_of_successors @successors.values.inject(0) {| sum, current | sum + current } end def next_position scaled_rand(sum_of_successors) end def scaled_rand(exc_upper_bound) @@random_number_generator.call(exc_upper_bound) end ... end
I have in mind exactly the types that I would like to use for each of the variables here, but I hate the idea of putting them in the source. What would happen if I could put them in a separate file like this?
class Word text : String words : Hash<String,Word> successors : Hash<String,Integer> def initialize( : Hash<String,Word>, : String, : Word) def add_successor( : String) def sum_of_successors : Integer
Yes, it's ugly. We're repeating outselves. But here's the trick. We don't have to specify everything. Note, for instance, that I didn't give a type declaration for the last method in the class: scaled_rand. It's all optional.
Think it's still bad? Okay, here's the next piece. We can let our IDEs manage things for us. Our IDE can read both files and show us a view where we see the types in the source (if they are present), and we can toggle off their display when we don't want to see them. The compiler will check all of the types for us, but they are independent of the source. We can delete all the types for a particular class if we want to, rename them.. alias them, etc. We can also take the code for the Word class above and give it another set of type signatures in a different program -- we can reuse the form with different types.
I suspect someone has thought of this before, but I haven't researched it. I think it might be a workable way to progressively add static typing to a program on an as-needed basis. What do you think?
Have an opinion? Readers have already posted 74 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Michael Feathers adds a new entry to his weblog, subscribe to his RSS feed.
Michael has been active in the XP community for the past five years, balancing his time between working with, training, and coaching various teams around the world. Prior to joining Object Mentor, Michael designed a proprietary programming language and wrote a compiler for it, he also designed a large multi-platform class library and a framework for instrumentation control. When he isn't engaged with a team, he spends most of this time investigating ways of altering design over time in codebases. |
Sponsored Links
|