How to Love a Framework You've Never Used
by Curtis Poe
The latest issue of Dr. Dobb's Journal arrived today. Frankly, I'm not a fan of this magazine but they keep offering me a free subscription and I keep hoping I'll get something useful out of it. The problem with Dr. Dobb's is that it's just not relevant to me as a programmer. With its heavy focus on Java, C++, .Net and similar languages, I find it useful for little more than taking up room in my recycling bin. With the latest issue, though, there's hope. The cover story is the luridly titled "Ruby On Rails - Java's Successor?"
To say the least, it's an extreme oversimplification. Don't take me wrong, I really like Ruby and Python, and even PHP for some use cases, but you're dismissing the really important aspects and don't mention the actual advantages of static typing.
First of all, most Java developers are not against dynamic languages, and the JVM even supports a few of them, side by side and interwingled with Java code (Jython, JRuby, Groovy, ...).
Dynamic typing is nice for either small applications or very small teams, but as soon as you get into frameworks, large applications and/or large teams, it is extremely counterproductive: either you have to implement invariants to check the runtime type inside the called function, which adds unnecessary complexity the compiler takes away in statically types languages, or you do it by documentation (and developers always read documentation, right), or you don't do it at all and be prepared for tough to reproduce application errors in production.
Strong typing is part of the contract of an interface and/or a method, and designing by contract (or at least, the essential idea of it) is an extremely important factor in building complex applications with more than 3 or 4 developers and that remain easy to maintain and extensible over time.
The point is, as you mention, "the faster your programmers can turn out good applications". Note that most projects and businesses don't care about producing good applications, nowadays it just has to be fast and cheap, as cheap as possible (i.e. unskilled but cheap developers, reduced testing, etc...). If you do care about the quality of design and implementation though, it doesn't matter to have a dynamic language with dynamic typing, nor being capable of writing something in a slightly cryptic one-liner in Ruby or Python instead of 3 or 4 lines to do the same in Java.
What matters is having capable developers and architects that are aware of current patterns, best practices and who have experience with it, in order to design applications that remain easily extensible and maintainable over time. Key concepts to that are multi-tier architecture, layering of view/domain/business objects/..., single concern, design by contract, dependency injection, unit testing (and use of mock objects and stubs), continuous build, etc...
It doesn't matter much whether you use Java, Ruby, Python or another object-oriented language (but Java offers excellent support, opensource stacks, standards and de-facto standard implementations for all of the above).
And Java isn't going to be "replaced by Ruby or RoR". In some cases, RoR is a better choice because fast prototyping and simplicity is very important, but never forget that complex tasks require complex technologies (and that's not very likely to change anytime soon), and Java has not only 10 years of maturity and evolution, but also a huge stack of built-in libraries, standards (JEE, amongst many others), and open-source projects.
As said, I don't want to bash dynamic languages like Python or Ruby, they're indeed very nice additions to or in certain scenarios a better choice than e.g. Java, but just don't oversimplify. Java is here to stay, and not as a legacy language/platform, and that's a good thing (it certainly beats the crap out of C and C++ for almost anything but implenting an operating system kernel, having a degree of productivity and quality that's magnitudes larger than the latter).
Pascal Bleser wrote:
Dynamic typing is nice for either small applications or very small teams, but as soon as you get into frameworks, large applications and/or large teams, it is extremely counterproductive ...
With all due respect, this is a common misconception that I typically encounter with folks who don't have enough experience with dynamically typed languages to understand how to program in them (most new Perl programmers write Perl like it's C). Once a programmer "groks" dynamically typed languages, the "they're only good for small projects" objection often goes away.
As for my background, I specialize in writing large-scale applications in Perl. I've programmed in Java, C, Prolog, COBOL and a number of other languages, but for sheer productivity, they just don't beat Perl (well, Prolog can often beat Perl, but for a restricted application domain). For one company, I was a developer on an application with about a quarter million lines of code, mostly in Perl. It's worth keeping in mind that this application, written in C or Java would have many more lines, perhaps over a million. We had to daily receive data from over 4000 movie theaters across the United States and summarize the data for major Hollywood studios. We would receive data in a variety of different formats via email, FTP, call center work, SOAP, and so on. We crushed our competition because they could not keep up with our speed of development or our reliability. Today when you read in the newspaper about how much money a movie made over the weekend, it probably came from our system. It was a critical application and it functioned very, very well.
How did we do this with a language which many feel is unsuited to large applications? Simple: test-driven development. While static typing often gives a nice performance boost, it is, at its core, a form of implicit testing -- a statement which might seem odd to those without a significant testing background. Since large applications should always have tests anyway, the implicit testing is almost superfluous. Our explicit testing caught the errors that folks assume will creep into dynamic languages.
To be fair, I would not recommend using dynamic languages in large systems without a commitment to automated testing. Of course, I wouldn't recommend skipping automated testinf for static languages, either. Once that commitment is there, dynamic languages are a huge win in many problem domains. Can we really claim that Amazon, Slashdot, LiveJournal, Craigslist and many other sites aren't in the big leagues in terms of either features or bandwidth? Those sites rely heavily on Perl. I also happen to know that quite a few financial companies rely heavily on Perl for handling large volumes of mission critical data. The idea that dynamic languages don't scale is a myth. You almost always need less code and you usually get more work done. I've got an extensive background here and I've seen it in action many times both in my work and the work of others.
In short, while you may view my comments as an oversimplification, the shift in cost from computer to programmer guarantees that, in the long run, technologies which boost programmer productivity -- even at the expense of CPU cycles -- have a huge advantage. There are exceptions, of course, but even in the most CPU intensive of industries, gaming, we see that dynamic languages are being used heavily (Python and Lua both come to mind) for portions of the code which don't require raw processing power. This is part of a long-term trend which will only grow more noticeable as processing power becomes less expensive.
Maybe I didn't put my previous post into the right context, but you basically already confirmed my point ;)
"Once a programmer "groks" dynamically typed languages, the "they're only good for small projects" objection often goes away."
Precisely. If you have either a small team of developers (on that large-scale Perl application you did, how many developers on the team ?) or you have almost only very skilled developers. In that case, you could actually use any language, it would work well.
The arguments I hear all the time are "we made a lot of unit tests" to catch contract definition deficiencies of a language, and "well, that's because your developers suck" both about the same point and against e.g. Python's lack of first class support for visibility (public/private/...).
I work in a team where we develop a large enterprise framework in Java that is used by many project development teams to implement various customer projects, mostly financial or telecom applications. And my comments and opinions are in the scope of that context, which I failed to mention in my first post ;)
1) most developers that use your software (or most developers in general) are not highly skilled; they code Java like it was C, they don't read the Javadocs, they don't grok most software patterns and best practices, they don't have good unit test coverage if at all
2) when you work with a capable development environment such as Eclipse JDT, syntactic and some contractual errors (e.g. wrong parameter type, use of deprecated APIs, failing to catch or forward exceptions, ...) are shown immediately, while you type, which is a great productivity gain in the first place, and that also counts for highly skilled developers when you're on a large application
Of course, that doesn't replace TDD and good test coverage, but still, it helps a lot on productivity in the first place. You also discard the fact that Java has much more capable development environments (Eclipse, Netbeans, IDEA, ...) that make the verbose code less effort to type, that show syntax or usage errors immediately, that make code completion based on types, etc...
As much as I love to use vim and emacs, they don't cope on ease of use and productivity when compared to e.g. Eclipse or IDEA (of course, I mean when writing Java code)
(and, yes, I do have a strong background on TDD)
Also, I personally don't see the verbosity of a language as a bad thing. You have to understand code even years later. And having to write a lot of comments isn't the right solution when you really think of it: code should be natural to understand without having to jump through hoops.
I wouldn't deny having first-class continuations support in the Java language, and the JDK 5 enhancements (auto-boxing, foreach-alike loops, generics and, to some extent, annotations) are very welcome. I also sometimes miss e.g. some Perl constructs, especially when working with regexes ;) And I would never consider using Java for writing e.g. sysadmin scripts, but would use bash/Perl/Python instead. And I'm not saying Java is perfect as a language or the best fit for every use case - amongst other things, it's still a mistery to me why e.g. integers are not fully-fledged Java objects as it is in Ruby.
Yet, I really think that Java indirectly has better language support for several patterns, obviously through OO (you have to admit Perl's OO is.. well... awkward at best ;) - Python and Ruby are perfectly fine though wrt that), but also through explicit visibility (public/private, Python can't do that, even the __ hack is both ugly and still doesn't really prevent access), first-class support for interfaces (not in Python, not in Ruby, not even near in Perl) to mention a few.
"Can we really claim that Amazon, Slashdot, LiveJournal, Craigslist and many other sites aren't in the big leagues in terms of either features or bandwidth? Those sites rely heavily on Perl."
They certainly are, and I wouldn't argue that. Yet, Slashdot or LiveJournal are not really very complex as far as the domain and business logic is concerned. Indeed, they have to cope with performance. And I didn't say that e.g. Perl is not good for large applications because it's slower than e.g. Java - I mean, it is (Python and Ruby are also slower than Java hotspot, and Java is usually slower than C or C++), but that's not really the point, I totally agree with you that as far as raw performance of the "language" (well, rather of the managed runtime / virtual machine, or the lack thereof as in C/C++) is not very important, as adding hardware is much cheaper than spending a lot more time and having more bugs in development (e.g. C/C++ memory management on your own vs. Java/Python/Ruby garbage collection).
My point would rather be: how maintainable are those applications ?
And even if they are, wouldn't they be easier and less costly to maintain if they were written in Java instead of Perl ?
Obviously, I don't deny that one can write crap whatever the language is, and using Java is in no way a guarantee that you'll have better code.
Still, and to come back to your original posting, I really think that Ruby or RoR are great for certain use cases, but that they by no means "replace Java", for several reasons, one of them being that static typing (or actually, "strong type checking", because you can also have dynamic typing with Java, just use an Object instead of e.g. a String, a Date or a TransformerFactory) is of help:
- to catch contract usage errors that sometimes only show up under certain circumstances because by "chance" most methods dynamically apply to the wrong runtime type as well, but the developer expected the type to be the one defined in the contract and are difficult to track down
- to enable good IDE support (code completion, some advanced refactoring abilities, instant parameter type violation errors, ...)
Just my 2 eurocents, and I totally agree that most of my points are in the context of a framework situation, and might apply to a less extent when you're writing the end-user application.
I learnt java from university. At that time, it was the only language I knew. When doing exercises, I feel it is too complex to do simple things, especially GUI part, also BufferedReader for reading file from disk. Sometimes I was so frustrated, that I wanted to change to other engineering courses. I asked myself "This is something I have to do when I finish the university. I have to sit the whole day to do such kind of things". But I just kept going to finish the course. Luckily for me, I got my first job as perl programmer later (I suggested to use java, but my employer said NO). I knew nothing about perl and never heard about it at university. So I had to borrow books from library to learn it quickly. My first program in perl was very java. Afterward, I like perl. It has "foreach", map, grep, simple open file, multilevel hash, excellent perl/TK. Now I still feel lucky that my first job was a perl programmer. Looking back, java brings many benefits for me too. It teached me the foundation of programming, be patient, simple syntax. Its problems are so slow to run, lack of major built in functions and unecessary complex like BufferedReader. Recently, I learn Ruby. Now I use both perl and ruby in my work.
I find it amusing to hear Java called "maintainable" when the language itself is cumbersome enough that it's difficult to maintain large projects without a powerful IDE. Part of maintainability must be the ability to create appropriate abstractions when necessary.
(I also find it amusing to hear Java called "mature" when compared to Ruby. Check the release dates.)
have you seen Grails at Codehaus? it is a clone of RoR that uses Groovy - the official dynamic langage of the java virtual machine. it has the productivity of programming by convension and a scripting language (compiled into byte code) - but you can script Spring services and Hibernate objects to use your java investments without any glue code.
i am always suspicious of developers that favour speed over correctness - but i have met both java and script developers that do that!
during the day i work on a million line mature online banking system written in Java and the code quality and architecture was crap. i joined as the code went live and i have bashed it through two re-launches and a one major upgrade. during my time i have noted every entry in the anti-pattern book 'Bitter Java' somewhere within the code.
at the weekends i run a number of ecommerce sites running on a major php opensource cart + content management system. the opensource php app has more functionality in it than the j2ee online banking system (which cost several million dollars by the way) in a lot less code. it also has a mature extensions plug-in architecture, heaps of functionality, loads of extensions and a thriving community. a buddy that is an executive at another firm that had spent $5m on a major spare parts ecommerce site says that the opensource php software is simply better - and would use the php app if he could start again. so scripting languages win hands down right?
well not really. i am writing a core extension that is much asked of on the forums of the opensource php app. the thing is with the opensource php app is that the content is not quit separated from the presentation - so it is hard to re-use or extend core functionality. so i catch myself tempted to either cut and paste - or refactor the core code (running the risk of being left behind on security fixes if i change a lot and don't have the time to get my changes into the next major release that is in the pipeline - i have a day job and a wife after all). so i see some of the problems that i have had to work though on the Java code in the php code - both of which are major applications.
(i should say that i have also found great code in both apps. but somehow it is always the thorns that come to mind rather than the roses...)
the moral to the story is that crap code is crap code and great code is great code no matter what language it is written in. the "my language is bigger than your language" argument to me like the "my football team is better than your football team" - heavy on opinion and short on substance. i will continue to use the tool at hand and would have no problem (and look forward to) working with other languages such as C# or Ruby. i am sure that at some point in my life i will see a mature C#/Ruby app with some crap code in it and another with great code.
something that i forgot to point out was that you my examples talk about mature applications with a long lifespan. at the end of the day the longer the life of the application the heavier the cheque that the client has to pay for poor code written along the way. only after a developer has been put through the grinder a couple of times supporrt and extend mature code in a couple of languages will they get over the "my football team is better than yours" attitude and focus on correctness in any language that they use.
Just a quick semi-OT response regarding Dr. Dobb's: I wish some publisher would put out a magazine devoted to languages frequently used in open source: Perl, Python, Ruby, and C, maybe shell and _maybe_ bits of coverage of languages like Java or C# as it relates to OSS (or even UNIX-like systems in general). I know single-language periodicals like the Perl Journal have been tried in the past, but maybe a broader OSS/UNIX approach would be more successful.
Some good points here about the economy of hardware vs that of programmers and languages. I'm a Perl fan since 1994. But still, Perl could end up like Cobol: hard to do simple things. For instance, why is Perl still lacking a built in function to slurp a file into a scalar or all lines of it into a list? (Yes, i guess you could $s=`cat file`, but thats not portable) Or for that matter: an entire directory of files into a list. When Perl was created, memory was tiny. In 2006 most files are small compared to the amount of memory most computers have. If Perl wants to stay current it should be able to do that by now. An often used excuse is "Its in a module", but most new students don't study the modules, the study the language before they decide whether they like it or not.
my @lines=load("file.txt"); #context