This is probably going to be a bit of a random ramble. You have been warned.
To start with, an odd statistic. On the 21st of January when SourceForge started tracking statistics for RoX it was ranked 52,731 based on page visits. There are 111,389 registered projects at the moment, so right from word go with just a handful of visitors (me, me and me) it was already ahead of more than half of those projects. As of today it's ranked at 4,439. That's a pretty significant bit of climbing. The thing is, the absolute page hits aren't that impressive. They peak at around 40 visits on any given day with an average of around 15 hits a day. That's not a lot. So how did it go from 50,000 to 4,500?
This tells me that there are a lot of SF projects that aren't getting any visits. Not even from their owners. Which means they're probably dead. That's a lot of dead projects.
Moving swiftly along. I've been writing some more Ruby code this week and I've had a few minor revelations in the process. I stand firm by my conviction that a lot of the "cool" stuff people are raving about (and this applies to other languages too) are mostly write-time optimizations. They let you do more in less. But I think that's the wrong place to be focusing on optimizing. It doesn't help in the vast majority of cases to reduce writing-time, especially when it's usually at the expense of the next person who has to read that code.
And no, I don't buy the "it's a more natural way to express it". That's completely subjective and while some people have raved about it I find Ruby code in general to be pretty jarring. Yes, I admit I'm more comfortable in languages I know better, like Java or Python, but a lot of the constructs that are Ruby-esque just get up my nose. And frankly, I don't know that any language truly feels natural out of the starting gate. There's always that initial "help, I can't find my own arsehole" phase while you get to grips with the way the API hangs together, naming conventions and library structures. Hell I remember Java's whole package structure/classpath approach caused it's fair share of headaches to start with.
So I realise that I have some way to go before I can really evaluate Ruby objectively. I'm still spending morning's calling my left ear my arsehole only to discover that, well, it's not. As a result I try my best to cut Ruby some slack and take this into account.
That said, a few things have crystallized for me this week. The first of these is that in general generated API docs suck. This is language independent. I noticed it first with Ruby's API docs. They tend to suck quite badly. There's usually nothing more than a handful of examples and that's if you're lucky. And if a method has a description it's often less than useless.
But this is not limited to Ruby. Indeed, look over the JavaDocs for a given open source project and you'll see what I mean. Sparse leaps to mind (occasionally, so does self-mutilation).
But, it occurs to me that in a dynamically typed language poor API docs are a bit more of a kick in the googlies than in a statically typed language. Often just having a method name and the types it takes (and returns) gives you enough of a hint to battle through an undocumented API (sure API designers can make even this impossible but it takes skill to do that). And if you're blessed with a decent editor (or IDE) then you get autocompletion which means you can usually get through any reasonable API without referring to the docs too often.
In a dynamically typed language neither of these "crutches" are available so you're at the mercy of the docs unless you feel like wading through the source code. And generated docs for a dynamically typed (Java/C++ style OO) language pretty much tell you that class Foo has a method called bar. If it's decently done you'll get names of parameters as well. Now granted, in some cases this is enough information, but it's still less than you get in a statically typed language. This is not about which is better or worse. It's just an observation that in one case there's less information available so you tend to be a bit more at the mercy of the person documenting their code.
Another thing that has crystallized for me is the whole write-time optimization thing I mentioned earlier. I've felt this for a while but I'm just seeing more things that reinforce it. One of these is the ability to reopen classes in Ruby. Effectively this lets you muck about with the class definition. This has some really cool uses. For example, if you do your logging through a static Log class (so you don't have to pass log handles between objects) then when it comes to unit testing time you have no way of confirming that that logging is happening under the appropriate conditions. So what you want is a mock object that records what is called and that you can query after the fact. One option is to back the Log class with some sort of pluggable instance and plug in a different implementation for testing. A simpler way (in Ruby) is to simply reopen the Log class and just change the way it works.
This is pretty cool until you realise that there's nothing stopping any code from doing this. What this means is that you can't really trust a class's definition at any point in your code. But that's not really a huge issue for me. What really bugs me about class reopening is when people do it repeatedly through their library. The Ruby net/http library does this. They reopen one of their central classes about half a dozen times in their library, each time adding a little more to the class.
So getting an overall picture of the class requires reading through the entire library, just to make sure you haven't missed any "additions". Ideally this would be non-issue because your IDE would show you the "finished product". But that's a little difficult because it would basically have to execute your code to get to that point because if it's going to be accurate (and who wants an inaccurate tool?) it can't afford to ignore the fact that any bit of code pulled into the library may tweak the class. But it can't blindly execute your code because you might have all sorts of ghetto shit in there writing files and opening sockets and doing all sorts of things you'd rather not have happening arbitrarily.
At the end of the day reopening a class, while cool, is a bit of a write-time optimization. It makes the job of writing the code far simpler but I think you trade away too much in terms of the ability to understand code you just inherited (or wrote a few weeks ago).
But I'll plow on and see if getting familiar with the libraries (probably my biggest frustration at the moment) reduces the impact of any of this.