Ode To My Anger With Dropbox
Dropbox is a great idea. If you
don't look behind the curtains, it works really well too. For the
unfamiliar, Dropbox is an application that sits resident on your
machine, syncing files in a magic directory up to the server.
Changes are propagated to any other machine you've linked to your
account. The files live on your drive so if your network connection
drops, you still have your data.
Lately, I've been working on Net::Dropbox, a library to connect to
a local dropboxd instance and get information about your files or
the daemon's operation. Here's the fun part. The Dropbox folks have
released an open source nautlius plugin to talk to the closed
source dropboxd. Instead of real documentation, the staff points to
this source code, and contributed community code on the wiki, as
"documentation of the 'api'".
The "api" (in this case, commands accepted over two local unix
sockets) changes in almost every release. The Dropbox team
certainly has the right to do that but it makes the aforementioned
"documentation" really problematic.
The wiki-provided code can immediately be dismissed. There are 10
or 15 scripts in every language imaginable on the wiki. For the
most part, they were written months and months ago. The "api" has
changed in ways that makes that code completely irrelevant and,
with few exceptions, totally unusable.
As for the nautilus plugin source.... *sigh*
Let me get my "I'm a C programmer" rant out of the way with first.
This code is terrible. Forget documentation. How about comments? We
have comments like "oh god" and "not thread safe". Great, guys. You
don't have much in the way of useful comments but you do have the
"low bridge" and "deaf child area" signs up.
The formatting.... Shortest summary: "STOP MIXING WHITE SPACE AND
HARD TABS IN INITIAL INDENTING. FIX YOUR EDITOR, DIPSHIT. YOU ARE A
PYTHON SHOP. HOW DO YOU NOT UNDERSTAND THIS" *ahem*
Look. This is C. It's a language that allows macros. This code uses
them a few times. When it comes to figuring out all the ways that a
connection might fail, however, the "let's disconnect and return
'uh, we timed out'" code is duplicated time and time again. In
send_command_to_db, I count 4 copy and paste moments. This
happens a lot.
These folks fucking adore glib. From my read, some python folks got
their hands on gcc and tried to do a literal translation.
Everything is a glib hash, no matter how temporary the data. "Find
some data. Shove it into a new glib hash. Look at the data. Free
the hash." Some routines do this 5 or 6 times. *grumble*
Further, the code is completely tied to gnome/nautilus. When it
builds the command block to as for status on a file, it takes a URI
from nautilus, converts it, via another magic nautilus comand, to a
better URI, utf8s that, and sends it along. Ok. What does the
nautilus URI look like? Certainly the gnome folks have documented
that. Nope. Their docs simply list that the relevant routine
exists. I have to write some goddamn test code, or guess wildly, to
figure out what that uri looks like internally. I am Jack's
perforated colon.
To summarize: While I've certainly worked with worse code, I was
getting paid lots of money to do so. Reading this code makes me
want to charge someone a consultancy fee.
Now for my "I'd like to use your code as 'documentation' as you
suggested" rant. Good documentation, or the myth of
self-documenting code, has one major attribute: clarity. What goes
in and what comes out? What commands can I use? "Clarity" is
apparently Swahili for "I'd like to play hide and seek in a septic
tank." As noted above, I have no love for this C code. The protocol
elements for dropboxd are pretty simple text blocks. It took me
about 20 minutes to figure that out as a C programmer. I can't
imagine how long it would take someone who doesn't know any C.
Anyway, generating output is this big "fun" glib hash run-through.
Parsing the output is buried in a single function which I missed
for a while. It calls out to *another* routine...
At this point I attempted suicide.
It turns out that generating commands and parsing the response is
brain-dead easy. The perl code is tiny tiny. I spent about 5
minutes on it. After several hours of digging through C code and
drinking myself into a stupor.
Question #2: what commands does the daemon accept? I've found 4
read-able commands and one write command. At this point, I have a
routine that lets me make crap up and throw it against the daemon
to see what happens. Most of the work I'm doing is figuring out new
commands and their arguments.
WHY IS THIS SO DIFFICULT? Seriously, all this work could be avoided
by a simple damn text file. It would be maybe 30 lines long.
I do have one thought. If you've made if this far, I have a
question. Would you be interested in an open source replacement? At
least then I could be angry at *my* crappy code...