<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6930361</id><updated>2011-12-07T11:24:11.537-05:00</updated><title type='text'>Platte daddy</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://daddy.platte.name/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>65</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6930361.post-4648396675320655785</id><published>2011-12-07T11:15:00.000-05:00</published><updated>2011-12-07T11:24:11.544-05:00</updated><title type='text'>Removing hard-coded cookies from ExpressionEngine</title><content type='html'>A client is using ExpressionEngine 2 as just a CMS and not using its membership features, and we're doing everything we can to improve performance, both back-end and front-end.&lt;br /&gt;&lt;br /&gt;On the front-end side, the cookie setting takes up some of the precious bytes that get transferred before the browser can start downloading assets.&lt;br /&gt;&lt;br /&gt;I have turned off everything I can turn off that adds cookies to ExpressionEngine's output, but there were still two cookies hard-coded into the output even for logged-off users: &lt;code&gt;exp_tracker&lt;/code&gt; and &lt;code&gt;exp_last_activity&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The code that does this is in &lt;code&gt;expressionengine/libraries/Session.php&lt;/code&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;$this-&amp;gt;EE-&amp;gt;functions-&amp;gt;set_cookie('tracker', serialize($tracker), '0'); &lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;$this-&amp;gt;EE-&amp;gt;functions-&amp;gt;set_cookie('last_activity', $this-&amp;gt;EE-&amp;gt;localize-&amp;gt;now, $expire);&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;This was a bit tricky to find, and I didn't see answers on Google, so there it is for posterity.&lt;br /&gt;&lt;br /&gt;Note that EllisLab staff says making this change&amp;nbsp;&lt;a href="http://expressionengine.com/archived_forums/viewthread/146760/#719168"&gt;"can affect your ability to upgrade, and your ability to receive support."&lt;/a&gt;&amp;nbsp;They also point out that&amp;nbsp;you would need to re-apply such changes after an upgrade.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-4648396675320655785?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/4648396675320655785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/4648396675320655785'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2011/12/removing-hard-coded-cookies-from.html' title='Removing hard-coded cookies from ExpressionEngine'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-2166048798533920676</id><published>2011-10-05T09:51:00.001-04:00</published><updated>2011-10-05T09:51:30.503-04:00</updated><title type='text'>Web performance</title><content type='html'>Several of my clients have asked me to do performance tuning for their websites. I find it fascinating work, and rewarding to deliver improvements that help machines serve humans rather than the other way around.&lt;br /&gt;&lt;br /&gt;I'll try to post nuggets of value as I come across them, regardless of whether they seem basic or advanced to me.&lt;br /&gt;&lt;br /&gt;A great one to start with this first day is &lt;a href="http://www.webpagetest.org/"&gt;WebPagetest&lt;/a&gt;. It loads a page with an empty cache, then a filled cache in one of many browsers and produces amazingly detailed reports.&lt;br /&gt;&lt;br /&gt;I have been doing a lot of tuning on one of my clients' sites, but mostly through my own Mac Chrome on a pretty fast connection. I had WebPagetest run the site on IE8 on a slower connection and got quite an education.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-2166048798533920676?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2166048798533920676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2166048798533920676'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2011/10/web-performance.html' title='Web performance'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-3520074348200839413</id><published>2010-04-12T08:56:00.002-04:00</published><updated>2010-04-12T08:58:50.519-04:00</updated><title type='text'>OO programming in JavaScript, neatly summarized</title><content type='html'>&lt;a href="http://www.crockford.com/javascript/private.html"&gt;This article from Douglas Crockford&lt;/a&gt; outlines the basics and feel of programming with objects in JavaScript very succinctly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-3520074348200839413?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.crockford.com/javascript/private.html' title='OO programming in JavaScript, neatly summarized'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3520074348200839413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3520074348200839413'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2010/04/oo-programming-in-javascript-neatly.html' title='OO programming in JavaScript, neatly summarized'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-7735143317662711488</id><published>2010-04-07T10:13:00.002-04:00</published><updated>2010-04-07T10:20:31.182-04:00</updated><title type='text'>On Documents vs. Streams, by Bryce Harrington</title><content type='html'>&lt;div&gt;&lt;i&gt;This article was written by &lt;a href="http://www2.bryceharrington.org:8080/"&gt;Bryce Harrington&lt;/a&gt;, and gave me a fresh perspective on interfaces when it was &lt;a href="http://www2.bryceharrington.org:8080/drupal/node/55"&gt;published&lt;/a&gt; and &lt;a href="http://www.infoq.com/news/2008/07/stream-oriented-ui"&gt;discussed on InfoQ&lt;/a&gt;. It's currently available only through Google's cache, so I'm republishing it here to preserve it.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other day I was trying to figure out what was making my desktop computer run so slow. This was pretty unusual on Linux. Way back when I used to use Windows, I'd encounter such things due to running too many programs, so of course I looked at what was running.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But these days I don't really run that many intensive applications. I hardly ever use spreadsheets, presentation tools, word processors, or so on like I used to. Really the only things visible in my task bar were Firefox and Terminal. Killing off Firefox made no difference. And even more oddly, rebooting had no effect - within minutes my load average was up in the 20-30's.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Of course, the culprit was that I had a bunch of automatic cron jobs scheduled to occur at the same time. Reordering the timings got the system back on track.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But this led to an epiphany moment.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This was my *desktop* machine. The last time I'd seen this cron job I/O blocking madness was on servers. What was I doing with so many cron jobs on a *desktop*??&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I looked at the individual cron jobs, and found that each and every one of them had something to do with my job. Disabling any one of them would reduce my work productivity. I could no longer do without one of these silly cron jobs than I could have done without Microsoft Excel a decade ago.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And then, as I looked around my desktop at the other things running on it - internet radio, IRC chat, mutt - that I noticed that I hardly ever use traditional "document-centric" applications. Everything running had something to do with dealing with _streams_ of information.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The realization sank in at that point, that our computer UI paradigm really stinks for what we actually use our computers for.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The prevailing UI paradigm today is built around the notion of document authoring. It expects that the main thing you do is create spreadsheets, word documents, presentations, and so on. There is a task bar to remind you of what documents you're editing, there is cross-application cut and paste so you can put pieces of one document into another. You can place documents on your desktop surface itself, so you can organize your work. You can define which applications to use for which types of docs. You can set up a default printer to put your documents to hard copy. You can set up system-wide fonts to use in documents. You can put icons to apps and even documents onto your panel. And on and on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Occasionally, some of that is actually useful to me. But most of the time, for most of the work I do, it's all irrelevant. To pick one example, I used absolutely none of that in order to write this blog post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Really, what I mostly do today is stream management. And I suspect this is true for the vast majority of people. I don't deal with writing documents, but with changes to documents. I put comments onto things. I slap patches onto things. I tweak the states of things. Once in a rare while I may author a completely new thingee, but even there I usually end up working with it as a stream of changes that I build up over time (and usually in collaboration with a few other people who stream changes to me).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thinking about user interfaces this way, it occurs to me that there are a LOT of different kinds of streams. Streams of emails. Streams of spam to take *out* of my email stream. Streaming radio broadcasts. Streams of bug reports. Streams of software updates to apply. Streams of chatter on IRC. Streams of youtube video URL's from friends and family to check out. Streams of updates to my weather applet. Even my todo list is more like a stream of things coming in and going out, than like a static document I can print and save and be done with.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Each one of those silly cron jobs bogging down my computer were critically important for me, because THEY were the tools I used for helping me stay atop all these streams. They summarized my bug streams in various ways. They filtered my email streams into more organized sub-streams. They flagged tasks (and took care of certain tasks for me). They took care of updating the tools I used day to day.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's weird that for all the document tools at my fingertips, it's a stodgy old *server* tool that is helps my productivity the most. I wonder how non-technical people not knowledgeable about crontab and scripting deal with such things?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This all got me to a key question... Since the purpose of our desktop UI is to make our work easier and more efficient, then if today's knowledge workers are, like me, more stream-oriented than document-oriented, then doesn't it stand to reason that we ought to re-think our UI design to optimize it for making stream management easier and more efficient? How would such optimization be done? How would such a UI look and feel? What kinds of toolkits would be needed?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-7735143317662711488?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7735143317662711488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7735143317662711488'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2010/04/on-documents-vs-streams-by-bryce.html' title='On Documents vs. Streams, by Bryce Harrington'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-2891956373586664388</id><published>2009-03-31T13:56:00.002-04:00</published><updated>2009-03-31T14:01:18.831-04:00</updated><title type='text'>Merlin Mann's How to Succeed in Business</title><content type='html'>&lt;p&gt;From John Gruber and Merlin Mann’s talk on &lt;a href="http://ratafia.info/post/90532973/transcript-of-howto-149-surprising-ways-to"&gt;making money by being authentically enthusiastic:&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;ol&gt;&lt;li&gt;Give away more stuff than you think you should, and make it easy for people to get.&lt;/li&gt;&lt;li&gt;Focus on diverse secondary revenue streams, and always have your eyes open for new and replacement ones.&lt;/li&gt;&lt;li&gt;Don’t do stuff that seems profitable, but potentially messes up the reason people like you.&lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-2891956373586664388?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2891956373586664388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2891956373586664388'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2009/03/merlin-manns-how-to-succeed-in-business.html' title='Merlin Mann&apos;s How to Succeed in Business'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-7857883726406038184</id><published>2009-03-20T12:15:00.002-04:00</published><updated>2009-03-20T12:18:51.017-04:00</updated><title type='text'>should be || should_not be</title><content type='html'>Stephen Eley has done something very clever on the rSpec list, it begins thus:&lt;br /&gt;&lt;blockquote&gt;should be || should_not be: that is the expectation:&lt;br /&gt;Whether 'tis nobler in the parser to interpret&lt;br /&gt;The outputs and side effects of outrageous duck typing,&lt;br /&gt;Or to inherit against a sea of matchers&lt;br /&gt;And by declaration extend them?&lt;/blockquote&gt;And on from there, to a satisfying conclusion.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-7857883726406038184?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://wiki.github.com/dchelimsky/rspec/should-be-should_not-be' title='should be || should_not be'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7857883726406038184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7857883726406038184'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2009/03/should-be-shouldnot-be.html' title='should be || should_not be'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-2859711570554810320</id><published>2009-03-20T10:18:00.002-04:00</published><updated>2009-03-20T10:20:55.662-04:00</updated><title type='text'>javascript_named_routes</title><content type='html'>Fred Polgardy has just released a tasty bit of code that will allow JavaScript to access Rails named routes in a very straightforward way.&lt;br /&gt;&lt;br /&gt;Check out his &lt;a href="http://sustainablecode.blogspot.com/2009/03/more-unobtrusive-javascript-with.html"&gt;javascript_named_routes Rails plugin&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-2859711570554810320?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://sustainablecode.blogspot.com/2009/03/more-unobtrusive-javascript-with.html' title='javascript_named_routes'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2859711570554810320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2859711570554810320'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2009/03/javascriptnamedroutes.html' title='javascript_named_routes'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-8236848953876322735</id><published>2008-12-10T14:05:00.002-05:00</published><updated>2008-12-10T14:08:39.459-05:00</updated><title type='text'>How much process, and why?</title><content type='html'>The best write-up in my memory of how agile processes fit into projects hackers build.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-8236848953876322735?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://startuplessonslearned.blogspot.com/2008/12/hackers-lament.html' title='How much process, and why?'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8236848953876322735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8236848953876322735'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/12/how-much-process-and-why.html' title='How much process, and why?'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-7163183352661554255</id><published>2008-09-25T11:27:00.002-04:00</published><updated>2008-09-25T11:33:19.710-04:00</updated><title type='text'>Don't steal from me, Senator Obama</title><content type='html'>&lt;em&gt;I signed a petition asking my legislators not to approve a bailout. I got a response from Senator Obama similar to &lt;a href="http://discuss.americasrevival.com/showpost.php?s=35cae8381c5e4c542f1da5841b71decf&amp;p=15529&amp;postcount=6"&gt;the one quoted elsewhere.&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Dear Senator Obama:&lt;br /&gt;&lt;br /&gt;I contacted you earlier writing against the bailout, and received your reply. &lt;br /&gt;&lt;br /&gt;Given your commitment to a bailout, I'm glad you're looking for ways to improve matters. But you are planning to remove thousands of dollars from my pocket, either as taxes or as devaluation of the dollar, to pay for mistakes made by private citizens. &lt;br /&gt;&lt;br /&gt;You do not have my consent to do this. It is stealing from me.&lt;br /&gt;&lt;br /&gt;Merely waving your hands and saying "liquidity" and "worsening downturn" is not enough explanation for why you're planning to take money from me. You owe us better than that.&lt;br /&gt;&lt;br /&gt;Furthermore, you point to a need to rescue the economy. Have you considered the effects of inflation on the economy? Talking about bailing out mortgages without any discussion of the inflation this will create makes it look like you are only interested in protecting the rich. I'm sure you don't want that.&lt;br /&gt;&lt;br /&gt;Another topic that isn't being discussed: is it the right answer to go on creating a socialist regime in the US? Buying up companies and personal loans? This isn't the America I grew up in. It sounds more like China. Are you for or against this approach?&lt;br /&gt;&lt;br /&gt;The closest you came to answering my call to vote against a bailout plan was "I agree that urgent and decisive action is necessary during this time of economic turmoil". Please come back with a better answer for your actions than that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-7163183352661554255?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7163183352661554255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7163183352661554255'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/09/dont-steal-from-me-senator-obama.html' title='Don&apos;t steal from me, Senator Obama'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-3378211621817531960</id><published>2008-09-16T11:40:00.003-04:00</published><updated>2008-09-16T15:27:46.463-04:00</updated><title type='text'>Eating well, or, please hold the sugar</title><content type='html'>Two members of our family were suffering new tooth-decay problems, and my wife Nicole had been reading about a dentist who researched the profound difference in health between people following traditional diets versus Western diets.&lt;br /&gt;&lt;br /&gt;Nicole decided to take the plunge and learn how to feed us a traditional diet. We have removed refined flour and sugar from our diet, and added lots of whole, organic, delicious vegetables, milk products (unpasteurized, like God&amp;mdash;&lt;a id="eating-well-pasteur-link" href="#eating-well-pasteur"&gt;and Louis Pasteur!&lt;/a&gt;&amp;mdash;intended), honey, and meat. There are lots of changes she's making as she learns, which I'll also share over time, but she's posting interesting articles on her &lt;a href="http://traditionalnutrition.blogspot.com/"&gt;traditional-food blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is incredible food, and our health is improving dramatically as we restore the levels of nutrition available to our bodies from the red zone to which modern Americans are accustomed, into normal ranges so our bodies have something to work with. Dental health, skin health, energy, mental function, sleep patterns, emotional health, you name it...every one of us is doing well and still improving rapidly.&lt;br /&gt;&lt;br /&gt;I was generously offered some chai at work this morning. I took a few ounces. It was delicious, but I noticed an immediate and all-too-familiar feeling of weakening. I used to regard this as normal, but now I realize that I would feel this whenever I ate or drank anything with refined flour or sugar. As long as I stay clear of sugar and flour, I don't crave it, and this kind of experience is quite the reinforcement of my desire to stay away.&lt;br /&gt;&lt;br /&gt;So my diet is very different now. This may sound inconvenient, and sometimes it is. But don't cry for me&amp;mdash;I'm eating delicious homemade butter, homemade ice cream (sweetened with dehydrated cane juice and/or honey), rich Indian dishes...&lt;br /&gt;&lt;br /&gt;&lt;ol style="font-size: smaller"&gt;&lt;li id="eating-well-pasteur"&gt;&lt;p&gt;Pasteurization was developed for wine. On hearing that pasteurization was to be used on milk, Pasteur is reported to have said, &lt;a href="http://www.realmilk.com/crime-against-raw-milk.html"&gt;"What are they doing to my wonderful food?"&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="#eating-well-pasteur-link"&gt;Back to article&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-3378211621817531960?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3378211621817531960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3378211621817531960'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/09/eating-well-or-please-hold-sugar.html' title='Eating well, or, please hold the sugar'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-2837189024356806558</id><published>2008-09-15T19:22:00.005-04:00</published><updated>2008-09-15T19:35:26.134-04:00</updated><title type='text'>Images: thrashing vs. process</title><content type='html'>Steve McConnell illustrated an &lt;a href="http://www.stevemcconnell.com/articles/art09.htm"&gt;article about software process&lt;/a&gt; with these images. I'm interested in this effort&amp;mdash;what is a success, and what could be improved?&lt;br /&gt;&lt;br /&gt;&lt;div style="margin: 2em; padding: 2em; background-color: #CDB;"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.stevemcconnell.com/articles/art09.htm"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px;" src="http://www.stevemcconnell.com/articles/art09-3.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.stevemcconnell.com/articles/art09.htm"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px;" src="http://www.stevemcconnell.com/articles/art09-2.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.stevemcconnell.com/articles/art09.htm"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px;" src="http://www.stevemcconnell.com/articles/art09-6.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.stevemcconnell.com/articles/art09.htm"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px;" src="http://www.stevemcconnell.com/articles/art09-1.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-2837189024356806558?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2837189024356806558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/2837189024356806558'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/09/images-thrashing-vs-process.html' title='Images: thrashing vs. process'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-6747481978770206948</id><published>2008-09-15T09:14:00.002-04:00</published><updated>2008-09-15T09:23:13.346-04:00</updated><title type='text'>How much to spend on security</title><content type='html'>&lt;p&gt;I love it when someone can give me a sound way to quantify wiggly and abstract things. Bruce Schneier wrote this about &lt;a href="http://www.csoonline.com/article/446866/Security_ROI_Fact_or_Fiction_"&gt;Security ROI&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&amp;hellip;a company should implement only security countermeasures that affect its bottom line positively. It shouldn't spend more on a security problem than the problem is worth. Conversely, it shouldn't ignore problems that are costing it money when there are cheaper mitigation alternatives. A smart company needs to approach security as it would any other business decision: costs versus benefits.&lt;/p&gt;&lt;p&gt;The classic methodology is called annualized loss expectancy (ALE), and it's straightforward. Calculate the cost of a security incident in both tangibles like time and money, and intangibles like reputation and competitive advantage. Multiply that by the chance the incident will occur in a year. That tells you how much you should spend to mitigate the risk. So, for example, &lt;strong&gt;if your store has a 10 percent chance of getting robbed and the cost of being robbed is $10,000, then you should spend $1,000 a year on security.&lt;/strong&gt; Spend more than that, and you're wasting money. Spend less than that, and you're also wasting money.&lt;/p&gt;&lt;p&gt;Of course, that $1,000 has to reduce the chance of being robbed to zero in order to be cost-effective. &lt;strong&gt;If a security measure cuts the chance of robbery by 40 percent -- to 6 percent a year -- then you should spend no more than $400 on it.&lt;/strong&gt; If another security measure reduces it by 80 percent, it's worth $800. And if two security measures both reduce the chance of being robbed by 50 percent and one costs $300 and the other $700, the first one is worth it and the second isn't.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-6747481978770206948?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/6747481978770206948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/6747481978770206948'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/09/how-much-to-spend-on-security.html' title='How much to spend on security'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-7677341637228527233</id><published>2008-09-04T20:12:00.002-04:00</published><updated>2008-09-04T20:21:42.326-04:00</updated><title type='text'>Taking back my corner of the web</title><content type='html'>I've decided to abandon the idea of focusing this blog on a narrow set of topics. I have very wide-ranging interests and strengths, and I don't think anybody's benefiting from the slow trickle of weak ideas that's left when I restrict this blog to agile + Ruby. I may even wind up posting more frequently on those topics.&lt;br /&gt;&lt;br /&gt;You may like this, you might not, but I wanted to give any subscribers fair warning.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-7677341637228527233?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7677341637228527233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7677341637228527233'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/09/taking-back-my-corner-of-web.html' title='Taking back my corner of the web'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-6052183910757314748</id><published>2008-01-20T22:42:00.000-05:00</published><updated>2008-01-20T22:44:41.232-05:00</updated><title type='text'>Quick letter about electronic voting</title><content type='html'>&lt;p&gt;Electronic voting has been thoroughly shown to be unreliable and manipulatable. As a professional software developer, I can attest to the difficulty of creating systems that cannot be tampered with. I can also add that many reports I have read of defects in voting machines have suggested a lack of competence in a task that would be difficult for the very best developers.&lt;/p&gt;&lt;p&gt;On the other hand, voting techniques that leave a paper trail give us a backup plan when machines fail us. It is long past time to add laws that encourage and aid officials in implementing paper trails for our elections. Inaction makes our elections look illegitimate, even if there is indeed no manipulation at all.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-6052183910757314748?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/6052183910757314748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/6052183910757314748'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/01/quick-letter-about-electronic-voting.html' title='Quick letter about electronic voting'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-3379577439748617248</id><published>2008-01-17T15:19:00.000-05:00</published><updated>2008-01-17T15:19:37.095-05:00</updated><title type='text'>Managing to capacity</title><content type='html'>&lt;a href="http://jchyip.blogspot.com/2007/11/two-main-topics-to-learn-in-agilelean.html"&gt;Jason Yip&lt;/a&gt; says managing to capacity is a prerequisite to other work on process:&lt;blockquote&gt;&lt;p&gt;When going down the path of Agile/Lean, there are two main topics:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Learning to manage to capacity&lt;/li&gt;&lt;li&gt;Learning how to improve process capability&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;If you can't accept the first point, the second point won't make any difference.... in fact, because of overburdening, you'll make the second point harder.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-3379577439748617248?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://jchyip.blogspot.com/2007/11/two-main-topics-to-learn-in-agilelean.html' title='Managing to capacity'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3379577439748617248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3379577439748617248'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/01/managing-to-capacity.html' title='Managing to capacity'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-8139957807100086386</id><published>2008-01-16T16:05:00.000-05:00</published><updated>2008-01-16T16:06:43.481-05:00</updated><title type='text'>assert_efficient_sql</title><content type='html'>&lt;p&gt;The ever-brilliant Phlip Plumlee with a way to lint SQL "pessimizations":&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.oreillynet.com/ruby/blog/2008/01/assert_efficient_sql.html"&gt;assert_efficient_sql - O'Reilly Ruby&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;To ensure your test cases call efficient MySQL…&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;def test_my_case&lt;br /&gt; assert_efficient_sql do&lt;br /&gt;&lt;br /&gt;   # just wrap them in this block!&lt;br /&gt;&lt;br /&gt; end&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The assertion intercepts and copies out your MySQL SELECT statements, then calls EXPLAIN on each one, and inspects the results for common problems.&lt;/p&gt;&lt;p&gt;The goal is test cases that resist database pessimization, even as you change your data relations, to add new features. If you run your tests after every few changes, you can easily detect which change broke your database’s indices and relations.&lt;/p&gt;&lt;p&gt;This article is a reference for this assertion’s options.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Phlip is soliciting help with implementing this feature across more database engines.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-8139957807100086386?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8139957807100086386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8139957807100086386'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/01/assertefficientsql.html' title='assert_efficient_sql'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-3372053874207399422</id><published>2008-01-10T01:26:00.000-05:00</published><updated>2008-01-10T10:23:06.719-05:00</updated><title type='text'>Four busted laptops, one measly task</title><content type='html'>Good friends of ours from out of state are staying with us tonight. They're fellow geeks, and he's a fellow developer.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Our task: copy 1.5 MB from a CD to his wife's MacBook.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Our challenge: his wife's MacBook does not currently read optical disks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tools available to solve the problem: a PC laptop with a failing hard drive, my work MacBook Pro that also has issues with optical disks, our family iBook that works but has no screen backlighting at present, and the destination MacBook, which, again, isn't reading optical disks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Solution: I fortunately had SSH enabled on the iBook before its backlight went out. I logged into that, and inserted the CD into the iBook. Checking in /Volumes, I found that the CD wouldn't mount until I logged in to the GUI. I'm sure there are dozens of ways I could have done that from the command line, but it went along with the silly mood of the whole thing, so I went ahead and logged in blind.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sure enough, during the GUI login process the CD appears in /Volumes. We make a tar file and my friend copies it down.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Easy peasy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PS: Oh, and the eject key on the iBook didn't cause ejection. Turns out a quick &lt;code&gt;drutil eject&lt;/code&gt; does fine.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-3372053874207399422?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3372053874207399422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3372053874207399422'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/01/four-busted-laptops-one-measly-task.html' title='Four busted laptops, one measly task'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-3004494442611781253</id><published>2008-01-04T11:20:00.000-05:00</published><updated>2008-01-04T12:01:41.207-05:00</updated><title type='text'>Track down warnings in Ruby test runs</title><content type='html'>Got warning or other spew in your Ruby test runs? To track down the source you can have a &lt;code&gt;setup&lt;/code&gt; method output the test name:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;p name&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This makes it very easy to track down the source of the unwanted output.&lt;br /&gt;&lt;br /&gt;This works because each test run is its own instance of your TestCase subclass.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-3004494442611781253?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3004494442611781253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3004494442611781253'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2008/01/track-down-warnings-in-ruby-test-runs.html' title='Track down warnings in Ruby test runs'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-1249192457585373058</id><published>2007-12-03T10:11:00.000-05:00</published><updated>2007-12-03T12:00:11.386-05:00</updated><title type='text'>Daniel J. Bernstein advocates for Ruby?</title><content type='html'>It's not your typical advocacy piece for Ruby (in fact it's not about Ruby at all), but Daniel J. Bernstein has written a paper reflecting on the success of his qmail mail server, which has a security guarantee (in the form of a $500 bounty) that has gone unclaimed since March 1997, and which runs several prominent mail houses.&lt;br /&gt;&lt;br /&gt;He notes several aspects of his development process and architectural decisions that contributed to qmail's success. Interestingly, many of his comments relate to his use of concepts in his C code that are usually associated with higher-level languages. Here he complains about C's dangerous handling of integers:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;Another surprise for the programmer is that y can be much smaller than x after y = x + 1. This happens if x is the largest representable integer, typically 2^&lt;super&gt;31&lt;/super&gt; − 1; y will then be the smallest representable integer, typically −2^&lt;super&gt;31&lt;/super&gt;.&lt;/p&gt;&lt;p&gt;...&lt;/p&gt;&lt;p&gt;Most programming environments are meta-engineered to make typical software easier to write. They should instead be meta-engineered to make &lt;em&gt;incorrect&lt;/em&gt; software &lt;em&gt;harder&lt;/em&gt; to write. An operation that is not exactly what I normally want should take &lt;em&gt;more&lt;/em&gt; work to express than an operation that is exactly what I normally want.&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Ruby does get many details like this right, and good object-oriented practices can help too. For example, I kept thinking of the &lt;a href="http://www.darrenhobbs.com/archives/2007/04/strong_typing_a.html"&gt;Tiny Types pattern&lt;/a&gt; while reading this.&lt;br /&gt;&lt;br /&gt;I'm reading this a bit at a time and still parsing what Bernstein's ideas mean to me, but the segments on spending some performance dollars to buy quality abstractions were refreshing to see from a developer who's met with measurable success.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-1249192457585373058?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/1249192457585373058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/1249192457585373058'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/12/daniel-j-bernstein-advocates-for-ruby.html' title='Daniel J. Bernstein advocates for Ruby?'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-1161236753183470773</id><published>2007-10-25T15:35:00.000-04:00</published><updated>2007-10-25T15:47:17.250-04:00</updated><title type='text'>Spying on assert_select</title><content type='html'>&lt;p&gt;When testing your views with assert_select, it's nice to get information on what response text failed to match, but it's too much to just throw @response.body into the test failure message:&lt;/p&gt;&lt;p&gt;&lt;code&gt;assert_select('div#whatever-id p.classname', 'small stuff', @response.body)&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Instead you can use nested assert_selects and the elements they yield:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;assert_select('div#whatever-id') do |whateverId|&lt;br /&gt; assert_select('p.classname', 'small stuff', whateverId)&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;That will dump out just div#whatever-id and its contents into your test failure message.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-1161236753183470773?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/1161236753183470773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/1161236753183470773'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/10/spying-on-assertselect.html' title='Spying on assert_select'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-846948145729784470</id><published>2007-07-12T16:01:00.000-04:00</published><updated>2007-07-14T13:05:25.213-04:00</updated><title type='text'>A solution for developing remotely: Vim's netrw</title><content type='html'>&lt;p&gt;I'm doing some work that has to be developed remotely, so I wanted a way to edit locally instead of doing everything in a terminal window. I tried using &lt;a href="http://code.google.com/p/macfuse/"&gt;MacFUSE&lt;/a&gt; and &lt;code&gt;sshfs&lt;/code&gt; to make the remote directory appear on my own desktop, and it worked after I figured out the options I needed, but opening files in &lt;code&gt;gvim&lt;/code&gt; was very slow.&lt;/p&gt;&lt;p&gt;So I took my friend &lt;a href="http://esm.logic.net/"&gt;Ed Marshall&lt;/a&gt;'s advice and tried Vim 7's netrw support. Bingo! It works via &lt;code&gt;scp&lt;/code&gt; (which is (almost?) always available when there's &lt;code&gt;ssh&lt;/code&gt; access) and is dreamy.&lt;/p&gt;&lt;p&gt;To edit a file &lt;code&gt;/path/to/file.rb&lt;/code&gt; owned by a user &lt;code&gt;joe&lt;/code&gt; on a machine &lt;code&gt;example.com&lt;/code&gt;:&lt;/p&gt;&lt;p&gt;&lt;code&gt;vim scp://joe@example.com/path/to/file.rb&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Brief pause while the file gets retrieved, but then it's copied to your &lt;code&gt;/tmp&lt;/code&gt; directory and everything's full speed. The only downside I ran into was that inter-file navigation wasn't as good. To get a file browser for the files in &lt;code&gt;~/path/to&lt;/code&gt;, I could then do:&lt;/p&gt;&lt;p&gt;&lt;code&gt;:sp %:h&lt;/code&gt;&lt;/p&gt;&lt;p&gt;or to edit &lt;code&gt;~/path/other_file.rb&lt;/code&gt; (again from a window opened on &lt;code&gt;~/path/to/file.rb&lt;/code&gt;):&lt;/p&gt;&lt;p&gt;&lt;code&gt;:sp %:h:h/other_file.rb&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;:sp&lt;/code&gt; means "split window". &lt;code&gt;%&lt;/code&gt; means "the current file". &lt;code&gt;:h&lt;/code&gt; means "the parent directory of the preceding file path", and can be repeated.&lt;/p&gt;&lt;p&gt;I'd love to hear more about navigating in Vim + netrw—I haven't even gotten my feet wet yet. I just wanted to share the nice experience I had right out of the box.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-846948145729784470?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/846948145729784470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/846948145729784470'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/07/solution-for-developing-remotely-vims.html' title='A solution for developing remotely: Vim&apos;s netrw'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-478871235183489498</id><published>2007-07-11T17:55:00.000-04:00</published><updated>2007-07-11T18:03:48.875-04:00</updated><title type='text'>Hidden in plain sight: script/runner</title><content type='html'>&lt;p&gt;I am loving the opportunity to work with my co-workers in the home office. We have "geek-out" lunches in the office once a week or so, and invariably all learn something.&lt;/p&gt;&lt;p&gt;So today I learned about &lt;code&gt;script/runner&lt;/code&gt;, a file that's in every Rails app that I never looked into for some reason. Turns out I wish I had. It's a replacement for calling the Ruby interpreter that gives your script your app's Rails environment preloaded, so you can just write Ruby code without having to monkey around with loading Rails yourself. Just call something like&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;script/runner my_file.rb&lt;/code&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;or&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;script/runner "puts 'My Ruby code here'; puts MyModel.count"&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;What are your favorite "hidden-before-your-eyes" features of Rails?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-478871235183489498?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/478871235183489498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/478871235183489498'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/07/hidden-in-plain-sight-scriptrunner.html' title='Hidden in plain sight: script/runner'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-1198621951169585204</id><published>2007-07-10T14:08:00.000-04:00</published><updated>2007-07-10T14:20:13.537-04:00</updated><title type='text'>Welcome Dave Astels!</title><content type='html'>&lt;p&gt;I'm excited to &lt;a href="http://daveastels.com/2007/07/10/obtiva/"&gt;welcome Dave Astels&lt;/a&gt; to the Obtiva team. Dave is a very active member of the Agile community and has shared some ideas over the years that I have found very valuable for better understanding TDD. It's an honor to have him working with us.&lt;/p&gt;&lt;p&gt;Obtiva is shaping up to be quite a strong software house with a promising future.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-1198621951169585204?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/1198621951169585204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/1198621951169585204'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/07/welcome-dave-astels.html' title='Welcome Dave Astels!'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-8376724558307740230</id><published>2007-06-25T07:38:00.000-04:00</published><updated>2007-06-25T07:43:01.177-04:00</updated><title type='text'>Land rush</title><content type='html'>&lt;p&gt;I have a workplace running gag with a friend at a client wherein when we encounter a Rails misfeature (especially the ones that have been solved carefully and elegantly in Java or elsewhere), we rip on Rails mercilessly to make ourselves feel better. My friend came up with this one almost unprovoked, I thought it eminently bloggable:&lt;/p&gt;&lt;blockquote&gt;"It's like the land rush.  We are all so excited about the free land that we forgot about all the bears and Indians waiting to kill us."&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-8376724558307740230?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8376724558307740230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8376724558307740230'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/06/land-rush.html' title='Land rush'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-8140748610805108491</id><published>2007-06-18T17:31:00.000-04:00</published><updated>2007-06-18T17:46:32.944-04:00</updated><title type='text'>How to stub out Rails helper methods with Mocha?</title><content type='html'>&lt;p&gt;&lt;em&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; The code given doesn't actually work. I'd love to hear if anyone knows of code that will do this. I hacked around the problem a very ugly way.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Rails helper methods are defined in modules and mixed into objects...of what class? Turns out it's anonymous copies of ActionView::Base. How does one mock or stub methods on such a beast? Here's a solution I found:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;class MyController&lt;br /&gt;  def rescue_action(e) raise e end&lt;br /&gt;  attr_reader :template&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class MyControllerTest &lt; Test::Unit::TestCase&lt;br /&gt;  def setup&lt;br /&gt;    @controller = ...&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def test_should_stub_helper_method&lt;br /&gt;    @controller.template.expects(:random_helper_method).returns('')&lt;br /&gt;    ...&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Thanks to &lt;a href="http://www.theagiledeveloper.com/articles/2007/05/02/rspec-view-tests-that-use-helpers#comments"&gt;Matthew Dieter&lt;/a&gt; for posting about this. I had to add the &lt;code&gt;attr_reader&lt;/code&gt; line to get this to work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-8140748610805108491?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8140748610805108491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8140748610805108491'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/06/stub-out-rails-helper-methods-with.html' title='How to stub out Rails helper methods with Mocha?'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-5635559015141114335</id><published>2007-05-21T12:25:00.000-04:00</published><updated>2007-05-21T13:02:03.245-04:00</updated><title type='text'>Rails plugins: keep init.rb thin</title><content type='html'>&lt;p&gt;Rails plugins' initializer script, &lt;code&gt;init.rb&lt;/code&gt;, is currently invoked via &lt;code&gt;eval&lt;/code&gt;, not &lt;code&gt;require&lt;/code&gt;—so it inherits whatever module-space Rails calls it from. If you reopen any classes in &lt;code&gt;init.rb&lt;/code&gt; itself (like the &lt;a href="http://errtheblog.com/post/4791"&gt;&lt;code&gt;will_paginate&lt;/code&gt; guys&lt;/a&gt; &lt;a href="http://require.errtheblog.com/plugins/browser/will_paginate/init.rb?rev=221"&gt;quite reasonably attempted&lt;/a&gt; to define &lt;code&gt;Hash#slice&lt;/code&gt;), your changes will be made—but to the wrong module.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So, to avoid strange gotchas, consider &lt;code&gt;init.rb&lt;/code&gt; just a generic hook point to kick things off, and always &lt;code&gt;require&lt;/code&gt; in any code that's to do actual work at plugin load time.&lt;/p&gt;&lt;p&gt;Alternatively, you can explicitly anchor referenced classes to the top level, like &lt;code&gt;::Hash&lt;/code&gt;. &lt;a href="http://require.errtheblog.com/plugins/changeset/223"&gt;That's the route &lt;code&gt;will_paginate&lt;/code&gt; took&lt;/a&gt;, but I would just break out a separate file and &lt;code&gt;require&lt;/code&gt; it to keep things plain and clear.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-5635559015141114335?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/5635559015141114335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/5635559015141114335'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/05/rails-plugins-keep-initrb-thin.html' title='Rails plugins: keep init.rb thin'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-5529011546964460323</id><published>2007-05-21T11:00:00.000-04:00</published><updated>2007-05-21T11:05:38.967-04:00</updated><title type='text'>Remove the menu bar and toolbar from gvim</title><content type='html'>&lt;p&gt;I wanted to reclaim some real estate from the top of my gvim screen. Here's a couple lines for the .vimrc or .gvimrc:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;" Remove menu bar&lt;br /&gt;set guioptions-=m&lt;br /&gt;&lt;br /&gt;" Remove toolbar&lt;br /&gt;set guioptions-=T&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-5529011546964460323?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/5529011546964460323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/5529011546964460323'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/05/remove-menu-bar-and-toolbar-from-gvim.html' title='Remove the menu bar and toolbar from gvim'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-7411379713971674247</id><published>2007-04-11T20:41:00.000-04:00</published><updated>2007-04-11T20:48:27.167-04:00</updated><title type='text'>GUID generation in Ruby</title><content type='html'>There's a good gem for &lt;a href="http://trac.labnotes.org/cgi-bin/trac.cgi/wiki/Ruby/UuidGenerator"&gt;Ruby GUID&lt;/a&gt; generation available:&lt;br /&gt;&lt;br /&gt;gem install uuid&lt;br /&gt;&lt;br /&gt;It's from the reliable-msg project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-7411379713971674247?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7411379713971674247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/7411379713971674247'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/04/guid-generation-in-ruby.html' title='GUID generation in Ruby'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-666219176591075688</id><published>2007-02-28T12:56:00.000-05:00</published><updated>2007-02-28T18:43:30.615-05:00</updated><title type='text'>Weekday code accepted into Ruby Facets</title><content type='html'>&lt;p&gt;&lt;a href="http://redsquirrel.com/cgi-bin/dave"&gt;Dave Hoover&lt;/a&gt; picked up the ball from my &lt;a href="http://daddy.platte.name/2006/12/calculate-next-weekday-in-ruby-on-rails.html"&gt;"next-weekday" post&lt;/a&gt; and submitted a contribution to the &lt;a href="http://facets.rubyforge.org/"&gt;Ruby Facets project&lt;/a&gt;. Now Ruby Facets lets you &lt;code&gt;require 'facets/more/times'&lt;/code&gt; and say things like &lt;code&gt;1.weekday.ago&lt;/code&gt;, &lt;code&gt;4.weekdays.from_now&lt;/code&gt;, and &lt;code&gt;9.weekdays.since(some_time)&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Have a look at &lt;a href="http://facets.rubyforge.org/src/lib/facets/more/times.rb"&gt;the source&lt;/a&gt;. Thanks for your work preparing this contribution, Dave!&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-666219176591075688?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/666219176591075688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/666219176591075688'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/02/weekday-code-accepted-into-ruby-facets.html' title='Weekday code accepted into Ruby Facets'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-8943779919425421013</id><published>2007-02-23T10:01:00.000-05:00</published><updated>2007-02-23T10:26:07.487-05:00</updated><title type='text'>Providing a format to RESTful resource routes</title><content type='html'>&lt;p&gt;I am absolutely loving the RESTful support in Rails 1.2. It uses conventions to tilt the playing field toward domain-driven design. Yum, yum, yum. My favorite use of conventions in Rails yet. The URLs are meaningful, the controllers now have a clear design, it's an appropriate and extensible abstraction, life is good and Rails apps are much improved for it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;But I ran into a hitch that foiled me for a little while. I only solved it by spelunking into the code, so I'm posting the solution in hopes that Google will be a better friend about this.&lt;/p&gt;&lt;p&gt;Simply providing a &lt;code&gt;:format&lt;/code&gt; option to a resource's named route doesn't work as expected.&lt;/p&gt;&lt;p&gt;&lt;code&gt;photo_path(:id =&gt; 1, :format =&gt; 'png') #=&gt; /photo/1?format=png&lt;/code&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Instead, the &lt;code&gt;resources&lt;/code&gt; routing method defines a separate named route prefixed with &lt;code&gt;formatted_&lt;/code&gt;:&lt;/p&gt;&lt;p&gt;&lt;code&gt;formatted_photo_path(:id =&gt; 1, :format =&gt; 'png') #=&gt; /photo/1.png&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Tricky...I wonder what it would take to make this complication unnecessary.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-8943779919425421013?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8943779919425421013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/8943779919425421013'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/02/providing-format-to-restful-resource.html' title='Providing a format to RESTful resource routes'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-9198647656470181958</id><published>2007-02-10T10:14:00.000-05:00</published><updated>2007-02-10T12:01:34.388-05:00</updated><title type='text'>Ruby on Rails and more at Obtiva</title><content type='html'>&lt;p&gt;I'm pleased to announce that I'm now working with &lt;a href="http://obtiva.com/"&gt;Obtiva&lt;/a&gt;, a group of Agile coders in Wheaton.&lt;/p&gt;&lt;p&gt;We do a lot of &lt;a href="http://www.obtiva.com/index.php?page=development"&gt;Ruby on Rails development&lt;/a&gt; work. I'm enjoying getting to know and learn from &lt;a href="http://redsquirrel.com/dave/"&gt;Dave Hoover&lt;/a&gt; and &lt;a href="http://tyler.officialopinion.com/"&gt;Tyler Jennings&lt;/a&gt;. We're hard at work on several exciting projects, some intranet apps and some major upcoming launches for national brands that are expected to get quite a lot of traffic. In addition to client work, there are rumored to be some very interesting internal efforts. Watch for some compelling announcements in this space.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Interestingly, we're also a top-shelf Java &lt;a href="http://obtiva.com/index.php?page=eclipse"&gt;Eclipse RCP&lt;/a&gt; shop. I got a demo of a major app we just delivered to a client's thousands of end users, and it's very polished and snappy. I'm quite excited about the opportunity to work with a serious agile team on this caliber of product.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We do &lt;a href="http://www.obtiva.com/index.php?page=coaching"&gt;agile coaching&lt;/a&gt; and training as well. I'll talk more about that in another post.&lt;/p&gt;&lt;p&gt;I'm excited to be part of this team. We're enthusiastic about developer testing and other agile practices,  we walk the walk, and it shows in the high quality of our deliverables and the friendly culture.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Full speed ahead!&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-9198647656470181958?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/9198647656470181958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/9198647656470181958'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/02/ruby-on-rails-and-more-at-obtiva.html' title='Ruby on Rails and more at Obtiva'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-3039143154554994617</id><published>2007-02-03T12:49:00.000-05:00</published><updated>2007-02-03T12:58:01.001-05:00</updated><title type='text'>Shortcut for locating files in TextMate</title><content type='html'>I haven't yet actually hunkered down and &lt;span style="font-style: italic;"&gt;learned&lt;/span&gt; TextMate as a key tool like I did when I learned Vim at the sage advice of &lt;span style="font-style: italic;"&gt;The Pragmatic Programmer.&lt;/span&gt; But I should.&lt;br /&gt;&lt;br /&gt;One bit I picked up recently: instead of scrolling through the file drawer to find a certain file in the project, just hit Command-T. Up pops a nice filename search box. Type a key word from the file name, and a list of filenames appears below. Type a little more to shorten the list, or just use arrows and Return, up pops the file. No mouse.&lt;br /&gt;&lt;br /&gt;Old hat for many, I'm sure, but for me it makes a big difference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-3039143154554994617?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3039143154554994617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/3039143154554994617'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2007/02/shortcut-for-locating-files-in-textmate.html' title='Shortcut for locating files in TextMate'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-4840941297025135351</id><published>2006-12-20T21:15:00.000-05:00</published><updated>2006-12-20T21:37:25.990-05:00</updated><title type='text'>Calculate next weekday in Ruby on Rails</title><content type='html'>&lt;p&gt;I had to advance a &lt;code&gt;Time&lt;/code&gt; to the next weekday for a client Ruby on Rails project. I admit I dreaded writing that code, I somehow imagined awful hacks atop awful hacks.&lt;/p&gt;&lt;p&gt;I'm happy to report it didn't turn out quite so bad after all:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;def next_weekday(original_date)&lt;br /&gt;&amp;nbsp;&amp;nbsp;one_day = 60 * 60 * 24 # in Rails just say 1.day&lt;br /&gt;&amp;nbsp;&amp;nbsp;weekdays = 1..5        # Monday is wday 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;result = original_date&lt;br /&gt;&amp;nbsp;&amp;nbsp;result += one_day until result &gt; original_date &amp;&amp; weekdays.member?(result.wday)&lt;br /&gt;&amp;nbsp;&amp;nbsp;result&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;And the test that drove it:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;pre&gt;def test_next_weekday_skips_weekend&lt;br /&gt;&amp;nbsp;&amp;nbsp;original_date = Time.at(1165606025) #  a Friday&lt;br /&gt;&amp;nbsp;&amp;nbsp;assert_equal(5, original_date.wday, "this test should give a Friday")&lt;br /&gt;&amp;nbsp;&amp;nbsp;new_date = next_weekday(original_date)&lt;br /&gt;&amp;nbsp;&amp;nbsp;assert(&lt;br /&gt;&amp;nbsp;&amp;nbsp&amp;nbsp;&amp;nbsp;new_date &gt; original_date, &lt;br /&gt;&amp;nbsp;&amp;nbsp&amp;nbsp;&amp;nbsp;"new date should be after the original date"&lt;br /&gt;&amp;nbsp;&amp;nbsp;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;assert_equal(&lt;br /&gt;&amp;nbsp;&amp;nbsp&amp;nbsp;&amp;nbsp;1, new_date.wday, &lt;br /&gt;&amp;nbsp;&amp;nbsp&amp;nbsp;&amp;nbsp;"new date should be a Monday since we gave a Friday"&lt;br /&gt;&amp;nbsp;&amp;nbsp;)&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Please feel free to embarrass me with your improvements in the comments.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-4840941297025135351?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/4840941297025135351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/4840941297025135351'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/12/calculate-next-weekday-in-ruby-on-rails.html' title='Calculate next weekday in Ruby on Rails'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-116118428812189067</id><published>2006-10-18T11:03:00.000-04:00</published><updated>2006-10-18T11:11:28.140-04:00</updated><title type='text'>Textpattern explains testable code concisely</title><content type='html'>&lt;p&gt;I've often stumbled over answering the question, "how is testable code different?" to people new to testing. Textpattern has the &lt;a href="http://textpattern.com/faq/175/will-you-add-my-code-to-textpattern"&gt;best elevator-speech answer I've seen&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;Scripted unit tests are becoming increasingly important in the Textpattern release process. You can make your code more testable by using a &lt;a href="http://en.wikipedia.org/wiki/Functional_design"&gt;functional design&lt;/a&gt; with minimal &lt;a href="http://en.wikipedia.org/wiki/Coupling_%28computer_science%29"&gt;coupling&lt;/a&gt;. A function that can be run in isolation, and returns a value based on its arguments, is easy to test. A function that prints output based on global variables, database records and configuration values is much harder to test.&lt;/blockquote&gt;&lt;p&gt;That's right. It's not about use of objects, it's about keeping side effects to a minimum. Nicely put.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-116118428812189067?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/116118428812189067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/116118428812189067'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/10/textpattern-explains-testable-code.html' title='Textpattern explains testable code concisely'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-115349056470023476</id><published>2006-07-21T09:58:00.000-04:00</published><updated>2006-07-21T10:02:44.743-04:00</updated><title type='text'>Find out what stakeholders are thinking</title><content type='html'>&lt;p&gt;&lt;a href="http://37signals.com/svn/archives2/fireside_chat_with_khoi_vinh_and_jeffrey_veen_inhouse_vs_on_your_own.php#message_5632700"&gt;Jeffrey Veen:&lt;/a&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;At Adaptive Path, we used to do a kick-off exercise where we got all stakeholders to quickly sketch their assumption of what the final product would look like.&lt;/p&gt;&lt;p&gt;Then, they would all stare at each other’s work in terror, realizing just how different they all were.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-115349056470023476?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/115349056470023476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/115349056470023476'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/07/find-out-what-stakeholders-are.html' title='Find out what stakeholders are thinking'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114957048320865950</id><published>2006-06-06T00:57:00.001-04:00</published><updated>2011-04-14T14:55:45.671-04:00</updated><title type='text'>A chat with myself, or Gmail Autochat</title><content type='html'>They need to fix the thing where you can chat with yourself. I saw a green dot on the message I'd just written to my brother Alex that said "Reply by chat to", and thought, "cool, I'll chat him for kicks". The absence of a name didn't clue me in.&lt;br /&gt;&lt;br /&gt;And then I noticed that whatever I said was echoed back to myself with an empty name. Huh, how strange, I wonder if Alex will see it twice. Then I noticed that he (my correspondent, who was Alex, of course?) was typing. Also strangely, he seemed to stop typing repeatedly and never actually send a message. He must be typing me a real epistle.&lt;br /&gt;&lt;br /&gt;And how is this that he's typing to me when I open up the quick contacts and it says he's offline?&lt;br /&gt;&lt;br /&gt;Oh wait.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note: presumably this odd use case is possible for me because send my Gmail messages with my custom &lt;tt&gt;platte.name&lt;/tt&gt; address in the From.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114957048320865950?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114957048320865950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114957048320865950'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/06/chat-with-myself-or-gmail-autochat.html' title='A chat with myself, or Gmail Autochat'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114842423208153442</id><published>2006-05-23T18:38:00.000-04:00</published><updated>2006-05-23T18:43:52.093-04:00</updated><title type='text'>\A and \z versus ^ and $</title><content type='html'>This one is subtle—if you’re anchoring a regular expression&lt;br /&gt;to the beginning and end of a &lt;span style="font-style: italic;"&gt;string&lt;/span&gt;, not a &lt;span style="font-style: italic;"&gt;line&lt;/span&gt;, you want &lt;a href="http://www.rubycentral.com/book/language.html#UL"&gt;&lt;code&gt;\A&lt;/code&gt; and &lt;code&gt;\z&lt;/code&gt;&lt;/a&gt;, not &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Guess who just got bit!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114842423208153442?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114842423208153442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114842423208153442'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/05/and-z-versus-and.html' title='\A and \z versus ^ and $'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114546608251668844</id><published>2006-04-19T12:46:00.000-04:00</published><updated>2006-04-19T14:43:36.860-04:00</updated><title type='text'>Bust your systems apart for maintainability</title><content type='html'>&lt;p&gt;Jeremy Voorhis recently posted a gem about &lt;a href="http://www.jvoorhis.com/articles/2006/04/18/heterogeneous-rails-applications"&gt;heterogenous architecture&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;There is something desirable about heterogenous architecture. Specialist components with clear lines of responsibility become a joy to work with, and easier to maintain. Don’t force heterogenous design, but consider it as an agile approach when you suspect your application is growing into a monolith.&lt;/blockquote&gt;&lt;p&gt;I've found this to be very true, and push for solutions that use independent tools over integrated frameworky things whenever possible.&lt;/p&gt;&lt;p&gt;The reason why it works is simple: when two moving parts are only able to affect each other through a well-defined interface, you have a very focused set of things to think about when you need to debug or add features. Using different technologies forces the system to have a well-defined interface even if some people don't like following rules or are ignorant of best practices.&lt;/p&gt;&lt;p&gt;Test-driven development creates a similar effect at a smaller scale: because there's always at least two users of any given code, the test code and other production code, the developer has a strong motivation to make it easier to isolate each piece of code. The result is loosely-coupled parts that communicate across well-defined interfaces.&lt;/p&gt;&lt;p&gt;So right there are two ways to get to increased maintainability:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Build heterogenous systems to force some hard boundaries between components.&lt;/li&gt;&lt;li&gt;Test first, and design to make the code easy to test.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The first works anywhere. The second is more subtle and requires more cooperation from other developers, but has a deeper benefit.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114546608251668844?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114546608251668844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114546608251668844'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/04/bust-your-systems-apart-for.html' title='Bust your systems apart for maintainability'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114542920822488051</id><published>2006-04-19T02:35:00.000-04:00</published><updated>2006-04-19T02:46:48.233-04:00</updated><title type='text'>New focus, new feed</title><content type='html'>&lt;p&gt;I'm planning to move this blog to my own domain at some point, and focus it on agile development, Ruby, and other things that aren't (overtly!) sociopolitical.&lt;/p&gt;&lt;p&gt;Please subscribe to &lt;a href="http://feeds.feedburner.com/PlatteDaddy"&gt;my new feed address&lt;/a&gt;, which will follow the blog to its new home.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114542920822488051?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114542920822488051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114542920822488051'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/04/new-focus-new-feed.html' title='New focus, new feed'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114426498086941659</id><published>2006-04-05T15:16:00.000-04:00</published><updated>2006-04-05T15:40:11.010-04:00</updated><title type='text'>Getting Gestural</title><content type='html'>&lt;div class="photo"&gt;&lt;img src="http://static.flickr.com/37/123400672_b03130f2ba.jpg?v=0" width="500" height="333" /&gt;&lt;/div&gt;&lt;p&gt;37signals put this photo of me gabbing into the &lt;a href="http://www.flickr.com/photos/37s/sets/72057594098983440/"&gt;photostream from their recent Getting Real seminar.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I don't remember exactly what I was saying, but I doubt it was quite so dramatic or important as I look like I'm trying to impart.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114426498086941659?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114426498086941659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114426498086941659'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/04/getting-gestural.html' title='Getting Gestural'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114418096857619450</id><published>2006-04-04T15:58:00.000-04:00</published><updated>2006-04-04T16:02:48.586-04:00</updated><title type='text'>Ward Cunnningham on testing in schools</title><content type='html'>&lt;blockquote&gt;The complexity of subjects and diversity of students renders any notion of uniform testing foolish. My administration will make testing and grading an extracurricular activity like sports or debate and thereby relieve public school teachers of their most unproductive daytime burden. If employers want a unidimensional metric for hiring, let them pay for it themselves. If the smart kids want to compete for valedictorian, let their parents form a booster club and host bake sales to pay for the examinations.&lt;/blockquote&gt;&lt;p&gt;&amp;mdash;what Ward Cunningham would do if elected President, from &lt;a href="http://www.c2.com/cgi/wiki?WardCunningham"&gt;his home page on his own wiki&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114418096857619450?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114418096857619450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114418096857619450'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/04/ward-cunnningham-on-testing-in-schools.html' title='Ward Cunnningham on testing in schools'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114357919659092703</id><published>2006-03-28T15:49:00.000-05:00</published><updated>2006-03-28T15:53:16.600-05:00</updated><title type='text'>Beautiful macro shots of insects</title><content type='html'>&lt;div style="float:left; margin-right: 1em;"&gt;&lt;img src="http://thumbs.photo.net/photo/4168055-sm.jpg" /&gt;&lt;/div&gt;&lt;p&gt;Via &lt;a href="http://37signals.com/svn/archives2/stunning_insect_photos.php"&gt;37signals&lt;/a&gt;, some beautiful &lt;a href="http://www.photo.net/photos/siwanowicz"&gt;macro shots of insects.&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114357919659092703?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114357919659092703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114357919659092703'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/beautiful-macro-shots-of-insects.html' title='Beautiful macro shots of insects'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114322324988923228</id><published>2006-03-24T12:57:00.000-05:00</published><updated>2006-03-24T13:00:49.900-05:00</updated><title type='text'>Some pair programming success</title><content type='html'>&lt;p&gt;I got to do some pair programming with a co-worker yesterday, about which I'm ecstatic. &lt;a href="http://vigilanteweb.com/?p=67"&gt;Sounds like he enjoyed it too.&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114322324988923228?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114322324988923228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114322324988923228'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/some-pair-programming-success.html' title='Some pair programming success'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114287511771192884</id><published>2006-03-20T12:12:00.000-05:00</published><updated>2006-03-20T12:18:37.743-05:00</updated><title type='text'>"Righteousness and peace"</title><content type='html'>&lt;blockquote&gt;How many times have I begged and pleaded, spoken and written in the media, that peace must be obtained; that we begin to make a break with the killings and the evil, that we become the human beings that we are, and behave as men of faith in the one God of justice, truth and peace who calls us to righteousness and peace, but whose call goes unheeded.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&amp;mdash;Patriarch Pavle of the Serbian Orthodox Church, in a letter to Islamic leader Reis-ul-ulimi Jakov&lt;br /&gt;&lt;br /&gt;From a compilation of &lt;a href="http://incommunion.org/articles/resources/several-statements-prayers-and-appeals-of-patriarch-pavle"&gt;several statements, prayers, and appeals of Patriarch Pavle.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114287511771192884?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114287511771192884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114287511771192884'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/righteousness-and-peace.html' title='&quot;Righteousness and peace&quot;'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114287393540488057</id><published>2006-03-20T11:58:00.000-05:00</published><updated>2006-03-20T12:07:15.703-05:00</updated><title type='text'>Is your design on the right track? Remember "PC-COF"</title><content type='html'>&lt;p&gt;&lt;a href="http://weblogs.asp.net/rosherove/articles/Design4Tesatbility1.aspx"&gt;Testable Software Design&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Here’s my current definition of a testable system:&lt;/p&gt;&lt;p&gt;For each logical part of the system, a unit test can be written relatively easily and quickly that satisfies all the following PC-COF rules at the same time:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Partial runs are possible&lt;/li&gt;&lt;li&gt;Consistent results on every test run&lt;/li&gt;&lt;li&gt;Configuration is unneeded before run&lt;/li&gt;&lt;li&gt;Order of tests does not matter&lt;/li&gt;&lt;li&gt;Fast run time&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;mdash;Roy Osherove via &lt;a href="http://homepage.mac.com/keithray/blog/2006/03/19#TestableDesigns"&gt;Keith Ray&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114287393540488057?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114287393540488057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114287393540488057'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/is-your-design-on-right-track-remember.html' title='Is your design on the right track? Remember &quot;PC-COF&quot;'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114227246607750569</id><published>2006-03-13T12:53:00.000-05:00</published><updated>2006-03-15T12:12:22.633-05:00</updated><title type='text'>Waiting to refactor</title><content type='html'>There's a slightly tangled area in the code of my current project. It's an aspect of the code that hasn't needed much flexibility to support the existing features, so this being an agile project with &lt;a href="http://article.gmane.org/gmane.comp.programming.extreme-programming.xp-explained2/251"&gt;gradual design&lt;/a&gt;, the code isn't very flexible yet.&lt;br /&gt;&lt;br /&gt;And then the request came to add several new features that would exercise the currently-inflexible code. Panic! At this point I'm not even sure what exactly is wrong with this code, only that I have been struggling uphill somewhat every time I set out to use it. It's a little research project each time.&lt;br /&gt;&lt;br /&gt;So I pour out my heart to my boss and the team member who's in the Customer role (it's an internal project, he really is the customer). "Oh boss, danger! There's something slowing me down, I know not exactly what, but I shall surely need extra time, etc.!" Too bad I let my fear run wild there. If I'd have had more patience and courage, everything would have been fine.&lt;br /&gt;&lt;br /&gt;I wound up simply keeping one eye on the "problem" area of the code while I continued to make forward progress on the new features. Turned out there were two problems I was smelling, 1) a &lt;code&gt;longish.message.chain&lt;/code&gt; in violation of the &lt;a href="http://c2.com/cgi/wiki?LawOfDemeter"&gt;Law of Demeter&lt;/a&gt; that &lt;em&gt;was&lt;/em&gt; causing coupling problems, but only at 2-3 sites, and 2) &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;inadequate model/presentation separation&lt;/a&gt;, a deeper and more widespread problem, but not hard to tackle either.&lt;br /&gt;&lt;br /&gt;And now that I understand what problems I'm facing, I'm calm and confident about the code again and can implement the refactorings gradually with minimal disruption.&lt;br /&gt;&lt;br /&gt;What did I learn?&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://xp.c2.com/CodeSmell.html"&gt;Code smells&lt;/a&gt; are good, not to be feared. They mean I'm learning about my code, and am about to make a nice improvement in its design once I figure out the source of the smell.&lt;/li&gt;&lt;li&gt;It's good to be bothered about the state of the code, but don't worry about the annoyance until I understand it as a clearly defined problem. Then I can take concrete action.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114227246607750569?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114227246607750569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114227246607750569'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/waiting-to-refactor.html' title='Waiting to refactor'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114131448099973383</id><published>2006-03-02T10:47:00.000-05:00</published><updated>2006-03-02T10:48:01.043-05:00</updated><title type='text'>Something not to do</title><content type='html'>&lt;ol&gt;&lt;li&gt;Work for a long time on a document, saving fairly infrequently.&lt;/li&gt;&lt;li&gt;Decide the document should have a different name, and instead of saving it again with that new name, &lt;em&gt;move&lt;/em&gt; the original file to that location.&lt;/li&gt;&lt;li&gt;Open the file at the new location, electing not to save the changes.&lt;/li&gt;&lt;/ol&gt;Hope you're having a great morning doing today's work. I'll be here repeating yesterday afternoon, which I don't recall enjoying too much.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114131448099973383?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114131448099973383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114131448099973383'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/something-not-to-do.html' title='Something not to do'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114124489839108498</id><published>2006-03-01T15:24:00.000-05:00</published><updated>2006-04-19T13:02:47.050-04:00</updated><title type='text'>urlencode in Ruby</title><content type='html'>&lt;p&gt;I dug around for too long to find &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/156079"&gt;this one&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;You can urlencode by calling &lt;code&gt;CGI.escape&lt;/code&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114124489839108498?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114124489839108498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114124489839108498'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/03/urlencode-in-ruby.html' title='urlencode in Ruby'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-114028676777764008</id><published>2006-02-18T13:12:00.000-05:00</published><updated>2006-02-19T00:24:14.430-05:00</updated><title type='text'>Brian Marick breaks it down</title><content type='html'>&lt;p&gt;Brian Marick wrote down a design he would use to allow the different web application layers to be tested &lt;a href="http://www.testing.com/cgi-bin/blog/2006/02/18#model-renderer-presenter-1"&gt;without too many end-to-end tests.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I wonder if Rails' components could be reimagined/rewired to work more like this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-114028676777764008?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114028676777764008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/114028676777764008'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/02/brian-marick-breaks-it-down.html' title='Brian Marick breaks it down'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-113884168555011765</id><published>2006-02-01T19:24:00.000-05:00</published><updated>2006-03-15T12:27:39.300-05:00</updated><title type='text'>Lurking dependencies in test doubles</title><content type='html'>&lt;p&gt;And so I find myself stroking my beard over an Object Mentor post again.&lt;/p&gt;&lt;p&gt;David Chelimsky points out that hand-rolled mocks create a dependency right in the test code. He relates a story similar to what I've experienced a few times, in which small &lt;a href="http://www.martinfowler.com/bliki/TestDouble.html"&gt;test doubles&lt;/a&gt; became a whole parallel hierarchy of classes implementation-coupled to the classes. It hadn't occurred to me that auto-generated mocks, or other techniques to abstract the creation of test doubles, would help keep the dependency tree clean, but there it is.&lt;/p&gt;&lt;blockquote&gt;The good news is this: the result of these observations has been that our service layer is morphing back to it's original form - very thin, simple APIs favoring dependency injection over service locator for both tests and the system under test.&lt;/blockquote&gt;&lt;p&gt;More solid concepts to work with as I consider scope and strategy for a plugin to Needle-ize Rails.&lt;/p&gt;&lt;p&gt;By the by, I'm giving up on the 2-post-long "Rails contrarian" schtick, about 2 posts too late. Ron Jeffries quotes Ralph Waldo Emerson:&lt;/p&gt;&lt;blockquote&gt;Speak the affirmative; emphasize your choice by utterly ignoring all that you reject.&lt;/blockquote&gt;&lt;p&gt;So it's time to evangelize why Ruby systems &lt;em&gt;do&lt;/em&gt; need dependency injection, or at least its full benefits. And try to ship some tools to help folks apply that advice easily.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-113884168555011765?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113884168555011765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113884168555011765'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/02/lurking-dependencies-in-test-doubles.html' title='Lurking dependencies in test doubles'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-113837904353938527</id><published>2006-01-27T11:16:00.000-05:00</published><updated>2006-01-27T11:25:32.493-05:00</updated><title type='text'>Rails contrarian, part 2: Some wisdom from Ward Cunningham</title><content type='html'>And now for some guidance from the brilliant minds that work on Fit, the acceptance-testing framework.&lt;br /&gt;&lt;br /&gt;Michael Feathers is doing to Fit something like I'm hoping to do to Rails in &lt;a href="http://www.butunclebob.com/ArticleS.MichaelFeathers.ComponentBasedFixturesForFit"&gt;this interesting post&lt;/a&gt;. Ward Cunningham himself weighs in with some of his profound insight in the comments:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Authors of large programs are wise to modularize things like application sequence, data access and input/output conversion. Where these modules exist in an application, it makes a lot of sense for Fit Fixtures to use them (after first testing them, of course). Be careful not to make your variation of Fit a platform for Fit-only modules that discourages modularity where it matters most, in the delivered application.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Thick and meaty stuff that goes right to the core of the issue, both for Fit and Rails, I think. I'll be thinking about that advice, and indeed the whole post, for a while. This is wonderful stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-113837904353938527?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113837904353938527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113837904353938527'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/01/rails-contrarian-part-2-some-wisdom.html' title='Rails contrarian, part 2: Some wisdom from Ward Cunningham'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-113791160299686740</id><published>2006-01-22T01:08:00.000-05:00</published><updated>2006-01-22T22:37:07.173-05:00</updated><title type='text'>Why Rails bugs me, part 1: test/mocks</title><content type='html'>&lt;strong&gt;UPDATE:&lt;/strong&gt; As I learn more, I'm collecting relevant links at the bottom of this post. Also, I didn't mean to sound anywhere near as negative as I did. My apologies, in particular to David, and I've reworded a few things.&lt;br /&gt;&lt;br /&gt;So here's my dilemma. I heart Ruby and have worked with it whenever possible since I learned it in 2002. Then this Heinemeier Hansson guy comes along and builds a web framework on it, markets the tar out of it, it becomes a killer app, and suddenly everybody from Slashdot to Scoble is making noise about Ruby. It's been astonishing and quite wonderful.&lt;br /&gt;&lt;br /&gt;So why am I less than enamored with Rails? Maybe I'm just playing the contrarian, as I'm wont to do, but I think I may have some reasons. Since I keep thinking of specific reasons and forgetting them at key moments, I'll try blogging even smallish issues here with whatever useful discussion I can come up with. Maybe then I can connect the dots more meaningfully.&lt;br /&gt;&lt;br /&gt;I'll start with a simple one:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;test/mocks&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I cringed when I saw this introduced. A nice, official-looking directory where I can put code that will screw with my Ruby environment only for tests, and for all tests. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Nooooooo!&lt;/strong&gt; Why not just start coding with lots of global variables and be done with it? &lt;br /&gt;&lt;br /&gt;Well-designed code has minimal dependencies at any one point, and its dependencies are on abstractions rather than implementations. This &lt;code&gt;test/mocks&lt;/code&gt; thing blesses the practice of reaching in and hacking on the dependencies of the code under test. This wouldn't be so bad for one or a small group of isolated tests; in fact it's one of the really nice things about Ruby that makes it great for test-driven development. But using &lt;code&gt;test/mocks&lt;/code&gt; applies said hacks to all the tests! &lt;br /&gt;&lt;br /&gt;Automated tests are worth the most when they can be confidently relied upon: "this test takes A, applies B and C, and I get D." Great. Now say I've changed all the B's in my system, let's call the new version "BB". My production code still uses B, but all of my tests use exclusively BB. How much confidence can a test like that give me when it matters most?&lt;br /&gt;&lt;br /&gt;Instead, I should be writing code that can be passed its dependencies so I can use BB only in the tests where it's useful, and have the real McCoy available the rest of the time so my tests catch unexpected integration problems or whatever will happen in the real world where B lurks and my little hacked-up BB ain't.&lt;br /&gt;&lt;br /&gt;I wish we could've scored a little chink in the Convention over Configuration armor for a sec back when Jamis wrote up &lt;a href="http://ruby.jamisbuck.org/rails-injected.html"&gt;a way to bring ubiquitous dependency injection to Rails&lt;/a&gt;. To me, Rails could be &lt;em&gt;so much&lt;/em&gt; stronger as a framework with the flexibility and the attention to dependency management Jamis's proposal embodied..&lt;br /&gt;&lt;br /&gt;And using the Needle dependency-injection tool this way wouldn't bring about the feared apocalypse of Rails2EE, wherein we do YAML situps to declare ServiceModuleAccessPointTriggers or whatever. It'd just add a spot where we can reach in and change which objects go where for a moment without screwing everything else up.&lt;br /&gt;&lt;br /&gt;I really want to know if there's something I can do to help solve this problem. Please fire away with flames, suggestions, questions, or massive groundswell of support in the comments.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Reverie inspired by &lt;a href="http://habtm.com/articles/2006/01/12/mocking-net-http-get"&gt;Stubbing Net::HTTP.get&lt;/a&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Updates&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;I went back and reread the pages from those few days in November 2004 when all this was shaking out. It looks like it may be possible to make a Needlizing plugin for Rails using Jamis's ideas and hacking the &lt;a href="http://api.rubyonrails.com/classes/ActionController/Dependencies/ClassMethods.html"&gt;ActionController::Dependencies&lt;/a&gt; API.&lt;br /&gt;&lt;br /&gt;And now for what might be perhaps the first Rails historical research project (?), wherein I'm trying to figure out who intended what, and what happened to those intentions:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://ruby.jamisbuck.org/rails-injected.html"&gt;Jamis's proposal&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Dave Thomas &lt;a href="http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/TransparentIOC.rdoc"&gt;hooks it up with some smart Ruby magic&lt;/a&gt; that turns class names into transparent accesses of the registry (looks like this became incorporated into Jamis's paper)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DHH likes Jamis's idea and especially Dave Thomas' simplification of it, but &lt;a href="http://www.loudthinking.com/arc/000357.html"&gt;isn't sure what it will do to Rails internals&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As Sam notes in the comments, Jamis says he's &lt;a href="http://jamis.jamisbuck.org/articles/2005/05/15/confessions"&gt;"not as convinced of the necessity of dependency injection in Ruby"&lt;/a&gt; as he once was.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Did anything happen after that? Has there been a definite decision not to incorporate dependency injection into Rails?&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-113791160299686740?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113791160299686740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113791160299686740'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/01/why-rails-bugs-me-part-1-testmocks.html' title='Why Rails bugs me, part 1: test/mocks'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-113776757654157579</id><published>2006-01-20T09:31:00.000-05:00</published><updated>2006-01-20T09:34:34.436-05:00</updated><title type='text'>The problem with software patents in a word</title><content type='html'>&lt;blockquote&gt;Imagine a world in which news was owned in such a way that once one guy reported it nobody else could report it for 20 years because the first guy to report it owned it. That's the problem that the patent law proposes to software.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Eben Moglen&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-113776757654157579?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113776757654157579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113776757654157579'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2006/01/problem-with-software-patents-in-word.html' title='The problem with software patents in a word'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-113267346046356409</id><published>2005-11-22T10:21:00.000-05:00</published><updated>2005-11-22T11:44:19.056-05:00</updated><title type='text'>Full night's sleep for Mama</title><content type='html'>&lt;p&gt;Nicole got a full night's sleep last night for the first time in a while. Gabriel had been waking lots from stuffiness. We'd repetorized (taken his symptoms and looked them up in homeopathic rubrics to find a suitable remedy) on as many symptoms as we could think of, with no results.&lt;/p&gt;&lt;p&gt;But last night, we just keyed in the main complaint, selected the matching symptom, gave him a dose of the &lt;a href="http://www.abchomeopathy.com/go.php?sr=73807"&gt;single remedy that matched&lt;/a&gt;, &lt;em&gt;et voilà&lt;/em&gt;. Problem gone instantly.&lt;/p&gt;&lt;p&gt;I'm guessing we won't again overlook &lt;a href="http://www.google.com/search?hl=en&amp;rls=en&amp;q=define%3A+characteristic+symptom"&gt;'striking, strange, unusual, peculiar'&lt;/a&gt; symptoms anytime soon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-113267346046356409?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113267346046356409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/113267346046356409'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/11/full-nights-sleep-for-mama.html' title='Full night&apos;s sleep for Mama'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-112844020890525454</id><published>2005-10-04T11:36:00.000-04:00</published><updated>2005-10-04T11:55:44.760-04:00</updated><title type='text'>RSS user experience</title><content type='html'>&lt;p&gt;It seems like RSS feeds are the most hyped and least finessed aspect of the web right now.&lt;/p&gt;&lt;p&gt;I subscribe to feeds from developers' hand-rolled blogs that seem to burp out umpteen recent posts as new every time they update. Some sites manage to remove formatting, making the feed nearly unreadable (&lt;a href="http://groklaw.net/"&gt;Groklaw&lt;/a&gt; hasn't returned my emails offering to fix their problem). Some sites include partial content, but include enough content that it's not clear whether the feed is a full-content feed or not. Even Apple's Safari browser muddies the water here by adding a "Read more..." link after each item, whether or not there's more to read.&lt;/p&gt;&lt;p&gt;So RSS is not a consistently smooth user experience.&lt;/p&gt;&lt;p&gt;But yesterday, 37signals launched &lt;a href="http://writeboard.com/"&gt;Writeboard&lt;/a&gt;, a nice little tool for collaborative editing. My friend is soliciting reviews for a paper he's writing, so he invited me to his writeboard for it. I subscribed to the RSS feed. I hadn't had any "wow" moments with Writeboard yet, but the RSS was &lt;em&gt;nice&lt;/em&gt;. Each revision marked with the author's name and the title of the writeboard, the full text of the article with underlining or strikethrough for the changes made, the author's name also appears in the author field -- why, they thought it through!&lt;/p&gt;&lt;p&gt;A nice breath of fresh air.&lt;/p&gt;&lt;p&gt;Update: changed the markup of this post to remove Blogger's spurious &amp;lt;br /&amp;gt; tags. Might as well practice what I'm preaching. I need to get on board Typo.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-112844020890525454?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/112844020890525454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/112844020890525454'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/10/rss-user-experience.html' title='RSS user experience'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-112226585503310818</id><published>2005-07-25T00:30:00.000-04:00</published><updated>2005-07-25T00:30:55.080-04:00</updated><title type='text'>We won't go to bed</title><content type='html'>&lt;p class="mobile-post"&gt;We won't go to bed until it's 12 billion o'clock.&lt;br /&gt;- Raphael&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-112226585503310818?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/112226585503310818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/112226585503310818'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/07/we-wont-go-to-bed.html' title='We won&apos;t go to bed'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-112226065692052046</id><published>2005-07-24T23:04:00.000-04:00</published><updated>2005-07-24T23:04:16.956-04:00</updated><title type='text'>I'm sure somebody analyzed it</title><content type='html'>&lt;p class="mobile-post"&gt;I'm sure somebody analyzed it and made sure it was the best decision for us all.&lt;br /&gt; - Nicole&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-112226065692052046?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/112226065692052046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/112226065692052046'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/07/im-sure-somebody-analyzed-it.html' title='I&apos;m sure somebody analyzed it'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-111765727846662249</id><published>2005-06-01T16:21:00.000-04:00</published><updated>2005-06-01T16:21:18.476-04:00</updated><title type='text'>Returning from restful visit with</title><content type='html'>&lt;p class="mobile-post"&gt; Returning from restful visit with my in-laws. Very encouraging: friends with MS and cancer resonated with Hamer's theories &amp;amp; wanted to know more.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-111765727846662249?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111765727846662249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111765727846662249'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/06/returning-from-restful-visit-with.html' title='Returning from restful visit with'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-111593683330285733</id><published>2005-05-12T18:27:00.000-04:00</published><updated>2005-05-12T18:27:13.320-04:00</updated><title type='text'>Sitting on a train wondering</title><content type='html'>&lt;p class="mobile-post"&gt; Sitting on a train wondering how to configure myself for the public. Noticed that the different Metra lines have their own personalities.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-111593683330285733?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111593683330285733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111593683330285733'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/05/sitting-on-train-wondering.html' title='Sitting on a train wondering'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-111582701712919186</id><published>2005-05-11T11:56:00.000-04:00</published><updated>2005-05-11T11:56:57.173-04:00</updated><title type='text'>How to work with dates</title><content type='html'>&lt;p class="mobile-post"&gt; How to work with dates in a sloppy way?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-111582701712919186?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111582701712919186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111582701712919186'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/05/how-to-work-with-dates.html' title='How to work with dates'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-111575673844742367</id><published>2005-05-10T16:25:00.000-04:00</published><updated>2005-05-10T16:34:30.176-04:00</updated><title type='text'>A more rugged Backpack</title><content type='html'>&lt;p class="mobile-post"&gt;I'm surprised at my reaction to &lt;a href="http://backpackit.com/"&gt;Backpack&lt;/a&gt;. I'm finding that it feels too clean, too packaged for something to which I could want to commit so thoroughly. I love 37signals' work, but I feel like Backpack's weakness is its failure to deliver something as open as the technologies from which it descends, namely blogs and wikis. The Backpack/Basecamp idiom is polished-looking, which is great for many purposes, but for me it doesn't work for brainstorming and other "raw bits" purposes that comprise what I need to do with what's in my head. Backpack suggests a larger integration of technologies and use cases than has been accounted for, and its ideas reach well beyond the scope of a single product.&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;I want an Ajax scratch pad that can share, email, receive mail, name URLs, remind, integrate fluidly. 37signals showed us how this can be packaged slickly. I'd like to open this idea up for a lot more collaboration and a lot more freedom.&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;I felt this way already, but Adam Bosworth of Google recently spoke about four criteria for evaluating whether a web technology will catch on: &lt;a href="http://www.onlamp.com/pub/a/onlamp/2005/04/22/bosworth.html"&gt;"Simple, sloppy, standards-based, scalable."&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;Backpack is standards-based. I've discussed a desire to make a sloppy version. I bet the remaining criteria of "simple" and "scalable" can be used to create something really interesting.&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;And towards "standards-based": what if in addition to creating and consuming email, whatever-it-is also created and consumed RSS? IM?&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;But also, as I complained to the 37signals team, Backpack doesn't have a clear focus. It's really slick, and its current huge success may make me look like a fool for saying so, but I don't think it's a winning idea without a better story. Whatever angle I come up with, Backpack is too big or too small, too personal or too prefab. I like the way Google is building focused services independently, then gradually tying them in to the larger Google experience. Backpack seems like several such services awkwardly rolled into one.&lt;/p&gt;&lt;br /&gt;&lt;p class="mobile-post"&gt;I'll collect ideas and action items toward the vision described above &lt;br /&gt;in the comments. Please speak up if this piques your interest.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-111575673844742367?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111575673844742367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111575673844742367'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/05/more-rugged-backpack.html' title='A more rugged Backpack'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-111574973299652444</id><published>2005-05-10T14:28:00.000-04:00</published><updated>2005-05-10T15:20:09.683-04:00</updated><title type='text'>It's an experiment.</title><content type='html'>&lt;p class="mobile-post"&gt;I'm typing this on my cell. Mini thoughts...like poetry. We'll see.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-111574973299652444?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111574973299652444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/111574973299652444'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2005/05/its-experiment.html' title='It&apos;s an experiment.'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-109414515088444256</id><published>2004-09-02T13:10:00.000-04:00</published><updated>2004-09-02T13:12:30.886-04:00</updated><title type='text'>Glass</title><content type='html'>I just realized, I really enjoy drinking from a glass, as in glass glass, not plastic glass. Maybe it's a silver-spoon thing, but it's a little bit of elegance or something.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-109414515088444256?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/109414515088444256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/109414515088444256'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2004/09/glass.html' title='Glass'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-108851931054589984</id><published>2004-06-29T10:26:00.000-04:00</published><updated>2004-06-29T11:36:52.580-04:00</updated><title type='text'>Cold blood</title><content type='html'>A father's &lt;a href="http://www.pchrgaza.org/special/tv2.htm" title="Palestinian Centre for Human Rights"&gt;last day&lt;/a&gt; with his son.&lt;br /&gt;&lt;br /&gt;Reports from &lt;a href="http://www.guardian.co.uk/israel/Story/0,2763,376639,00.html"&gt;the Guardian,&lt;/a&gt; &lt;a href="http://www.wnyc.org/onthemedia/transcripts/transcripts_122201_images.html"&gt;WNYC's On the Media.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-108851931054589984?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/108851931054589984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/108851931054589984'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2004/06/cold-blood.html' title='Cold blood'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-6930361.post-108420240712665788</id><published>2004-05-10T11:18:00.000-04:00</published><updated>2004-05-10T11:20:07.126-04:00</updated><title type='text'>FP</title><content type='html'>* first post&lt;br /&gt;* faux pas&lt;br /&gt;* Fisher-Price&lt;br /&gt;* functional programming&lt;br /&gt;* fap poofer&lt;br /&gt;* fat pig&lt;br /&gt;* fluffy pigeon&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6930361-108420240712665788?l=daddy.platte.name' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/108420240712665788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6930361/posts/default/108420240712665788'/><link rel='alternate' type='text/html' href='http://daddy.platte.name/2004/05/fp.html' title='FP'/><author><name>Ryan Platte</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>
