"In my post, I was taking issue with the claim that Ruby syntax is more "terse". The author clearly exaggerated this by making the Java code unnecessarily verbose. Of course you are right concerning type declarations, however, this doesn't count as verbosity for me. In my feeling, code doesn't take longer to read because of type declarations. Proponents of dynamic languages tend to identify the readability/complexity issue with number of characters, which is plain stupid. What is important is the number of logical entities that you have to keep in mind in order to understand the code, not the number or lengths of words to read. Type declarations actually reduce complexity because the reader doesn't have to try to infer what the code is about. Whatever may be the benefits of dynamic typing, readability is clearly not among them. I wish that we could get at least that one straight."

Even if I agreed with you that type declaration isn't an issue, the difference turns out to be much bigger because it snowballs -- what started as a very small snowball becomes a dangerously big snowball and it never stops, though people try to at least contain it with good frameworks and tools.

If you revert that, if you actually cared that the snowball never increases unless it's necessary (like when we write a big program or library), that's what is Ruby -- a little and controllable snowball. Think about the universe before the Big Bang. :-)

Actually, I think I have written much more classes and modules in Ruby than millions of Java programmers have in Java, though by using Hash and Array in Ruby I save some obvious classes that people sometimes create in Java.

As an addendum, I would like to say that even with Ruby you won't find miracles. For instance, given all the optimum conditions of temperature and pressure, I have broken my own APIs many times by deciding that they weren't good enough, but I have done that because I needed to support evolution or else I would need to live with what I had for ever. If Ruby was any miracle, I would have gotten the APIs right in the first try. But no, up till now I'm still creating new things -- some time ago I considered some of them close to impossible, but thankful to the dynamicity of Ruby and to my commitment to Ruby, I have found the strength to keep evolving my libraries till I consider them ready.

Now, take Java's evolution to study. Java itself has broken many APIs and programs through the course of its evolution. It's no wonder when people decide to couple the Java program with a specific version of a JSDK or JRE. So, type declaration is not enough to help with backwards compatibility. And backwards compatibility does not help the further evolution of APIs. Not to mention that people might not commit to creating good and easy to use APIs, because they don't want to commit to them -- they rather prefer to create very generic APIs (rings any bell?).

> As an addendum, I would like to say that even with Ruby> you won't find miracles. For instance, given all the> optimum conditions of temperature and pressure, I have> broken my own APIs many times by deciding that they> weren't good enough, but I have done that because I needed> to support evolution or else I would need to live with> what I had for ever. If Ruby was any miracle, I would have> gotten the APIs right in the first try.

The nice thing about static typing and a compiler is that this provides a "test" up front that will come much closer to validating your callee/caller compatibility on the first shot. I don't believe for a moment that it is cost effective to write sufficient tests, for every project, to provide 100% type compatibility testing that a compiler and types can provide over and over. Some might argue that there is a movement of cost from development time with types to testing time without types, but I don't see that being a realistic, works everytime argument. There are probably examples to cite, but not concrete repeatability.

> Now, take Java's evolution to study. Java itself has> broken many APIs and programs through the course of its> evolution.

This is a different issue altogether. Bugs in library routines are something all of us get to deal with. And don't get me started on java.util.GregorianCalendar.

> It's no wonder when people decide to couple the> Java program with a specific version of a JSDK or JRE.

J2SE 1.2 was a complete and total nightmare. Anyone who tried to create something new starting with 1.2 was greeted with the worst possible experience of a lifetime. J2SE1.3 started to repair the huge array of problems 1.2 introduced. This is a common story for any platform/API. 1.2 changed many things that really needed changing, just like you talk about.

> So,> type declaration is not enough to help with backwards> compatibility.

There are multiple facits here, and you are lumping API signature compatibility with implementation compatibility. Those are two completely different issues which each require separate emphasis. API signature compatibilty testing is provided by the type system and compilier in Java. In typeless or untyped languages, you have to write more/new tests repeatedly to address this. That's an open ended cost to that language choice.

Implementation compatibility is a different set of tests that focus specifically on the effects and sideeffects of each piece of an API.

> And backwards compatibility does not help> the further evolution of APIs.

It depends on the design of the API. If the API design is wrong, it can be implemented with a new name that allows the old uses/users to have compatibility and we can move on to something that actually does work as needed.

The java.util.Hashtable and java.util.Vector classes are extremely useful for people who don't understand multithreaded programming very well, and in applications where there are lots of threads accessing the same mutable data.

The java.util.Map and java.util.List interfaces provide the same functional programming capabilities, but don't stipulate synchronization as part of the implementation. What this allows is that you can have optimized mutiple structures where a single thread is used for all access. The provision of a java.util.Collections.synchronized*() methods allow a standardization of APIs to be used.Moving beyond Vector and Hashtable is possible without breaking any APIs.

In other cases, existing APIs have been maintained and fixes to logic or stabilization of behavior provided inside of the same signatures.

It's silly to keep arguing about specific cases where human's have injected failure and to say these are the only necessary justifications we need to say something is bad.

What we need to speak to is the rather small advantages any of these languages provide to the total programming experience compared to what we had 10 or 20 years ago. The languages haven't improved things. It's the libraries and the IDEs that the languages have inspired and allowed to be created that are making the differences.

> Not to mention that people> might not commit to creating good and easy to use APIs,> because they don't want to commit to them -- they rather> prefer to create very generic APIs (rings any bell?).

"The nice thing about static typing and a compiler is that this provides a "test" up front that will come much closer to validating your callee/caller compatibility on the first shot. I don't believe for a moment that it is cost effective to write sufficient tests, for every project, to provide 100% type compatibility testing that a compiler and types can provide over and over. Some might argue that there is a movement of cost from development time with types to testing time without types, but I don't see that being a realistic, works everytime argument. There are probably examples to cite, but not concrete repeatability."

First of all, I agree that creating test code for everything is close to impossible, and I don't claim that "Test Driven Development" is any silver bullet. I don't support "TDD" as a "promise land". On the other hand, by creating units of code reuse (components), we ensure that we have good APIs and that they are used all the time (so, they are tested all the time), meaning that once the bugs are eliminated from the components, we have a good and stable code to reuse as much as we like. I defend components as the "promise land". And the more succinct the component is, the more that it behaves like a component, and languages like Ruby really help in creating components or libraries that behave like components, as well as the language itself is a good means for consuming (using) the components, instead of creating another layer with XML, Template Library, etc.

"What we need to speak to is the rather small advantages any of these languages provide to the total programming experience compared to what we had 10 or 20 years ago. The languages haven't improved things. It's the libraries and the IDEs that the languages have inspired and allowed to be created that are making the differences."

Here is how we can create a Thread in Ruby:

Thread.new{ sleep 1000 }

And we can access variables from the thread without needing to declare them as final. Imagine my surprise to find that Ruby had threads in an easier way than in Java, on the other hand, we still need the Native Threads, though by the tradition of Ruby, once the Native Threads arrive, I hope they will be just as easy to use.

So, in my opinion and experience, languages do influence the programmers, though we have many different kinds of programmers, varying from the hobbyist (me) to the professional (millions of Java programmers). Just like Sun created the NetBeans, IBM created the Eclipse, Borland created the JBuilder and the supporting tools, I'm creating my own development tools, the difference is that I support Ruby and I don't need to support genericity in the same way that those companies need. You may have all the genericity that you need, but sometimes people need some cozy tools like Rails, for example -- and they are the same kind of professionals to which Java is appealing in a general sense (tool users).

"Even if I agreed with you that type declaration isn't an issue, the difference turns out to be much bigger because it snowballs -- what started as a very small snowball becomes a dangerously big snowball and it never stops, though people try to at least contain it with good frameworks and tools."

I'm not sure what you are trying to say, Joao. First, type declaration IS an issue, only we completely disagree on it. I regard lack of type declaration as a *huge disadvantage*, a potential time bomb for future development and maintenance. "what started as a very small snowball becomes a dangerously big snowball", I would say that for a dynamic language.

"Actually, I think I have written much more classes and modules in Ruby than millions of Java programmers have in Java, though by using Hash and Array in Ruby I save some obvious classes that people sometimes create in Java."Were all those classes justified or did you create them simply because it's so easy?

1) "As an addendum, I would like to say that even with Ruby you won't find miracles. For instance, given all the optimum conditions of temperature and pressure, I have broken my own APIs many times by deciding that they weren't good enough, but I have done that because I needed to support evolution or else I would need to live with what I had for ever. If Ruby was any miracle, I would have gotten the APIs right in the first try."2) "On the other hand, by creating units of code reuse (components), we ensure that we have good APIs and that they are used all the time (so, they are tested all the time), meaning that once the bugs are eliminated from the components, we have a good and stable code to reuse as much as we like."

1) and 2) seem contradictory to me... BTW, getting an API right or not is hardly the fault of the language. Maybe dynamic languages tempt the programmer to do quick and dirty design. Languages like Java emphasize interface stability but in the end, you can get it wrong in any language.

> When I see people use "this" when they don't have to, it> always makes me wonder how well they really understand the> language.

Some people are as AR about using this as some are about importing every single class, instead of a package.

In the worst case, not importing by class causes later compilation errors when a new class by the same name is introduced into another package also imported.

In the case of not using 'this', you run into the problem that sometimes, people will declare new method parameters that have the same name as a class member and miss the fact that they might cause the scope of a reference to change to a different value/instance!

"If we set everything in stone, we go back to procedural programming."

"On the other hand, by creating units of code reuse (components), we ensure that we have good APIs and that they are used all the time (so, they are tested all the time), meaning that once the bugs are eliminated from the components, we have a good and stable code to reuse as much as we like."

Java is stable yet? Are all the core Java APIs and libraries stable yet? What if an interface changes? What if an abstract class changes? Is Java "final" in any sense?

When we develop APIs, we may change our minds from time to time, and it may be worth it to change an API while it's not a too big hassle. Imagine if Java was developed for 5 years before it reached the hands of developers? Would it be more improved than developing it for one years and then releasing it? How much "a priori" can a dozen geniuses think to create the perfect APIs?

Tell you what, the niggards among us set everything in stone if they can, because they don't care as much about generalities, they just want to get their jobs done as soon as possible. So it's not too hard to find many "finals" in Java code, not to mention those "immutable" pesky things.

I'm going to tell you an example of an API change. In GTK+, there is a command called "pack_start" and another one called "pack_end". I created a shortcut called "pack" with some default variables, but then I chose to make it even more easier by adding an "horizontal_pack" which I called "hpack" and another one "vertical_pack" which I called "vpack". But then I used the same terminology for reporting and other toolkits (Fox, WX, Web). Then I finally decided that "hpack" was too ugly and "pack" was enough for the new APIs. Even though I had used it in several examples, programs and libraries, I decided that it was still time to change it. Was it worth it? Definitely. I will use it for everything for the next 5 years.

So, a deliberate change, though it was much more a problem for me as a tools developer, then it would have been for a user if I had documented it.

But please, not that I'm not defensive about it. I know that a static typed language could help me make such a change, but a static typed language wouldn't help me as much to create the tools in the first hand. It's a tradeoff. I like OO more than millions of Java programmers, who barely know the design patterns by heart, because they don't find a lot of opportunities to use them in a sensible way. I'm baffled when people say that they use OO when they barely use polymorphism -- their code seeming a lot more procedural to me, even though it might use classes, interfaces, etc.

Give me Ruby a static typed system (maybe inferred), and maybe I might use it. Until then, there isn't much choice.

> Java is stable yet? Are all the core Java APIs and> libraries stable yet? What if an interface changes? What> if an abstract class changes? Is Java "final" in any> sense?

I not sure I understand what you asking. Is the Java "language" finished? I don't think so. Is the Java Standard Edition platform finished? I don't think so. Is the Java Micro Edition platform finished? I don't think so. Is the Java Enterprise Edition platform finished? I don't know, but I think it should be tossed in the trash, but I'm just a Jini fanatic some say.

I can't tell whether your wondering if a Java platform bug will bite you and break a program you wrote, or if you think that your java program will not run because of an API change.

Sun has continued to make sure that all APIs remain backward compatible as far as I can see. They've made statements to this effect in many forums, and my experience has been that this is the case where I would expect compatibility to be possible. Sometimes they have broken things with serialization and other places where they needed to make changes. The latest JMX-Remoting update 4 of v1.0.1 is not compatible with v1.0 without asking it to be.

Stuff changes...

Software will have bugs, plain and simple...

> When we develop APIs, we may change our minds from time to> time, and it may be worth it to change an API while it's> not a too big hassle. Imagine if Java was developed for 5> years before it reached the hands of developers? Would it> be more improved than developing it for one years and then> releasing it? How much "a priori" can a dozen geniuses> think to create the perfect APIs?

I don't understand this comment. Sun is releasing bug fixes every quarter for their implementation. Other people with JVM implementations can have different schedules.

Sun is not the only provided of JVM technologies. It is a non-trivial technology involving a non-trivial amount of software. So, there aren't a lot of people single handedly recreating it that I've seen... It makes sense to license it from Sun and build on their base.

It is a standards based platform with community based participation in its features. The JCP has a pretty stagnant group of participants which are fairly controlling of the focus of the development. But that is the fault of others for not participating rather than the fault of the JCP participants. They'll do whatever they agree to do. If you don't participate, you don't have a say in what happens, and you get to live with the results.

> Tell you what, the niggards among us set everything in> stone if they can, because they don't care as much about> generalities, they just want to get their jobs done as> soon as possible. So it's not too hard to find many> "finals" in Java code, not to mention those "immutable"> pesky things.

There are some interesting issues with the use of final classes and immutable objects.

You see, Java has a security model built into the language, unlike almost all other programming languages. That security model relies on the fact that string values that you can look at to see sets of things in the configuration, can't be changed by you to subvert security. So, there is a need for some immutable objects.

On the other face of the issue is garbage collection. There are some optimizations to be made with String.intern() that help to greatly reduce the total number of bytes allocated to string data in your running JVM. Many people probably don't use String.intern(). I use it in a String intensive database intensive application that I have to make sure that I have only a single instance of some very repetative String values active.

Immutability is what makes these types of optimizations possible.

> I'm going to tell you an example of an API change. In> GTK+, there is a command called "pack_start" and another> one called "pack_end". I created a shortcut called "pack"

I have absolutely no idea how this relates to this discussion. If you're interested, I wrote a cover class for the java.awt.GridbagLayout class to provide a TK like pack facility because I liked that interface to layout. It's athttp://packer.dev.java.net. I did it back in 1995/1996 or so, and have used it without any version of Java breaking it since that time. This year, I made a change to it for JSE1.6 to allow it to support some new layout features added in JSE1.6.

> Give me Ruby a static typed system (maybe inferred), and> maybe I might use it. Until then, there isn't much choice.

Based on your above comments and arguments, I'm not certain you have all of the "correct" information about Java.

"On the other face of the issue is garbage collection. There are some optimizations to be made with String.intern() that help to greatly reduce the total number of bytes allocated to string data in your running JVM. Many people probably don't use String.intern(). I use it in a String intensive database intensive application that I have to make sure that I have only a single instance of some very repetative String values active.Immutability is what makes these types of optimizations possible."

Have you seen Symbols in Ruby? One instance of String in the memory. Example:"this is a string""this will be a symbol".to_sym

"I have absolutely no idea how this relates to this discussion. If you're interested, I wrote a cover class for the java.awt.GridbagLayout class to provide a TK like pack facility because I liked that interface to layout. It's athttp://packer.dev.java.net. I did it back in 1995/1996 or so, and have used it without any version of Java breaking it since that time. This year, I made a change to it for JSE1.6 to allow it to support some new layout features added in JSE1.6."

It is Ruby, not Java, that's why you didn't understand it. I wasn't clear enough.

"Based on your above comments and arguments, I'm not certain you have all of the "correct" information about Java."

It has been a while that I haven't programmed in Java nor read with interest anything on it, so you may be right.