What Makes a Programming Language Good

A year and a half ago, I quit being a professional programmer. For the four years or so previous to that, I’d made websites for a living, either for clients or for my own startup.

At that time, if you’d asked me what matters in a programming language — what makes one good — I would probably have talked about features. The languages I knew (and loved) best were Ruby and Javascript so I would have sung you a song of the epic deeds of dynamic languages: the clean uncluttered syntax, the power of easy extensibility, etc.

At that time I thought of a programming language’s virtues as inherent to the language. Having struggled, and mostly failed, to learn C and PHP before picking up Ruby, I felt strongly that I’d succeeded with Ruby due to its technical elegance. I’d failed with C and PHP for very different reasons: C because it was too technical, too close to the machine, PHP because it was too messy and cluttered. Ruby was the right balance.

But then I packed up my laptop and went to art school where I share a floor with 200 other students, most of whom are beginner programmers. Hence, I’ve found myself doing a lot of helping with other people’s code. This help ranges from debugging a simple typo, to working with someone until they really get objects for the first time, to teaching a semester-long weekly tutorial on web technologies.

Simultaneously, I’ve been learning a lot myself. I’ve wildly expanded the number and variety of languages that I work with. While I haven’t been programming professionally, I have been doing so creatively in a way that’s required me to take on everything from ATMega8 assembly to C++, Java, and Python.

These parallel experiences have simultaneously deepened my love for Ruby while completely transforming my understanding of what exactly Ruby got so right. While I started off thinking it was Ruby’s intrinsic qualities that made it good, now I realize that most of what I love about Ruby are not language features, but rather systemic and cultural qualities that I took for granted at the time never having experienced their lack.

Put simply, Ruby makes it easy to find and install code, easy to figure out what the code does and how to use it, and easy to run the code and see its results. That may sound like a statement so simple as to approach absurdity. Getting, writing, and running code are pretty much the only things that programmers do. However, it is increasingly shocking to me how painful these things can be in each new language I learn. I think the reasons for this are partially cultural and partially historical and I’ll return to them at the end of this post, but first I want to be more specific about what I think Ruby does so well — the parts of the Ruby ecosystem every other language most desperately needs to emulate.

Getting Code

It sounds kind of crazy when you type it out, but Rubygems might just be Ruby’s best feature. Rubygems is a package manager. It makes it possible to install Ruby libraries from the internet with a single command and then to use them with a single line of code. Importantly, Rubygems doesn’t force the user to think about where on their system the code is installed; they don’t need to know anything about paths or multiple versions of libraries or nested dependencies or anything like that. They just install the library and then use it. Rubygems also has a built in search command that lets users find libraries so, for example, if you need a gem to wrap the Foursquare API, you’d immediately find four results which you’d then be one additional command away from installing.

Rubygems has two major characteristics that distinguish it from other languages’ dependency management systems: it is centralized and it takes the existence of the internet for granted. The gem system is organized around Rubygems.org, a community-maintained site that provides free hosting for gems and their documentation as well as APIs that make the command line discovery and publishing tools work so well.

While anyone is free to run their own gem server or distribute gems by Jazz drive or whatever other means they find appropriate (in fact the current rubygems.org started off as Gemcutter, a competitor to the original centralized gem host), in practice 99% of publicly available code is on rubygems.org. And the technical infrastructure around gems makes it simple for users to configure their machines to access multiple hosts transparently. As we’ll see over and over again, this is an example of Ruby’s culture which values competition to come up with the best way to do something combined with a rapid total adoption of new systems whenever consensus is reached.

These characteristics also make it extraordinarily easy to publish a gem. It is a simple matter of moving your code into a couple of files in a specific format and then running some command-line tools that package and submit the gem via rubygems.org’s API. There’s no hosting to setup or maintain. It really is fire and forget.

Figuring Out Code

But Ruby programmers don’t tend to fire their code and forget it. They tend to write thorough blog posts and clear READMEs, produce slick tutorial videos, and publish regular podcasts explaining it and teaching people how to use it. This is the next “feature” of Ruby that I most miss when dealing with other languages: the culture of documentation.

With many other languages and frameworks, when you google looking for code or answers, you’re most likely to find forum threads, q&a sites, and a heap of broken links. With Ruby, you’ll usually find the gem’s Rubyforge page and a recent blog post. To continue the Foursquare example I started above, I just popped “ruby foursquare api” into google. The first two results were the Rubyforge site for the API wrapper and a blog post from November about it.

At a deeper non-day-to-day level, Ruby has amazing materials for beginners: Chris Pine’s “Learn to Program”, which may be the best introductory programming text I’ve ever seen and, of course, the legendary _why’s Poignant Guide to Ruby. It also has great podcasts and about a billion blogs tracking all the most recent developments.

Ruby has these things because they are valued by the community. People like Geoff Grossenbach at Peepcode can make a living creating awesome, beautifully well-crafted educational materials because Ruby programmers are willing to pay for something so good. I know from personal experience that people who write about Ruby well and often get offered conference gigs and jobs.

Writing Code

When you’re working on software anything that isn’t thinking, typing, or watching your code run is extraneous bullshit. This includes waiting for your editor to launch, waiting for your code to compile, editing build scripts, creating arcane directory structures, and modifying configuration files or boilerplate code, amongst many other things.

There is simply no other development environment I’ve found that includes as few of these things as the Interactive Ruby Console. Being able to input code and immediately see the results means you can explore an API, build a data structure, or test out an algorithm at a rate limited only by your mind and fingers.
While other languages and platforms have similar setups (notably Javascript with Firebug and the WebKit Error Console) in my experience, code written in IRB better translates into “real” code in a project than any other such system.

Further, while I know there are people who like IDEs, for me they serve to cripple the exploratory play of coding so that it’s about as fun as filling out tax forms. A big exception here for the Processing and Arduino IDEs which, though imperfect as text editors, really do eliminate an immense amount of bullshit usually associated with building and running programs in Java and C++. But, in general, if your language, platform, or environment, has such a complex dependency management situation, maybe you should solve that by, I don’t know, improving the packaging system, rather than also ruining the editor.

Granted the command line also has a learning curve and can be intimidating for beginning users. But I don’t think these compare in any way to the problems created by IDEs or complex builds. There’s even an eccentric tradition in the Ruby community of trying to automate and GUI-ify the running of command line scripts to address this problem (see, for example Aaron Quint’s Vegas and Locomotive for Rails from back in the day).

Having only the tab key, the up arrow, and the return key between having made changes in your code and seeing them run on the command line or in the browser is priceless.

Conclusion

Obviously there are ways in which these extrinsic qualities are made possible or at least easier by some of Ruby’s intrinsic properties. Rubygems would be harder to implement in a static language that couldn’t override its own built-in “require” method. The interactive console is mainly the domain of interpreted dynamic languages (even though compiled Erlang has one too).

But other languages with very similar technical aspects, notably Python, have not succeeded as fully on important things listed here mostly for cultural reasons. For example Python has at least three package distribution systems you’ll encounter when attempting to install software of any complexity (eggs, easy_install, and plain old download files into place). And great ideas in Python that need standardization (such as WSGI) have failed to achieve universal adoption only to be picked up by the Ruby community to great effect (i.e. Rack).

Why? I don’t know enough about that community to really answer, but since it’s basically the only major contrast between them I’ll bet it has at least partially to do with the languages’ difference in age.

What makes Ruby different? Why does Ruby get these things right where so many other languages get them wrong? How did Ruby acquire the good parts of its culture? I think the answer lies, mainly, in Ruby’s youth. Ruby was first created in the mid-90s and didn’t even begin to achieve adoption until 2003 or 2004. Hence it is the first widely influential language born and bred in the web era.

Nearly all of the positive aspects I described in this post would be hard to imagine without the omnipresence of the internet. The Ruby community comes to consensus quickly because all of its communication tools have always been online (and as Web 2.0-ish communities rather than old school geek slugfests) and many of its users are “digital natives”. It uses centralized but loosely-coupled technical infrastructure (such as Rubygems.org and Github) because that’s the kind of infrastructure the internet encourages. Reputations are made online via public contributions to code and documentation rather than privately through corporate jobs and invisible projects.

If I were a zealot for one of the older languages (C++ or one of its frameworks; Java or one of the new languages running on the JVM, etc.) I wouldn’t be porting web application design patterns or bragging about performance. I’d be making sure it’s stupid simple for web-connected users to find and install libraries, that no google search ever returned an 18-month old forum thread, that any user who wrote awesome blog posts was treasured, that creating a new project or running an example app was always a one click operation, and, above all, that getting, writing, and running code on my platform was easy and surrounded with joy.

This entry was posted in Opinion. Bookmark the permalink.

14 Responses to What Makes a Programming Language Good

  1. empire says:

    I don’t see how any of this is unique to Ruby. Rubygems isn’t unique or without fault — I don’t suppose you’ve ever heard of CPAN, pip, easy_install, PEAR, cabal, et al.? Rubygems is basically a poor man’s CPAN. BTW eggs and easy_install are the same thing, and any package worth having is available at PyPI. But that’s not necessary because the Python standard library kicks ass (Ruby’s doesn’t).

    Additionally “anything that isn’t thinking, typing, or watching your code run is bullshit” — you’ve probably never taken the time to think of how much time you waste watching slow Ruby scripts run. It’s far less than the time spent compiling a C or Java program, and guess what else — you can do other things while your code compiles!

    WSGI is now a standard, thank you very much.

    Feel free to like Ruby but it is not The One Way to do things.

    • Ernie says:

      I came to Ruby after spending years in the Perl world, and while I love CPAN, to call Rubygems a “poor man’s CPAN” does an immense disservice to Rubygems.

      Greg’s already done a great job explaining what makes Rubygems special, but the most important thing is ease of use, and ease of contribution. The fact that http://www.cpan.org/modules/04pause.html exists to describe the process of contributing to CPAN, while https://rubygems.org/users/new is the process to start contributing to Rubygems should make that difference abundantly clear.

      There are many reasons for the data at http://www.modulecounts.com/, but simplicity alone is reason enough.

  2. greg says:

    I have, of course, heard of CPAN and PEAR. And thanks for correcting me on pip vs. eggs vs. easy_install, I can never keep straight which is which.

    My point was never that other languages don’t have package management systems, but that like in every other case I mentioned in the post, it’s the complete consensus that eliminates any possible confusion and the focus on ironing out every irritating kink or obstacle that makes the Rubygems systems work so well for me.

    In regards to your comment about “watching slow scripts run” that’s totally a red herring. Not to pick on anyone, but I watched an Open Frameworks app in XCode take more than a minute to compile today. I don’t think I’ve ever written a Ruby script that took more than a few seconds to start up. At least while code is running I’m learning something about what it’s doing (if I’m debugging). Maybe you live in a world where most of your concerns are how long your code takes to run, but I spend a lot more time writing explorative code and designing on paper than I do watching my programs run.

    In Eclipse and XCode you definitely can do other things while your code compiles: you can read twitter. Or Hacker News. Or Reddit.

    And my point here at all is not that Ruby is The One True Way at all. The whole premise of my post is that there’s nothing in these virtues that are intrinsic to Ruby, they’re things that every language can do and that (as you point out) many other do to a greater or lesser extent. I guess what I’d emphasize (if I didn’t do so clearly enough in the post) is that it’s the attention to design detail of these three core processes that I really appreciate when returning to Ruby from other languages and environments.

  3. Anonymous says:

    What do you know of haskell and Hackage?

    It’s fully statically typed and it works great. Hackage and cabal work just fine for pulling down and resolving dependencies and it’s build system is absolutely excellent.

    The fact is that you shouldn’t have made such broad claims and you probably shouldn’t have written this blog post. When one does not do their due diligence and bother to research the topic they are writing about, one tends to make regrettable and unintentionally controversial yet ignorant blog posts.

    Use google, it would’ve showed you otherwise.

    • greg says:

      Great to hear that Haskell has some of these good features. If you read my post you’ll notice that the whole point of it is not that Ruby is great because it’s dynamically typed or even that Ruby is great at all. It’s just some observations about the sources of pain I’ve experienced using other languages in contrast to some of the things that I found worked smoothly in Ruby because of design consideration given to extrinsic parts of the programming process.

      I’m glad Haskell has some of these too, though, I haven’t really been able to get too started with Haskell despite having some interest in it because I haven’t found great friendly, inviting documentation. I bet some it is out there, but it did not immediately reveal itself to a first curious search.

  4. mike says:

    I first started using ruby about four years ago, and continue to use it today. In terms of intrinsic qualities, I think the ruby syntax structure is both a blessing and a curse: sure you can write up a DSL in half an hour that produces some gorgeous code, but by the same virtue, a lot can be expressed with relatively-little code, and when lines carry so much and move so fast it can get confusing for other people reading your code, or even yourself when you revisit your project after a few months. I guess what I’m saying is that with the freedom comes the responsibility to write clearly, and you have to be careful because this responsibility can be *easily* abused.

    In terms of non-intrinsics, I totally agree and love the token blogs and podcasts that demo how to build up a project with impressive functionality in five minutes. But there are many parts of the process that are still platform-specific, e.g., developing on windows when using particular gems can be a huge pain. This has been slowly improving over the years, but it still has a long way to go. I think this may be in part because of where ruby is in its lifecycle, but also in part that the general trend in coding is to streamline the development process so that coders can devote more time to the problems their application is trying to solve as opposed to the problems that need solving in order to implement the application.

    great post, i enjoyed reading this

  5. florin says:

    Your post betrays love struck. That’s a good thing. As far as I am concerned, I’m waiting for ruby to produce a web framework that does not mix html with code. When that happens, I jump in. My brains numb when I think that some of these dynamic languages wield this arcane templating habits.

    When doing java / groovy / javascript, I use IntelliJ IDEA with jrebel. The compilation is on the fly via error highlighting. With jrebel I rarely need to restart the app – webapp or not. Navigating code and refactoring are unmatched.

    But I do itch for ruby. Still waiting..

  6. Jim says:

    I think you’re on to something about the importance of the community. It is more of a meritocracy than other languages. Rubyists earn respect by their programming talent, rather than how many degrees they have, what Fortune 500 company they are working for, or some fancy job title. It just feels more free of corporate BS and “white papers”.

  7. Mark Essel says:

    This goes a long way to explaining how I feel about developing with Ruby and why JavaScript feels like a cousin (albeit a crazy one). Coming from 14 years with c++ I has assumed the dynamic nature and readabilty of code were the features that I was evaluate with. But there’s so much more.

    Thanks for pointing out why you appreciate Ruby’s design and usage.

  8. James Iry says:

    > The interactive console is mainly the domain of interpreted dynamic languages (even though compiled Erlang has one too)

    Nope! It’s just mainly the domain of non-C languages, whether interpreted or not, whether static or not. http://james-iry.blogspot.com/2011/01/read-eval-print-lie.html

  9. Chris Eigner says:

    Enjoyed your post Greg. I think you hit the nail on the head. It’s very easy to pull down some code and hop right in to an entirely foreign project. Rubygems, and recently bundler, make it easy to resolve dependencies, getting a local copy of a project up and running can be as simple as 3 commands. The ease of development, and readability of the language to an extent, lower the barrier to entry for contributing to open source ruby projects.

    In a sort of language natural selection, I see some of that enthusiasm bleeding into other communities as of late. I would have considered some of the more esoteric languages like Haskell and Erlang out of my immediate reach. But sites like http://learnyouahaskell.com/ and http://learnyousomeerlang.com/ are making these languages much more approachable for beginners.

    Good post. Keep up the good work.

  10. j1n3l0 says:

    Great post Greg. I agree with most of what you’ve said and I’m glad to see I’m not entirely crazy when I think of features to look for in other languages:

    > easy to find and install code
    Rubygems does make this a very painless process

    > easy to run the code and see its results
    irb handles this great and you can quickly try things out, find they work as you expect and make them more permanent 😉

    > easy to figure out what the code does
    This one i think could do with some work. You’d be surprised how useful a little snippet showing how the module you’ve found could be used can be. Very few gems have this feature, opting instead for a professional website and a list of classes and methods. This is improving but it’s something that has bitten me on a number of occasions … most recently yesterday 🙂

    Thanks 🙂

  11. Phil says:

    If you like irb, you should try SLIME, it’s really a whole new level of interactivity.

Leave a Reply

Your email address will not be published. Required fields are marked *