Emacs Demystified

There’s a discussion on the Clojure mailing list about which development environment is most suitable for beginners who want to get started with Clojure.

If you’re already an expert IDE user for other work, such as Java development, it makes sense to try Clojure out in environment you’re used to. However, what should a beginner do if they aren’t already familiar with an IDE? If this is you, my strong advice is that you learn Emacs.

Emacs optimises the tail

Most tools try to optimise the first few hours of use by giving access to all the features via menu-bars and icons. These certainly make learning the tool easier. In fact, the Windows operating system seems to me to be designed to optimise a person’s first experience with a computer.

However, once you are familiar with how to use a tool most users find that using keyboard shortcuts makes them more productive, just as many computer users discover that they get more done with a command line. Duplicating access to a feature via a menu and/or an icon only adds to the visual clutter which, detracting from the overall experience. And when you’re trying to focus on creating content, visual noise can be a distraction.

Emacs is different. In Emacs, the keyboard shortcut is the primary way of accessing a feature. Many features aren’t even available via the menu and toolbar. For the sake of reducing visual clutter to a minimum I recommend you toggle off even the basic menu and toolbar that Emacs
displays when you first start it (see below for how).

So rather than optimise the first few hours of use, Emacs makes the subsequent years as productive as possible.

Once you’re familiar with a tool it’s easy to forget how you felt when you started out. I remember being a little overwhelmed the first time I tried IntelliJ, I couldn’t work out how to view 2 files side by side. I also remember finding Eclipse overwhelming, I was confused by its views and perspectives.

Practicalities

Learning any complex tool like an IDE or Emacs is not a trivial undertaking. But scrambling up the initial learning curve with Emacs is really not all that hard. Here’s how :-

Get Emacs.

Get a recent copy, version 24 or above. If you’re on a Mac, avoid Aquamacs for the time being.

Start Emacs.

Read the text in front of you. Start the tutorial. Run through the tutorial, have a break, come back and do it again. This is really important. Don’t try to do anything complex (like configure a Clojure environment) until you’re comfortable with the basics. Don’t try to learn everything in one go. Emacs has a long learning curve but it doesn’t have to be steep. Nobody knows all of Emacs and you don’t have to know much of it to start with. Gradually you will pick up new tips and tricks from other Emacs users and your own curiosity.

Minimise the visual clutter.

The tutorial will have taught you what M-x means.

 M-x cust-var<RET>
 Customize variable: menu-bar-mode
 (click Toggle, then State - 'Save for Future Sessions')

 M-x cust-var<RET>
 Customize variable: tool-bar-mode
 (click Toggle, then State - 'Save for Future Sessions')

 M-x cust-var<RET>
 Customize variable: scroll-bar-mode
 (click Toggle, then State - 'Save for Future Sessions')

Kill the caps

Rebind your useless CAPS-LOCK key to a Control key. On a Mac, you can
do that by going to Sytsem Preferences/Keyboard/Modifiers. GNOME and KDE
users can also do this via settings. For raw X Windows, I find it’s best
to add the following to your X conf :

Section "InputClass"
    Identifier  "Keyboard Defaults"
    MatchIsKeyboard "yes"
    Option  "XkbOptions" "ctrl:nocaps"
EndSection

Customize your Clojure environment.

There are plenty of tutorials on this. Find a recent one and follow it. Most advice is to use
nRepl. Personally I find nRepl to be still lacking in certain useful features so I run the original swank instead. In my lein user profile I add the swank plugin.

~/.lein/profiles.clj

{:user {:plugins [
                  [lein-swank "1.4.4"]
                  ]}}

Then I run up an Emacs shell

M-x eshell

Then I run the swank listener via lein to start my JVM with my project’s classpath

$ cd ~/src/myproject
$ lein swank

Then I connect to localhost and port 4005 (ie. the defaults).

M-x slime-connect

Then I locate a Clojure file and compile it with C-c C-k.

Install and learn paredit.

Many people recommend using an Emacs ‘starter kit’ which provide various bells and whistles intended for certain user groups (eg. Clojure developers). You’ll find many examples on github. My advice is to avoid these until you are more comfortable with the default Emacs environment. Personally I don’t use a starter kit and find that Emacs 24 has ironed out plenty of the wrinkles that these starter kits were created to address.

IDE strengths are not tuned to Clojure development

For Java developers there are a number of features that tip the balance
firmly in favour of using an IDE :-

  1. Java, being both statically types and verbose lends itself to
    code-completion facilities in the editor.

  2. Improving the design of object oriented code demands heavy
    refactoring, where a good IDE can greatly help.

  3. Java’s requirements on file organisation (one file per public class)
    means that large project can run into thousands of individual files,
    which are more easily accessed using tree controls characteristic of
    IDEs.

All these benefits are significantly less useful for Clojure
development, so the balance tips in back in favour of Emacs which excels
at text editing. As an expert user in multiple IDEs and Emacs I can
attest that the text editing in IDEs feels awkward and even cumbersome
by Emacs standards.

A sound investment

Commiting the time to learn Emacs is a very sound investment. I’ve been using Emacs myself since 1991. The initial learning curve was a few days, which is a tiny fraction of that 20 years. Many tools have come and gone since 1991, including Windows 3.1, Lotus Notes, Visual Age for Java. Emacs predates all these and it’s very much the same tool now (at version 24) as it was then (at version 18). I fully expect to be using Emacs for another 20 years.

That would be a big payback if I only used Emacs for development. But I can use Emacs for lots of other tasks. Right now I’m writing this blog in Emacs using a mode specially designed for creating Markdown formatted articles (which this is one). The same keybindings apply and much of the feature set is just as relevant as when I’m developing :-

  • slick navigation
  • text manipulation
  • bookmarks
  • git integration
  • kill-rings
  • macros
  • narrowing to region
  • grep-find

I don’t have to work hard to remember all the keybindings associated with these features, they are burnt into my muscle memory. If you haven’t yet learned to properly touch-type, I also recommend you add that to your ‘to-do’ list. Emacs is kind to touch-typists. Like vi, Emacs allows you to navigate without moving your hands over to the arrow keys and back.

The sixty-million-dollar mistake

The sixty-million-dollar mistake

Consider the following Java code :-

public class MoneyAmount {

    private double value;
    private String currency;

    public void getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public void getCurrency() {
        return currency;
    }

    public void setCurrency(String currency) {
        String validCcy = CurrencyManager.lookupCurrency(currency);
        if (validCcy != null) {
            this.currency = validCcy;
        }
    }
}

public static void main(String[] args) {
    MoneyAmount amt = new MoneyAmount();
    for (row : spreadsheet) {
        amt.setValue(row.getValue());
        amt.setCurrency(row.getCurrency());
        bookCash(amt);
    }
}

So far so good. All the unit tests pass, let’s deploy it into
production.

Everything goes well for many years. Then a small error occurs in the
input data :-

40000 USD
60000000 JPy

What happens?

Ouch! We’re going to book 60,000,000 USD instead of 60,000,000
Yen. That’s a significant mistake.

You may think that I’ve contrived this example (I couldn’t possibly
confirm or deny that on this blog) but it does show how subtle a
horrifying coding mistake can be.

Why did we make that $60M mistake?

  1. The developer shouldn’t have re-used the instance of MoneyAmount.
  2. The developer should have checked for the null case returning from CurrencyManager.lookupCurrency.
  3. The developer should have avoided using setter methods.

Let’s direct our questioning at a deeper level.

Why did the developer make these mistakes?

  1. The developer didn’t receive adequate education.
  2. Due to tight deadlines, the developer was not given enough time to think about the edge cases.
  3. The developer’s code wasn’t properly reviewed by a code-reviewer.
  4. There weren’t enough tests in the test suite.

These are all potential causes, but it’s not easy to see which one is
relevant and take corrective action.

  1. What constitutes ‘adequate’ education for developers?
  2. How do we manage projects so that estimates are accurate and there are no slippages.
  3. How do we enforce proper code-review and how much review is necessary?
  4. What constitutes adequate testing?

Many people are involved in discovering better answers to these
questions working within, as well as supplementing, their existing
toolsets.

I think these approaches are mostly ineffectual, at some
level. Otherwise I wouldn’t have contemplated bringing in a new
programming language into the bank. In the case of Clojure, it has meant
building a whole new toolset around it (including the IDE where most of
the developers on my team have moved to Emacs).

Mere tools?

Despite the disruption, I’ve been very encouraged by the effectiveness
that a modern tool like Clojure has on software quality. While I
consider a programming language as a tool, that may unfairly diminish
its importance. As an industry we are continually discovering better
ways of creating software and new programming languages are still the
main vessels in which we distill that experience
. Those who adopt a
modern programming language inherit the wealth of a generation’s
experience.

I began this article by presenting a real coding mistake. My experience
with Clojure means that nowadays I approach the issue differently. Why
did the developer make these mistakes?

  1. The tool encouraged it.

Ultimately, delivering reliable software to our users is more important
than our development tools, however much we’ve grown used to them. If
our tools are letting us make these expensive mistakes then we need to
consider their replacement.