<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-5733547231775030285</atom:id><lastBuildDate>Mon, 17 Nov 2008 22:24:10 +0000</lastBuildDate><title>Mere Code</title><description>Hacking, Software Collaboration, Testing and Diverse Other Topics of General Interest to the Practicing Programmer</description><link>http://code.mumak.net/</link><managingEditor>noreply@blogger.com (jml)</managingEditor><generator>Blogger</generator><openSearch:totalResults>47</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-2458215621591676531</guid><pubDate>Sat, 15 Nov 2008 01:54:00 +0000</pubDate><atom:updated>2008-11-15T13:09:14.471+11:00</atom:updated><title>Review Thoughts</title><description>So, I think I've figured out what it is I dislike about Twisted's review process: reviews aren't thorough enough.&lt;br /&gt;&lt;br /&gt;This sounds a little weird, since it's actually &lt;span style="font-style: italic;"&gt;really hard&lt;/span&gt; to get a patch into Twisted: it almost always takes me at least three round trips just to get something in. But I think the number of round-trips is actually a symptom of this lack of completeness.&lt;br /&gt;&lt;br /&gt;In Launchpad, reviews are done as in-line replies to diffs. A reviewer is obliged to note each chunk of code that needs to be changed, along with exactly what needs to be changed. In Twisted, reviews are done as Trac comments and generally provided as bullet points. In Launchpad, a reviewer would say, "You need to change foo_bar to fooBar, because our coding standards require camel case". In Twisted, a reviewer might say "There are some naming convention issues".&lt;br /&gt;&lt;br /&gt;This obviously varies between reviewers and even between reviews, but I think that the difference in technologies encourages differences in review style.&lt;br /&gt;&lt;br /&gt;As a patch submitter, I find the in-line-comments-on-diff form much more helpful. It provides me with a convenient todo list, and it lets me know that the reviewer has looked through and tried to understand all of my code. It essentially turns the review into a series of mini bug reports with "observed, expected, how to reproduce" sections (where "how to reproduce" is "where to find").&lt;br /&gt;&lt;br /&gt;I also like it as a reviewer, since it means less typing.</description><link>http://code.mumak.net/2008/11/review-thoughts.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>8</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-4202567634447752128</guid><pubDate>Sat, 01 Nov 2008 11:14:00 +0000</pubDate><atom:updated>2008-11-01T22:18:43.220+11:00</atom:updated><title>Papers and Talks</title><description>At the Launchpad Epic, I presented a paper on Twisted for the other Launchpadders. I think that the paper itself is a good introduction to how Twisted works and why, and I'll be publishing it here once I get a chance to format it for the web.&lt;br /&gt;&lt;br /&gt;I did two lightning talks that might be interesting to readers. One was on &lt;a href="https://launchpad.net/testresources"&gt;testresources&lt;/a&gt; and the other was on how to hack like an Evil Overlord. I think I'll try present the second one at OSDC.</description><link>http://code.mumak.net/2008/11/papers-and-talks.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-7799471131710798688</guid><pubDate>Thu, 30 Oct 2008 10:40:00 +0000</pubDate><atom:updated>2008-10-30T21:40:52.902+11:00</atom:updated><title>Lange's Law</title><description>"With threads, all things are possible."</description><link>http://code.mumak.net/2008/10/langes-law.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-8735723393616821708</guid><pubDate>Thu, 16 Oct 2008 09:10:00 +0000</pubDate><atom:updated>2008-10-16T20:11:59.098+11:00</atom:updated><title>Stacked branches in Launchpad</title><description>Via the medium of the charming &lt;a href="http://www.understated.co.uk/"&gt;Matthew Revell&lt;/a&gt;, I've posted about &lt;a href="http://news.launchpad.net/cool-new-stuff/stacked-branches-holding-post"&gt;stacked branches&lt;/a&gt; on the Launchpad News blog. I'm so glad this is finally out.</description><link>http://code.mumak.net/2008/10/stacked-branches-in-launchpad.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-4581957531852088183</guid><pubDate>Tue, 07 Oct 2008 01:24:00 +0000</pubDate><atom:updated>2008-10-07T12:27:33.627+11:00</atom:updated><title>Super Happy?</title><description>Does Sydney have a Super Happy Dev House or Hacking Society or &lt;span style="font-style: italic;"&gt;anything&lt;/span&gt; where a bunch of busy programmers can sit down together and &lt;span style="font-style: italic;"&gt;hack&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;If not, could you please organize one for me — that'd be great.</description><link>http://code.mumak.net/2008/10/super-happy.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-3069404486951925456</guid><pubDate>Mon, 06 Oct 2008 06:34:00 +0000</pubDate><atom:updated>2008-10-06T17:39:27.124+11:00</atom:updated><title>More bzr hacking</title><description>I've extended bzr-establish to give it a new command: hack.&lt;br /&gt;&lt;br /&gt;'bzr hack lp:foo' will create a repository with working trees called 'foo' and fetch the lp:foo branch into that repository.&lt;br /&gt;'bzr hack --repository ~/repos lp:foo' will create a repository in '~/repos/foo', a working tree area in 'foo', fetch the branch into the repo and make a light-weight checkout in the working tree area.&lt;br /&gt;&lt;br /&gt;You can also specify a non-Launchpad branch, e.g. 'bzr hack http://example.com/some/branch/trunk foo'. This will make a repository called 'foo', put the branch in there and... well, you get the picture.&lt;br /&gt;&lt;br /&gt;The plugin lives at lp:~jml/+junk/bzr-establish. It's buggy, not particularly well tested and rough as guts. Still, it's worth a play.</description><link>http://code.mumak.net/2008/10/more-bzr-hacking.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-1086359397400155017</guid><pubDate>Sat, 04 Oct 2008 12:54:00 +0000</pubDate><atom:updated>2008-10-04T23:05:26.733+10:00</atom:updated><title>Bazaar hacking</title><description>I spent a little bit of time mucking around with some Bazaar plugin ideas I've had.&lt;br /&gt;&lt;br /&gt;The first is a command that switches from "branches and trees together inside a shared repository" to "treeless repository with lightweight checkouts". I ran it against a couple of my local repositories and it works out rather nicely. If you are thinking of using cbranch and the like, you should have a look at this plugin. If you don't know why it's a good idea, well, umm, maybe one of the &lt;a href="http://planet.bazaar-vcs.org"&gt;other people on the Planet&lt;/a&gt; will blog an answer.&lt;br /&gt;&lt;br /&gt;The second adds 'bzr new' to the command list.&lt;br /&gt;    $ bzr new awesomer&lt;br /&gt;&lt;br /&gt;will create a new shared repository called 'awesomer' and a new branch in that repository called 'trunk'. If you think trunk is a terrible name, you can do:&lt;br /&gt;    $ bzr new awesomer devel&lt;br /&gt;&lt;br /&gt;If you are like Tim or Aaron, you'll want your repository and branches separated from your working tree:&lt;br /&gt;    $ bzr --repository ~/repos/foo foo devel&lt;br /&gt;&lt;br /&gt;I'd like to figure out a nice way of letting users specify a default directory for repositories to go into, for those people who always use the split model.&lt;br /&gt;&lt;br /&gt;The plugin with both of these commands can be found at https://code.edge.launchpad.net/~jml/+junk/bzr-establish. As the "junk" in the name indicates, it's really rough code.&lt;br /&gt;&lt;br /&gt;If either of these features sound like good ideas to you, let me know!</description><link>http://code.mumak.net/2008/10/bazaar-hacking.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-3091270858396273780</guid><pubDate>Sat, 04 Oct 2008 05:20:00 +0000</pubDate><atom:updated>2008-10-04T15:47:20.547+10:00</atom:updated><title>testresources: some examples</title><description>There's been a clamor for more documentation on how to use &lt;a href="https://launchpad.net/testresources"&gt;testresources&lt;/a&gt;. While I'm not qualified to show you the &lt;span style="font-style: italic;"&gt;best&lt;/span&gt; way to use it, I can show you the way that I would begin to use it.&lt;br /&gt;&lt;br /&gt;The linked files are a bunch of unit tests for database code that uses &lt;a href="http://storm.canonical.com/"&gt;Storm&lt;/a&gt;. Where a real test suite might use an in-memory database, this test suite uses on on-disk sqlite database to better illustrate testresources. This database needs to be removed and built again after each test to guarantee test isolation.&lt;br /&gt;&lt;br /&gt;You'll need testresources, Storm and testtools in your Python import path to run these examples.&lt;br /&gt;&lt;br /&gt;The first file, &lt;a href="http://code.mumak.net/complex-example.py"&gt;complex-example.py&lt;/a&gt;, shows how I might do this without testresources. I create a DatabaseService class that has a setUp and tearDown of its own, and a get_store() method that tests are likely to use. This might not be the best thing for databases, but is very close to what I'd do for network services in tests, where I would need to start the service, stop it and have methods to get URLs, clients and other information about the service. If you run the file, you'll see that the database is &lt;span style="font-style: italic;"&gt;created&lt;/span&gt; at the start of each test, and &lt;span style="font-style: italic;"&gt;destroyed&lt;/span&gt; before the test finishes. In total, it's created and destroyed three times.&lt;br /&gt;&lt;br /&gt;The second file, &lt;a href="http://code.mumak.net/complex-example-2.py"&gt;complex-example-2.py&lt;/a&gt;, shows how to switch to using testresources. To do this I,&lt;br /&gt;&lt;ul&gt;&lt;li&gt;added a TestResource subclass called DatabaseResource that implements make() and clean() by delegating to a DatabaseService.&lt;/li&gt;&lt;li&gt;changed the test case to subclass ResourcedTestCase&lt;/li&gt;&lt;li&gt;added 'resources = [('database', DatabaseResource())] as a class variable of the test case.&lt;/li&gt;&lt;/ul&gt;Instead of using DatabaseService() in the test, I could have, and perhaps should have, declared a module level instance of DatabaseResource. In that case, the code would have looked like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class _DatabaseResource(TestResource):&lt;br /&gt;   ...&lt;br /&gt;DatabaseResource = _DatabaseResource()&lt;br /&gt;&lt;br /&gt;class TestPerson(unittest.TestPerson):&lt;br /&gt;  ...&lt;br /&gt;  resources = [('database', DatabaseResource)]&lt;br /&gt;  ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Running the file shows that the behaviour is the same as the first example: the database is &lt;span style="font-style: italic;"&gt;created&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;destroyed&lt;/span&gt; in each test.&lt;br /&gt;&lt;br /&gt;The third file, &lt;a href="http://code.mumak.net/complex-example-3.py"&gt;complex-example-3.py&lt;/a&gt;, shows how to take advantage of OptimisingTestSuite (sic). We load the test suite as usual, &lt;span style="font-style: italic;"&gt;adsorb&lt;/span&gt; (sic) them into an OptimisingTestSuite and return that. We also have to explicity declare when a test &lt;span style="font-style: italic;"&gt;dirties&lt;/span&gt; the DatabaseResource. I chose to do this by adding a dirtied() method to the DatabaseService. If I had used a singleton (as above), then I would have just called dirtied on that.&lt;br /&gt;&lt;br /&gt;Anyway, if you run the third example, you'll see that the database is &lt;span style="font-style: italic;"&gt;created&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;destroyed&lt;/span&gt; outside the tests and that its only done &lt;span style="font-style: italic;"&gt;twice&lt;/span&gt;. The test suite has been optimized by sharing resources between tests when possible.&lt;br /&gt;&lt;br /&gt;I hope this helps explain how to use testresources. Certainly writing has been a useful exercise for me, it's highlighted that:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a list of 2-tuples isn't quite right for declaring which resources a test uses.&lt;/li&gt;&lt;li&gt;the dirtied API is inconvenient&lt;/li&gt;&lt;li&gt;TestResource remains a confusing name for the class, as it conflates the resource acquisition and cleanup with the actual &lt;span style="font-style: italic;"&gt;resource&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Some of the API docs are wrong (notably the ones for ResourcedTestCase).&lt;/li&gt;&lt;li&gt;The pattern of "resource object with setUp, tearDown, dirtied (and addCleanup)" should perhaps be turned into Python code.&lt;/li&gt;&lt;/ul&gt;I long for your thoughts.&lt;br /&gt;&lt;br /&gt;Examples:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.mumak.net/complex-example.py"&gt;complex-example.py&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.mumak.net/complex-example-2.py"&gt;complex-example-2.py&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.mumak.net/complex-example-3.py"&gt;complex-example-3.py&lt;/a&gt;</description><link>http://code.mumak.net/2008/10/testresources-some-examples.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-7127497693726662203</guid><pubDate>Sat, 04 Oct 2008 03:59:00 +0000</pubDate><atom:updated>2008-10-04T14:04:26.282+10:00</atom:updated><title>pyunit3k renamed to testtools</title><description>After thinking and talking about it for ages, I've renamed 'pyunit3k' to 'testtools'. You can now find it at https://launchpad.net/testtools or get your copy by running 'bzr branch lp:testtools'.&lt;br /&gt;&lt;br /&gt;This is the only major API change I plan to do without introducing some sort of formal release process. The code as it stands is highly stable, well tested and in use on production systems. Download it, use it, send me patches.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Addendum&lt;/span&gt;&lt;br /&gt;I forgot to mention that ITestResult has been removed, and thus the undocumented dependency on zope.interfaces. If this matters to you, please let me know.</description><link>http://code.mumak.net/2008/10/pyunit3k-renamed-to-testtools.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-2274616785888637855</guid><pubDate>Fri, 03 Oct 2008 09:13:00 +0000</pubDate><atom:updated>2008-10-03T20:55:05.407+10:00</atom:updated><title>LCA 2008 Conference Report</title><description>Yeah, yeah, I know it's a bit late. I found this while emptying out my Drafts folder and thought you guys might like it.&lt;br /&gt;&lt;br /&gt;It's very much a personal, in-the-moment, opinionated account. I've only edited it for formatting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sunday, January 27&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Arrived in Melbourne. Good. Next step, dump bags and get beer. Bump into skinny guys with puns on their T-shirts and hunted expressions. Follow them to pub. Rusty is buying free drinks for first-timers. I take two.&lt;br /&gt;&lt;br /&gt;Go to Lygon Street. Eat pizza.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Monday, January 28&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Public holiday today. No coffee for sale on campus. The buzz so far is that everyone loves Ubuntu, or at least takes it for granted — which can sometimes pass for love.&lt;br /&gt;&lt;br /&gt;The chatter about Bazaar is more interesting. Everyone says "Bee-Zed-Ahh" and lists it along with Git and Mercurial. When I talk to people, they don't seem to really care about VCS, they just fall in whatever their project uses. Those who have used DVCS talk about "modern version control" (distributed) and "legacy version control" (CVS, SVN). Those who haven't aren't even aware of how much DVCS can help:&lt;br /&gt;&lt;br /&gt; &lt;jml&gt; jml: [[ something about branches ]]&lt;br /&gt; &lt;other_guy&gt;other_guy: yeah, I know what branches are.&lt;br /&gt; &lt;jml&gt; jml: but we make a new branch for every single bug fix.&lt;br /&gt; &lt;other_guy&gt; other_guy: what? how can you do that? isn't that an pain in the arse?&lt;br /&gt; * jml takes other_guy aside and quietly explains.&lt;br /&gt;&lt;br /&gt;The guy who talked about securing code — making sure the stuff you release is the stuff you wrote — knew about Bazaar's GPG revision signing, but didn't like it. I reckon there's some nice stuff we could do here.&lt;br /&gt;&lt;br /&gt;At the Debian miniconf, I sat down and listened to someone explain how to use Git to make Debian packages. The speaker kept saying "... because Git is stupid" and then showed us a diagram that had more lines than a telephone exchange.&lt;br /&gt;&lt;br /&gt;He also did an interactive demo. Before then, I hadn't seen git being used. It's not a friendly application. I mentioned this to some people on the way out and got answers that were too complex for a hallway. Bazaar rocks, we just need to get people to &lt;span style="font-style: italic;"&gt;use&lt;/span&gt; it.&lt;br /&gt;&lt;br /&gt;Went to the OpenSSH talk. It was packed, and the content was interesting, strong and a little dry. Got some ideas for improving Conch (the SSH server that Launchpad uses for codehosting).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tuesday, January 29&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At the Gnome mini conf, trying to get a leg up into contributing. My grand aim is to get a calendar on my desktop that is as beautiful and pleasurable as iCal.&lt;br /&gt;&lt;br /&gt;It seems that lots of others share my desire. I ended up chatting to Rob Bradford from Opened Hand and a couple of other Gnome guys — it sounds like it might be approaching possible.&lt;br /&gt;&lt;br /&gt;Found my phone charger.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Wednesday, January 30&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bruce Schneier keynoted. The talk had a few ideas but was light on point. The tutorial on hardening Linux apps was cancelled, and I'm now sitting here while Russell Coker talks about SELinux.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Thursday, January 31&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tired and cranky. Decide to do some hacking.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Friday, February 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's 6:45pm now and all I can think about is signing off and zoning out. Lots of cool talks today.&lt;br /&gt;&lt;br /&gt;During the Speaker's Panel, someone asked "What was your favourite thing that happened in Open Source last year?". One person put up their hand and said "git".&lt;/other_guy&gt;&lt;/jml&gt;&lt;/other_guy&gt;&lt;/jml&gt;</description><link>http://code.mumak.net/2008/10/lca-2008-conference-report.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-1597206659759773248</guid><pubDate>Thu, 02 Oct 2008 12:20:00 +0000</pubDate><atom:updated>2008-10-02T22:34:00.502+10:00</atom:updated><title>testresources overhaul</title><description>&lt;a href="https://launchpad.net/%7Elifeless"&gt;Rob&lt;/a&gt; has landed my overhaul of &lt;a href="https://launchpad.net/testresources"&gt;testresources&lt;/a&gt;. testresources is now a lot cleaner, with more tests, more documentation and fewer classmethods. If you've looked at it before and found it a bit confusing, now is a great time to have a fresh look.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://bazaar.launchpad.net/%7Elifeless/testresources/trunk/annotate/18?file_id=news-20080828110236-ku9h8n676vfwcwad-1"&gt;NEWS&lt;/a&gt; file, &lt;a href="http://bazaar.launchpad.net/%7Elifeless/testresources/trunk/annotate/18?file_id=README-20050904000703-ba3978635caa34f7"&gt;README&lt;/a&gt; or &lt;a href="http://bazaar.launchpad.net/%7Elifeless/testresources/trunk/annotate/18?file_id=todo-20080817122443-kaikqdedcg57lr4v-1"&gt;TODO&lt;/a&gt; are all great places to start. Or, you could just download the &lt;a href="https://code.edge.launchpad.net/%7Elifeless/testresources/trunk"&gt;branch&lt;/a&gt; from Launchpad. 'bzr branch lp:testresources' should do the trick.&lt;br /&gt;&lt;br /&gt;There's still so much I want to do, but this has been the big step: getting a firm conceptual base to work from.</description><link>http://code.mumak.net/2008/10/testresources-overhaul.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>3</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-246790443235994368</guid><pubDate>Mon, 18 Aug 2008 03:21:00 +0000</pubDate><atom:updated>2008-08-18T13:52:28.738+10:00</atom:updated><title>Flow, Interruptions and Gold-Titanium Alloys</title><description>As I mentioned earlier, I've just had a very productive and fun weekend of hacking on &lt;a href="https://launchpad.net/testresources"&gt;testresources&lt;/a&gt;. But why was it so good?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fast Commits&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Because I was working offline using Bazaar, I could make commits to testresources and they'd be done before I could Alt-Tab back to Emacs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fast Tests&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It takes about 0.15 seconds to run the test suite. This meant I was running it all the time, which in turn meant that I was totally certain about whether the code worked all the time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Clarity of Purpose&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I knew where I was and where I wanted to go.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No Rabbit Holes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The testresources code base is small enough that it is nearly impossible to get distracted by &lt;span style="font-style: italic;"&gt;other&lt;/span&gt; systemic defects. If there is such a defect, it's probably the one that you're working on right now. This might be another way of saying...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No Blockers&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I wasn't waiting on anyone to do anything. There weren't any other bugs that needed to get fixed before I could continue.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No Integration&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The system is about as self-contained as it gets. No signals, subprocesses or sockets: just Python. The only dependency is pyunit3k, which is small, robust, well-tested and also pretty darn self-contained.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;No Interruptions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I wasn't answering questions on IRC, taking Skype calls, handling incoming email, doing the washing, checking Facebook, catching up on my blogs, watching a film or wrestling a bear. "Fast Commits" and "Fast Tests" probably fall into this category too.&lt;br /&gt;&lt;br /&gt;In other words:&lt;br /&gt;&lt;blockquote&gt;There is nothing except this. There's no art opening, no charity, nothing to sign. There's the next mission, and nothing else.  &lt;/blockquote&gt;</description><link>http://code.mumak.net/2008/08/flow-interruptions-and-gold-titanium.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-3620018535113229223</guid><pubDate>Mon, 18 Aug 2008 01:11:00 +0000</pubDate><atom:updated>2008-08-18T11:50:03.492+10:00</atom:updated><title>testresources: fresh blood</title><description>Last weekend I spent a bunch of timing hacking on &lt;a href="https://launchpad.net/testresources"&gt;testresources&lt;/a&gt; with &lt;a href="http://robertcollins.net/"&gt;Rob&lt;/a&gt; over at &lt;a href="https://launchpad.net/%7Eraof"&gt;Chris&lt;/a&gt;'s place. testresources is an extension to unittest that allows tests to specify the resources they use declaratively, so that these resources can be cleanly shared between tests. On Saturday, we talked a bit about direction and decided on some goals. On Sunday, &lt;a href="https://code.launchpad.net/%7Ejml/testresources/tests-meaning-cleanup/+merge/767"&gt;I got busy&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The idea isn't particularly new: zope.testing has had "layers" for a long time. The key differences between testresources and Zope layers are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You can use more than one TestResource. You can only use one layer. Allowing tests to specify many resources makes it easier to use only the resources that you need, which in turn makes for a faster test suite.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A test that uses testresources can be used independently of other testresources machinery. With layers, you pretty much need the whole shebang. This means that you can use testresources with trial, bzr, nose, tribunal or unittest.TextTestRunner.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Layers have magical inheritance stuff. testresources has no magic.&lt;/li&gt;&lt;li&gt;Layers do some work in subprocesses to accommodate some setUps that can have no tearDown. testresources doesn't know what a process is.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;That said, I'm mainly familiar with layers from Zope 3.2—they may have changed since then.&lt;br /&gt;&lt;br /&gt;testresources itself is somewhat old. Rob hacked up the first version about three years ago and little has happened to it since. I've always agreed with the approach, but have also had a few qualms about implementation details that made me reluctant to use it or to recommend it. Now, it's well on its way to being something that I can trust and perhaps, love.&lt;br /&gt;&lt;br /&gt;If you are interested, check out &lt;a href="https://code.launchpad.net/%7Ejml/testresources/tests-meaning-cleanup"&gt;my branch&lt;/a&gt; or at least flick through the &lt;a href="http://bazaar.launchpad.net/%7Ejml/testresources/tests-meaning-cleanup/annotate/77?file_id=todo-20080817122443-kaikqdedcg57lr4v-1"&gt;TODO&lt;/a&gt; file.</description><link>http://code.mumak.net/2008/08/testresources-fresh-blood.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-7623350122185148360</guid><pubDate>Fri, 25 Jul 2008 05:38:00 +0000</pubDate><atom:updated>2008-07-25T15:52:28.793+10:00</atom:updated><title>Cool Launchpad/Bazaar hack</title><description>If you push a lot of Bazaar branches to Launchpad, you might want to add something like this to your .bazaar/locations.conf:&lt;pre&gt;[/home/jml/Code]&lt;br /&gt;public_branch = lp:~jml&lt;br /&gt;public_branch:policy = appendpath&lt;br /&gt;push_location = lp:~jml&lt;br /&gt;push_location:policy = appendpath&lt;br /&gt;&lt;/pre&gt;Once it's there, 'bzr push' will Just Work... as long as you want it to do something like:&lt;pre&gt;jml@rhino:~$ cd ~/Code/&lt;a href="https://launchpad.net/pyunit3k" title="What is pyunit3k?"&gt;pyunit3k&lt;/a&gt;/trunk&lt;br /&gt;jml@rhino:~/Code/pyunit3k/trunk$ bzr push&lt;br /&gt;Using saved location: lp:~jml/pyunit3k/trunk&lt;br /&gt;No new revisions to push.&lt;br /&gt;&lt;/pre&gt;So if I've got a branch in &lt;code&gt;~/Code/&amp;lt;project-name&amp;gt;/&amp;lt;branch-name&amp;gt;&lt;/code&gt;, it'll be published at &lt;code&gt;https://launchpad.net/~jml/&amp;lt;project-name&amp;gt;/&amp;lt;branch-name&amp;gt;&lt;/code&gt;. This is only a default, of course: you can override it for a given branch by doing:&lt;pre&gt;bzr push --remember &amp;lt;new_location&amp;gt;&lt;/pre&gt;Or you can override it for a bunch of branches by hacking locations.conf.&lt;br /&gt;&lt;br /&gt;Neat huh?</description><link>http://code.mumak.net/2008/07/cool-launchpadbazaar-hack.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-4536070818872098294</guid><pubDate>Mon, 07 Jul 2008 07:00:00 +0000</pubDate><atom:updated>2008-07-07T18:22:37.506+10:00</atom:updated><title>I Love Data</title><description>At work, we recently started to graph the time it takes to access a branch in Launchpad via SSH, both on our staging and production servers.&lt;br /&gt;&lt;br /&gt;I love this so much. Having this data is &lt;span style="font-style: italic;"&gt;liberating&lt;/span&gt;. It's like turning on a light in a dark room: suddenly I can go from uncertain, careful, hesitant steps to bold, confident strides.&lt;br /&gt;&lt;br /&gt;In fact, the metaphor stretches further. This new light has revealed objects of interest (that is, spikes in the time taken) that I wasn't aware of before. I need to know how long these spikes last, how they correlate with load on the system and so forth. Soon there'll be more graphs, and I'll be able to correlate them and analyze them and suck on their delicious, numerical marrow (the light metaphor long abandoned).&lt;br /&gt;&lt;br /&gt;Regardless of whether it's liberating illumination or nourishing, savoury meat, this new graph makes me wonder why I don't chart other things I care about. Having such graphs would help me see the &lt;span style="font-style: italic;"&gt;impact&lt;/span&gt; of my actions. I could chart things like my bank balance, my waistline or the number of Latin words I learned this week. Then I could answer questions like "do I spend more on Tuesdays?" or "can I afford this iPod/cake/gerund?". This is important, because when I am tempted with a sleek/delicious/perplexing iPod/cake/gerund, I fall back on my own judgment. I think it's time to confess, dear reader, that my own judgment isn't very good. And yet I continue to trust it.&lt;br /&gt;&lt;br /&gt;The reason I don't have such graphs is that they are inconvenient to maintain. A graph of branch access times is &lt;span style="font-style: italic;"&gt;easy&lt;/span&gt;. All you need to do is describe how to get the measurement, and then do a bit of once-off set up. If you want to graph your body weight, you need to get on the scales at a fixed time and then look at the dial and adjust for parallax and then write a number down somewhere and maybe note down whether this is before or after a meal and then take the number and then add it to a spreadsheet. Most online banking sites I've seen are even &lt;span style="font-style: italic;"&gt;less&lt;/span&gt; convenient than this.&lt;br /&gt;&lt;br /&gt;Getting data on life is hard, but for programming it's easy. What things do you care about on your project? Features, user experience, how fast bugs get fixed? Can you quantify these things? Can you make a pretty picture out of it? If so, do it now! Post your answers here, set up something like&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt; &lt;a href="http://cricket.sourceforge.net/"&gt;Cricket&lt;/a&gt; and then profit!&lt;br /&gt;&lt;br /&gt;P.S. I can't believe I got to the end of this post without saying how awesome the Canonical sysadmins are. Let me correct that now. The Canonical sysadmins are heck of awesome. They could &lt;a href="http://cdn-www.i-am-bored.com/media/95709_mordoranim8.gif"&gt;simply walk into Mortor&lt;/a&gt;.</description><link>http://code.mumak.net/2008/07/i-love-data.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-6225331854382219297</guid><pubDate>Thu, 03 Jul 2008 06:17:00 +0000</pubDate><atom:updated>2008-07-05T20:39:55.980+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>Somebody Do This Please</title><description> &amp;lt;jml&amp;gt; What's the difference between &lt;a href="http://gobby.0x539.de/trac/"&gt;Gobby&lt;/a&gt; and a &lt;a href="http://moinmo.in/" title="Moin Moin"&gt;wiki&lt;/a&gt;?&lt;br /&gt;&amp;lt;mwh&amp;gt; NAT</description><link>http://code.mumak.net/2008/07/somebody-do-this-please_9690.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-8089889730512879183</guid><pubDate>Mon, 30 Jun 2008 23:09:00 +0000</pubDate><atom:updated>2008-07-05T19:24:05.478+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>GMail feature request</title><description>First, where should I make these requests?&lt;br /&gt;&lt;br /&gt;Second, I'd like to be able to open my GMail without seeing all the new mail in my inbox. Very often, I open up GMail just to look up some fact that I've forgotten, or to put a date to a particular event. Seeing new mail and an unempty inbox distracts me, leading me down a rabbit hole of processing.&lt;br /&gt;&lt;br /&gt;I guess a GreaseMonkey hack wouldn't be &lt;em&gt;too&lt;/em&gt; hard.</description><link>http://code.mumak.net/2008/06/gmail-feature-request.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-6587088400853659934</guid><pubDate>Mon, 23 Jun 2008 10:12:00 +0000</pubDate><atom:updated>2008-07-05T19:24:06.516+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>2008</title><description>&lt;h1 color="#ff0000"&gt;&lt;blink&gt;Firefox 3 is awesome!&lt;/blink&gt;&lt;/h1&gt;</description><link>http://code.mumak.net/2008/06/2008.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-2877195152772565777</guid><pubDate>Fri, 13 Jun 2008 05:23:00 +0000</pubDate><atom:updated>2008-07-05T19:24:07.559+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>Really Satisfying</title><description>I have just returned from the shops with a Snickers bar. The packet says that one out of every six Snickers bars will instantly win me a free Snickers bar.&lt;br /&gt;&lt;br /&gt;So, &lt;em&gt;statistically speaking&lt;/em&gt;, how many Snickers bars do I have? Show working.</description><link>http://code.mumak.net/2008/06/really-satisfying.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-7643804025471441798</guid><pubDate>Fri, 13 Jun 2008 04:37:00 +0000</pubDate><atom:updated>2008-07-05T19:24:08.610+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>Aren't code reviews great?</title><description>Ben Sussman-Collins writes about &lt;a href="http://blog.red-bean.com/sussman/?p=96"&gt;programmer insecurity&lt;/a&gt; and how a lot of programmers dread having others see their code.&lt;br /&gt;&lt;br /&gt;Some of the &lt;a href="http://jcalderone.livejournal.com"&gt;best&lt;/a&gt; &lt;a href="http://robertcollins.net"&gt;programmers&lt;/a&gt; &lt;a href="http://radix.twistedmatrix.com"&gt;I've&lt;/a&gt; &lt;a href="http://sourcefrog.net"&gt;worked&lt;/a&gt; &lt;a href="http://glyph.twistedmatrix.com"&gt;with&lt;/a&gt; &lt;a href="http://python.net/crew/mwh/"&gt;are&lt;/a&gt; in love with code reviews, and all great writers have editors. (The "linked list" is in no way exhaustive.)  Personally, I see reviews as being a great opportunity to learn.&lt;br /&gt;&lt;br /&gt;Sussman-Collins also writes about how distributed version control can exacerbate the "isolated genius" problem by shielding ones code from the public eye. This is definitely a big potential drawback of DVCS, but one that's largely mitigated by a culture of short-lived branches and &lt;a href="https://code.launchpad.net"&gt;an easy-to-use public registry of all branches for a project&lt;/a&gt;.</description><link>http://code.mumak.net/2008/06/aren-code-reviews-great.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-622417601081979853</guid><pubDate>Fri, 13 Jun 2008 01:29:00 +0000</pubDate><atom:updated>2008-07-05T20:09:04.829+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Bazaar</category><title>Another Bazaar story</title><description>I'm currently hacking away on Launchpad's support for "&lt;a href="http://jam-bazaar.blogspot.com/2008/05/this-week-in-bazaar_29.html"&gt;stacked branches&lt;/a&gt;", something that will really make Launchpad's codehosting a joy to use.&lt;br /&gt;&lt;br /&gt;At the moment, I'm writing some tests that require a user to login. This was becoming a bit cumbersome, until I remembered something: Tim has recently landed some code to make this easy. But how do I get these changes without messing up all of the work I'm doing now? bzr shelve to the rescue!&lt;br /&gt;&lt;br /&gt;'shelve' interactively goes through each change you've made to your current working tree and allows you to decide whether to keep a change or shelve it. It comes with a twin command 'unshelve', which lets you interactively restore your changes.&lt;br /&gt;&lt;br /&gt;In this case, I don't even care about the interactivity, so here's what I did:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# Shelve my changes&lt;br /&gt;bzr shelve --all&lt;br /&gt;# Fetch the latest trunk&lt;br /&gt;cd ../trunk&lt;br /&gt;bzr pull&lt;br /&gt;# Merge it into my branch&lt;br /&gt;cd ../stacking&lt;br /&gt;bzr merge ../trunk&lt;br /&gt;bzr ci -m "Merge in changes from trunk to get login testing improvements."&lt;br /&gt;# Restore my changes&lt;br /&gt;bzr unshelve --all&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The 'shelve' command comes with the &lt;a href="http://launchpad.net/bzrtools"&gt;bzrtools&lt;/a&gt; plugin, and I am basically in love with it.&lt;br /&gt;&lt;br /&gt;As a parting shot, I should mention that things like bzrtools aren't accidents. They are natural and inevitable when you have &lt;a href="http://starship.python.net/crew/mwh/bzrlibapi/bzrlib.html"&gt;good APIs&lt;/a&gt; in a &lt;a href="http://python.org"&gt;high-level language&lt;/a&gt; and a &lt;a href="http://bazaar-vcs.org/WritingPlugins"&gt;very nice plugin system&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And now I'm off to keep working on this branch.&lt;br /&gt;&lt;br /&gt;</description><link>http://code.mumak.net/2008/06/another-bazaar-story.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-7465383142016112088</guid><pubDate>Thu, 05 Jun 2008 01:17:00 +0000</pubDate><atom:updated>2008-07-05T20:09:10.945+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>Real Life</title><description>Inspired by &lt;a href="http://mikeylynch.blogspot.com"&gt;Mikey&lt;/a&gt;, I've set up my own &lt;a href="http://life.mumak.net"&gt;real-life blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've done this one using Blogger's "upload to remote server" feature. It looks nice, has the features I need and means less WordPress &amp;amp; PHP. I'm hoping to migrate this sucker to the same technology.</description><link>http://code.mumak.net/2008/06/real-life.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-3847165362970608763</guid><pubDate>Mon, 02 Jun 2008 03:28:00 +0000</pubDate><atom:updated>2008-07-05T20:40:04.743+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>Neat Bazaar feature</title><description>Ever find yourself working away on a branch, enjoying yourself and getting just a little carried away? Maybe you're working on a feature and you notice and fix a bug that's not strictly related to that feature.&lt;br /&gt;&lt;br /&gt;If you catch yourself in time, there's a nice little feature in Bazaar that can help with this: &lt;code&gt;bzr merge --uncommitted&lt;/code&gt;. It will merge in the changes that you've made to your working tree but haven't committed yet.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ cd some-feature-branch&lt;br /&gt;&lt;br /&gt;... hack hack hack ... oops!&lt;br /&gt;&lt;br /&gt;$ cd ..&lt;br /&gt;&lt;br /&gt;$ bzr branch trunk bug-fix-2357&lt;br /&gt;&lt;br /&gt;$ cd bug-fix-2357&lt;br /&gt;&lt;br /&gt;$ bzr merge --uncommitted ../some-feature-branch&lt;br /&gt;&lt;br /&gt;$ bzr ci -m "Fix up bug 2357. Found this while working on some-feature."&lt;br /&gt;&lt;br /&gt;$ bzr send&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Don't know what &lt;code&gt;bzr send&lt;/code&gt; does? Trust me, you want to find out.</description><link>http://code.mumak.net/2008/06/neat-bazaar-feature_9205.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-1749283964198347471</guid><pubDate>Mon, 21 Apr 2008 01:39:00 +0000</pubDate><atom:updated>2008-07-05T20:09:13.534+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>What I meant</title><description>&lt;a href="http://z3p.tumblr.com/"&gt;z3p&lt;/a&gt; recently &lt;a href="http://z3p.tumblr.com/post/32324725"&gt;blogged about&lt;/a&gt; a comment I made in &lt;a href="http://twistedmatrix.com/trac/ticket/2710"&gt;a code review&lt;/a&gt;. In the review, I linked to:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://74.54.212.169/2ERcULhJC81alpg64P4WN7Of_400.jpg" alt="The only measure of code quality is WTFs / minute" /&gt;&lt;br /&gt;&lt;br /&gt;That's a negative and grumpy way of phrasing an idea that I've come to value a lot: &lt;em&gt;good code expresses its intent clearly.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;When looking at a patch, the reviewer needs to understand two things: the intent of the code and the intent of each &lt;em&gt;change&lt;/em&gt; to the code. To be clear on the former, you need:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;	&lt;li&gt;intent-revealing names.&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;good abstractions / interfaces.&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;good, small tests.&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;simple implementations where possible.[1]&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;docstrings where appropriate&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;comments where appropriate.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;That's not exhaustive, but it's in a rough order.&lt;br /&gt;&lt;br /&gt;To be clear on the intent of your change to code, you need:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;	&lt;li&gt;Small patches.&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;A good bug / spec with a good, short summary.&lt;/li&gt;&lt;br /&gt;	&lt;li&gt;A review request letter, summarizing your implementation strategy, any compromises you made, gaps in testing, future work etc.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;That's not exhaustive either. In #2037, I didn't understand the motivation for lots of the code, nor for some of the changes to the code.&lt;br /&gt;&lt;br /&gt;I'm indebted to &lt;a href="http://andrew.puzzling.org"&gt;Andrew Bennetts&lt;/a&gt; for teaching me that the first duty of a reviewer is to ensure that the code is clear and to &lt;a href="http://intellectronica.net/"&gt;Tom Berger&lt;/a&gt; for reminding me that compromises are worth noting.&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;&lt;br /&gt;[1] Actually, this reminds me of something I heard &lt;a href="http://en.wikipedia.org/wiki/Don_Carson"&gt;a preacher&lt;/a&gt; say, "before I give a sermon, I go through it, find everything clever, and take it out" (I paraphrase, not having a reference on hand).&lt;br /&gt;&lt;br /&gt;In as much as sermons and code should both be ego-free communications of ideas, I think this is sound advice for hackers.</description><link>http://code.mumak.net/2008/04/what-i-meant_20.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-5733547231775030285.post-8216437880894786544</guid><pubDate>Mon, 21 Apr 2008 01:04:00 +0000</pubDate><atom:updated>2008-07-05T20:40:06.940+10:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>Uncategorized</category><title>bzr-removable</title><description>The plugin I talked about in a previous post is now at https://launchpad.net/bzr-removable. Please file bugs.&lt;br /&gt;&lt;br /&gt;Thanks to Michael Hudson and Daniel Watkins for submitting patches.&lt;br /&gt;&lt;br /&gt;You can get the plugin by typing 'bzr branch lp:bzr-removable' on the command line.</description><link>http://code.mumak.net/2008/04/bzr-removable_20.html</link><author>noreply@blogger.com (jml)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item></channel></rss>