Tech Pubs Tuesday: Use Spellcheck

I’m pretty sleep deprived this week thanks to my ADORABLE BABIES WHO I ASSURE YOU CAN DO NO WRONG, and so my wife recommended keeping this week’s Tech Pubs Tuesday short and sweet. “How about something like, ‘Use spellcheck,'” she joked.

Ha! Little did she know that “Use Spellcheck” is actually on the list of possible topics I wrote out ahead of time. The joke is on her!

So. Use spellcheck!

Spellcheck is one of your best friends when you’re writing technical documentation. More accurately, spellcheck is your only friend when writing technical documentation.

Certainly grammar check isn’t a very good friend. Grammar check is like that “friend” who keeps passing around links to Truther theories or inane inspirational messages, and man, you’re totally going to unfriend grammar check when you finally get around to pruning your friends list. But spellcheck! When you need to move furniture across town, spellcheck is right there with her truck. Good old spellcheck.

“But Evan,” I hear you say. “Spellcheck doesn’t have all the technical terminology that I need! ” To which I say, “Right-click, Add to Dictionary.”

“But Evan,” I hear you say. “I use vim to write documentation, not some sissy GUI text editor.” To which I say, “I use vim to write documentation too!” And vim has a spellchecker. In fact, the vim spellchecker is… kind of interestingly nerdy. So start using it.

Seriously! Use spellcheck. It’s like having a test suite for your documentation. Or it’s about as close as you’re going to get to testing your documentation this side of the year 2050.

Thank you for your attention. And God help me if there are any spelling errors in this one.

Tech Pubs Tuesday: The 25% Rule for Editing (AKA Be Aggressive. Be-ee Aggressive!)

Even for a professional writer, long editing sessions are a challenge. Was I actually editing those last ten pages, or did I nod off around page three?

To help make sure I’ve been editing aggressively enough, I use a simple checkpoint rule:

After editing a first draft, the text should be 25% shorter.

Cutting 25% probably sounds like a lot. How does this work in practice? Let’s take a look at two short real-world examples.

Example 1: jQuery Document Ready

From the “How jQuery Works” tutorial, “Launching Code on Document Ready“:

The first thing that most Javascript programmers end up doing is adding some code to their program, similar to this:

window.onload = function(){ alert(“welcome”); }

Inside of which is the code that you want to run right when the page is loaded. Problematically, however, the Javascript code isn’t run until all images are finished downloading (this includes banner ads). The reason for using window.onload in the first place is that the HTML ‘document’ isn’t finished loading yet, when you first try to run your code.

Breaking this down step-by-step:

  1. “The first thing that most Javascript programmers end up doing is adding some code to their program, similar to this” — Already I’m not a fan of this intro, as it doesn’t explain to the poor newbie jQuery developer why “most” JavaScript programmers do this.

    • “The first thing that” — This is throat-clearing. Instead lead off with, “Most JavaScript programmers…” or more accurately, “Many JavaScript programmers…”
    • “end up doing is” — More throat-clearing. Instead, say what the programmers are doing directly.
    • “adding some code to their program” — Too vague. Replace with something more specific, like “wrap their code in an onload function…”
    • “similar to this:” — Also unnecessary. Launching into an example already implies “similar to this.” If you do want to have a transition to the example, you can always go with the classic, “For example:”
  2. “Inside of which is the code that you want to run right when the page is loaded.” — The first paragraph now already says most of this, thanks to the “wrap their code in an onload function.” The slightly new information is the “right when the page is loaded.” Delete this sentence, but remember that last bit…

  3. “Problematically, however,” — Replace with, “Unfortunately,”

  4. “… the JavaScript code isn’t run until all images are finished downloading (this includes banner ads).” — Minor stylistic changes: “isn’t run” to “doesn’t run” and “(this includes banner ads)” to “, including banner ads.” Parenthetical statements are a bit harder to parse, so I try to use them only when necessary.

  5. “The reason for using window.onload in the first place is that the HTML ‘document’ isn’t finished loading yet, when you first try to run your code.” — Finally, here is the reasoning we were looking for back in the first paragraph. Why do “most JavaScript programmers” use onload? Because they are waiting for the browser to finish loading the document. So let’s say that, and while we’re at it, move the concept up to the top of the section. “To ensure that their code runs after the browser finishes loading the document…”

The revised passage is now:

To ensure that their code runs after the browser finishes loading the document, many JavaScript programmers wrap their code in an onload function:

window.onload = function(){ alert(“welcome”); }

Unfortunately, the code doesn’t run until all images are finished downloading, including banner ads.

Example 2: Facebook API

From the Facebook Graph API documentation for Achievement(Instance):

The achievement(Instance) object represents the achievement achieved by a user for a particular app.

You can read more about achievements here.

An app can always access achievement(instance) associated with their app with an app or user access_token associated with their app. To access achievements for a user for other apps they require user_games_activity permission and to access achievements for the user’s friends, the app requires friends_games_activity permission.

Breaking this down step-by-step:

  1. “… represents the achievement achieved by a user…” — The obvious weak spot is the “achievement achieved.” Eliminating this repetition and changing the clause to active yields, “represents a user’s achievement for a particular app.”

  2. “You can read more about achievements here.” — A “click here” sentence! Excellent, a freebie. Just link “achievement” above and then nuke this sentence entirely.

  3. “An app can always access achievement(instance) associated with their app with an app or user access_token associated with their app.” — This sentence is hopelessly mangled. Without talking to an actual Facebook engineer, my best stab at this sentence is:

    • “An app” — Shorten to just, “Apps.” This is just a minor stylistic change.
    • “achievement(instance) associated with their app” — Shorten to, “their own achievements.” Since this whole section is about the achievement(instance) object, it’s unambiguous here to just refer to them as “achievements” most of the time. As a side benefit, it’s not clear what Facebook’s convention is around capitalizing achievement(instance), so using “achievements” sidesteps this style issue.
    • “with an app or user access_token associated with their app.” — Change to, “using an app access_token or user access_token.” The “associated with their app” is implied given the sentence that follows. Also, clarify whether we’re talking about a single type of access token (a user or app access token), or two types of access tokens (a user access token or an app access token). Here, I’m guessing it’s the latter.
  4. “To access achievements for a user for other apps they require user_games_activity permission” — Break this off into a new sentence, “Accessing a user’s achievements in other apps requires user_games_activity permission.”

    • “To access” — Change to “Accessing.” Another minor stylistic change. The main reason I like it better is that it makes it a bit easier to get rid of the “they” later on in the sentence.
    • “achievements for a user for other apps” — Eliminate the double “for” and shorten to, a “user’s achievements in other apps.”
  5. “and to access achievements for the user’s friends, the app requires friends_games_activity permission.” — Create a parallel sentence to the previous one, “Accessing a user’s friend’s achievements requires friends_games_activity permission.” Saying “user’s friend’s achievements” is a little dicey, but I can live with it.

The revised passage is now:

The achievement(Instance) object represents a user’s achievement for a particular app.

Apps can always access their own achievements using an app access_token or user access_token. Accessing a user’s achievements in other apps requires user_games_activity permission. Accessing a user’s friend’s achievements requires friends_games_activity permission.

Conclusion

$ wc /tmp/*.txt
5 67 475 /tmp/facebook-orig.txt
3 43 354 /tmp/facebook-revised.txt
5 85 522 /tmp/jquery-orig.txt
5 42 301 /tmp/jquery-revised.txt
18 237 1652 total

There are a couple of takeaways here.

The first is that you won’t reach the 25% by tinkering at the margins, fixing little issues around grammar and wordiness. You need to dive in and rework entire sentences, paragraphs, and sections. Don’t worry — in a first draft you will always, always find sections that you can delete or radically shorten. The 25% Rule is there to force you to do the harder, more important work of rethinking the text.

The second is that the overall idea is not, “Whoever reduces the text the most WINS AT TECH WRITING!” The idea is only that if you are editing a first draft aggressively enough, then you should probably see a reduction of around 25% or more.

In other words, the 25% Rule is just a rough self-check for your edit. If you’ve crossed the 25% threshold, you’re probably doing okay. There are no “extra points” for going further.

Tech Pubs Tuesday: Code Proximity

So I’m going to try a new thing in 2013 — a weekly series of short posts on the craft of software technical writing. Welcome to Tech Pubs Tuesday! Today’s topic is code proximity: what it is and why you want it.

There are lots of paths to broken documentation, but one of the most popular paths is to make sure your documentation source and software source live as far apart from each other as possible. In practice, this could mean:

  • keeping your documentation source in a separate repo from your software source
  • keeping your documentation in a proprietary binary format that only a few people can actually open and use
  • keeping your documentation authors as far as possible from your software authors

By contrast, in a healthy project:

  • documentation source sits right alongside your software in a /doc directory, embedded inside your source code as doc comments, or both
  • corollary: documentation source should be in an open, plain text format
  • documentation builds as part of your normal CI process or build process
  • documentation authors work right alongside software authors (or are the same people)

In other words, documentation must be part of your project, just like your tests and build scripts. It needs to be in your face every time you view your repo. The last thing you want is for it to be hidden away, in a place you don’t know about, in a format you don’t understand, controlled by people you don’t really know. Code proximity is your first line of defense against documentation rot.

Fraud Prevention is Hard

[Wife placed online purchase; card was declined.]

Me: Okay, I called the credit card company. They’ve removed the hold.

Sarah: But why did they put the hold on it instead of letting me shop?

Me: The customer service rep doesn’t know anything about that. It’s some crazy algorithm that some mathematicians developed for them…

Sarah (indignantly): What? You’re blaming math?

Me: No, I —

Sarah: “Math is hard, let’s go shopping” — oh wait, I can’t!

User Comments in Documentation: Stop It. Stop. It!

Today I took a look at WebPlatform.org, which (among other things) reminded me that man oh man, do I hate user comments in documentation.

If you want an example of how user comments degrade perfectly good documentation — well, there are many, but the most obvious one is PHP.net. PHP is a monster of a language, but thankfully PHP also has been blessed with a longtime dedicated documentation team that has built up a substantial and highly useful set of user guides and API reference documentation. The core documentation is solid, and the site’s use of redirects (typing php.net/functionname “just works”) is absolutely brilliant.

But if you scroll down to comments on any given page, you’ll see bad practices that should have died years ago, code that doesn’t do what the user thinks it does, people complaining about (imagined) bugs, and worse.

Wait, but people really like documentation comments.

It’s true that when you ask developers what they like about the PHP documentation, they often cite the comments. Engineers often decide that comments are a need-to-have feature for documentation sites. After all, it’s the community contributing to the documentation. Who doesn’t like community? Yay community!

Comments make people feel good. But comments are also just about the worst way possible to collect and incorporate feedback.

The key problem is that for documentation, comments are part of the product. It’s as if you built a web app by building the datastore, adding application logic, tuning the user interface… and then allowing any random user to modify the navigation bar any way they like for all other users.

Oh, I see. So you’re saying you hate the community and kittens?

No. What I am saying is that contributing feedback is a solved problem in software development. Make a goddamned pull request! Or send a patch. Or whatever you do normally. Treat your documentation source the same way you treat source code.

That’s setting the bar too high. We want feedback from a wide range of users.

Respectfully, if someone is writing technical documentation for software developers, and they haven’t grasped the basics of version control, they should not be allowed to directly contribute changes to your documentation. Period.

That said, feedback from less experienced users is still valuable. If someone notices something is wrong, or wants to add an example, or needs to point out a section that is confusing, there are plenty of ways to collect that feedback. These include:

  • Issue trackers
  • Email
  • Wikis
  • IRC
  • Social media
  • Meetups

Again, collecting feedback from users of all knowledge levels is a solved problem. Tools exist for this. Some of them are even pretty good!

In any case, please stop inventing new commenting systems and gluing them into your documentation sites. You are taking what should be a relatively straightforward generated/static site and turning it into a dynamic CRUD site for no good reason. A more colossal waste of engineering time I cannot imagine.

Well, okay, I can imagine quite a bit.

JSFABulous

After yesterday’s post, I heard from Jan Lehnardt. Jan, Tiffany Conroy, and Marijn Haverbeke are piloting a workshop named JSFAB (JS for Absolute Beginners) that, well, does what it says on the tin. The initial curriculum (source code) was written by Conroy and Haverbeke, who not coincidentally wrote the highly recommended Eloquent JavaScript.

JSFAB has a clever take on this problem: they’re using an in-browser sandbox and editor, and within that environment, they’ve made available some high level drawing functions. This means that students just learn programming principles and JS syntax by jumping in and drawing shapes and graphs right away. This approach neatly sidesteps many of the problems I mentioned in the last post, and seems perfect for “absolute beginners” who don’t know HTML or CSS. Later on, of course, you can go back and teach them how to rip apart and remake web pages; the key thing is that they’re on their way.

On a personal note, I believe that courses like JSFAB have great potential. We are starting to live in a world that is soaking in ambient computing power. Knowing how to program (even a little) means eliminating drudge work. It means taking more control over your world. So with that in mind, I’m really pleased to hear that the JSFAB crew have already had great success with their first workshop in Europe, and are iterating further. If you have feedback for them, I know for a fact they’d be happy to hear from you!

Scattered Notes on Writing a JS Tutorial for Non-programmers

As you might or might not know, I’ve expressed my frustration with the sad state of JavaScript tutorials in the past. Since the universe has not seen fit to fix this problem on its own, I’m finally at the point where I’m working up an actual TOC.

Attention conservation notice: over 900 words collecting some thoughts about a JavaScript book / tutorial for non-programmers.

  • There are a tremendous number of people who know at least some HTML and CSS, but who don’t know any programming languages per se.
  • Included in that count are people who know at some HTML and CSS, and a smattering of jQuery. This is not a knock on jQuery — quite the contrary, I actually think it’s very impressive that jQuery enables non-programmers to sprinkle in UI effects, etc.
  • Still, those who know a smattering of jQuery would also be well-served if they understood JavaScript-the-language.
  • Oddly, although JavaScript seems like it would be a natural next language for people who know HTML and CSS, there isn’t a single JavaScript tutorial out there for non-programmers.
  • Or at least, there isn’t one that’s any good. As previously discussed, searching for JavaScript tutorials brings up a wasteland of confusing, outdated, incorrect crap.
  • It’s actually worse than the situation for HTML, where if you look hard enough, you can find something possibly worth reading.
  • Thus, the actual path people follow is: learn HTML and CSS, learn Ruby, PHP, or Python, and then go back and learn JavaScript.
  • For experienced programmers, good JavaScript resources exist, if you know where to find them.
  • But a lot of what people throw out as introductory resources (MDN, Eloquent JavaScript, The Good Parts) are really introductory resources for programmers.
  • Eloquent JavaScript is the closest thing I know of that kinda sorta works for non-programmers. It’s very well written and covers lots of critical topics. I really, really like it.
  • The wrinkle is that it’s still too complicated. Chapters 1 and 2 work for non-programmers, but after that the book quickly veers off into functional programming geekery and other advanced topics. I feel safe recommending Eloquent JavaScript to programmers, and possibly science or engineering majors with little or no programming experience, but I just don’t think it works as an introduction to programming itself.
  • Writing a guide that teaches non-programmers how to program is tricky, but not impossible. Some people do it brilliantly.
  • What the world probably needs is a Learn JavaScript the Hard Way. But Zed Shaw hasn’t written that book yet, and I’m not sure if he cares to.
  • In any case, a hypothetical Learn JavaScript the Hard Way couldn’t be a straight port of Learn Python the Hard Way, for reasons mentioned below…
  • Problem 1: Printing. Unlike just about every language you can think of, JavaScript in the browser does not have a dead-simple way to write text to the screen. And without a dead-simple way to write text to the screen, it’s awfully hard to get started.
  • There’s alert() — um, no.
  • There’s document.write() — also, um, no. Any guide that trains newbies to use alert() or document.write() should be set on fire.
  • There’s console.log() — better, but I’m not keen on explaining to people that they have to open some inspector or console to see what’s happening. And people who know HTML and CSS really want to be manipulating the page.
  • Or, you could ask people to install Node.js. Node.js is great for backend programmers who want to learn JavaScript — particularly because it decouples JavaScript from the DOM. But it’s nice to not have to ask people to install software to get going. More importantly than that, I think people who know HTML and CSS want to be mucking around with the DOM. That’s the touchpoint between programming and what they already know.
  • Eloquent JavaScript cleverly works around this whole “print” mess by, well, providing a damn print function.
  • In any case, I think there is a way to bootstrap around this. It means we won’t be starting with “Hello World.” Or even, “HELLOSKI.”
  • Problem 2: The most interesting early concept to teach is event listeners. That’s a huge part of why client side JavaScript exists, and it has everything to do with why an HTML/CSS jockey would want to branch out into JavaScript.
  • But this is not simple. You need to know what a function is — this is a mind blowing concept for non-programmers. You need to know what a callback is!
  • Most JavaScript tutorials teach event listeners using the onclick attribute. Partly this is because most JavaScript tutorials were written in 1997 and are total dogshit. But partly this is because using onclick short-circuits the problem of having to grab the element and then attach the listener: complexity is reduced.
  • In a Python or Ruby tutorial, you have the luxury of discussing fundamentals like primitive types, etc. before eventually working their way up to callbacks.
  • I don’t think this traditional approach cuts it when it comes to client-side JavaScript. I think the reader wants to learn how to click a button and have some interesting stuff happen, ASAP. Then you can start sneaking in numbers, string manipulation, booleans, loops, and so on.
  • I think there is a straight line from zero to event listeners that cuts out most of the fat. But I’ll need to try it on some real readers to see if it works.

Why is it a Bad Idea to Listen for Internal DOM Events in YUI Widgets?

Continuing in the same vein as the previous post, I thought I’d highlight another basic, but interesting facet of YUI development: listening to events from widgets.

Let’s say you have a TabView, and you want to take some action each time the user changes tabs. (Let’s say in this case, just count the tab switches.) Naively, you might do something like:

var tabview = new Y.TabView().render('#tabview'),
numSwitches = 0;

tabview.get('boundingBox').on('click', function (ev) {
    numSwitches += 1;
    Y.one('#counter').setHTML(numSwitches);
});

However, a far better way to go is to listen for widget state changes directly — in this case, the TabView‘s selectionChange event:

var tabview = new Y.TabView().render('#tabview'),
numSwitches = 0;

tabview.after('selectionChange', function (ev) {
    numSwitches += 1;
    Y.one('#counter').setHTML(numSwitches);
});

There are three reasons why you would want to use the latter approach over the former.

First, repeated clicks on the same label do not indicate a tab switch.

Second, a tabview might supply additional ways to navigate to different tabs such as keystrokes or gestures, which a click listener would miss.

Third, it is poor practice to depend on the internal structure of a widget’s HTML. The HTML produced by a widget is a reflection of the data the widget represents, and the UI elements produced are a consequence of that data. Changes to the widget’s data can trigger the widget to refresh its internal HTML, which in turn can destroy any DOM event listeners you might have set. If you need to react to widget state changes, listen directly for those state change events, not the DOM events that might have triggered the state change.

Naturally, these principles apply to any library that provides widgets, not just YUI. If you’re building a widget or plugin with some other JS library, think about how you can use that library to directly indicate a state change, rather than forcing other developers to listen for DOM events.

To sum up: if you’re trying to keep track of widget state changes, listen for state changes, not DOM changes. The DOM within a widget is volatile, and DOM events don’t necessarily correspond 1-to-1 to the thing you are actually trying to track.

Posted in Web

Why Does YUI Have a Y.one() Method?

When I was working on the YUI 3 Cookbook, one of the things I really enjoyed was being able to pick the brains of the YUI team and get a straight-from-the-horse’s-mouth account of YUI’s architecture and design. With the release of the cookbook, I thought it would be fun to look back through the manuscript and pick out some short topics that might be of interest to new and intermediate YUI users.

One basic thing you might be wondering about is… why does YUI have two idioms for reaching into the DOM?

YUI’s first method, Y.all(), retrieves a Y.NodeList instance:

var errorDivs = Y.all('div.error');

If the selector fails to match any elements, Y.all() returns an empty Y.NodeList.

By contrast, the second method, Y.one(), retrieves a single Y.Node instance:

var errorDiv = Y.one('div.error');

If the selector matches multiple nodes, Y.one() returns the first match (as if you were using the :first jQuery pseudo-selector). If the selector fails to match any elements, Y.one() returns null.

So what’s up with this? Why bother having two methods, and why do they behave so differently? Why not just have querySelectorAll()-like behavior and be done with it?

The answer is that it’s helpful to know ahead of time whether you will receive a single node or a collection. This in turn is why the two methods return different values when the selector fails to find a match. Since Y.one() returns null, it is great for simple node existence checks:

if (Y.one('#myDiv')) {
    ...
}

As for Y.all(), the fact that it always returns an empty collection makes it always safe for doing bulk operations. For instance, the following works just fine even if there are no error divs in the document:

Y.all('div.error').remove();

Some libraries rely on a single abstraction (reaching into the DOM always returns a collection), but the choice of Y.all() and Y.one() — or, if you’re thinking in native terms, querySelectorAll() and querySelector() — ultimately enables you to write cleaner code. The cost is having an extra API method to think about. Fortunately, YUI’s methods have short, distinct names, so it’s pretty easy to remember which one does what.

Posted in Web