Articles

I often find, when adopting a new tool or language, to try to learn how to use it as it was meant to be used. Sure you could write Ruby code like a Java developer but far better to write Ruby like a Ruby developer. Idiom\
s matter.

To that end, lets approach Emacs as a beginner with few preconceived notions from VIM. I’m not suggesting that you forget all of the lovely features that you enjoyed in VIM but instead that you should start with the basics\
and build up from there.

So to begin at the beginning:

A quick google led me to Emacs’s built-in tutorial: C-h t. The built-in tutorial is a fantastic place to start. I found it more accessible, due to its narrow focus, than vim’s. That said, the tutorial will \
give you just enough to be comfortable with simple navigation within emacs.

Among the many features the tutorial will introduce you to is “help on help”: C-h C-h is perhaps your best friend. From there, emacs provides several different avenues to discover new functionality and elabor\
ate upon what you will learn.

Help yourself!

C-h C-h: help on help, literally. This function gives a summary of all of the built in help features and the keybindings to invoke them directly.

C-h b: list all keybindings.

C-h c: display the function run by a specific keybinding

Copying, yanking, pasting, deleting, and killing

As a newly-minted Emacs user, you’re probably wondering how to yank and delete. Be warned “yank” means exactly the opposite in Emacs as it does in VIM. Wacky, right?

In VIM, you yanked/deleted text and then pasted it. With Emacs, you “copy” or “kill” text then “yank” it into place.

With all of this in mind, let’s turn to our new friend C-h b.

Text search

C-s RET : This puts you in interactive search mode (which, frankly, at this point, I’ve far from mastered). At its most basic, interactive search will navigate you forward through your current bu\
ffer toward the first matching characters. Subsequent presses of C-s will lead you to matches further forward in the buffer and then eventually wrap to the top of the buffer.

Discovering functions

My first big “Ah ha” moment with emacs came when I realized that I could use to invoke any “interactive” functions in emacs. That is, you enter M-x then begin typing the name of a function. Aft\
er a few letters, if you hit return, emacs opens a window showing you all of the matching function names.

yanking: I’m sure there’s a scholarly article somewhere in uncovering the history of yanking in the *NIX community but I will leave that as an exercise for the extremely atypical readers.interactive: functions are emacs lisp functions containing a call to the “interactive” function thus informing Emacs that they may be invoked interactively.

After 18 long years of vi, I finally switched to emacs. Despite many attempted explanations in <= 140 characters and numerous requests, I’ve relented and written this to explain why.

I’ve been a remote worker for over 4 years now. But, as an extrovert (yes, I’m freakish that way as a developer), I love to pair program. I’ve blogged about my pair-programming tool chain in the past. That tool chain has continued to evolve. The crucial point: I need to live in my shell to remote pair as I do.

And most recently, I learned that modality kills.

VI is modal. Tmux, my preferred terminal multiplexer, is also modal.

modal * modal = modality2

Put another way, usability goes straight to hell.

So here I am, minding my own business, writing some code in VI. When, all of a sudden, I decide that I want to switch to my terminal running in the other window in my vertically split tmux session. So I switch windows and try to scroll up with Ctrl-u. What the hell? Why doesn’t this work? Ctrl-u Ctrl-u Ctrl-u dammit!

Oh. Right. I’m in tmux. Ctrl-b [ Ctrl-u works. Finally.

Now repeat this a few hundred times.

(Much cursing at VI and tmux have been elided here to reduce your enjoyment of this article.)

The basal ganglia, physical memory, doesn’t understand this modal shit. You’re doing something. Then you’re doing something similar. It should work pretty much the same way, dammit. If I’m banging around in a terminal or hunting a sabertooth tiger the mental model should remain consistent. But, oh, that’s right: digital reality has little basis in the real world. Unfortunately, our brains just don’t quite get that.

And, dammit, modality makes all of that worse.

Sure, I learned to cope with VIs modality. Sort of. Let’s be honest, VI users. You know that you frequently are in command mode when you thought you were in insert mode and vice versa. But you develop coping strategies. Then you almost forget that you’re using them.

Now imagine having to have habits to cope with making that same mistake but in a shell within tmux instead of the VI session that you thought you were in.

Down this path lies madness.

And, so, I found my way to emacs. Emacs gives you eshell for standard: a LISP-based terminal emulator. ansi-term is a small step up from eshell. But I still found myself having problems with it. Then my friend Avdi Grimm pointed me at multi-term. I have been happy ever since.

You see, multi-term is a “major mode” of emacs. While it does commandeer a great many of the ordinary key bindings, at least I can scroll up or search through a multi-term history the same way that I would any ordinary emacs buffer. Though, for the life of me, I cannot understand why scroll down automatically throws me back to the prompt instead of actually scrolling down.

Oh, did I mention that emacs has an actual programming language, emacs lisp, instead of the vim’s sadomasochistic vision of hell known as vimscript?

Yes, I still use tmux. But now I solely use tmux per its name: as a terminal multiplexer. I don’t need to create windows: emacs gives me that. I don’t search within tmux sessions: emacs gives me that. Tmux barely matters any more except for facilitating sharing my session with another user. And that’s about it.

In case you’re deeply concerned about the productivity hit, I was running at about 75% or so after just a few days.

If you remote pair and live in the shell, you owe it to yourself: switch to emacs.

It is key to abstraction. An abstraction with a poor name will often be misunderstood.

As I teach myself Clojure, I find myself reflecting on all of the functional code that I’ve seen in my career: the Lisp, Haskell, Erlang, and Clojure.

There is a single common thread through them all that troubles me: the names chosen for their core library. There’s a terseness to all of them. It makes for a steeper learning curve. However, for some aspiring functional programmers, the curve may be so steep as to be exclusionary.

The core functions outline the idiomatic use of the language. And, so, most functional programs I’ve seen have a strong tendency toward abbreviated names for their functions and their variables.

I fail to see how this is a good thing.

I can hear them now: “But, Evan, you’re a pathetic C/Java/Ruby programmer who has only dabbled in functional programming. You just don’t understand.”

What am I missing here? We’re far from the world where programmers may have measure code in byte sizes due to storage constraints. Can we all agree then, in this modern age, that we can stop fussing over saving bytes and just use meaningful (in the literal interpretation: full of meaning) names?

While I prefer conciseness, I’ll gladly take verbosity in its absence. Either are better than a name so terse that it results in a leaky abstraction!

Over the past year, there has been a strong popular push toward what I’ll describe as purely SOLID-based approaches to building Rails apps. While I attempt to adhere to SOLID as a series of guidelines, they are just that: guidelines.

Evidently, once, someone caught me saying “Use Rails until it hurts”. By this, I meant “don’t preemptively implement around perceived Rails weaknesses solely to respect SOLID/your-favorite-OO-principle”. This does not add value to an application.

I recently wrote about #accepts_nested_attributes_for. In that post, I explained that there are clear circumstances where #accepts_nested_attributes_for will save you time and code. However, in many cases, it won’t. And, for those, I began working on an alternative.

Contingencies are good. Once you deviate from Rails’ “golden path”, your work can quickly become challenging. But knowing that a person/tool/technique has a weakness does not mean that you automatically preempt them. It means that you should remain aware of that weakness. You should compensate for weakness when it becomes an issue. To do so sooner smacks of angst.

Let’s consider the discussion here around the Observer pattern versus the benefit of a tightly coupled imperative style. The Observer pattern decouples event producers from event consumers. For that matter, the Observer pattern is similar to Queue-based messaging services such as the CORBA Notification Service, Java Messaging Service(JMS), and all of those that followed save that it is, typically, implemented in a synchronous fashion and within a single process.

As cited in the C2 wiki, the Observer pattern is best used for “dynamic relationships between objects.” There are relatively clear guidelines around when to consider employing it.

So what about when relationships are not dynamic?

Under these circumstances, I posit that tight coupling can be helpful.

What is tight coupling good for? Used selectively, in a word: clarity.

Which is clearer? (Please bear with my non-ActiveRecord ActiveRecord example for the sake of argument)

or

The Observer (listener)-based example at the top decouples the save event from the pushing the change to the client event. While you can argue that these are two different responsibilties, they are both directly related to the change on the User’s name. I argue that this approach adds unecessary indirection.

To speak more broadly, I argue that our campaign against tight coupling has simply gone too far.

In the latter case, we have less code! This is, often, considered a good thing1. The controller, responsible for performing the change to the User object, also pushes a notification to the client of the change. The tight coupling makes this entirely clear: when I change the user’s name and save the user, I immediately push the change out on a socket to the client.

Yes, you can make a case for extracting the behavior from the UserController#update method into its own method or even class.

Whether to extract the logic out of the controller or not should be a fuzzy decision. Yes, the update method is clearly responsible for more than just routing. This is “bad”, right? Or is it?

If we extract a class to represent the context of the User’s name changing, we’ve just created another file and another class. Also, where does this class go? To me, it’s just a delegate of the controller. It’s certainly not business logic. Pushing a message out on a socket does not represent business logic at all. Instead, it’s just how we interface with our View/Client. Extracting a class, in this case, increases the cognitive burden on ourselves or any developer who comes after us.

If we extract a private method instead of extracting a class, we’ve added a layer of indirection instead of abstraction. Frankly, I’d lean toward something like this.

But, clearly, this will lead to a fat controller! ¡Qué terrible!

Personally, I would instead characterize it as a controller of a healthy weight.

Moderation is key. Noticing its lack is as well.

I hope that, from the above example, you’ve decided to stop factoring everything into another class and, occasionally, give tight coupling a chance. That said, if you’re among those who write “god classes”, “god methods”, and is unfmiliar with “loose coupling”, I strongly suggest reading Working With Legacy Code by Michael Feathers (the man who coined “SOLID”).

Rails isn’t perfect. But it is one of the best solutions for the problem space that most of us work in. Use Rails until it hurts. Don’t preemptively replace Rails features. Use Rails until you find yourself writing more code doing it “The Rails Way” than if you rolled your own solution. Then identify an alternative solution. Use that alternative solution as your application’s fallback convention for when the matching Rails convention fails.

While Rails provides many solutions out of the box, you should make a concerted effort to keep your own personal toolbox of fallback techniques (such as the Form object) on hand. Share them. Convert them into tools for use by your peers whenever possible.

TL;DR: #accepts_nested_attributes_for is not evil but it should be used infrequently. It often results in brittle code. Consider using the redtape gem (which offers an implementation of the “Form Object” pattern), instead.

#accepts_nested_attributes_for is used, in ActiveRecord classes, to reduce the amount of code in Rails applications needed to create/update records across multiple tables with a single HTTP POST/PUT. As with many things Rails, this is convention-driven: the ActiveRecord classes expect to receive their POST/PUT parameter according to specific naming conventions used solely for nested data.

While this sometimes results in less code, it often results in brittle code.

In order to benefit from this coupling, we now have to:

Write forms/HTTP clients that will send the nested data expected by the model

Have the receiving controller action simply passes the data through to the correct “top-level” model’s #new method.

Not require additional massaging of the HTTP params otherwise we’re just writing more code which is what #accepts_nested_attributes_for is trying so hard to avoid.

In my experience, use of nested forms often requires at least some massaging of the data if not outright removal of #accepts_nested_attributes_for at a later time in favor of handling the data manually within the controller action.

That is, it’s brittle.

So let’s go on a tangent: “best practices”.

“Best practices” are dangerous. Few, if any, so-called “best practices” are universally best. They’re perhaps best in a particular context. Yet developers often treat them as panaceas (a discussion for another day…).

So let’s put this in context:

Only use #accepts_nested_attributes_for if all of these conditions are met:

(If you have a UI,) The UI fields can map, one-to-one, to the model fields; You know that you can afford to tightly couple the view and model so that they vary codependently on one another.

Conversely…

Use redtape if you need your UI to vary independently from your model.1.

Consider using redtape if your input data requires pre-processing prior to hand-off to the model. Obviously, you can do this in a private/protected method of your controller as well.

Ultimately, the goal is to have working, maintainable code that satisfies your needs with minimal effort. Choose the simplest path to arrive there. Consider your options and weight them accordingly.

1: I know what some devs out there are thinking: “But, Evan, SRP says I should always allow them to vary independently.” Yeah, well, sometimes you should break the rules but that should be the exception and not the norm. Not that SRP is a “rule” so much as a “guideline”. Pretty much the only “rule” of software development is “thy program should execute deterministically”.

UPDATE 1: I had considered making this argument in my Frustration Driven Development talk but, then, I didn’t have a solution at the time. I hate providing a criticism without presenting an alternative…

UPDATE 2: Redtape::Form includes ActiveModel::Validations. You can add validations to your Redtape::Form just as you would an ActiveRecord::Base subclass. Beware: Don’t duplicate validations from your model in your Redtape::Form. Instead, add validations if your form inputs are raw values requiring processing before being used in your model. Your form can then catch these errors early and provide contextually useful error messages.

Posted by evan on Nov 07, 2012

My business

About Me

My name is Evan Light and, yes, I am a nerd. I'm also a professional software developer who, after spending one too many years contracting to the federal government, escaped into the far more enjoyable commercial world. Having spent several years using C and even more using Java (the latter very nearly caused me to give up programming entirely), I consider myself fortunate to have discovered Ruby and to use it as part of my daily work.