Steve Conover's blog
Here's a good, quick read. It got its start about 10 years ago:
http://www.w3.org/DesignIssues/Principles.html
Topics:
- Simplicity
- Modular Design
- Tolerance ("Be liberal in what you require but conservative in what you do")
- Decentralization
- Test of Independent Invention ("If someone else had already invented your system, would theirs work with yours?")
- Principle of Least Power
When you're heads-down doing Agile or OOP sometimes you find yourself accidentally assuming that certain useful general principles are special to what you practice - when the truth is they're probably not even unique to your discipline, and some Greeks wrote them down around 500 BC.
Craig Newmark: Peer To Patent: government using social networking
"Peer To Patent is Washington's first social networking iniative, using a network of volunteers to help figure out if an invention deserves to be patented. The volunteers, normally scientists and technologies, connect with patent examiners, and like Obama says, this "taps the intelligence" of the American public. "
Google CEO touts green energy shock doctrine
Pressing a theme popular with Barack Obama's tech surrogates, Schmidt also waxed enthusiastic about the power of network technology to create a more transparent and participatory politics. "Government has not embraced, generically, the tools we all use every day," said Schmidt. "It's time." Pointing to the Patent Office's Peer-to-Patent program for crowdsourcing patent application analysis, Schmidt asked "why is that not true of every branch of government?" The same "police of the Internet" who debunked political rumors during the campaign could be turned on key legislative and regulatory issues. "A lot of people care passionately about them," joked Schmidt, "and they obviously have a lot of free time."
Writing good code and writing good English are a strikingly similar endeavors. We should be able to apply writing advice to code - not perfectly, but on the whole.
These are some of my favorites - I welcome more thoughts and citations in the comments:
- Never use a metaphor, simile, or other figure of speech which you are used to seeing in print.
- Never use a long word where a short one will do.
- If it is possible to cut a word out, always cut it out.
- Never use the passive where you can use the active.
- Never use a foreign phrase, a scientific word, or a jargon word if you can think of an everyday English equivalent.
- Break any of these rules sooner than say anything outright barbarous.
...
A scrupulous writer in every sentence that he writes will ask himself at least four questions, thus: What am I trying to say? What words will express it? What image or idiom will make it clearer? Is this image fresh enough to have an effect? And he will probably as himself two more: Could I put it more shortly? Have I said anything that is avoidably ugly?
Orwell, "Politics and the English Language" (a brilliant essay)
To write a genuine, familiar, or truly English style is to write as anyone would speak in common conversation and who had a thorough command or choice of words or who could discourse with ease, force, and perspicuity setting aside all pedantic and oratorical flourishes.
As a general rule, run your pen through every other word you have written, you have no idea what vigor it will give to your style
Sydney Smith
Clarity of writing usually follows clarity of thought. So think what you want to say, then say it as simply as possible.
...
(Selected do's and do-not's, summarized)
- Do not be stuffy. Use the language of everyday speech, not that of spokesmen or bureaucrats. Consider rephrasing sentences more pithily and accurately. Avoid, where possible, euphemisms and circumlocutions promoted by interest groups.
- Do not be too pleased with yourself (perhaps akin to Kill Your Darlings)
- Do your best to be lucid. Simple sentences help. Keep complicated constructions and gimmicks to a minimum.
...
Scrupulous writers will also notice that their copy is edited only lightly and is likely to be used. It may even be read.
More resources:
Eric Evans' emphasis on Ubiquitous Language in Domain-Driven Design (book, website, wikipedia) is in the same spirit.
Style guides for writers and journalists are good resources, examples are the Economist Style Guide (online, book) quoted from above, and the Chicago Manual of Style (online, book).
Steven Pinker's The Language Instinct is a great starting point for exploring the connection between cognition and language.
Chapter 17 of Zen and the Art of Motorcycle Maintenance, which merits its own post...
You could do this:
Person.tall_people.length.should == 3
Person.tall_people[0].should == people(:linda)
Person.tall_people[1].should == people(:dwane)
Person.tall_people[2].should == people(:rick)
This is better, because it's clearer, and because in one stroke you prove bounds, content, and order:
Person.tall_people.should == [
people(:linda),
people(:dwane),
people(:rick)
]
I argue that this is best:
Person.tall_people.collect{|p|p.first_name}.should == [
"Linda",
"Dwane",
"Rick"
]
Failures messages are a pleasure to read
expected: ["Linda", "Dwane", "Rick"],
got: ["Juliette", "Jeanne"] (using ==)
And code is clearer overall (the price is a "collect")
Collecting away from the original object (and into primitives) is not only clearer, in most cases your aim is not to re-prove that the element objects are fully and properly configured. You've already done that elsewhere. You only want to prove, in the simplest possible terms, that the group of things you got is what you expected to get.
Let's say you don't intend to care about order. Sorting on primitives is a snap:
Person.tall_people.collect{|p|p.first_name}.sort.should == [
"Dwane",
"Linda",
"Rick"
]
Slightly more controversial:
Person.short_people.collect{|p|p.first_name}.should == []
The collect seems silly at first glance, but you're making present and future assertion failures much friendlier. You'll be happy about brain cycles saved and sanity kept during big refactorings.
From CNN.com:
Program brings Web's collective wisdom to patent process
"The concept behind the program, called Peer-to-Patent, is straightforward: Publish patent applications on the Web for all to see and let anyone with relevant expertise -- academics, colleagues, even potential rivals -- offer input to be passed along to the Patent Office.
By using the power of the Internet to tap the wisdom of the masses, Peer-to-Patent aims to dig up hard-to-find "prior art" -- evidence that an invention already exists or is obvious and therefore doesn't deserve a patent."
More Peer to Patent articles available on the Pivotal clients page.
Interesting Things
ActiveRecord::Base.connection.select_all reads all records into an array, which is not good if you have a very large result set. Use a combination of ActiveRecord::Base.connection.execute with .each, or .each_hash if you want the same column<=>value mappings you get with select_all, only streamed.
There was some confusion about BlueCloth:
- There's a gem and a plugin available, and it appears that you need to use both
- It seems like the only live BlueCloth development (i.e. where patches should be sumbitted) is here: http://github.com/github/bluecloth/tree/master
A recent MySql trigger experience:
- In summary, think twice before using them when you have a viable application code alternative
- They're not cloned from the dev to test database
- The hosting provider this project is using requires that we submit a change request each time we want to add/change/delete triggers. The problem with that is your trigger changes aren't in sync with your code deployments.
- It wasn't hard to write the application code
During a discussion about humanize, a couple other nifty transforms were mentioned:
- parameterize: You have a string, and you want to strip out characters that aren't url-friendly. (follow the link for good example/discussion)
- auto_link a Rails helper that takes text and links up all urls and email addresses.
- Draw something on an index card
- Run photobooth
- Edit => Auto Flip New Photos
- Take a photo of your index card
- Attach to email

(Don't take the finger personally)
By Steve Conover and Brian Takita
Peer-to-Patent, one of Pivotal Labs' clients, got Slashdotted last week, and we had no trouble handling the load. The site was just as responsive as it always is, and we didn't come close to having a scale problem.
Moral of the story: the technology for serving static web pages is old, boring, and extremely scalable. If you have the type of site that can be page-cached, do so aggressively, starting with the front page and any pages likely to be linked to. We got a huge payoff for the engineering time that we invested in our page-caching strategy.
Highlights:
- We moved away from Rails page-caching and developed our own "holeless cache", which uses a symlink trick (see below) to instantly and "holelessly" switch to a new version of a cached page. (The cache "hole" is the time between the expiration or purge of a cached page and the time when it's regenerated. The danger is that in that time your Mongrels can be saturated with requests - something we proved to ourselves could easily happen.)
Here's our symlink trick, using the front page as an example:
- Have index.html point to index.html.current
- If (index.html.current is >= 20 minutes old)
- Copy index.html.current to index.html.old
- Point index.html to index.html.old
- Rewrite index.html.current by asking Rails for the page (using the process method)
- Repoint index.html back at index.html.current
- Repeat step 2 every minute using a cron job.
For cache expiration that's model-based, we make a call from the model observer class to our holeless cache routine, instead of using Rails cache sweepers. So, instead of just deleting the cached page we regenerate it in place.
It was important to write tests that proved that the HTML we generated for cached pages looked exactly the same in different "modes" (user logged in vs not, for example). This forced us to push modal decision logic out of Markaby templates and into JavaScript, meaning that view-oriented Rspec tests asserting modal differences became useless. We rewrote them as Selenium tests.
Performance/load testing: we tried several tools and approaches and found that a simple Ruby script that launches wget requests (that write to /dev/null) in many separate threads worked best for us.
We send down exactly one .js and one .css file. If you are sending down more than one of each of these to the browser, you have a performance problem. Fix it with asset packager.
Update: one clarification about the cron job: we deploy this "automatically" using capistrano.
This is nice in a heavy Ajax application - you can use the same data format on the request and the response.
You might not have been aware that prototype'sprototype's Ajax.Request can send a postBody, instead of parameters.
So if you don't mind all of your Ajax requests being POSTs (I don't), you can just ignore serializing parameters and just stick JSON in the postBody.
This makes my jsunit tests (and therefore my production code) nicer:
BEFORE:
<code>
function testRequest() {
var settings = {volume:"high", color:"red"}
var command = new SaveSettings(settings);
assertEquals("/save_settings", command.asAjaxPayload().url);
assertEquals("volume=high&color=red", command.asAjaxPayload().parameters);
}
</code>
AFTER:
<code>
function testRequest() {
var settings = {volume:"high", color:"red"}
var command = new SaveSettings(settings);
assertEquals("/save_settings", command.asAjaxPayload().url);
assertEquals(settings, JSON.parse(command.asAjaxPayload().postBody));
}
</code>
(and of course, you can push the stringifying of the post body down a layer, to get rid of the JSON.parse at this level)
