I think the language design makes tooling difficult, maybe even impossible. RubyMine does an ‘ok’ job, but still can’t follow a most metaprogramming patterns, and automated refactors are fairly likely to break things, which renders them unusable.
I think this is a real problem - I’ve actually experience code review debates where an implementation was dinged for not being greppable, which is a bizarre requirement when you think about it.
Fun fact: the modern IDE was first developed on Smalltalk because of its reflection capabilities. Nowadays most ‘dynamic’ languages seem to lack tooling pioneered by their forefathers. The tooling on Pharo, an smalltalk implementation, is awesome and continues to improve with every release.
Tooling nowadays is associated with static analysis, which is hard but it was pioneered an enabled by runtime reflection.
[Comment removed by author]
That’s awesome, and impressive, but does it mean that the IDE has just searched the entire set of messages and tried them all? That’s going to be dog slow in a large project. Is it based on documentation conventions (similar to “optional typing” in comments)?
No. It’s using the specified arguments to deduce a method type signature, and filtering the string object’s methods using the deduced signature. Then it iterates over the matches and calls each one, looking for which one returns the expected value. Most objects don’t have enough methods for the filtering to be slow. Calling each one may or may not be slow, but apparently it’s fast enough often enough to be a useful feature in the IDE.
I’ve never used SmallTalk, so I don’t know how well it works in practice. I could see it being great for learning the language, but I can think of a lot of cases where it couldn’t work (impure functions, etc.).
I’m not a Ruby expert, but I think it could be implemented in Ruby well enough to work most of the time. I don’t know how it would work for more complicated code depending on method_missing and weird meta-programming smoke and mirrors.
The author seems to think the grass is always greener. On the other side of the coin you have Java and Scala, which given a strong type system, have a vast array of tools with bundles of features that always seem impede more than help. Indeed, the nature of those languages allows you to make tools that on the label say they will make you a latte, but then proceed to take 20 minutes to compile your hello world program. This is speaking from experience; I can make my own latte, your job is to compile my program. Maybe this is a Java thing, but I’m reasonably certain C++ also uploads your entire program to skynet at 9600 baud each time you want to compile.
Or perhaps this is the inherently human element of software devolving into a cesspit as more people hop on the gravy train. Maybe this is why haskell has an elegant type system and tooling that doesn’t make my want to curl up into the fetal position and cry. But the fact that ruby is exceedingly dynamic actually spared it from the horrors that would have been introduced had it been possible to write more elaborate tooling for it.
tl;dr i wrote this entire post while my scala microservice was compiling
The lack of an “image” ala Smalltalk definitely has a downside in very dynamic language…..
A lot of information about a Ruby system simply fundamentally isn’t available until runtime.
A lot of Ruby code only “potentially” works….. it’s working is dependent on having The Right other stuff around at run time.
Sort of why I’m starting to favour the D language…. where you have the dynamism (at compile time) of Ruby, but the locked in static all types known at compile time of C++.