Hi.
Beep. Boop beep beep boop boop boop beep beep DING! boop boop bzzt bzzt bzzt...
I don't write too many nerdy posts nowadays. I decided to begin this one with a textual representation of the computer noises I'm making on my side of the screen. I'm like all, "Beep boop boop beep DING! boop beep beep bzzt bzzt..."
It gets me in the mood.
I'm making dot-matrix printer noises now, but I don't know how to spell them.
Before getting into the meat, I'm gonna remind you again about the $200 discount on JavaOne tickets. I figure it's more appropriate to mention it here than it was in my post about Snow Gods and The Never Ending Story. To take advantage of the discount, head over here and use the promotional code "iphone".
Now. The post.
As I've discussed here (and quite a few other places now), I'm not happy with the dev tools for OS X. I don't like Objective-C. The last time I dealt with a header file and felt OK about it was in 1992. Unless you're holding a gun to my head, it's unlikely that I'm going to willingly subject myself to my coding adolescence all over again. If you plan to take me up on the gun thing, by the by, make sure it's loaded and that you're ready to use it. If you hold a gun to my head, my ninja instincts will take over. I'll break your arm, break your nose, break your throat (yeah - the whole thing), and then hadooken you until you can't take it any more. Your only hope will be that you're faster with your gun than I am with my nunchucks.
I want to write client apps. Barring Objective-C and Cocoa, there really aren't that many options. When I code, I use an IDE. I never code with notepad or emacs or vi or any other antiquated crap. I want code-completion, a nice interactive debugger, a fancy form-builder, and a sane language that ties it all together like the rug from The Big Lebowski.
All roads lead to RealBasic [company page here], which is unfortunate. It's so close to being great that I have a hard time seeing the good in it. The biggest thing they're missing, from my point of view, is a nice, proper framework.
The current system is a messy combo of the global functions you'd find in Visual Basic 6- that come from who-knows-where, and halfway decent objects that offer some of the functionality you'd expect of them. What's frustrating is the division of labor between object functionality and those global, module-based operations. It divides your attention, and it more than doubles your effort.
I don't have a "code mode" for representing code here, but I'll see what I can do with block quotes and a little Courier New.
To give you a brief idea of something that drives me insane because it could so easily be solved, check this out - it's a little simple array handling:
for i as integer = 0 to UBound(someArray)
someOperationWith(someArray(i))
next
What do you notice?
Yeah: UBound. I haven't had to use something like UBound in... years?
That sort of thing pisses me off. I just want something like:
for i as integer = 0 to someArray.Count
someOperationWith(someArray(i))
next
That's all. Too much to ask? I don't think so. There might already be some nice object wrapper out there that provides this functionality, but I haven't seen it, and I think I read the manual, like, eighty times last night, and didn't find anything relevant.
My complaint, of course, isn't just with arrays - it's the design philosophy, and it's rampant throughout RealBasic. I'd list the number of global functions required for string-manipulation, but the quantity of data required would clog and bring down the entire net. Economies would collapse. The medical and emergency-response infrastructures would come apart. By the end of the day, we'd all be looting - we'd be fighting each other for flashlight batteries, bottled water, antibiotics, weapons, food, and shelter.
So, in the interest of the survival of our species, I won't list them.
You might not think this kind of "design" a big deal, but you might also be one of the people who only moved on to, say, VB.Net kicking and screaming.
There's no consistency to a language like this. With Java or .Net or any other platform out there with a proper framework, much of it is self-documenting. I've worked with enough languages and platforms that figuring out how iterate over an array using a property like "Count" isn't going to be very difficult. The namespaces change, the names change, the hierarchies are different, there are differences between the languages (think .Net properties vs. the standard Java getter/setter methods), but if you Get how to use and explore frameworks like these, just spelunking through the frameworks can teach you much more than a manual ever could. It's useful, but, if you love coding, it's also fun. Within twenty minutes, you can have a list of "Wow!" functionality you can't wait to use. Sure, it might exist in a VB6 or a RealBasic, but finding it will be a totally different experience, and one that, in my opinion, isn't especially fun.
Systems like this where "UBound" type functions are still the rule rather than the exception are much harder to learn. Picking up a language's syntax is often simple to the point of being trivial. It's the same thing for spoken languages of similar families - although I don't speak Italian, I've studied Italian grammar, and I can do just fine reading and writing it. I don't practice it enough to know it inside-out, but once I get warmed up, a lot of it comes back to me. It's easy because I already speak French and know a bit of Latin. I can read many Indo-European languages even without a grammar and do so with enough accuracy that I can at least get the gist of things, and that's because there are patterns that carry over from, for example, Spanish, Italian, and whatever else.
The difficulty comes from things like vocabulary. For me to express myself in one of these languages, I need to know more than the syntax/grammar, and the more consistent and regular the rules of the language, the easier it'll be.
Coding languages are basically the same. Many exhibit more or less shared patterns and structures. The real work isn't in learning the syntax. You could pick up the syntax of a brand new coding language in an afternoon as long as the document from which you're learning was written expressly on the language and its keywords/operators/etc. rather than the functions and frameworks you drive with the language.
The analogy breaks down in that spoken languages change too quickly to enjoy much regularity, but there are exemptions. Whether you like it or hate it, Esperanto has such regularity that you can learn the grammar in twenty minutes and a lot about its vocabulary in a few more hours.
A sensible language + a sensible framework is closer to Esperanto. A (possibly) sensible language + higgeldy-piggeldy inconsistent global functions and no proper framework is more like English. I love English, but it's highly irregular, and it's cruft upon cruft.
For me, languages like RealBasic fall somewhere between. I get the basic syntax, and I see the same patterns, but there are "symbols" that I don't have to deal with in my favorite (more) modern languages.
It's certainly possible to find "UBound" type cruft in C# or Java, but where there are oddities and relics, there are almost always clean ways to avoid them. VB.Net is a good example. It supports a lot of the lameness of VB6, but you don't have to use it. I'd be perfectly satisfied of RealBasic were the same. I don't care for the verbosity of VB.Net, but when you accept it, it's not much different from C#. The first app I ever wrote with VB.Net (Beta 1 of VS.Net) left me thinking, "They turned VB into Java! GOOD!"
The real pain of the "UBound"s of the universe is that you have to find them. You want to do something perfectly ordinary, and then realize that you can't do it until you find it in the documentation. Then, once you learn it, it's tougher - at least for me - to remember it because, unlike string functions sitting in a well-organized OO framework, it has no context. It's global. It's not self-documenting.
If I spent my entire life in RealBasic, I'd still dislike this, but I'd learn to live with it as I internalized all these functions. But, with no reason to their naming and organization, it's a real pain in the ass, and I plan to jump ship the second something better comes along, so putting in the effort doesn't appeal to me. I have faith. With the increasing popularity of OS X, I have to believe that things will get better as others experience the same frustration.
Anyway, it looks like there's been some effort put toward correcting this mess in RealBasic, but, in the example I'm going to give, it's actually not much better than it was before.
In an app I'm writing, I need to get a "FolderItem" that represents the user's home folder. If you code at all, and even if you don't use RealBasic, you ought to be able to figure out what a "FolderItem" is, so I won't bother explaining it.
I have two paths to the solution. The first is the Old Really Sucky Way, and the second is the New Not as Sucky Way. Something to note is that the first way is a sloppy hack because, although you'd expect to find a simple function that returned the user's home directory, you actually have to do a little work yourself, whereas, in the New Way, you don't. But, when looking through the documentation and code samples I found online, the first way was all I found until I knew where to look in the help for the second. But... the second STILL isn't properly documented, so it STILL isn't easily discoverable.
Perpend:
Old Really Sucky Way:
dim f as new FolderItem
f = DocumentsFolder.Parent
New Not as Sucky Way:
dim f as new FolderItem
f = SpecialFolder.DocumentsFolder
Looking at the Old Sucky Way, you'll see that there isn't a way to get a reference to the user's home folder - I have to ask for the DocumentFolder's Parent. This method should return the user's home folder most of the time, but this might change in some networked scenarios.
There are similar functions that will get you several other folders, though, oddly, not the user's home folder, which is just weird since that's one I'd expect to use fairly often. With the built-in global functions, it'd be easier to get into the user's pants than the user's home folder.
I did a search in the language reference for "DocumentsFolder," but it only returned an entry on the function "DocumentsFolder" I used above (or property, or however you'd like to refer to it). Unless you follow a hierarchical document tree in the language reference to the section on "SpecialFolder," you won't find out about "SpecialFolder," and that would suck since SpecialFolder does provide easy access to the folders you'll need.
What's even more frustrating is that, when you drill down to the "SpecialFolder" section of the docs, you get a list of some of the "special folders" you can get access to through it, but:
1. It's a partial list - it only lists the folders for which there are already global functions such as the one in the "Old Sucky Way" example ("DocumentsFolder").
2. It doesn't make it clear that "SpecialFolder" itself is a module. Because of this, I didn't think to try typing in "SpecialFolder." to get a code-completion list of its members. Since the list of "special folders" in the docs was the same as the ones accessible through global functions, I had no reason at all to think that it was anything more than the title for some entries in that section of the documentation.
This is just messy. They offer two way to get to the same functionality. The older one sucks, and the newer one is very poorly documented. That makes them both about as easy to use. Ultimately, they both suck, though, because they're both globally exposed without being part of a framework - you still have to either guess they're there, or divine their from the not-so-great docs.
Now, if there were a proper RealBasic framework, you'd expect a sensible object hierarchy that, under some File or Folder namespace, would expose a "SpecialFolder" static class. It would be self-documenting. I could find it with a few keystrokes and some code-completion. Something like "RealBasic.IO.Folders.SpecialFolder" - just import the proper namespace and go to town. File IO is common, common, common, and you'd just import the appropriate namespace so you wouldn't have to type out the fully qualified name. No biggie. Done. It's self-documenting and well organized.
I expect to find the usual apologists leaving comments and telling me that I'm stupid/lazy/hate it because it isn't Microsoft stuff or Java, but the reality is that I simply hate it for what it is. It isn't that I can't learn it - it's that there's a greater barrier to entry for RealBasic than there should be.
What's the point of offering an "easy" alternative to Objective-C/Cocoa when you have to do stuff like this? As much as I dislike Objective-C, Cocoa as a framework still makes sense.
I'm not just going to whine about it, though. That'd be the usual Crappy Customer thing to do.
I'm writing a simple framework to wrap some of the functions I'm most likely to use. I also plan to possibly write some object-wrappers for data types that could really use them. It might be that a lot of this has already been done. I didn't see anything in the docs, so if someone out there knows otherwise, do tell. Until I learn of an extant solution to his problem, I shall endeavor to do whatever I can to group this functionality in a sensible way that'll make coding for RealBasic a hell of a lot easier.
And, to address some concerns that might arise...
Whether you're into .Net, Java, Cocoa, RealBasic, or whatever, one of the first things you might be thinking about when it comes to object-wrappers is performance. This won't be a problem - at least not for the kind of apps I'm going to write. These are good ol' fashioned desktop apps. I'm not trying to optimize a web-app for eighty-billion simultaneous connections. I'm not rewriting SETI@home.
Eventually, I'm either going to set up a little site for OS X dev stuff I'm working on, or I'm going to post it here. I hope I put in the effort to do the site, but these Big Plans of mine have a way of getting pushed aside when Real Life and Real Work need my attention.
Wherever it winds up, I'm still doing it. The app I finished is a cute little utility that I think Mac users will dig. The other apps I'm planning are going to be larger. Not huge, but big enough that I don't want to deal with these poorly-documented global functions with inconsistent names.
That is all, my people.
Solidarity among Those Who Understand.
Like Neopoleon? Then donate, you cheap bastard: 