Steve Conover's blog



Steve ConoverSteve Conover
Tim Berners-Lee: Principles of Design
edit Posted by Steve Conover on Sunday December 21, 2008 at 09:00AM

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.

Steve ConoverSteve Conover
Recent Peer-to-Patent mentions
edit Posted by Steve Conover on Wednesday December 10, 2008 at 01:00PM

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."

More Pivotal clients and partners.

Steve ConoverSteve Conover
Apply writing advice to code
edit Posted by Steve Conover on Saturday December 06, 2008 at 11:39PM

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.

William Hazlitt


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.

from The Economist Style Guide

More resources:

Steve ConoverSteve Conover
Better array assertions using collect
edit Posted by Steve Conover on Monday October 27, 2008 at 10:00AM

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.

Steve ConoverSteve Conover
Peer to Patent in its second pilot year
edit Posted by Steve Conover on Tuesday September 16, 2008 at 05:00PM

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.

Steve ConoverSteve Conover
Standup: Sep 9th,10th,11th 2008
edit Posted by Steve Conover on Thursday September 11, 2008 at 03:58PM

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:

  • 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.

Steve ConoverSteve Conover
use photobooth to exchange ideas quickly
edit Posted by Steve Conover on Friday May 02, 2008 at 01:02AM
  1. Draw something on an index card
  2. Run photobooth
  3. Edit => Auto Flip New Photos
  4. Take a photo of your index card
  5. Attach to email

(Don't take the finger personally)

Steve ConoverSteve Conover
Rails, Slashdotted: no problem
edit Posted by Steve Conover on Wednesday June 27, 2007 at 03:29AM

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:

    1. Have index.html point to index.html.current
    2. If (index.html.current is >= 20 minutes old)
      1. Copy index.html.current to index.html.old
      2. Point index.html to index.html.old
      3. Rewrite index.html.current by asking Rails for the page (using the process method)
      4. Repoint index.html back at index.html.current
    3. 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.

Steve ConoverSteve Conover
Using JSON on the request with Ajax.Request postBody
edit Posted by Steve Conover on Wednesday May 16, 2007 at 03:52PM

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)

Other articles: