July 10, 2007Dynamic and static languages are fighting again
Maybe we should look more closely at the kind of programs being written in Ruby and Python and Javascript, and the way good programmers use those languages, to understand if there are reasons that refactoring might seem less obviously helpful in those languages.I've read and written a lot of reasonably long (> 10,000 lines of code) programs in various dynamic languages (Python, Ruby, PHP and more obscure ones as well) and I haven't seen any evidence that refactoring is less needed in these languages. Granted, these listings sometimes have constructs that would take more code to write in Java, but here is the catch: if you are using a more expressive language, you don't write shorter programs, you write programs with more functionalities in them. And at the end of the day, you face the exact same problem that Java and other statically typed languages face: you need to refactor if you want your code to evolve. I feel much more comfortable refactoring Java code than I do Ruby or Python. It doesn't even matter whether I authored that code and how confident I am about the test coverage. I just know that I can't rely on the compiler and the type system to catch my mistakes, and this impacts my productivity immensely. Suddenly, I'm more hesitant and I'm afraid to break something with my changes. Here are a few select quotes from this discussion that match my own experience very closely: What I find in Python is that I can barely reuse my old code, much less modify it without a lot of pain. (James Watson) I, at least, find that my Ruby or Javascript code degrades over time more than my Java code does, mainly because I get lazy and avoid refactorings that I would be more likely to do if they were safer and more automatic. (Alan Keefer)Ultimately, I have found that big programs written in dynamic languages don't age as well as those written in a statically typed language because developers are more afraid to refactor them. And rightfully so, since certain refactorings are just plain impossible to achieve automatically in these languages (another reason why duck typing is too dangerous to use in large scale projects). The bottom line is actually fairly simple: nothing beats a dynamic language to write a prototype, but if you know that the code will have to be maintained and that it will be in use for several years, the initial cost of using a statically typed language is an investment that is very quickly amortized... Comments
I work in both platforms with some regularity and I love developing greenfield projects in Rails so much more than I do in Java, but when it comes to refactoring (arguably the most important part of good maintainability) I much prefer Java. Posted by: Todd Huss at July 10, 2007 09:00 AMI am wondering.. Why then the newer web2.0 sites like Youtube, Facebook, Pownce etc., are using dynamic languages like PHP, ROR, Python and not Java. http://groups.google.com/group/etoe Posted by: Muthu Ramadoss at July 10, 2007 09:42 AMThere is always Groovy as a solution; it swings both ways: you can use static or dynamic typing, as you prefer. Posted by: andrew binstock at July 10, 2007 10:57 AM@Muthu I guess we'll find out how that works when they get a little older and they have more code to maintain. I think eBay was originally built on Perl, but they re-built it on Java... Posted by: Jason Carreira at July 10, 2007 11:01 AMthis fight will go on as long as both camps don't understand that you simply need both. types and no types within your project. Jason Carreira: and Steve Yegge wrote that seeing apples-to-apples comparison of Java and Perl turned him from a static typing believer to a dynamic typing proponent. Hmm. Btw, I haven’t felt any problems refactoring Perl, but then I also find my XSLT transforms excessively easy to maintain, so maybe I’m just a weirdly wired bird. I don’t disregard the value of static typing though; I just think that the industry-common languages like Java and C++ have stupid type systems that return very little value for the work they cause. You need an expressive type system with inferencing like what ML, Haskell and others provide, in order to draw gains from it. Optional static typing with moderately expressive type systems such as those in Javascript 2 or Perl 6 are practical compromise for the time being. Posted by: Aristotle Pagaltzis at July 10, 2007 12:27 PMI totally agree. Thanks, this was interesting. Posted by: Antoine at July 10, 2007 02:02 PM"if you are using a more expressive language, you don't write shorter programs, you write programs with more functionalities in them" Is that really true? Programmers write code with some end-functionality in mind. If they accomplish that functionality in 100 lines of code instead of 150 lines of code, they don't turn around and jam in however many features can be afforded by 50 more lines of code. I guess it might be true that this efficiency is incorporated in time estimates, thus the programmers agrees to fit in more features in the same amount of time. This assumes an unrealistic linear association between lines of code and time to develop. With that in mind, your post is a pure strawman. Posted by: Michael at July 10, 2007 04:47 PMMy experience says i refactor when You said: "I have found that big programs written in dynamic languages don't age as well as those written in a statically typed language because developers are more afraid to refactor them." I've worked on quite a few large Rails codebases now, and there is never fear of refactoring, because there is always great test coverage. A good test suite is way better than a compiler. Posted by: Obie Fernandez at July 12, 2007 06:13 AMMuthu: Web 2.0 has NOTHING to do with dynamic languages on the server side. It is a huge misunderstanding that Web 2.0 is only 'possible' with the Scripting Language du Jour. Posted by: Stefan Arentz at July 13, 2007 09:23 AM"A good test suite is way better than a compiler." Of course it is but you have to invest time and money for a good test suite. The compiler is already there and does some very good "sanity checking" on your code before it's ever executed. Posted by: Cliff Meyers at July 13, 2007 11:39 AMGreat post. Doesn't have to mention the fact that the duck typers are just the latest spawn in the VB tradition: crack smoking their way into a frenzy, never realizing that constantly rewriting things ultimately leads to the gray goo syndrome (witness, Microsoft's last OS release was 5 years late and contained few new features)... Posted by: Rob at July 15, 2007 11:28 AMThe most intelligent post I've seen on this topic: "My RSS reader uncovered a thought provoking paper by Chris Smith entitled “What To Know Before Debating Type Systems”. It clears up a lot of the confusion around the differences between static and dynamic type systems. Much of the debate comes from people with limited exposure to both static and dynamic typing. He observes that: 1. Many programmers have used very poor statically typed languages. ... http://talklikeaduck.denhaven2.com/articles/2007/06/29/perspective-on-the-static-vs-dynamic-type-debate Posted by: Gabriel Handford at July 15, 2007 03:18 PMMaybe the dynamic folks should start naming their methods with the interface name in it .. haha. Hi! Your web site is helpful. Many thanks. Best regards! Would you care to share with us exactly what "large" systems (and in which dynamic languages) you have worked on and are basing your assumptions regarding them on? Otherwise, like most of your postings regarding dynamic languages, a lot of hot air. Otherwise, please see #2 in the comment by Gabriel above. Posted by: Rob at July 16, 2007 05:17 PMCedric in the Artima discussion: "Can you think of any features of certain dynamic languages that make them inherently more testable than, say, C++? (I can't at the moment, but I'll think about it some more)" Actually once you start writing real tests in Ruby you'll start appreciating it's power. MOCKING public void testAddAndChangeDocument() {
def test_add_and_change_document And if I put an object between class_under_test and collaborator the ruby test could stay the same while the Java code could get really ugly quickly (with another replay/verify..etc). Another good one is mocking class/static methods. CREATING OBJECTS class DynamicLanguage Ruby = Class.new(DynamicLanguage) You can also use a Struct (sort of a Javabean that can be created dynamically with minimal syntax).
Then you have irb to quickly try something...and of course you have the use of blocks, instance_eval, define method, etc.. to remove lots of duplication in test and code. Posted by: Petrik de Heus at July 17, 2007 02:29 PMCedric, I have this feeling ever since I started Perl, Python and Ruby in the 90es. Im happily back to Java (and some parts Groovy). @Jon: I feel sad whenever I read something from you, because you've been a great loss to the Java community. As I've written somewhere (google it ;-) with runtime analysis (I guess ST refactoring tools do this), path simulation (as JTest or FindBugs does) types can be determined for some parts of the code. But I have the feeling (and search for numbers) that the level of security for Java and Ruby refactoring are different. @Petrik: I guess it was just a mistake to Peace
@Petrik: And when we're at it, why not write your Java tests in Groovy? http://groovy.codehaus.org/Groovy+Mocks Peace The general problem with dynamic typing beside refactoring is this: Documentation I've written about this several times, like here http://stephan.reposita.org/archives/2007/06/21/ruby-complexity-cannot-be-reduced/ It's easier to read Java code several months in the future than to read dynamic reference typed code. def person = Persons.getOldestPerson() after several months or years, it might not be the case that Persons returns a Person type object. It could return something else. When then working with the person object in the IDE, it's not clear how to handle it, what to do with it. Person person = Persons.getOldestPerson() has a statically typed reference of type Person and this a.) documents the object But consider this: def getOldestPerson(date) What type is date? Several months in the future, or when I'm new to the code I need to decide what date is. Date type, Calendar type, long? Person getOldestPerson(Date date) makes it much easier to understand. Funny thing is that some dynamic type users add this to their method definitions // {Date} date to make the type clear. How this is better, or shorter, or easier to understand than the type in the method declaration is beside me. The funniest thing was from Ola Bini though: http://ola-bini.b-l-o-gspot.com/2007/09/should-ruby-have-optional-typing-and.html He proposes this: def test_one(first, second, *rest) to Ruby. How is this more readable than FixNum test_one(FixNum first, Enumerable second, Array rest) you can decide for yourself Peace Post a comment
|