I'm following very closely what is happening in the "dynamic languages on the JVM space", and I agree there is really ambitious work and progress there (Mirah & JRuby from Charles Nutter & others, Kotlin, Groovy, etc). I like the fact that we are coming to a situation where you can use the language you want on the platform you want.
I agree, there is a middle ground and it is worth looking at that.
Worked a lot with Java, but also dynamic languages (lots of Python, but also Smalltalk and Ruby). My experience was similar: I was missing something on either side.
Currently I like Scala a lot, and it has a console as well as great collections.
The weak points are definitely there, but I think they can be mitigated by training or using proper tools:
Parameter types: use YARD and use its notations to describe parameters. It actually allows things like <Document|Hash|#to_h> which go far beyond what you can describe with types. While in the Java world, you would just overload methods for such things, Ruby allows you to describe all this in one place. Turn flaws into benefits.
Refactoring: strangely, I never miss this. I think bad refactorability is a weak-point of your code, not of the tooling. Ruby allows you to take the Single Source of Truth-Principle (aka DRY) to the extreme, which can allow you to turn most refactorings into search-and-replace operations.
Interfaces as contracts: I hate Java Interfaces, mostly because they don't allow implementations. In Ruby, you can use Modules to a similar effect and raise NotImplementedError on methods that were not implemented correctly. Thats maybe the hackiest thing in this collection, but there is no one-size-fits it all solution :).
I think the theme here is "no static guarantees" and thats definitely true, but after years of programming in dynamic languages, I rate those problems far lower than most others. Most of those things can be mitigated by thinking a lot about your code, which you should do anyways.
I think bad refactorability is a weak-point of your code, not of the tooling.
I used to think so too when I was doing Rails but since switching to static languages for mobile development I've changed my thinking.
There's something a little bit magical about quickly renaming a function and knowing that every caller of that function has been instantly updated. It changes the way you write code. I'm constantly, aggressively refactoring when I write Obj-C or Java and my code is cleaner for it.
Thats why I said mitigated: you are not going to make the problem go away, but you can lessen the impact. I have a similar workflow as you have in Ruby, but it takes great care to make sure that this kind of workflow is possible. Usually, I use a regexp and sign off every change by hand. Considering that I read my own code a lot, I also get to see my own stuff again.
Thanks for the informed answer. I agree on most of your points, and my experience goes in the same direction as yours : most of the problems I thought would happen due to the dynamic nature of the language did not really happen.
You are right, the reason for the examples are that I wanted to start from a practical situation I experienced, in place of making another discussion about the pro's and con's of dynamicly vs staticly typed languages (I found both to have their use, depending on the project but also on the people).
13 comments
[ 3.9 ms ] story [ 36.7 ms ] thread- Java 8 (lambda, mixins and functional collections) - Mirah (Nutter's typed Ruby on the JVM) - Scala (like Java 8, but even more functional)
But my money is currently on Kotlin.
Worked a lot with Java, but also dynamic languages (lots of Python, but also Smalltalk and Ruby). My experience was similar: I was missing something on either side.
Currently I like Scala a lot, and it has a console as well as great collections.
Parameter types: use YARD and use its notations to describe parameters. It actually allows things like <Document|Hash|#to_h> which go far beyond what you can describe with types. While in the Java world, you would just overload methods for such things, Ruby allows you to describe all this in one place. Turn flaws into benefits.
Refactoring: strangely, I never miss this. I think bad refactorability is a weak-point of your code, not of the tooling. Ruby allows you to take the Single Source of Truth-Principle (aka DRY) to the extreme, which can allow you to turn most refactorings into search-and-replace operations.
Interfaces as contracts: I hate Java Interfaces, mostly because they don't allow implementations. In Ruby, you can use Modules to a similar effect and raise NotImplementedError on methods that were not implemented correctly. Thats maybe the hackiest thing in this collection, but there is no one-size-fits it all solution :).
I think the theme here is "no static guarantees" and thats definitely true, but after years of programming in dynamic languages, I rate those problems far lower than most others. Most of those things can be mitigated by thinking a lot about your code, which you should do anyways.
I used to think so too when I was doing Rails but since switching to static languages for mobile development I've changed my thinking.
There's something a little bit magical about quickly renaming a function and knowing that every caller of that function has been instantly updated. It changes the way you write code. I'm constantly, aggressively refactoring when I write Obj-C or Java and my code is cleaner for it.
Thanks for catching this one.
I'll certainly take a look at YARD.
"Error establishing a database connection"