<?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-13463691</id><updated>2011-09-30T11:19:05.218-06:00</updated><category term='ruby'/><category term='nostalgia'/><category term='flash'/><category term='tools'/><category term='javascript'/><category term='apple'/><category term='development'/><category term='sunhil'/><category term='ipad'/><category term='interfaces'/><category term='zope3'/><category term='http'/><category term='distributed vcs'/><category term='gear'/><category term='spreadsheets'/><category term='cocoa'/><category term='applescript'/><category term='audio'/><category term='make'/><category term='applications'/><category term='iphone'/><category term='git'/><category term='python'/><category term='professional'/><category term='distutils'/><category term='scons'/><category term='rake'/><category term='notebook'/><category term='toolkits'/><category term='drone'/><category term='scripting'/><category term='gtd'/><category term='cvs'/><category term='vitriol'/><category term='setuptools'/><category term='soap'/><category term='iwork'/><category term='aesthetics'/><category term='rage'/><category term='webservices'/><category term='politics'/><category term='dvcs'/><category term='sqlalchemy'/><category term='scm'/><category term='buildout'/><category term='music'/><category term='coding style'/><category term='gui'/><category term='flex'/><category term='mochikit'/><category term='movie'/><category term='jquery'/><category term='dojo'/><category term='desktop'/><category term='bbedit'/><category term='python3000'/><category term='sucks'/><category term='mac'/><category term='file management'/><category term='design'/><category term='testing'/><category term='numbers'/><category term='mercurial'/><category term='omnifocus'/><category term='studio'/><category term='svn'/><category term='subversion'/><category term='hafler trio'/><title type='text'>Griddle Noise</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://griddlenoise.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default?start-index=101&amp;max-results=100'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>127</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-13463691.post-262605333086791869</id><published>2011-09-06T15:17:00.001-06:00</published><updated>2011-09-06T15:17:28.876-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>HTTP Basic Auth problems that affect Zope (2 and 3) in Safari 5.1, Mac OS X Lion</title><content type='html'>&lt;p&gt;One very frustrating experience that I encountered after upgrading to &lt;a href="http://developer.apple.com/library/mac/#documentation/Networking/Conceptual/CFNetwork/Introduction/Introduction.html"&gt;OS X&lt;/a&gt; Lion (10.7) was that &lt;a href="http://www.apple.com/safari/"&gt;Safari&lt;/a&gt; 5.1, as included in Lion, would constantly pop up basic-authentication dialog boxes on our CMS sites, which are based on the Zope Toolkit (kind of between &lt;a href="http://download.zope.org/zope3.4/3.4.1/index.html"&gt;Zope 3.4&lt;/a&gt; and &lt;a href="http://bluebream.zope.org/"&gt;Bluebream&lt;/a&gt;). Just about every page in our admin UI would do this. To get around this, I switched to &lt;a href="http://www.mozilla.org/firefox"&gt;Firefox&lt;/a&gt; for interacting with our admin screens, but still used Safari as my primary browser (better OS X citizen, takes advantage of Lion features which I enjoy, bookmark syncing, etc). This lead to problems as Firefox could get pushed way back in the usage stack and would be paged out, and it did NOT like to wake up after long periods of inactivity.&lt;/p&gt;
&lt;p&gt;A couple of days ago I decided to take another look at the &lt;a href="http://www.webkit.org/"&gt;WebKit project&lt;/a&gt; as I was certain that I was not the only person having this issue. And I found a bug that had been recently closed relating to this issue. It's &lt;a href="https://bugs.webkit.org/show_bug.cgi?id=66354"&gt;WebKit bug 66354&lt;/a&gt; and it's resolution is in the &lt;a href="http://nightly.webkit.org/"&gt;WebKit nightly builds&lt;/a&gt; since at least September 2, 2011.&lt;/p&gt;
&lt;p&gt;Apparently this only affects OS X Lion as it has to do with low level &lt;a href="http://developer.apple.com/library/mac/#documentation/Networking/Conceptual/CFNetwork/Introduction/Introduction.html"&gt;CFNetwork&lt;/a&gt; changes in Lion. The bug occurs not with basic auth, exactly, as I was able to use other systems behind basic auth. &lt;strong&gt;The bug occurs when there are redirects with Basic Auth&lt;/strong&gt;, which our CMS uses a fair bit in its admins for basic navigation links.&lt;/p&gt;
&lt;p&gt;As of OS X 10.7.1 and its Safari (Version 5.1 (7534.48.3)) this is broken. If you use OS X Lion and Safari and encounter HTTP Basic Auth problems, I'd recommend switching to the &lt;a href="http://nightly.webkit.org/"&gt;nightly builds&lt;/a&gt;.&lt;/p&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/13463691-262605333086791869?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/262605333086791869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/262605333086791869'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/09/http-basic-auth-problems-that-affect.html' title='HTTP Basic Auth problems that affect Zope (2 and 3) in Safari 5.1, Mac OS X Lion'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2265171472372361950</id><published>2011-08-19T13:34:00.001-06:00</published><updated>2011-08-19T13:34:56.526-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='bbedit'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>PyFlakes and BBEdit, kind of together (at last?!)</title><content type='html'>&lt;p&gt;I've recently returned to &lt;a href="http://barebones.com/products/bbedit/"&gt;BBEdit&lt;/a&gt; as my primary development editor after spending the past few years with the increasingly neglected &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt;. One thing that I missed from TextMate was some nice '&lt;a href="http://pypi.python.org/pypi/pyflakes"&gt;PyFlakes&lt;/a&gt;' integration. Since adding PyFlakes to my daily workflow in TextMate, either through the 'PyCheckMate' option or via the 'PyFlakes On Save' option (which popped up in a tooltip), my module imports have been cleaner and refactorings have gone more smoothly as I can catch forgotten names and imports in moved code.&lt;/p&gt;
&lt;p&gt;The first thing I did when I moved to BBEdit was to rig up a quick script that ran PyFlakes and bound it to command-shift-V (V for Verify, or validate), based on the PyFlakes-On-Save TextMate command (which I found in a Zope bundle, I think). My script just dumped the results into a new BBEdit 'Unix Script Output' text document window. It worked, but was not particularly helpful. BBEdit has a 'check syntax' command built in that will catch SyntaxErrors in a python file, and its results go into the 'search results' window which allows you to step through the errors nicely in a dedicated window. I remember using something like this with Emacs and things that modified Make-mode to jump to error results in unit tests, making it easy to step through failures with a single key-chord.&lt;/p&gt;
&lt;p&gt;Well today, I finally found how to get my results into that window. The script is now up on GitHub in &lt;a href="https://gist.github.com/1157742"&gt;Gist 1157742&lt;/a&gt;.&lt;/p&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/13463691-2265171472372361950?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2265171472372361950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2265171472372361950'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/08/pyflakes-and-bbedit-kind-of-together-at.html' title='PyFlakes and BBEdit, kind of together (at last?!)'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-6537350468629487441</id><published>2011-08-15T19:33:00.001-06:00</published><updated>2011-08-15T19:33:26.053-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gear'/><category scheme='http://www.blogger.com/atom/ns#' term='sunhil'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><title type='text'>New Synthesizer Purchase, and near-future music ideas</title><content type='html'>&lt;p&gt;I bought another synth and am just waiting for it to arrive. I bought the &lt;a href="http://www.akaipro.com/miniak"&gt;Akai MiniAK&lt;/a&gt; after seeing a friend, himself quite an accomplished &amp;#8216;experimental music&amp;#8217; composer, get quite delighted after purchasing one. I&amp;#8217;m also exploring a new collaborative electronic music project, possibly quite club oriented, that may also do some live shows in the future. For myself, I&amp;#8217;m interested in doing this without a computer. My laptop is getting quite aged and I don&amp;#8217;t have the desire (or funds), yet, to replace the studio iMac with a Macbook Pro that could venture out on occasion while retaining the master keys for my suite of software. Granted, with my software suite, I could do pretty amazing things, but I&amp;#8217;m more of a tweaker here than a performer.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been interested in getting a keyboard synth for a while now. I have a &lt;a href="http://www.soundonsound.com/sos/oct06/articles/novation.htm"&gt;keyboard USB MIDI controller&lt;/a&gt; and in theory I could just attach it to my &lt;a href="http://www.vintagesynth.com/korg/ms2000.php"&gt;Korg MS2000BR&lt;/a&gt; rack mountable module. I have no power adapter for this controller (it prefers USB power and I haven&amp;#8217;t bothered looking for an AC adapter for it), and the MS2000BR is cool, but the two pieces of gear together are a bit beefy.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve considered the &lt;a href="http://www.korg.com/microkorg"&gt;microKORG&lt;/a&gt;, partially for its kitsch value, partially because it is an interesting synth. But it&amp;#8217;s essentially the MS2000BR in a toy-ish package, and I already have that engine in a more complete synth. Since I haven&amp;#8217;t done much programming with the MS2000BR, I sometimes wish I had bought the microKORG instead. Then again, the programming that I have done with the MS2000BR has produced some nice results.&lt;/p&gt;

&lt;p&gt;Recently, after revisiting some half-finished electronic experiments from the past few years, I started reconsidering getting the &lt;a href="http://www.alesis.com/micron"&gt;Alesis Micron&lt;/a&gt;. I like the Micron&amp;#8217;s visual design and found its sounds interesting, although a bit too clean. The sounds can be easily dirtied up with the plethora of noise gear and MoogerFoogers and Metasonix modules I already have. Then I noticed that the Micron was disappearing from various online resellers, and appeared to have been discontinued. Still, after my friend&amp;#8217;s &lt;a href="http://www.akaipro.com/miniak"&gt;MiniAK&lt;/a&gt; purchase and in light of my other desires, I came very close to buying a Micron&amp;#8230;&lt;/p&gt;

&lt;p&gt;Until I found out that the &lt;a href="http://www.akaipro.com/miniak"&gt;MiniAK&lt;/a&gt; is essentially a re-packaged Micron, with a sturdier Akai Pro body and a (silly) emphasis on the vocoder. I like my &lt;a href="http://www.akaipro.com/mpc500"&gt;MPC500&lt;/a&gt; and plan to have it at the center of whatever the hell I&amp;#8217;m building out here.&lt;/p&gt;

&lt;p&gt;I guess I finally have to learn (and learn to like) MIDI. I’ve got plenty of disparate pieces, just need to put them together. &lt;a href="http://www.vintagesynth.com/korg/ms2000.php"&gt;MS2000BR&lt;/a&gt;, &lt;a href="http://www.akaipro.com/mpc500"&gt;MPC500&lt;/a&gt;, &lt;a href="http://www.korg.com/EMX1"&gt;Electribe EMX-1&lt;/a&gt;, and now MiniAK. Plus all my pedals and little analog bits.&lt;/p&gt;

&lt;p&gt;And I have my eye on getting a Dave Smith module or two. I’ve been fascinated with the &lt;a href="http://www.davesmithinstruments.com/products/med/"&gt;Evolver&lt;/a&gt; for a while, and the &lt;a href="http://www.davesmithinstruments.com/products/mopho/"&gt;Mo&amp;#8217;Pho&lt;/a&gt; and &lt;a href="http://www.davesmithinstruments.com/products/tetra/"&gt;Tetra&lt;/a&gt; are pretty damn cool. My big analog modular plan can wait a little while longer.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-6537350468629487441?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6537350468629487441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6537350468629487441'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/08/new-synthesizer-purchase-and-near.html' title='New Synthesizer Purchase, and near-future music ideas'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-8622837831565876924</id><published>2011-06-09T11:21:00.001-06:00</published><updated>2011-06-09T11:21:05.595-06:00</updated><title type='text'>Is This Sensationalist Headline In The Form Of A Question?</title><content type='html'>&lt;p&gt;It depends. We'll have to wait and see. Only time will tell. And other such bullshit.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-8622837831565876924?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8622837831565876924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8622837831565876924'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/06/is-this-sensationalist-headline-in-form.html' title='Is This Sensationalist Headline In The Form Of A Question?'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4979603845267839600</id><published>2011-05-19T15:11:00.001-06:00</published><updated>2011-05-19T15:17:22.488-06:00</updated><title type='text'>To square and back again</title><content type='html'>&lt;p&gt;I believe I'm ending my personal &lt;a href="http://www.squarespace.com/"&gt;Squarespace&lt;/a&gt; experience. While I like Squarespace's UI and tools quite a bit, I just don't write enough to make it worth even the small amount I spend per month on their most basic package. I've copied some of my better posts from the [now old] &lt;a href="http://eucci.squarespace.com/"&gt;http://eucci.squarespace.com/&lt;/a&gt; blog back into this one, and give no further promises on whether I will suddenly feel like posting more often or not. But, of course, I do hope to post more. On Python, on audio, on iPads and file management... 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/13463691-4979603845267839600?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4979603845267839600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4979603845267839600'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/05/to-square-and-back-again.html' title='To square and back again'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-5252086195760189068</id><published>2011-03-29T13:07:00.000-06:00</published><updated>2011-05-19T15:08:10.011-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Needlessly adding complexity in tests in order to hide their complexity</title><content type='html'>&lt;p&gt;Some tweets from DHH on testing:&lt;/p&gt;
&lt;blockquote style="border-left-width: 4px; border-left-style: solid; border-left-color: #777777; margin-left: 34px; padding-left: 10px;"&gt;
&lt;p&gt;I respect the guys behind it and I'm all for experimentation, but the proliferation of &lt;a href="http://rspec.info/"&gt;rSpec&lt;/a&gt; and &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt; makes me sad. (&lt;a href="https://twitter.com/dhh/status/52806992150007808"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;RSpec offends me aesthetically with no discernible benefit for its added complexity over test/unit. (&lt;a href="https://twitter.com/dhh/status/52807321499340800"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Cucumber makes no sense to me unless you have clients reading the tests. Why would you build a test-specific parser for English? (&lt;a href="https://twitter.com/dhh/status/52807649145782272"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The important thing is of course that we get people testing, so tools shouldn't matter too much. But the added complexity still upsets me. (&lt;a href="https://twitter.com/dhh/status/52808555895595008"&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I agree, and I'm glad that these kinds of tests have never really caught fire in the Python world. There are implementations of the RSpec and Cucumber ideas, but they don't seem to be as fully embraced. In my opinion, the dark side of testing in the Python world is the abuse of doc tests, thinking that they make both good test cases and good documentation, when in fact they're neither. There are good use cases for doc tests, but I think they've been horribly abused by certain sects within the Python world. However, even when they've been horribly abused, the people writing them seem to go after pretty broad code coverage, and they don't waste a lot of time trying to be cleverly concise (in fact, the verbosity of these large doc tests is what makes them so awful when they're also treated as documentation).&lt;/p&gt;
&lt;p&gt;One of my main issues with RSpec and Cucumber as I've seen them in the wild is that there seems to be very few tests, and they're not terribly useful. They seem to be repeats of the classic "baby's first use case", which is "user logs in". Maybe their usage outside of the open-source world is different, but the few projects I've seen which use them have very few test cases that always has me going "that's it? you think you're tested?"&lt;/p&gt;
&lt;p&gt;And as David points out, the complexity going on behind the scenes to make the tests just seems silly. Granted, 'Unit Tests' aren't always that easy to read, but they offer a finer example of API interactions. And if you want clarity, just add some comments. Take a cucumber-esque line like "verify that the file is encoded in UTF-8" and "now the file is encoded as latin-1" and put them as comments above the test/assert/verify statements that prove that line.&lt;/p&gt;
&lt;p&gt;RSpec and Cucumber feel like the kinds of fiddly things that get in the way of doing real work - you can spend a lot of time writing all the back-end support to get a single test to read like an english Haiku. Or you can spend time writing a good battery of tests that actually get good coverage of the system.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-5252086195760189068?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/5252086195760189068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/5252086195760189068'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/03/needlessly-adding-complexity-in-tests.html' title='Needlessly adding complexity in tests in order to hide their complexity'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-356874598623239426</id><published>2011-03-24T21:05:00.000-06:00</published><updated>2011-05-19T15:07:00.473-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='file management'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>Forget distraction free, I want file-management free!</title><content type='html'>&lt;p&gt;A few years back I downloaded an interesting piece of software for the Mac OS - &lt;a href="http://www.hogbaysoftware.com/products/writeroom"&gt;Writeroom&lt;/a&gt; version 1.0. Writeroom sells itself as a "distraction free writing environment." It's main feature was that it was plain text only and could run in a full screen mode with default colors of being green text on black background. There was some fanfare around it and &lt;a href="http://diveintomark.org/archives/2007/01/21/wrongroom"&gt;some skepticism&lt;/a&gt;. Personally, I liked the idea - get rid of all of the other windows, instant messages, dancing gifs, email notifications, etc, and just write.&lt;/p&gt;
&lt;p&gt;This is something which I like about the iPad - only the current application has my attention. I hope that this doesn't change. I do not like what I see in Android 3.0, nor what little I've seen of the Blackberry Playbook. Their interfaces look too busy. I deal with busy interfaces all day. For me, the iPad is a relief from the world of current desktop computing.&lt;/p&gt;
&lt;p&gt;My favorite key combination on Mac OS X is &lt;strong&gt;option-command-h&lt;/strong&gt;, aka &lt;strong&gt;Hide Others&lt;/strong&gt;. When the screen starts filling up with windows and more windows and more windows, &lt;em&gt;Hide Others&lt;/em&gt; temporarily brings some order to the madness.&lt;/p&gt;
&lt;p&gt;Back to &lt;strong&gt;Writeroom&lt;/strong&gt;. My favorite feature of 1.0 was actually not this 'distraction free writing environment' nonsense. That was a useful feature, to be sure. But the feature I liked most was that it was a &lt;strong&gt;file management free writing environment&lt;/strong&gt;. Writeroom 1.0 managed its own files. There was &lt;strong&gt;no saving&lt;/strong&gt;, &lt;strong&gt;no filename choosing&lt;/strong&gt; (the document name was taken from the first line of the document). This made it a perfect place for just jotting things down, working small ideas out, and maybe taking them into bigger things. That &lt;strong&gt;file management free writing environment&lt;/strong&gt; was bliss, at least for my uses. Every time you opened the app, there were all your documents. You could close them to hide them, but they were easily accessible from a menu and a keyboard shortcut.&lt;/p&gt;
&lt;p&gt;There were some other apps that offered similar features - the &lt;a href="http://en.wikipedia.org/wiki/Stickies_(software)"&gt;Stickies application&lt;/a&gt; that comes with Mac OS X (and dates back to Mac OS System 7.5) is another nice tool for temporarily holding small pieces of information without having to worry about file management; &lt;a href="http://www.barebones.com/products/yojimbo/"&gt;Yojimbo&lt;/a&gt; is a collection bucket of notes, PDFs, etc, and can be another place for notes to quickly go; and Apple Mail in Mac OS X 10.5 added Notes which could be stored in IMAP (and can &lt;em&gt;finally&lt;/em&gt; sync to the Notes app in iOS 4) and offer a nice quick jot-down place that also takes its title from the first line.&lt;/p&gt;
&lt;p&gt;Writeroom 2.0 killed this feature. I avoided writeroom 2.0, but when version 2.5 was on the Mac App Store at a temporary discount, I bought it. And I hate it. Now I have to think about filenames. Now I have to think about where things are being stored. Writeroom 1.0 allowed you to easily export a document out, but that kind of decision was usually made AFTER you were finished with the document. There are times when I don't want to think about that stuff when starting out. This is not true for all cases - much of my day work is spent in TextMate writing Python code, reStructuredText documents, and managing configuration files. Of course I need full file management in that situation. But when it comes to just writing down some notes, capturing some ideas, and maybe thinking through a proposal, I miss that Writeroom 1.0 functionality.&lt;/p&gt;
&lt;p&gt;And again, this is something that the iPad (and iPhone) gets right, for most instances. Whether its OmniGraffle, Pages, Garageband, or the built in Notes app, starting a new document is damn easy. Saving is automatic. You just start using it.&lt;/p&gt;
&lt;p&gt;Fortunately, the next version of Mac OS X, "Lion", looks like it offers many long overdue file/document management features for developers so that they can offer functionality closer to Writeroom 1.0. Again - I'll always need TextMate and some apps to do manual file management, but those uses are specialized and becoming more rare. Mac OS X Lion adds support now for auto-save, reversion, locking, and historical change tracking. In some ways, this feels like going back to some of the ideas explored in the LISA and other pre-Mac user interfaces that weren't shackled to the hardware limitations of the original Mac OS (file management in the Lisa OS was quite a bit different - everything started from the finder, including new documents). In other ways, it feels like we're catching up to what the Newton OS, Palm OS, and iOS devices have long done in their aims of imitating paper notebooks and planners - everything is just saved, automatically.&lt;/p&gt;
&lt;p&gt;It's not perfect for every situation, but it's something I've long been wanting in more places than just calendar and contact apps.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-356874598623239426?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/356874598623239426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/356874598623239426'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/03/forget-distraction-free-i-want-file.html' title='Forget distraction free, I want file-management free!'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2064726016887905269</id><published>2011-02-15T13:08:00.000-07:00</published><updated>2011-05-19T15:05:09.080-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='studio'/><category scheme='http://www.blogger.com/atom/ns#' term='sunhil'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>Dead SCSI Bits</title><content type='html'>&lt;p&gt;Some time ago, there was a cool audio project hosted by &lt;a href="http://www.radiantslab.com/"&gt;Radiantslab&lt;/a&gt; called DeadSCSI. And there was also DeadSCSI 2. It all appears to be gone now, but there is at least some information available &lt;a href="http://web.archive.org/web/20070815131904/http://www.radiantslab.com/musiek/deadscsi/"&gt;in the wayback machine&lt;/a&gt;. I contributed in both rounds as &lt;a href="http://euc.cx/eucci/"&gt;Eucci&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When &lt;a href="http://ergophizmiz.net/"&gt;Ergo Phizmiz&lt;/a&gt; recently tweeted a link to &lt;a href="http://datacent.com/hard_drive_sounds.php"&gt;this page of failing hard drive sounds&lt;/a&gt;, it got me thinking about my bits of the DeadSCSI project that I had laying around on my studio drobo. I spent some of saturday doing some lightweight remastering. Early Eucci, where I abused the computer like I used to abuse tape, is pretty rough in its output quality. Levels are just all over the place. DC Offset lingers here and there. It's a mess. But there are some pretty spectrum graphs.&lt;/p&gt;
&lt;p&gt;Last night I uploaded the tracks to my &lt;a href="http://www.archive.org/details/rive"&gt;Rive collection on archive.org&lt;/a&gt; and cut a release &lt;a href="http://euc.cx/rive/058/"&gt;as rive 058&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What is mildly interesting about this is that although all of the tracks were re-finalized on Saturday, I didn't upload them until last night. It was a process I was starting to put off, remembering that I needed to name the files properly, upload them, enter metadata, and make a web page on euc.cx. Not that big of a deal, really, but big enough to put off until tomorrow and tomorrow and tomorrow.&lt;/p&gt;
&lt;p&gt;Last night, when I got home from work and after I had walked the dog (enjoying some unseasonal warmth before winter makes its fierce return later this week), I was thinking about what to do from that moment until dinner. I was starting to get ready to play the excellent Red Dead Redemption, but I knew I had to cut this release. Then I remembered something Merlin Mann said in the &lt;a href="http://5by5.tv/b2w/1"&gt;first&lt;/a&gt; or &lt;a href="http://5by5.tv/b2w/2"&gt;second&lt;/a&gt; episode of the &lt;a href="http://5by5.tv/b2w/"&gt;Back To Work podcast&lt;/a&gt;. He basically said that it's easy to complain about needing time or certain circumstances in order to work on something, but that we don't complain about needing that time or certain circumstances to play video games, and we sure as hell can sit there and play a video game for an hour. It feels like a shame to have to be reminded of this ridiculousness, but it's something I apparently need to remember constantly. So instead of playing Red Dead for an hour, I spent the time preparing the release. It took a little bit longer than expected and the dog was getting impatient towards the end. But overall it was a nice use of that time.&lt;/p&gt;
&lt;p&gt;There are many more releases to come, including some new material.&lt;/p&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/13463691-2064726016887905269?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2064726016887905269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2064726016887905269'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/02/dead-scsi-bits.html' title='Dead SCSI Bits'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1668041310735376381</id><published>2011-02-13T23:36:00.000-07:00</published><updated>2011-05-19T15:03:40.969-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='notebook'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>To Laptop or Not To Laptop</title><content type='html'>&lt;p&gt;&lt;a href="http://us.pycon.org/2011/"&gt;PyCon 2011&lt;/a&gt; is coming soon, and as it does, I find myself facing the question "do I bring my Macbook this year or not?"&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.everymac.com/systems/apple/macbook/stats/macbook-core-2-duo-2.1-white-13-early-2008-penryn-specs.html"&gt;My Macbook&lt;/a&gt; has spent most of the past couple of years serving as a vehicle for viewing DVDs, Hulu, or Netflix streaming from bed. It does get used occasionally as a home / travel development machine, but that use has declined significantly over the past year. I'm fortunate to be at the place in my life where I can leave work at work; but I also have been rather uninspired to do personal development work. Hence, the laptop is basically a DVD viewer.&lt;/p&gt;
&lt;p&gt;And for DVDs, it's quite nice to watch TV series DVDs from bed. I only watch about 20-30 minutes a night before tiring out. It's a fun way to revisit personal favorites like HBO's &lt;a href="http://www.amazon.com/Wire-Complete-Lance-Reddick/dp/B004BZ5AFU/"&gt;The Wire&lt;/a&gt; and &lt;a href="http://www.amazon.com/Deadwood-Complete-Ian-McShane/dp/B001FA1OTU"&gt;Deadwood&lt;/a&gt;. I'm currently watching &lt;a href="http://www.amazon.com/Twin-Peaks-Definitive-Gold-Complete/dp/B000UX6THK/"&gt;Twin Peaks&lt;/a&gt;, seeing season 2 for the first time.&lt;/p&gt;
&lt;p&gt;But for DVDs, it's also starting to become a liability, as I own more and more blu-ray. As soon as I decide to get a blu-ray player for upstairs (either a portable one or getting a second television), the laptop's uses will be near zero.&lt;/p&gt;
&lt;p&gt;One potential use is for travel, at least for technical conferences. I brought the Macbook along to PyCon last year. I did the whole trip out of my day-to-day backpack, which accommodates the Macbook just fine. While at the airport and in flight, the extra weight and space did stand out, but that was only a fraction of the trip. I'm trying to remember now just how much I used it once there. I took far less notes on the device than I expected, and have done little with the notes I did take. They still sit in a folder on the Macbook's desktop.&lt;/p&gt;
&lt;p&gt;I know I did some coding while there, but not much. I don't believe I made any major commits or pushes while at the conference. I wasn't involved in tutorials or sprints last year and won't be this year either, so there's little need to code while at the conference.&lt;/p&gt;
&lt;p&gt;Finally, my co-worker had brought his laptop and while he did use it to maintain some situations back at the office, he told me he never used it on the conference floor. I think the most use we got out of our laptops was for watching movies on the plane. And hey, I've got an iPad for that.&lt;/p&gt;
&lt;p&gt;So as this next tech conference comes up, I'm seriously considering leaving the laptop behind and just using good old &lt;a href="http://www.spacepen.com/chromebullet.aspx"&gt;pen&lt;/a&gt; and &lt;a href="http://fieldnotesbrand.com/2011/02/05/introducing-the-steno/"&gt;paper&lt;/a&gt;. Maybe my personal era of the laptop is officially over. Weird.&lt;/p&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/13463691-1668041310735376381?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1668041310735376381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1668041310735376381'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/02/to-laptop-or-not-to-laptop.html' title='To Laptop or Not To Laptop'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-6906457058625677142</id><published>2011-01-27T17:33:00.000-07:00</published><updated>2011-05-19T15:02:19.857-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='studio'/><category scheme='http://www.blogger.com/atom/ns#' term='sunhil'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>Sunhil Intentions for 2011</title><content type='html'>&lt;p&gt;As announcing one's intentions is the simplest way of hearing God laugh, I'm planning on doing the following for Eucci and AODL this year: it's time to finish cleaning out the back catalog. Whether this is a coda at the end or the beginning of the next phase for both projects is uncertain. I just know that it's time to stop letting these unreleased pieces hold me back. Yes, I'd like for some of them to be released in beautiful physical form, and some might still be so. But chances are that most of them will be released online, for free. The candidates are:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://euc.cx/eucci/"&gt;Eucci&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pachyderm&lt;/strong&gt; (1994) - Tape collage, and really the first proper 'Eucci' recording where the early style really came together. Meant to be on tape, but it's long (45 minutes) and I could never find a satisfactory b-side.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Star City&lt;/strong&gt; (1996-1999) - mid-era electroacoustics and musique concrete, some for radio programs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apt&lt;/strong&gt; (2004) - unreleased sounds for an empty apartment in the world's last perfect spring.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Like The City, We're Bound To Last&lt;/strong&gt; (2000-2009) - Spans some of the earliest Eucci (2000), mid-era (2004) and some late-era work (2007-2009).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://euc.cx/aodl/"&gt;AODL&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fans of Flesh and Textured Wrecks&lt;/strong&gt; (2004-2007) - the most likely to get a proper vinyl release. Long form dark AODL, most of it in special live broadcast performances.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Maybe&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Eucci, "&lt;strong&gt;Because 1999 Needs an Enemy&lt;/strong&gt;" - very limited edition tape from a bad start to the year. Of interest, mostly, as it is the direct ancestor of AODL. It was the first experiments in doing feedback loops of effect pedals, and using those as the only sound source.&lt;/li&gt;
&lt;/ul&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/13463691-6906457058625677142?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6906457058625677142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6906457058625677142'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2011/01/sunhil-intentions-for-2011.html' title='Sunhil Intentions for 2011'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-6663130192398289235</id><published>2010-11-29T14:59:00.000-07:00</published><updated>2011-05-19T15:00:09.738-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='omnifocus'/><title type='text'>Keeping History</title><content type='html'>&lt;p&gt;Back in mid 2005 I worked on a project for customer wherein I was generating "Froogle Feed" data for the customer's e-commerce sites. For some reason, the project never went live. Suddenly, a request shows up from the customer mentioning "Froogle Project" and asking for a couple of features.&lt;/p&gt;
&lt;p&gt;I have no memory of how I accomplished this project in the first place. I don't know if the customer does either. I just have a couple of features in an email project and zero context. Does the customer remember the experimental work we did a couple of years ago? Does he remember the UI?&lt;/p&gt;
&lt;p&gt;The big problem is that aside from a couple of emails and basecamp messages, and a couple of generated 'feed' files, I have nothing for this project. Looking through source code history returns nothing. Looking through the current site (an old Zope 2 based site, built out of page templates, python scripts, and SQL Methods) yields nothing either. Unfortunately, there's not a lot of history in the site. And if the feature in question never went live, there's (of course) not going to be ANY history.&lt;/p&gt;
&lt;p&gt;I dug through a big folder of printouts and such collected over the eight-plus years of history with this customer. Nothing.&lt;/p&gt;
&lt;p&gt;I finally turned to notepads and notebooks, and did manage to find a couple of notes in a couple of different places. And digging through some basecamp messages yielded a mention of a 'froogle.py' file in a development instance that was not put into source control (CVS at the time). That development server was killed off long ago. It may have been hobbling around, but after moving offices twice in the last year or so, the number of internal servers is nearly zero. Long unused development servers tend not to get plugged back in.&lt;/p&gt;
&lt;p&gt;Some lessons learned:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Always put a date stamp on handwritten notes.&lt;/strong&gt; This is now a habit for me, but it apparently wasn't a habit back in 2005. I did find some dates on some pages and used that to backtrack to when this work was initially done (using date stamps on Basecamp and email messages). A side lesson to this is to &lt;strong&gt;always include the year when date stamping&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always use source control, even for unfinished projects.&lt;/strong&gt; If this one file had been checked into CVS, I would be a bit less stressed right now. I'm far less familiar with this customer's site now than I was then and trying to remember how I built multiple Froogle files and put them into a Zip file would be great knowledge right now, even if the format has changed. Since moving to Git, it's easier to keep dead branches in the central repository. CVS made branching so painful that we never would start a 'froogle-feed' branch. Even if that branch never goes live, it's damn useful to have.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don't trust development servers.&lt;/strong&gt; They may not be around forever, and odd little unfinished files or projects can get lost very easily over time. May not seem like a big deal, but sometimes these little projects come roaring back to life after five years. We now do most of our development on our desktop machines. When we get a new machine, all of our files roll over. Central servers work if it's a central common copy (like a master account server). I've found that development servers just lose luster over time, and tend to get very far behind in terms of hardware and core OS performance. Plus they tend not to have the kind of machine/account migration tools that desktop OS's like Mac OS X have.&lt;/li&gt;
&lt;/ol&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/13463691-6663130192398289235?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6663130192398289235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6663130192398289235'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2010/11/keeping-history.html' title='Keeping History'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4615355531435296918</id><published>2010-04-09T23:54:00.000-06:00</published><updated>2011-05-19T14:58:52.776-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>iPad and Creativity, I</title><content type='html'>&lt;p&gt;&lt;img class="iphone-image" style="border: 0px initial initial;" src="http://eucci.squarespace.com/resource/iphone-20100409235407-1.jpg?fileId=6482687" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://gilesbowkett.blogspot.com/2010/04/ipad.html"&gt;This Post&lt;/a&gt; by Giles Bowkett goes into why the iPad is NOT where creativity goes to die. It's something I have been meaning to write up myself, but haven't gotten around to doing so just yet. I do hope to write more on the subject, but until then I will just add this: if the iPad was only about consumption, I would not have bought one. For months, dating back to when the iPad was just an ever growing rumor, I would show friends apps like &lt;a href="http://www.soundtrends.com/apps/looptastic_producer/"&gt;Looptastic&lt;/a&gt; and &lt;a href="http://www.jasuto.com/site/"&gt;Jasuto&lt;/a&gt; and say "imagine this on a bigger screen!"&lt;/p&gt;
&lt;p&gt;I didn't even see the i-Electribe app coming. I have a real Korg Electribe as well. The iPad implementation is just stunning. (I also have both a real Korg MS-10 and a DS-10 cartridge for Nintendo DS. It's fun to have these real tools, and then have software representations of them in unusual places. A VST plug-in is just so boring compared to an iPad or DS surface, and both of those surfaces are far more fun to use on trains or patios than a laptop).&lt;/p&gt;
&lt;p&gt;The iPhone has already proven itself as a fun and capable device for making music, visual art, and even for writing. It's like the universal pocket notebook, capable of capturing not just words and doodles and snapshots but also drum beats and synth sounds and singing and on and on and on. The quantity and quality of creative apps for the iPhone is part of what excites me about the platform. The iPad just adds to that excitement.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-4615355531435296918?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4615355531435296918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4615355531435296918'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2010/04/ipad-and-creativity-i.html' title='iPad and Creativity, I'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4031552852324582247</id><published>2010-03-05T09:10:00.000-07:00</published><updated>2011-05-19T14:57:38.580-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>iPad, Periodicals, and Purchase Options</title><content type='html'>&lt;p&gt;&lt;img class="iphone-image" style="border: 0px initial initial;" src="http://eucci.squarespace.com/resource/iphone-20100305091001-1.jpg?fileId=6018779" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Apple has announced an iPad ship date of Apr 3 for the wi-fi only edition, with the 3G model slated for late April. Pre-orders start next week.&lt;/p&gt;
&lt;p&gt;I'm hoping for good magazine content, and I would be willing to pay. The web often sucks for magazine content as obtrusive advertising, annoying pagination (often in support of more obtrusive advertising), and random encounters with pay walls get in the way. And it just sucks to read on a computer screen. It's not the LCD display, but the position and layout of the screen that is frustrating.&lt;/p&gt;
&lt;p&gt;I've had subscriptions to The Economist, The New Yorker, and Harper's in the past, and I'm starting to miss them as I've been trying to make more time for reading. The weeklies, especially, are the ones I would like to have electronically if I could pay on a month by month basis. Sometimes it's hard to keep up when life gets busy, and those weekly magazines can pile up quickly.&lt;/p&gt;
&lt;p&gt;Finally, I'd love for the magazines to work offline. Then I think I could totally buy into the wi-fi only iPad. I'm already sold on the iPad, just can't decide which model to get. I don't leave the house or travel too often, and the iPhone is often good enough when I am out like that. But having the 3G as a pay-as-you-go option for the iPad could be handy on those occasional small trips.&lt;/p&gt;
&lt;p&gt;Still, I think that when I take the train from SLC to DEN later next month, I will be much happier with traditional books and cameras than with a gadget, no matter how cool the gadget is. It's nice to just turn things off for a couple of days.&lt;/p&gt;
&lt;p&gt;I think I just talked myself into the wi-fi only iPad.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-4031552852324582247?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4031552852324582247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4031552852324582247'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2010/03/ipad-periodicals-and-purchase-options.html' title='iPad, Periodicals, and Purchase Options'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4076857650737347662</id><published>2010-03-03T15:06:00.000-07:00</published><updated>2011-05-19T14:56:16.404-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python Buildutils for local release management</title><content type='html'>&lt;p&gt;Earlier today, I saw a question on Twitter asking "is there some setuptools extensions for uploading a sdist to a server over scp?" I responded with a "yes - we use buildutils' publish command for that."&lt;/p&gt;
&lt;p&gt;&lt;a href="http://pypi.python.org/pypi/buildutils"&gt;Buildutils&lt;/a&gt; is a collection of useful extensions to Distutils. It hasn't been touched in a while, but it mostly works. It adds some commands like "stats", "pyflakes" (useful, but does not work with recent versions of PyFlakes), and "publish", which allows you to upload a release via SCP or SFTP.&lt;/p&gt;
&lt;p&gt;The "publish" command is an extension that must be configured explicitly, so we do it in our 'setup.cfg'. We have a setup.cfg template that we use for all of our packages that uploads releases into one big directory. It looks like this:&lt;/p&gt;
&lt;pre style="margin: 8px;"&gt;; Enable the buildutils publish command
[global]
command_packages = buildutils.publish_command

; Set the destination of the publish command
[publish]
dist_dest = scp://@internalserver/path/to/releases/

; In one command, generate a distribution and checksum,
; upload them, and then clean out the build-related turds.
[aliases]
mkrelease = sdist checksum publish clean --all
&lt;/pre&gt;
&lt;p&gt;We also use &lt;a href="http://pypi.python.org/pypi/zc.buildout"&gt;zc.buildout&lt;/a&gt; in-house, and I've been using that to ensure that I have Buildutils and &lt;a href="http://pypi.python.org/pypi/setuptools-git"&gt;setuptools-git&lt;/a&gt; (uses what's tracked by Git to generate the Manifest of files to include in the distribution package). In our buildout configs, I usually have a 'devtools' section that looks like this:&lt;/p&gt;
&lt;pre style="margin: 8px;"&gt;[devtools]
recipe = zc.recipe.egg:scripts
interpreter = py
eggs =
    current.package [test]
    buildutils
    setuptools-git
&lt;/pre&gt;
&lt;p&gt;With the above, I get a 'bin/pbu' script that has the Buildutils and setuptools-git extensions installed. 'pbu' is a convenience command-line tool from Buildutils that is basically shorthand for 'python setup.py'. Using Buildout like this, I just ensure that the tools I need to generate and publish a distribution are available, no matter what machine I'm using. It's not needed, but I just find it convenient, particularly when other developers in our company need to generate a release from their machines and may not have remembered to install something like &lt;em&gt;setuptools-git&lt;/em&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-4076857650737347662?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4076857650737347662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4076857650737347662'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2010/03/python-buildutils-for-local-release.html' title='Python Buildutils for local release management'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4819461604178582744</id><published>2008-10-16T12:31:00.000-06:00</published><updated>2011-05-19T14:54:36.896-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scm'/><category scheme='http://www.blogger.com/atom/ns#' term='buildout'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='dvcs'/><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Leaps and Pains (or - changing development/deployment and scm tools to more closely realize the component architecture dream)</title><content type='html'>&lt;p&gt;A year or more ago, I was really struggling with &lt;a href="http://pypi.python.org/pypi/zc.buildout"&gt;zc.buildout&lt;/a&gt;, a Python based tool for building out "repeatable" deployments. Buildout makes &lt;a href="http://peak.telecommunity.com/DevCenter/setuptools"&gt;setuptools&lt;/a&gt; actually usable, particularly for development and deployment of web apps, although there are many other uses.&lt;/p&gt;
&lt;p&gt;Buildout keeps everything local, allowing one app to use version 3.4.2 of one package while another app can use 3.5.2. But more than just being an 'egg' / Python package manager, it can do other tasks as well - local builds of tools (from libxml to MySQL and more), again allowing one app to build and use MySQL 5.0.x and another app to use 5.1.x; or just allowing an app to be installed onto a new box and get everything it needs, from web server to RDBMS to Memcached and beyond. We don't use all of these features (yet), but it's a nice dream.&lt;/p&gt;
&lt;p&gt;Already it's very nice to be able to make a git clone of a customer app, run &lt;code&gt;buildout&lt;/code&gt;, and then start it up. Buildout will put setuptools to work to ensure that proper versions of dependent components are installed (and, quite nicely, it's very easy to share both a download cache and a collection of 'installed eggs' - multiple versions living side by side, with individual buildouts picking the one they desire).&lt;/p&gt;
&lt;p&gt;But it was not easy to get to this golden land. Prior to using Buildout, we'd check our code out of our CVS repository. Our customer apps were just another Python package, nothing special (not an application, and - more importantly - not packaged up in 'distutils' style). As we started to make more and more reusable parts, we had to do a lot of checkouts; and so I wrote a tool to help automate this checkout process. It would also check out other third party code from public Subversion repositories; all because it was easier to check out a particular tag of 'SQLAlchemy' or 'zc.table' than to try to install them into a classic-style Zope 3 'instance home'.&lt;/p&gt;
&lt;p&gt;But it was getting harder and harder to keep up with other packages. We couldn't follow dependencies in this way, for one thing; and it required some deep knowledge of some public SVN repository layouts in order to get particular revision numbers or tags.&lt;/p&gt;
&lt;p&gt;'Buildout' promised to change all of that, and offer us the chance to use real, honest-to-goodness distributed Python packages/eggs. But getting there was so very hard when there are deadlines beating you down.&lt;/p&gt;
&lt;p&gt;I took a lot of my frustration out on both Setuptools (which is so goddamn woefully incomplete) and Buildout. But the fault was really in ourselves... at least, in a way. As mentioned above, it was easier to just checkout 'mypackage' into&lt;code&gt;$INSTANCE_HOME/lib/python/mypackage&lt;/code&gt; than to figure out the install options for distutils/setuptools. As such, NONE of our code was in the Python 'distutils' style. We put some new packages into that style, but would still just check out a sub-path explicitly with CVS just like we were doing with public SVN code.&lt;/p&gt;
&lt;p&gt;Part of the big problem that we had which made it so difficult was that we had hung onto CVS for, perhaps, too long. And doing massive file and directory restructuring with CVS is too painful to contemplate. But moving to Subversion never seemed worth the effort, and so we held on to CVS. But I knew I'd have to restructure the code someday.&lt;/p&gt;
&lt;p&gt;Fortunately, Git arrived. Well, it had been there for a while; but it was maturing and quite fascinating and it offered us a chance to leapfrog over SVN and into proper source code management. Git is an amazing tool (perhaps made more so by being chained to CVS for so long), and it provided me with the opportunities to really restructure our code, including ripping apart single top-level packages into multiple namespaced packages (ie - instead of 'example' being the root node with 'core' and 'kickass' subpackages, I could split that into 'example.core' and 'example.kickass' as separate packages and Git repositories while keeping full histories).&lt;/p&gt;
&lt;p&gt;For a while, I used Git with its cvsimport and cvsexportcommit tools to clean up some of our wayward branches in CVS, while starting to play with Buildout. I was still struggling to get a Zope 3 site up and running using our frameworks. And here... well, the fault was partly in ourselves for having to go through fire to get our code into acceptable 'distutils' style packages, which made learning Buildout all the more hard. But the available documentation (comprehensive, but in long doctest style documents) for some of the Zope 3 related recipes was very difficult to follow. Hell - just knowing which recipes to use was difficult!&lt;/p&gt;
&lt;p&gt;But after many months of frustrated half-attempts, often beaten down by other pressures, I opened a few different tabs for different core Buildout recipes in my browser and furiously fought through them all... And boom! Got something working!&lt;/p&gt;
&lt;p&gt;Unfortunately it was one of those processes where by the time I got out of the tunnel, I had no idea how exactly I had made it through. One of my big complaints as I was struggling was the lack of additional information, stories of struggle and triumph, etc. And there I was - unable to share much myself! I can't even remember when I was able to break through. It's been quite a few months. Just a couple of weeks ago we deployed our last major old customer on this new setup; and we can't imagine working any other way now.&lt;/p&gt;
&lt;p&gt;'Git' and 'Buildout' have both been incredibly empowering. What was most difficult, for us, was that it was very difficult to make the move in small steps. Once we started having proper distutils style packages in Git, they couldn't be cloned into an instance home as a basic Python package (ie, we couldn't do the equivalent of &lt;code&gt;cvs checkout -d mypackage Packages/mypackage/src/mypackage&lt;/code&gt; and get just that subdirectory). And we couldn't easily make distributions of our core packages and use them in a classic Zope 3 style instance home (I did come up with a solution that used &lt;code&gt;virtualenv&lt;/code&gt; to mix and match the two worlds, but I don't think it was ever put to use in production).&lt;/p&gt;
&lt;p&gt;So it was a long and hard road, but the payoffs were nearly immediate: we could start using more community components (and there are some terrific components/packages available for Zope 3); we could more easily use other Python packages as well (no need to have some custom trick to install ezPyCrypto, or be surprised when we deploy onto a new server and realize that we forgot some common packages). Moving customers to new server boxes was much easier, particularly for the smaller customers. And we can update customer apps to new versions with greater confidence than before when we might just try to 'cvs up' from a high location and hope everything updated OK (and who knows what versions would actually come out the other end). Now a customer deployment is a single Git package - everything else is supplied as fully packaged distributions. It's now very hard to 'break the build' as all of the components that are NOT specific to that customer have to come from a software release, which requires a very explicit action.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-4819461604178582744?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4819461604178582744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4819461604178582744'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/10/leaps-and-pains-or-changing.html' title='Leaps and Pains (or - changing development/deployment and scm tools to more closely realize the component architecture dream)'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-9108034236984750318</id><published>2008-10-01T20:36:00.000-06:00</published><updated>2011-05-19T14:51:54.460-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Giddy-up 401, File Uploads, and Safari</title><content type='html'>&lt;p&gt;I've recently been doing some work to support ZODB 3.8 BlobFiles in our Zope 3 based sites and applications. Doing this brought me back around to seeing some behavior I've seen in the past and probably learned to ignore: uploading a large file from Safari using a basic HTML form (with proper encoding type, POST, etc) seems to take inexplicably long. Even worse - once behind Apache, you might not get an expected response, if any. You might get a 'timed out' response, unsure if the app server has everything and will finish the request/response cycle on its own.&lt;/p&gt;
&lt;p&gt;It turns out that Safari does not eagerly send along authentication information along with each request when logged in with Basic Auth. When it does, it seems to have a very short time window.&lt;/p&gt;
&lt;p&gt;So say you're logged in to your application with basic auth (for better or worse). The normal pattern is that when encountering an unauthenticated situation, Zope will challenge with a 401 status code and the WWW-Authenticate header (or something like that - I'm away from all specs right now). If you're not logged in, then you get the basic auth dialog box and send along the credentials. If you are "logged in", then the browser doesn't ask for credentials again, but just sends them along.&lt;/p&gt;
&lt;p&gt;The downside is that this causes a request to be repeated. And if you just tried uploading a 5 MB file, then that whole file has to be re-submitted to make the full request.&lt;/p&gt;
&lt;p&gt;It's the right thing to do with the basic (ha!) information at hand - trying to post all of that data in a single request. But Safari&lt;em&gt;should&lt;/em&gt; recognize that it's submitting to the same server (if not the same URL!) and should automatically include the auth headers. Safari seems to do this, but only on requests in very short windows.&lt;/p&gt;
&lt;p&gt;Firefox, on the other hand, seems to have a much longer window in which it will send the credentials along automatically &lt;em&gt;on the first request&lt;/em&gt;, instead of &lt;em&gt;waiting for the challenge&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I don't know how other browsers do it. I'm not sure what the spec says, if anything. Glancing at O'Reilly's "HTTP - The Definitive Guide" didn't seem to give any indication of whether it's better for the client to assume that it should send the authentication tokens along with each request back to the same server, or if it's better for the client to hold off on constantly sending that info along unless challenged.&lt;/p&gt;
&lt;p&gt;Most of the time this doesn't really seem to matter - it's not something end users typically see as it goes by fast enough to rarely be noticed. Of course there are other ways of getting credentials (cookies, sessions, subdomain/remote ip mapping, etc) which we often use on the main public-facing side of our sites. But for content management and admin, Basic Auth is such an easy fallback, especially in a framework like Zope (1, 2, or 3) which has long had a strong security story and would automatically handle this crap for you way back in the days of Bobo (1996, if not earlier).&lt;/p&gt;
&lt;p&gt;It's just an annoyance. Glad I nailed it down to this: uploading large files with Safari (I think IE is, or was, similar) to basic-auth protected sites often can time out because the browser posts once, gets the 401-Unauthorized challenge, and does the post again - this time with the auth info.&lt;/p&gt;
&lt;p&gt;Solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;don't use basic auth for sites that expect moderate to heavy uploading via forms.&lt;/li&gt;
&lt;li&gt;recommend and/or use browsers that send the auth token along more often in the first request.&lt;/li&gt;
&lt;li&gt;provide better interfaces for uploading files; providing better communication with the uploader about status, and perhaps having a better interface into the destination web app. Fortunately there are appear to be some free and open solutions out there already.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wheee!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-9108034236984750318?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9108034236984750318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9108034236984750318'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/10/giddy-up-401-file-uploads-and-safari.html' title='Giddy-up 401, File Uploads, and Safari'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1871609019212871398</id><published>2008-09-03T07:27:00.004-06:00</published><updated>2008-09-03T07:35:37.579-06:00</updated><title type='text'>New Blogging Pastures</title><content type='html'>&lt;p&gt;With a fair amount of success, I've pulled in the entries from the old &lt;em&gt;Griddle Noise&lt;/em&gt; into a Squarespace account. I've long been dissatisfied with Blogger... It was good enough for a free service, I guess, but I just couldn't take it any more. It was hard to use Markdown, and it was hard to use its "wysiwyg" editor on Safari. Results were unpredictable. So I'm giving &lt;a href="http://www.squarespace.com/"&gt;Squarespace&lt;/a&gt; a try.&lt;/p&gt;
&lt;p&gt;It's really quite a nice service, and it will definitely do for now. The big issue is to either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make time to write&lt;/li&gt;
&lt;li&gt;Write smaller&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
So head over to &lt;a href="http://eucci.squarespace.com/griddle-noise/"&gt;eucci.squarespace.com/griddle-noise&lt;/a&gt;. Gods and time willing, I'll get around to knocking out my tech thoughts again on topics such as:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Zope 3 Component Architecture&lt;/li&gt;
&lt;li&gt;Buildout and the realization of the component dream (almost)&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Object publishing&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1871609019212871398?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1871609019212871398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1871609019212871398'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/09/new-blogging-pastures.html' title='New Blogging Pastures'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-7240753574623946703</id><published>2008-07-25T19:26:00.002-06:00</published><updated>2008-07-25T19:40:12.116-06:00</updated><title type='text'>Remembering Pausch</title><content type='html'>&lt;p&gt;
There are three things that I remember about IPC 8 (International Python Conference 8), besides it being the only Python conference which I've had the luxury of attending.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Riding from Fredericksburg to somewhere outside of DC in a major Virginia snowstorm, only the first or second such snowstorm I had seen since moving to the area in late 1997.&lt;/li&gt;
&lt;li&gt;Meeting &lt;em&gt;Tres Seaver&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The final keynote, masterfully given by &lt;strong&gt;Randy Pausch&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Pausch, who passed away earlier today (July 25, 2008),  was charismatic, smart, and opinionated, and his keynote was funny and engaging. I must admit that I forgot Randy's name, but I'll also gladly admit that many of the points he made have remained with me and I still think of them often. There are even a couple of anecdotes which I repeat to others. Not many people can give such memorable speeches and presentations. Thanks, Randy. I'm glad to have met and heard him in person once, and wish I had been able to do so again to thank him for some great insights and inspirations.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-7240753574623946703?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/7240753574623946703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/7240753574623946703'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/07/remembering-pausch.html' title='Remembering Pausch'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-8697119096017739855</id><published>2008-07-16T12:35:00.000-06:00</published><updated>2008-07-16T13:07:23.406-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='omnifocus'/><category scheme='http://www.blogger.com/atom/ns#' term='gtd'/><title type='text'>OmniFocus Revisited</title><content type='html'>&lt;p&gt;
  I've been using &lt;a href="http://www.omnigroup.com/applications/omnifocus/" title="The Omni Group - OmniFocus"&gt;OmniFocus&lt;/a&gt; for a while now on my Mac, and made occassional
  use of it's predecessor, &lt;a href="http://kinkless.com/kgtd" title="kgtd | Kinkless"&gt;Kinkless GTD&lt;/a&gt;. As an implementation of the
  &lt;a href="http://www.davidco.com/what_is_gtd.php" title="What is GTD ?"&gt;"Getting Things Done"&lt;/a&gt;
  method, or just as a personal "what am I doing?"
  manager, OmniFocus 1.0 was pretty good. I, personally, liked it better than
  the alternatives I tried, but some of that may be due to familiarity with
  the &lt;a href="http://www.omnigroup.com/applications/omnioutliner/" title="The Omni Group - OmniOutliner"&gt;OmniOutliner&lt;/a&gt; heritage.
  And OmniOutliner remains one of the greatest Mac OS X applications ever written.
  I believe it's one of the greatest outliners ever written. Sure, it doesn't have Mind Mapping support and it
  can't run a slideshow (although its data can be exported to OmniGraffle or Keynote).
  OmniOutliner is a joy because it's fast, beautiful, ridiculously easy to use,
  while still having a fair amount of power and flexibility. Kinkless GTD was
  actually a set of AppleScripts that made OmniOutliner act like a specialized
  GTD application (which OmniFocus now does natively).
&lt;/p&gt;
&lt;p&gt;
  But when it came to OmniFocus, I only used it at work, and even there I only used it intermittently. 
  But with the 1.1 "Sneaky-Peek" version of the desktop client (still under development), OmniFocus
  supports synchronization via &lt;a href="http://www.apple.com/mobileme/" title="Apple - MobileMe"&gt;MobileMe&lt;/a&gt; or any WebDAV server. This not only
  enables me to share this information between the office, home, and the
  rarely used laptop, but it enables sharing with the awesome new 
  &lt;a href="http://www.omnigroup.com/applications/omnifocus/iphone/" title="The Omni Group - OmniFocus for iPhone and iPod touch"&gt;OmniFocus for iPhone&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Second only to the iTunes Remote, OmniFocus for iPhone is the coolest mobile
  application I've seen so far on this young platform. OmniFocus for iPhone
  (or iPod Touch) can synchronize over Wi-Fi, Edge, or 3G. That alone makes it
  very useful. Cooler still is that it's location aware. "GTD" has a strong
  concept of contexts. A project may require picking up supplies at an office
  supply store, assembling at home, and mailing out items at the post office.
  With OmniFocus, you can add location information to any context. This
  location information may be based on where you currently stand (using
  Location Services), on a manually entered address, on an address from a
  Contact record, or on a business search. Then when looking at the "By
  Location" screen in OmniFocus, available actions get grouped by their
  location in relation to where you currently stand. "Grocery Store: 1 Mile;
  Post Office: 3 Miles..." &lt;strong&gt;Very Cool&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
  This is the first electronic implementation of GTD that actually appears
  usable. Even if you don't follow GTD religiously (I certainly don't), the
  projects/contexts combination is an effective way of organizing actions.
  The location-aware contexts in OmniFocus for iPhone help answer the 
  question "what can I do based on where I am?" When used well, it should make
  it harder to forget those little items that you needed to do or pick up
  for some small project.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-8697119096017739855?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8697119096017739855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8697119096017739855'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/07/omnifocus-revisited.html' title='OmniFocus Revisited'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2530876269572653946</id><published>2008-07-12T00:27:00.003-06:00</published><updated>2008-07-12T00:40:40.477-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>iPhone 2.0 and the iTunes Remote</title><content type='html'>&lt;p&gt;Like many others, I was bit &lt;strong&gt;hard&lt;/strong&gt; by the server failure that crippled the big iPhone 2.0 update process this morning. It robbed me of said morning, and I opted to take the day off work. It's been a bit of a tough week, and last night I did my first show in months, and had company over until past 3AM afterwards. Since things are about to get crazy at work, I decided that I needed a day to catch back up on sleep while waiting for my phone to work again.&lt;/p&gt;
&lt;p&gt;A few hours later, the phone worked.&lt;/p&gt;
&lt;p&gt;One of the most surprising and enjoyable elements is the iTunes Remote. Full and comprehensive access to my fairly large iTunes library on the iMac: all playlists, etc, with the ability to control volume, jump around in songs, see artwork - just like the 'iPod' iPhone application! Sometimes, particularly in the morning, I might turn on Front Row and carry the nice little Apple Remote around with me to have some control over songs while getting dressed in the upstairs loft, but using the remote from up there often required reaching far over the edges and trying to point the remote in the direction of the iMac, just to be able to skip forward a track or two.&lt;/p&gt;
&lt;p&gt;But now, I can control it all from the iPhone, without needing a line of sight! In fact, this might be what pushes me to pick up an &lt;em&gt;Airport Express&lt;/em&gt; or two (one for speakers in said upstairs loft, maybe one to bring music out on the patio or the bathroom). Full access and control of 29 and a half days of available music playable out of real speakers and controlled by an untethered iPod size device - beautiful.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-2530876269572653946?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2530876269572653946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2530876269572653946'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/07/iphone-20-and-itunes-remote.html' title='iPhone 2.0 and the iTunes Remote'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2608284779460250005</id><published>2008-06-10T14:34:00.001-06:00</published><updated>2008-06-10T14:35:19.772-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Looking to a Snow Leopard Winter.. er... Summer.</title><content type='html'>&lt;p&gt;I&amp;#8217;m a bit excited about Mac OS X &amp;#8220;Snow Leopard&amp;#8221;. Few user-visible changes, with a focus on fine-tuning and giving developers better access to capabilities of modern hardware. It appears that Apple&amp;#8217;s experience in making a lightweight Mac OS X &amp;#8220;Core OS&amp;#8221; for the iPhone will also drive this release.&lt;/p&gt;

&lt;p&gt;One of my favorite operating system releases was OS/2 &amp;#8220;Warp&amp;#8221; (OS/2 3.0). OS/2 2.0 was a fascinating creature - completely divorced from Microsoft, OS/2 2.0 delivered an aggressively object-oriented runtime built on SOM (a desktop implementation of some of CORBA 1.x, I believe). It was radically different from Window 3.x. It&amp;#8217;s hardware requirements were a bit high for the times, but it was a solid OS.&lt;/p&gt;

&lt;p&gt;What impressed me about OS/2 3.0 &amp;#8220;Warp&amp;#8221; was that it&amp;#8217;s system requirements were in some cases significantly LESS than OS/2 2.0, while performing better. I don&amp;#8217;t know of any majoro user-visible adjustments (this was before operating system releases became the giant dog&amp;#8217;n&amp;#8217;pony shows that have been expected since both Windows 95 and Mac OS X).&lt;/p&gt;

&lt;p&gt;I think that even though desktop and laptop hardware continue to get better, the rapid growth rates seen between 1995 and 2005 are slowing down. Now the pressure is on connectivity, portability, and storage storage storage for all of those mp3s and movies and photos. I think both Windows XP and Vista, along with Mac OS X 10.4 and particularly 10.5 have been a bit cavalier about their usage / expectation of resource availability without doing a good job of cleaning up afterwards. Removing a &amp;#8216;TemporaryFiles&amp;#8217; folder used by Apple&amp;#8217;s &amp;#8220;Soundtrack Pro&amp;#8221; program gave me back 25 GB of disk space. 25GB! I expect that when doing lossless audio work, I&amp;#8217;m going to leave a lot of turds behind. But not that many. That&amp;#8217;s an accumulation over only a few months. Now some of that may have been due to crashes brought on by the instability in Mac OS X 10.5.2&amp;#8217;s audio subsystem (particularly in relation to some USB audio devices). But still - 25 gig! Over the course of just a couple of months!&lt;/p&gt;

&lt;p&gt;I think that Apple is at a good place to do this. Good housekeeping is required - otherwise you end up with situations like Mac OS &amp;#8216;Classic&amp;#8217; or even Windows Vista, where there is so much old baggage, bad hacks, outdated mentalities, etc, all in play; it makes it difficult to move the platform forward. Some companies and developers have always been mindful of this, electing to keep their products lean and fast, always (see Ableton Live - hands down, the most impressive audio application out there). Other companies don&amp;#8217;t support that philosophy for whatever reason - backwards compatibility, rush to market, a combination of the two, etc.&lt;/p&gt;

&lt;p&gt;This far into the Mac OS X life cycle, there&amp;#8217;s not many new dog&amp;#8217;n&amp;#8217;pony features to add. The API&amp;#8217;s have stabalized, the developer tools offer more than they ever have (Interface Builder 3 is a terrific update), the Finder and Spotlight are actually fast and usable; applications and utilities from both inside and outside of Apple are going to really shine on Mac OS X 10.5 with all that it offers to developers. A new age of PDA&amp;#8217;s are upon us, whether it&amp;#8217;s a device like an iPhone, an ultra-mobile Asus Eee-PC style portable, or even the Macbook Air: secondary and tertiary devices are really taking off. &lt;/p&gt;

&lt;p&gt;I think that an underlying aspect part of the &amp;#8216;Snow Leopard&amp;#8217; plan is to allow such devices, made by Apple (naturally), to proliferate. When it was announced that the iPhone was built on Mac OS X, I was surprised - Mac OS X has been a pretty wasteful OS - or at least, one that would consume more resources than realized (often for caching, interestingly enough). A standard install is full of crap that may be useful, but often takes up space. How many gigabytes of printer drivers now? To take the fine tuning and resource management ideas from the iPhone variation of OS X into the main system is what I think will allow for Apple to finally make the Eee PC style portable that everyone wanted the Macbook Air to be.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m putting my money on some kind of small device, priced around $600-$800, coming out at or around the same time as Snow Leopard. Combined with Mobile Me and Snow Leopard Server&amp;#8217;s increasingly Exchange-like feature set (but better priced and more understandable for small organizations), the ubiquitous-data-access capability is there.&lt;/p&gt;

&lt;p&gt;Today&amp;#8217;s full-featured laptops (MacBooks, Inspirons, whatever) are their own entities; my aging iBook gets used rarely as I just don&amp;#8217;t have as much data or software set up on it, and it&amp;#8217;s sometimes too big of a pain to keep in sync.&lt;/p&gt;

&lt;p&gt;The XO and Eee-PCs (or whatever they&amp;#8217;re called) are also separate from the rest of one&amp;#8217;s life; useful as a fun or educational toy, or as a geek&amp;#8217;s favorite gadget to see what they can get running on such a little device. Most of the other developments I&amp;#8217;ve seen in this area have centered around &amp;#8220;how cheap and how small can we make a laptop/portable that will run (Linux/Windows XP)&amp;#8221;. But outside of education, if this is the only focus being given, then these companies are going to be making nothing more than the next round of casual gadgets that get tossed or buried after a few months - especially if a key factor of what made Palm devices so popular (for a while) is completely neglected.&lt;/p&gt;

&lt;p&gt;The Macbook Air is deliberately designed as a complementary computer, using the master&amp;#8217;s optical drive even. While sexy, I think the Macbook Air misses the mark on a few items. But I think it&amp;#8217;s an indication of things to come - laptops deliberately designed to complement your main machine. Smaller devices, from the Palm to the iPhone, have done this. And they&amp;#8217;ll also be designed to work with your (or your company&amp;#8217;s) data, which the Blackberry has done (and the iPhone will do when its new &amp;#8216;enterprise&amp;#8217; support rolls out). Getting this onto other devices, without being constrained to an enterprisey system like Notes or Outlook, is where things really appear to be headed. It&amp;#8217;s certainly something that I&amp;#8217;d like to have. And the more I look at Snow Leopard, the more I believe that Apple is sneaking ahead of the crowd into delivering this into the hands of consumers. They&amp;#8217;re skating to where the puck is going to be.&lt;/p&gt;

&lt;p&gt;Granted, Windows &amp;#8220;Live Mesh&amp;#8221; looks to be heading in the same direction. But after Vista, Microsoft needs to reign in the Windows kernel and distribution. Windows Server 2008 and some of what has been leaked (or speculated) about &amp;#8220;Windows 7&amp;#8221; seem to indicate that Microsoft is aware of this. And how could they not be? But I think that even with their vast resources, Microsoft has a long ways to go to catch up - even though it appears that they&amp;#8217;ve been playing in this area (tablet computing, ultra-mobile pc&amp;#8217;s) for a while. A deep cleansing of the Windows core is desparately needed. And then a deep re-implementation of the UI may be needed.&lt;/p&gt;

&lt;p&gt;Apple had a terrific luxury (and great idea) with the iPhone. While sharing the same kernel and many same APIs as the desktop (and server) Mac OS X, it has an entirely new UI that is dedicated to its intended use. Windows CE, on the other hand, tried to bring the Windows 95 look and feel to tiny devices and now I&amp;#8217;m really not so sure it was a good idea. It allowed Microsoft to punt on some usability and design issues by falling back on the way things work on the desktop. I still see this, even in some of the newest and fanciest &amp;#8220;iPhone killers&amp;#8221;: some of these have a very fancy launcher app; some even have a very fancy phone and contact app that spins around in 3D and responds to gestures. But then, suddenly, you&amp;#8217;re in the tiny-font, tiny-scrollbar, pixelated, stylus-driven world of the interior. It&amp;#8217;s like going into a grand building like The Plaza (back when it was a hotel, at least), and finding the inside full of grey linoleum floors, flickering flourescent lights, and cinderblock walls reminiscent of an old hospital or elementary school. Quite the let-down (a lot of courthouses are like this, actually).&lt;/p&gt;

&lt;p&gt;I also think Apple was smart to NOT have an SDK at the launch of the iPhone. I bet they would have liked one, but I think the iPhone had to launch when it did, and perhaps not-quite-everything was ready yet. If one looks back at the classic Macintosh and Palm devices and operating systems, you see systems that pulled of very clever hacks to fit within the price and size constraints of the time. The Lisa was much more than a $10,000 Macintosh - it had many features from power management to an OpenDoc style multi-tasking document based UI. But to offer those features, it was priced well out of reach. The Macintosh squeezed as much as it could down into a 128K Ram machine, and the compromises they had to make in order for that to work would end up haunting the company until its near-death. The Palm, too, took the ideas of the Newton and other tablet devices and stripped them down into a size and price point approachable by the masses. And like Apple, the design decisions that were made to make that work have crippled the Palm OS so much that even Palm sells half of its devices with Windows CE (or whatever CE is called these days). Those compromises are bad enough to deal with on your own - but when having to support third party developers and then provide some degree of backwards compatibility, it can just kill you.&lt;/p&gt;

&lt;p&gt;By taking the time to put the SDK into beta, to polish up the OS and its APIs, I think Apple will avoid a repeat of that story. Instead of having to support every little exposed compromise that may have been made to get the iPhones out the door last June, Apple could tidy them up. By using a beta period for the SDK and next major release of the software, Apple can respond to feedback and make changes and adjustments before they become permanent.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-2608284779460250005?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2608284779460250005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2608284779460250005'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/06/looking-to-snow-leopard-winter-er.html' title='Looking to a Snow Leopard Winter.. er... Summer.'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-3763099836331524967</id><published>2008-04-29T00:48:00.001-06:00</published><updated>2008-04-29T00:49:59.975-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hafler trio'/><category scheme='http://www.blogger.com/atom/ns#' term='aesthetics'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>The Hafler Trio, Dislocation</title><content type='html'>&lt;p&gt;I just received the Korm Plastics re-release of The Hafler Trio&amp;#8217;s &lt;a href="http://brainwashed.com/h3o/Dislocation/re/"&gt;Dislocation&lt;/a&gt;. I&amp;#8217;ve been waiting for this one more than any of the others thus far. The &lt;a href="http://www.brainwashed.com/h3o/korm_plastics.html"&gt;Korm Plastics re-issue series&lt;/a&gt; is a magnificent undertaking wherein a large chunk of Hafler Trio material that has long been unavailable or available only in &amp;#8220;wrong&amp;#8221; versions is being re-issued in definitive form. The packaging for each has been stunning: each release in a booklet sized &amp;#8220;wallet&amp;#8221; form, with full booklets, posters, post-cards, and more. The releases are all wrapped in a vellum (or vellum-like) material with additional writing. The packaging alone is of the highest grade - far higher than what these releases saw in their original forms (even ones that were also in wallet/booklet form).&lt;/p&gt;

&lt;p&gt;I first became interested in The Hafler Trio when the Hafler Trio / Nurse With Wound &lt;a href="http://brainwashed.com/h3o/mfo.html"&gt;collaboration was issued on CD&lt;/a&gt;, which I picked up in &amp;#8230; 1995? 96? I was a big Nurse With Wound fan at the time and, thus, gobbled this one up. I was blown away. While I recognized many Nurse With Wound sounds, the overall production and flow was of a different nature. Similar, yes, in it all being (perhaps) some form of &lt;em&gt;Musique:Concrete&lt;/em&gt;. It just sounded a bit more &amp;#8230; polished? Subtle? In any case, it remains a personal favorite.&lt;/p&gt;

&lt;p&gt;At this time, I was 20-21 years old, poor, bla bla bla. Most of these CDs that I liked were all import and out of my price range (when they could even be found). But one day around this time, I was in a used cassette shop, and came across the original Hafler Trio &lt;a href="http://www.brainwashed.com/h3o/Dislocation/tape.html"&gt;Dislocation cassette&lt;/a&gt;. For $4! It was a Staaltape release, in a bag (my second one - a couple of years earlier I picked up what turned out to be a fairly rare Legendary Pink Dots cassette in the same style of packaging, mostly because I didn&amp;#8217;t yet have a CD player). Not knowing much of The Hafler Trio at the time, I knew that this was something I should get, as it was unlikely that I would easily come across such a find for years to come.&lt;/p&gt;

&lt;p&gt;I liked the tape, but I admit that it took a while to grow on me. It was very quiet and subtle, with a lot of field recordings. It was something that I enjoyed, but I found that I had to give it more attention than similar recordings from other artists. I loved having it on tape, though. It heightened the &amp;#8220;found sound&amp;#8221; feeling. And I loved what was inside the bag (besides the unlabeled cassette). Inside, there was heavy paper with fragments of maps on one side and various clippings on the other. It was far more interesting than some of the cheap shock imagery (or just cheap packaging) used, again, by somewhat similar artists that interested me at that time.&lt;/p&gt;

&lt;p&gt;However, as fascinating as it all was, that would be it for me and The Hafler Trio until 3-4 years later when, after moving to the east coast, I&amp;#8217;d find a copy of &lt;a href="http://www.brainwashed.com/h3o/BagofCats/index.html"&gt;A bag of cats&lt;/a&gt; at &lt;a href="http://printedmatter.org/"&gt;Printed Matter&lt;/a&gt;&amp;#8217;s old Wooster Street location in NYC. After that find, I&amp;#8217;d lap up whatever I could.&lt;/p&gt;

&lt;p&gt;So &lt;a href="http://brainwashed.com/h3o/Dislocation/re/"&gt;Dislocation&lt;/a&gt; has been held in a special place, and I&amp;#8217;d been watching that &lt;a href="http://www.brainwashed.com/h3o/korm_plastics.html"&gt;Korm re-issue series&lt;/a&gt; list tick along, waiting for this one to show up. Now it&amp;#8217;s here. And it&amp;#8217;s much more impressive than imagined. First, the booklet is a new heavy-stock foldout variation of the same maps found within the &lt;a href="http://www.brainwashed.com/h3o/Dislocation/tape.html"&gt;cassette version&lt;/a&gt;. When folded up&amp;#8230; I can&amp;#8217;t even describe it, really. It&amp;#8217;s just beautiful and very different from the booklets that have accompanied the rest of the re-issue series.&lt;/p&gt;

&lt;p&gt;But what&amp;#8217;s really been impressive has been the audio. This time, I have no prior CD to compare; only tape. And I love tape. But now, more than any other re-issue done thus far, I can really see how well done the audio restoration has been. Remarkably well done. This album deserved (and required) it. As much as I loved the &amp;#8220;found sound&amp;#8221; fuzzy feeling I got from the tape, there are a lot of nuances here that I may now appreciate. Goddamn well done.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-3763099836331524967?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/3763099836331524967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/3763099836331524967'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/04/i-just-received-korm-plastics-re.html' title='The Hafler Trio, Dislocation'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2278235399758343043</id><published>2008-04-07T23:28:00.004-06:00</published><updated>2008-04-08T08:43:08.279-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scm'/><category scheme='http://www.blogger.com/atom/ns#' term='mercurial'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='dvcs'/><title type='text'>What a DVCS gives me</title><content type='html'>I've seen some posts floating around about what a distributed version control system might give you. For me, these are the key elements:&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Committing changes is separate from sharing.&lt;/span&gt; While the phrase "you can edit on a plane!" gets thrown around quite frequently, I think this is the far more important aspect of that vision. As a developer, you don't always know how a particular path of development might impact the code base. With a purely centralized system, you have to think first about where a path may be taking you as it could affect everybody else. Time and time again, I've seen developers work without any revision control safety net for days or weeks at a time because they don't want to "break the build", and they don't have time to look up the policies for branch naming, merging, etc. Not that such a thing should take a long time, but when under pressure, it's the last thing one wants to deal with. And the untracked changes keep getting bigger, and bigger. And when I say "I've seen developers..." here, I include myself.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;With a DVCS, I can commit immediately. I took heavy advantage of this on a recent project where the set of work for which I was responsible was in no state to be set up on other systems. It required new configuration and possibly new tool installations and I didn't have time to help everyone else install and update their sandboxes. They didn't need my code anyways. Instead, I was able to pull in and rebase my work on updates from my co-workers while my personal branch was in development. When my code was mature, it was easy to merge into a more centralized branch. Very easy. In fact, it was just a fast-forward (in Git parlance), since I was rebasing my changes on top of those by my colleagues.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Again, this is &lt;span class="Apple-style-span" style="font-style: italic;"&gt;possible&lt;/span&gt; with a purely centralized system, but it would have required me to realize the significance of my changes and their impact on others. My sandbox was in a "guts on the table" kind of state. Just about every commit I made was stable, but sharing them would have made it harder on other team members to do their work due to the changes made in tool and configuration dependencies.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;In essence, &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;a DVCS inverts the control back to individuals&lt;/span&gt;. As a developer, I can commit my changes whenever I want. With a purely centralized system, I have to think more about what I'm about to commit, since it immediately impacts all other developers.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;A DVCS encourages experimentation&lt;/span&gt;. Being able to commit my changes whenever I want and being able to make local branches so easily makes it easier for me to start playing around with new ideas. Whether that's doing a big refactoring or restructuring of code, experimenting with a new feature of third party library, or working on updating the code to run well on the latest release of Foo, I know that I can experiment and SAVE those experiments in small chunks, without impacting anybody else. I can choose when and how I want to share my results. I can choose to throw my experiment away and not have to be reminded by its grizzly branch name for years to come.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;We have an internal toolkit that bridges SQLAlchemy and Zope 3 and provides various other useful features and integrations. Late last year, I started looking into updating the code to work with SQLAlchemy 0.4 and to also clean up some ancient hacks. We were still using CVS at the time. I can't remember when I made the branch, but I knew at some point that I was heading down a potentially long path and that a branch would be required. Other priorities were coming up and I'd have to leave this work aside for a while.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Well, there's 2-3 days of feverish work, all held hostage within a single check-in. I've been wanting to pull some features out of that branch and into the current mainline branch, but since it's all in one big check-in, I can't do that easily. This is the second time I've done that (the other time was on a feature branch that lead to a dead end, but along the way I had some good ideas that I'd love to be able to extract now).&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;If I'd been using Git, I would have been making more commits, more frequently, and in much smaller sizes. Using Git, I would then be able to quite easily cherry pick individual commits out of that branch and apply them to the mainline. &lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Finally, a DVCS makes it easy to vet changes through the system. We don't have to give new employees the keys to the kingdom, particularly when their skill set is focused on a specific area. Instead, the code can go through review channels. They make commits in their local repository, and tell someone (like me) that they've made some changes. Using Git (or any other tool - but Git's named remotes makes this hella easy), I can pull in changes from their repository, verify that they're good, and push them to the canonical repository. I can merge them into other branches, if required.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Imagine this in a team situation: team members can share their repositories with each other as needed, giving each other chances to do code reviews and fixes before sharing those changes with the larger group or division; all without requiring permission to touch the central repository. Suddenly whole new workflows open up, based on the "networks of trust" inherent in all of us: a team leader collects commits from their team, and shares those changes with other team leaders. Those team leaders pull together changes from all of their teams (while sharing said changes across team lines) and push those on to a QA / Testing division. The QA / Testing division then puts their seal of approval on things by being the ones who control pushing to the "canonical" repository from which builds are based.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;There's just so much more that can be done with a DVCS, and we're in an age now where there are very usable and useful tools for this job. A DVCS restores individual responsibility, encourages experimentation, enables adaptive workflows, and I believe it fits more naturally into how we humans organize our interactions. Whether this is in a rigidly defined corporate structure or a loosely connected set of worldwide open source contributors, the peer to peer nature combined with getting the whole repository enables people to step up and do bold things without having to go through channels to get any coveted "write access".&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-2278235399758343043?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2278235399758343043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2278235399758343043'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/04/what-dvcs-gives-me.html' title='What a DVCS gives me'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-5529359661027861595</id><published>2008-04-06T10:49:00.000-06:00</published><updated>2008-04-06T10:50:09.978-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hafler trio'/><category scheme='http://www.blogger.com/atom/ns#' term='aesthetics'/><category scheme='http://www.blogger.com/atom/ns#' term='drone'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>Sunday Great Openings</title><content type='html'>&lt;p&gt;In my &lt;a href="http://griddlenoise.blogspot.com/2008/03/trilogy-revisited.html"&gt;last post&lt;/a&gt;, I revisited an earlier write-up of a personal experience involving &lt;a href="http://brainwashed.com/h3o/"&gt;The Hafler Trio&lt;/a&gt;’s so-called &lt;a href="http://brainwashed.com/h3o/trilogy/"&gt;Trilogy in Three Parts&lt;/a&gt;. I’ve been on a bit of a binge lately, trying to grab up a lot of Hafler Trio releases that I let slip by over the past few years. Right now, I’ve got two thirds of the &lt;a href="http://classicaldrone.blogspot.com/2007/07/drone-classics-exactly.html"&gt;Exactly&lt;/a&gt; series of long-form dual disc releases revolving around the voice of Jónsi Birgisson (Sigur Ros), with one of those releases being in the form of the deluxe packaging from &lt;a href="http://simplysuperior.org/"&gt;Simply Superior&lt;/a&gt;. I’ve been starting to pick up vinyl releases as well and will soon have all three evidences according to &lt;a href="http://www.brainwashed.com/h3o/wsc/index.html"&gt;Wolf Sheep Cabbage&lt;/a&gt;, among others. I even managed to find a well priced vinyl copy of what has become one of my all time favorite albums: &lt;a href="http://www.brainwashed.com/h3o/fish.html"&gt;A Thirsty Fish&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But on this here Sunday morning, I find myself ill at ease. Shoulders are tense, bones are cracking, mind is dazed yet burning. To try to find a spot of calm, I first went through what I have so far of the &lt;a href="http://classicaldrone.blogspot.com/2007/07/drone-classics-exactly.html"&gt;Exactly&lt;/a&gt; set, but it wasn’t helping today. So I returned, again, to this initial &lt;a href="http://brainwashed.com/h3o/trilogy/"&gt;trilogy&lt;/a&gt;. I haven’t listened to it much since my &lt;a href="http://euc.cx/toulouse/archives/2004/04/06/trilogy_tuesday.html"&gt;grand encounter&lt;/a&gt; four years ago. That was just a little too powerful. But up until that point, I got a fair amount of comfort out of the series. It’s still a remarkably powerful. The trick is not to get too lost in it when not wanting great and terrible visions. All I need right now is a warm, sustained, and calming presence. These can do that job rather well - enough to get me through the morning and into a much needed hot shower followed by a cold walk with the dog and some lukewarm coffee.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-5529359661027861595?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/5529359661027861595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/5529359661027861595'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/04/sunday-great-openings.html' title='Sunday Great Openings'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-5341767976041398</id><published>2008-03-24T07:57:00.004-06:00</published><updated>2008-03-24T14:35:26.586-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aesthetics'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><category scheme='http://www.blogger.com/atom/ns#' term='nostalgia'/><title type='text'>A Trilogy Revisited</title><content type='html'>&lt;p&gt;I was killing late night minutes by reading through &lt;em&gt;&lt;a href="http://brainwashed.com/h3o/e-void/explain.html#no_twain"&gt;pouring empty into the void&lt;/a&gt;&lt;/em&gt; - a collection of reviews of &lt;a href="http://brainwashed.com/h3o/"&gt;Hafler Trio&lt;/a&gt; material - when I came across a review of the entire &lt;a href="http://brainwashed.com/h3o/trilogy/"&gt;trilogy in three parts&lt;/a&gt;. The writing was more personal than many of the other reviews, which were written for larger audiences (magazines, record shops, etc). And then I got to the final paragraph:
&lt;/p&gt;
&lt;blockquote&gt;Deep into &lt;em&gt;No More Twain, Of One Flesh: 11 Unequivocal Obsecrations&lt;/em&gt;, I was deep into trance and ripped apart by my own twain — two entities guiding and dividing my life right now — and had to fight my way out of such deep and frightening consciousness and back into the body. Scratches and cold medal were put to use to reinvigorate the breath and to bring myself down out of the super present to the merely present.&lt;/blockquote&gt;

&lt;p&gt;"Wow," I thought, "this guy had an experience similar to mine!"&lt;/p&gt;

&lt;p&gt;And then I clicked on the source link - &lt;a href="http://euc.cx/toulouse/archives/2004/04/06/trilogy_tuesday.html"&gt;and it was, in fact, my own&lt;/a&gt;. April 6, 2004. What a wonderful, horrible spring.&lt;/p&gt;

&lt;p&gt;And what the fuck has happened to my brain when I look back at &lt;a href="http://euc.cx/toulouse/archives/2004/03/11/luxury_spring_rising.html"&gt;many of the things produced / released at that time&lt;/a&gt; and wonder how the hell I could do that (and find time to write about it in fairly eloquent terms). Now I have a hard time making a single, simple, goddamn web page for a simple four track online album. How anyone's ever going to hear &lt;em&gt;Like the city, we're bound to last&lt;/em&gt; is beyond me at this point.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-5341767976041398?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/5341767976041398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/5341767976041398'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/03/trilogy-revisited.html' title='A Trilogy Revisited'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-3605297034738671400</id><published>2008-02-24T12:47:00.002-07:00</published><updated>2008-02-24T12:51:33.993-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rage'/><category scheme='http://www.blogger.com/atom/ns#' term='vitriol'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>Quit blaming Nader</title><content type='html'>&lt;p&gt;A friend of mine says, &amp;#8220;&lt;a href="http://blog.amber.org/2008/02/24/ralph-nader-is-an-idiot/"&gt;Ralph Nader is an idiot&lt;/a&gt;&amp;#8221;, just because Nader is running for president again.&lt;/p&gt;

&lt;p&gt;I fucking HATE this line of thinking. Nothing pissed me off more than when watching the documentary on Nader recently and seeing how everyone fucking turned on him in 2004 after championing him in 2000. At least Nader has principals and stands by them. Nearly every &amp;#8216;liberal&amp;#8217; voice that I had respected proved to me that they had no fucking principals.&lt;/p&gt;

&lt;p&gt;Michael Moore in 2000 at a Nader rally: &amp;#8220;If you&amp;#8217;re voting for the lesser of two evils, you&amp;#8217;re still voting for evil!&amp;#8221; Four years later, Moore was on the anti-Nader bandwagon.&lt;/p&gt;

&lt;p&gt;If we believe in democracy and having choices and voices, then anyone should be able to run for president. 2000 was not Nader&amp;#8217;s fault. Gore, and the democrats in general, should have run a better campaign. Just like when teams complained about the Patriots running up the score on them: it&amp;#8217;s not the Patriots job to take Tom Brady off the field and stop scoring. It&amp;#8217;s YOUR defense&amp;#8217;s job to get on the field and stop them (the Giants did it; Philly and Baltimore nearly did it). The democrats should have run better campaigns in 2000 and 2004. They could have stopped Nader from running in 2004 if they had picked some of his causes (just some simple ones) and championed them. But the democrats didn&amp;#8217;t.&lt;/p&gt;

&lt;p&gt;Honestly - whenever I hear this vitriol against Nader, a man who has championed consumer rights far more than anyone currently running or serving this country, it sounds like people wanting a fucking dictatorship. It&amp;#8217;s like the movie &amp;#8216;moon over paramour&amp;#8217; (or something like that) where there are two posters for the same dictator - red and blue. One guy asks the other who he&amp;#8217;s going to vote for, &amp;#8220;red or blue&amp;#8221;. The other guy says, &amp;#8220;it doesn&amp;#8217;t matter, it&amp;#8217;s a free dictatorship.&amp;#8221;&lt;/p&gt;

&lt;p&gt;I have the right to vote for whomever I want. And on principal, I will cast my vote for whomever I feel best represents what I want out of a leader. I&amp;#8217;m not going to vote for someone just because they where an elephant or donkey lapel pin. I don&amp;#8217;t care if my one single vote hands the election over to another eight years of Bush tyranny.&lt;/p&gt;

&lt;p&gt;The two party system sucks big time fucking hairy nutsacks. I think South Park represented it best with the &amp;#8220;Giant Douche versus Turd Sandwich&amp;#8221; vote for school mascot (one of the greatest, and saddest, South Park episodes).&lt;/p&gt;

&lt;p&gt;What sucks even more than the two party system is the electoral college being based on representative seats plus senate seats. This causes a vote in Wyoming to count four times as much as a vote in california. Now that&amp;#8217;s not fucking fair at all.&lt;/p&gt;

&lt;p&gt;The problem isn&amp;#8217;t Nader. The whole system is flawed and corrupt and I feel like the anti-Nader rhetoric comes from people who would like to see it stay that way as long as they think they can rig the system to swing to their guy who may be the lesser of two evils.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s still evil.&lt;/p&gt;

&lt;p&gt;And honestly - seeing the response of so many people against Nader in that film made me absolutely sick with the democratic party and the people who claim to champion its causes. They do not believe in freedom or standing for principals. They&amp;#8217;re the selfish, self-absorbed, narcissistic pricks. &amp;#8220;Oh, look at me, I write for the nation.&amp;#8221; Bit whoop. Nader actually fucking fought hard for things like seatbelts in cars. Big auto wouldn&amp;#8217;t do it. They resisted like hell. We all take this for granted now. But it took someone with actual balls to stand up and fight for something so seemingly trivial (now) but which has been a big deal when it comes to saving lives. What has Eric Alterman done for us lately?&lt;/p&gt;

&lt;p&gt;The general democratic response to Nader shows that most of these people have no spine, no guts, and they don&amp;#8217;t deserve any glory. They certainly don&amp;#8217;t deserve my support.&lt;/p&gt;

&lt;p&gt;Blaming Nader is a sign of weakness, and a sign that the general democratic party and pundits can't own up to their own fucking mistakes. If they can't do that, they can't lead.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-3605297034738671400?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/3605297034738671400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/3605297034738671400'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2008/02/quit-blaming-nader.html' title='Quit blaming Nader'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1984955612308634460</id><published>2007-12-02T22:58:00.000-07:00</published><updated>2007-12-02T23:04:02.968-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scm'/><category scheme='http://www.blogger.com/atom/ns#' term='mercurial'/><category scheme='http://www.blogger.com/atom/ns#' term='tools'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='subversion'/><category scheme='http://www.blogger.com/atom/ns#' term='distributed vcs'/><category scheme='http://www.blogger.com/atom/ns#' term='cvs'/><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>Distributed VCS's are the Great Enablers (or: don't fear the repo)</title><content type='html'>&lt;p&gt;The more I play with the new breed of VCS tools, the more I appreciate them. The older generations (CVS, SVN) look increasingly archaic, supporting a computing and development model that seems unsustainable. Yet most of us lived with those tools, or something similar, for most of our development-focused lives.&lt;/p&gt;

&lt;p&gt;When I speak of the new breed, the two standouts (to me) are &lt;a href="http://git.or.cz/"&gt;Git&lt;/a&gt; and &lt;a href="http://www.selenic.com/mercurial/"&gt;Mercurial&lt;/a&gt;. There are some other interesting ones, particularly &lt;a href="http://darcs.net/"&gt;Darcs&lt;/a&gt;, but Git and Mercurial seem to have the most steam and seem fairly grounded and stable. Between those two, I still find myself preferring Git. I&amp;#8217;ve had some nasty webs to untangle and Git has provided me with the best resources to untangle them.&lt;/p&gt;

&lt;p&gt;Those webs are actually all related to CVS and some messed up trunks and branches. Some of the code lives on in CVS, but thanks to Git, sorting out the mess and/or bringing in a huge amount of new work (done outside of version control because no one likes branching in CVS and is afraid of &amp;#8216;breaking the build&amp;#8217;) was far less traumatic than usual.&lt;/p&gt;

&lt;p&gt;One of those messes could have been avoided had we been using Git as a company (which is planned). One of the great things these tools provide is the ability to easily do speculative development. Branching and merging is so easy. And most of those branches are private. One big problem we have with CVS is what to name a branch: how to make the name unique, informative, and communicative to others. And then we have to tag its beginnings, its breaking off points, its merge points, etc, just in case something goes wrong (or even right, in the case of multiple merges). All of those tags end up in the big cloud: long, stuffy, confusing names that outlive their usefulness. It&amp;#8217;s one thing to deal with all of this for an important branch that everyone agrees is important. It&amp;#8217;s another to go through all of this just for a couple of days or weeks of personal work. So no one does it. And big chunks of work are just done dangerously - nothing checked in for days at a time. And what if that big chunk of work turned out to be a failed experiment? Maybe there are a couple of good ideas in that work, and it might be worth referring to later, so maybe now one makes a branch and does a single gigantic check-in, just so that there&amp;#8217;s a record somewhere. But now, one can&amp;#8217;t easily untangle a couple of good ideas from the majority of failed-experiment code. &amp;#8220;Oh!&amp;#8221; they&amp;#8217;ll say in the future, &amp;#8220;I had that problem solved! It&amp;#8217;s just all tangled up in the soft-link-experimental-branch in one big check in and I didn&amp;#8217;t have the time to sort it out!&amp;#8221;&lt;/p&gt;

&lt;p&gt;I speak from personal experience on that last one. I&amp;#8217;m still kicking myself over that scenario. The whole problem turned out to be bigger than expected, and now there&amp;#8217;s just a big blob of crap, sitting in the CVS repository somewhere.&lt;/p&gt;

&lt;p&gt;With a distributed VCS, I could have branched the moment that it looked like the problem was getting to be bigger than expected. Then I could keep committing in small chunks to my personal branch until I realized the experiment failed. With smaller check-ins, navigating the history to cherry-pick the couple of good usable ideas out would have been much easier, even if everything else was dicarded. I wouldn&amp;#8217;t have to worry about &amp;#8216;breaking the build&amp;#8217; or worry about a good name for my branch since everyone else would end up seeing it. I could manage it all myself.&lt;/p&gt;

&lt;p&gt;This is the speculative development benefit that alone makes these tools great. It&amp;#8217;s so easy to branch, MERGE, rebase, etc. And it can all be done without impacting anyone else.&lt;/p&gt;

&lt;p&gt;One thing that I often hear when I start advocating distributed VCS&amp;#8217;s is &amp;#8220;well, I like having a central repository that I can always get to&amp;#8221; or &amp;#8220;is always backed up&amp;#8221; or &amp;#8220;is the known master copy.&amp;#8221; There&amp;#8217;s nothing inherant in distributed VCS&amp;#8217;s that prevents you from having that. You can totally have a model similar to SVN/CVS in regards to a central repository with a mixture of read-only and read/write access. But unlike CVS (or SVN), what you publish out of that repository is basically the same thing that you have in a local clone. No repository is more special than any other, but that policy makes it so. You can say &amp;#8220;all of our company&amp;#8217;s main code is on server X under path /pub/scm/&amp;#8230;&amp;#8221;. &lt;/p&gt;

&lt;p&gt;And unlike CVS (or SVN), really wild development can be done totally away from that central collection. A small team can share repositories amongst themselves, and then one person can push the changes in to the central place. Or the team may publish their repository at a new location for someone else to review and integrate. Since they all stem from the same source, comparisons and merges should all still work, even though the repositories are separate.&lt;/p&gt;

&lt;p&gt;Imagine this in a company that has hired a new developer. Perhaps during their first three months (a typical probationary period), they do not get write access to the core repositories. With a distributed VCS, they can clone the project(s) on which they&amp;#8217;re assigned, do their work, and then publish their results by telling their supervisor &amp;#8220;hey, look at my changes, you can read them here &amp;#8230;&amp;#8221; where here may be an HTTP or just a file system path. Their supervisor can then conduct code reviews on the new guys work and make suggestions or push in changes of his own. When the new developers code is approved, the supervisor or some other higher developer is repsonsible for doing the merge. It&amp;#8217;s all still tracked, all under version control, but the source is protected from any new-guy mistakes, and the new-guy doesn&amp;#8217;t have to feel pressure about committing changes to a large code-base which he doesn&amp;#8217;t yet fully grasp.&lt;/p&gt;

&lt;p&gt;But perhaps the most killer feature of these tools is how easy it is to put &lt;em&gt;anything&lt;/em&gt; under revision management. I sometimes have scripts that I start writing to do a small job, typically some kind of data transformation. Sometimes those scripts get changed a lot over the course of some small project, which is typically OK: they&amp;#8217;re only going to be used once, right?&lt;/p&gt;

&lt;p&gt;This past week, I found myself having to track down one such set of scripts again because some files had gotten overridden with new files based on WAY old formats of the data. Basically I needed to find my old transformations and run them again. Fortunately, I still had the scripts. But they didn&amp;#8217;t work 100%, and as I looked at the code I remembered one small difference that 5% of the old old files had. Well, I didn&amp;#8217;t remember the difference, I just remembered that they had a minor difference and I had adjusted the script appropriately to finish up that final small set of files. But now, I didn&amp;#8217;t have the script that worked against the other 95%.  When I did the work initially, it was done in such a time that I was probably using my editors UNDO/REDO buffer to move between differences if needed.&lt;/p&gt;

&lt;p&gt;Now if I had just gone in to the directory with the scripts and done a &lt;code&gt;git init; git add .; git commit&lt;/code&gt; sequence, I would probably have the minor differences right there. But I didn&amp;#8217;t know such tools were available at the time. So now I had to rewrite things. This time, I put the scripts and data files under git&amp;#8217;s control so that I had easy reference to the before and after stages of the data files, just in case this scenario ever happened again.&lt;/p&gt;

&lt;p&gt;I didn&amp;#8217;t have to think of a good place to put these things in our CVS repo. I just made the repository for myself and worried about where to put it for future access later. With CVS/SVN, you have to think about this up front. And when it&amp;#8217;s just a personal little project or a personal couple of scripts, it hardly seems worth it, even if you may want some kind of history.&lt;/p&gt;

&lt;p&gt;Actually, that is the killer feature! By making everything local, you can just do it: make a repository, make a branch, make a radical change, take a chance! If it&amp;#8217;s worth sharing, you can think about how to do that when the time is right. With the forced-central/always-on repository structure of CVS and SVN, you have to think about those things ahead of time: where to import this code, what should I name this branch so it doesn&amp;#8217;t interfere with others, how can I save this very experimental work safely so I can come back to it later without impacting others, is this work big enough to merit the headaches of maintaining a branch, can I commit this change and not break the build&amp;#8230;.?&lt;/p&gt;

&lt;p&gt;As such, those systems punish speculation. I notice this behavior in myself and in my colleages: it&amp;#8217;s preferred to just work for two weeks on something critical with no backup solution, no ability to share, no ability to backtrack, etc, than it is do deal with CVS. I once lost three days worth of work due to working like this - and it was on a project that no one else was working on or depending on! I was just doing a lot of work simultaneously and never felt comfortable committing it to CVS. And then one day, I accidentally wiped out a parent directory and lost everything.&lt;/p&gt;

&lt;p&gt;Now, in a distributed VCS, I could have been committing and committing and could have lost everything anyways since the local repository is contained there: but I could have made my own &amp;#8220;central&amp;#8221; repository on my development machine or on the network to which I could push from time to time. I would have lost a lot less.&lt;/p&gt;

&lt;p&gt;There are so many good reasons to try one of these new tools out. But I think the most important one comes down to this: just get it out of your head. Just commit the changes. Just start a local repository. Don&amp;#8217;t create undue stress and open loops in your head about what, where, or when to import or commit something. Don&amp;#8217;t start making copies of &amp;#8216;index.html&amp;#8217; as &amp;#8216;index1.html&amp;#8217;, &amp;#8216;index2.html&amp;#8217;, index1-older.html&amp;#8217; &amp;#8216;old/index.html&amp;#8217;, &amp;#8216;older/index.html&amp;#8217; and hope that you&amp;#8217;ll remember their relationships to each other in the future. Just do your work, commit the changes, get that stress out of your head. Share the changes when you&amp;#8217;re ready.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s a much better way of working, even if it&amp;#8217;s only for yourself. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1984955612308634460?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1984955612308634460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1984955612308634460'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/12/distributed-vcss-are-great-enablers-or.html' title='Distributed VCS&apos;s are the Great Enablers (or: don&apos;t fear the repo)'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1065664562220326273</id><published>2007-11-20T14:44:00.000-07:00</published><updated>2007-11-20T14:45:29.775-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sucks'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><title type='text'>Broken Bulb</title><content type='html'>With apologies to Johnny Cash: "Flash, I hate every inch of you."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1065664562220326273?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1065664562220326273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1065664562220326273'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/11/broken-bulb.html' title='Broken Bulb'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-8757505951513943648</id><published>2007-11-07T21:26:00.000-07:00</published><updated>2007-11-07T21:34:01.005-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scm'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='cvs'/><title type='text'>Falling for Git</title><content type='html'>&lt;p&gt;You know what? &lt;a href="http://git.or.cz/"&gt;Git&lt;/a&gt; must have come a long way in the last year. I keep reading that Git is hard to learn, has rough documentation, etc. But it&amp;#8217;s really been quite nice in comparison to many things.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s especially nice once you quickly learn that the HTML &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git.html"&gt;man pages for Git&lt;/a&gt; follow a simple pattern (as I guess many online man page collections must). Just change the end of the URL from &lt;code&gt;git-cvsimport.html&lt;/code&gt; to &lt;code&gt;git-push.html&lt;/code&gt; or &lt;code&gt;git-pull.html&lt;/code&gt; to look up documentation.&lt;/p&gt;

&lt;p&gt;That I&amp;#8217;ve been able to play around with Git quite successfully and easily just makes my frustration with some Python tools (like &lt;em&gt;easy_install&lt;/em&gt; and &lt;em&gt;zc.buildout&lt;/em&gt;, particularly its recipes) even more &amp;#8230;. frustrating.&lt;/p&gt;

&lt;p&gt;And, I&amp;#8217;ve totally fallen in love with Git. Yes, I know there are alternatives written in Python that are quite comparable. But Git&amp;#8217;s actually been easier to install and figure out (particularly the CVS interaction that I must currently suffer). And people who know me know that I&amp;#8217;m no &amp;#8220;Kernel monkey&amp;#8221;. I&amp;#8217;m really impressed with Git&amp;#8217;s implementation and general behavior. Very impressed with the implementation.&lt;/p&gt;

&lt;p&gt;By the way: if you&amp;#8217;re having to work two ways with a CVS repository, &lt;a href="http://tsunanet.blogspot.com/2007/07/git-cvs-in-5min.html"&gt;this post has been absolutely invaluable&lt;/a&gt;. &lt;a href="http://wincent.com/knowledge-base/Category:Git"&gt;This collection of Git articles&lt;/a&gt; has been invaluable in getting some good defaults established, and some tips for building on Mac OS X (with a nice tip to download and untar the &lt;a href="http://www.kernel.org/pub/software/scm/git/git-manpages-1.5.3.5.tar.bz2"&gt;man pages&lt;/a&gt; directly instead of trying to build them with the &lt;em&gt;asciidoc&lt;/em&gt; tool and its terrible dependency on troublesome XML libraries. Goddamn, how I hate XML).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-8757505951513943648?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8757505951513943648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8757505951513943648'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/11/falling-for-git.html' title='Falling for Git'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-9073426687678533609</id><published>2007-11-01T01:52:00.000-06:00</published><updated>2007-11-01T02:51:32.829-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='cocoa'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='applescript'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>AppleScripting Across the Universe</title><content type='html'>&lt;p&gt;After a long day at work, I wrote a long message in Basecamp about what I had accomplished, how to access it, etc. But I forgot to submit the message! Crud. I wanted to send it out before morning and didn&amp;#8217;t want to go into the office. I couldn&amp;#8217;t get any screen sharing connection to go between the machines. I just had a handful of SSH leaps.&lt;/p&gt;

&lt;p&gt;AppleScript to the rescue!&lt;/p&gt;

&lt;p&gt;This is probably the most AppleScript that I&amp;#8217;ve ever written. Fortunately, Safari supports the command &lt;code&gt;do JavaScript ... in tab&lt;/code&gt;. After some floundering around with a similar setup on my local machine, I finally figured out AppleScript&amp;#8217;s interesting reference notation and was able to ferret out the window and tab containing the unsent message, add some text to the message&amp;#8217;s textarea element, submit the form, and return the extended value.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tell application "Safari"
    set message_tab to current tab of window named "Web site &amp;gt; New message"

    set extended to ".... Fun fact - i wrote this before i left the office and forgot to submit it. as a result, i now know how to submit forms like this via AppleScript."
    set post_body_value to "$('post_body').value"
    set extend_value to post_body_value &amp;amp; " += '" &amp;amp; extended &amp;amp; "';"

    do JavaScript extend_value in message_tab
    set body_value to do JavaScript post_body_value in message_tab

    do JavaScript "document.forms[0].submit();" in message_tab

    return body_value
end tell
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I pasted the above code into VIM and ran it with the command line &lt;code&gt;osascript&lt;/code&gt; command. Worked like a champ.&lt;/p&gt;

&lt;p&gt;And because sleep is for the weak, I decided to track down how to do the equivalent in Python. Mac OS X 10.5 provides a &amp;#8220;Scripting Bridge&amp;#8221; for Python and Ruby (and potentially others), which causes many frameworks and other objects to be dynamically exposed. Without the need (for better or worse) of yet-another-virtual-machine. Anyways, I cobbled the following together:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from Foundation import *
from ScriptingBridge import *
safari = SBApplication.applicationWithBundleIdentifier_('com.apple.Safari')

def find_window_named(name):
    for win in safari.windows():
        if win.name() == name:
            return win

window = find_window_named("Web site &amp;gt; New message")
message_tab = window.currentTab()

print safari.doJavaScript_in_("$('post_body').value", message_tab)
safari.doJavaScript_in_("document.forms[0].submit()", message_tab)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There may be a better way to do the &lt;code&gt;find_window_named&lt;/code&gt; method, but I didn&amp;#8217;t have the time to track it down. As it was, I was able to do do the above by playing around with everybody&amp;#8217;s favorite Python tool, &lt;code&gt;dir()&lt;/code&gt;, which verified my suspicion that many of the commands exposed to AppleScript were also available via the Scripting Bridge. This is evidenced by the &lt;code&gt;currentTab()&lt;/code&gt; method of a Safari window, analogous to the &lt;code&gt;current tab of window ...&lt;/code&gt; AppleScript. And I imagine most of these are just Objective C methods. And since AppleScript editor&amp;#8217;s Dictionary browser told me about the &lt;code&gt;do Javascript [v] in tab [t]&lt;/code&gt; command, it stood to reason that it would exist on the Safari object. It was there when I did &lt;code&gt;pprint(dir(safari))&lt;/code&gt;, and I knew that I&amp;#8217;d need to pass in a Tab object.&lt;/p&gt;

&lt;p&gt;In any case, it&amp;#8217;s awesome that Apple has embraced Python and Ruby and has tied them in to the Cocoa runtime. Historical note: the first Python - Objective C bindings that I know of where commissioned by a NeXT Developer who wanted to use Python and Bobo (zope.publisher) to do web work with NeXT&amp;#8217;s Enterprise Objects Framework, without the weight and cost of WebObjects. I think that means that Python was bridged into the Objective C runtime and NeXTStep frameworks before Jython ever got going. I believe that work was done by the developer who later released &lt;a href="http://www.stepwise.com/PR/Nov/TipTop_971124.html"&gt;Objective Everything&lt;/a&gt; which bridged into Perl and TCL as well as Python.&lt;/p&gt;

&lt;p&gt;Of course, traditional MacPython from the classic Mac OS was also natively tied in to the AppleScript of that era; AppleScript has always supported other dialects (FrontierScript was a common one).&lt;/p&gt;

&lt;p&gt;But it&amp;#8217;s nice now to see support coming out of both Apple and Microsoft (and Sun too, I guess) for these languages. The above scripting of Safari was surprisingly easy. As was an earlier experiment to fish around my calendar store for incomplete To-Do items. Quite nice.&lt;/p&gt;

&lt;p&gt;But what&amp;#8217;s especially nice is that I was able to SSH into my office Mac and tell Safari to submit that form that I had neglected earlier.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-9073426687678533609?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9073426687678533609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9073426687678533609'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/11/applescripting-across-universe.html' title='AppleScripting Across the Universe'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4868037104070497659</id><published>2007-10-29T22:29:00.000-06:00</published><updated>2007-10-30T01:58:02.222-06:00</updated><title type='text'>Java Crybabies</title><content type='html'>&lt;p&gt;So Mac OS X 10.5 (Leopard) doesn&amp;#8217;t ship with Java 6.  And now &lt;a href="http://www.javalobby.org/java/forums/t102936.html"&gt;Java people are all sad&lt;/a&gt; and mad and yelling at Apple for dropping the ball on this.&lt;/p&gt;

&lt;p&gt;Why should Apple go out of their way to provide Java 6? After the aborted Java - Objective C bridge experiments, what else is there to do? &amp;#8220;Native&amp;#8221; Java applications have still never come close to feeling like a native or near native piece of the operating system. Why should Apple keep throwing engineering efforts at this system?&lt;/p&gt;

&lt;p&gt;And whatever happened to OpenStep for Solaris by the way?&lt;/p&gt;

&lt;p&gt;Honestly, Apple has a dynamic object runtime environment heavily tied to a C based language already. It&amp;#8217;s done much of what Java and the .Net framework are now doing, and has been doing that since the latter half of the eighties. It&amp;#8217;s interesting to look back to the mid nineties and at the criticisms of NeXTStep/OpenStep. &amp;#8220;Why are you using this Objective C thing? Why not C++?&amp;#8221;&lt;/p&gt;

&lt;p&gt;Because what NeXT understood that others didn&amp;#8217;t was that the runtime is what&amp;#8217;s important. NeXTStep came closest to providing a Smalltalk-style runtime of dynamic collaborating objects without being the alien and self contained environment that Smalltalk can often be. Initially tied in to a Unix operating system, it later went multi-platform (at least to an extent - I think FoundationKit, Enterprise Objects Framework, WebObjects, and PDO (Portable Distributed Objects) ran on HP-UX and Solaris, while all of those plus AppKit ran on NT, along with D&amp;#8217;OLE (distributing COM/OLE while Microsoft was still struggling to provide DCOM)).&lt;/p&gt;

&lt;p&gt;In those same mid nineties, there were other attempts to provide some of the power of the NeXTStep / OpenStep platform. IBM perhaps came closes with their CORBA (Corba 1.x) based SOM, which was also to be at the heart of OpenDoc. SOM was the heart of the fascinating OS/2 2.0 and Warp. It also was used in the classic Mac OS. Of course, it was there in OpenDoc&amp;#8217;s brief life. But beyond that, SOM was used to provide contextual menu plug-ins, interestingly enough. But it was still fairly heavy, as CORBA could be. Too much wringing and wrangling to help non-dynamic languages function in a semi-dynamic world.&lt;/p&gt;

&lt;p&gt;And then there was Microsoft&amp;#8217;s Cairo. Never shipped. Some of its technologies found their way into NT&amp;#8230; But the big features? One of the big features was to be an &amp;#8220;object oriented file system&amp;#8221;. This resurfaced as WinFS for Vista. Twelve-plus years later, and it&amp;#8217;s still not done.&lt;/p&gt;

&lt;p&gt;And of course, there was Taligent. Initially, Taligent was going to be an all-new Operating System, aggressively object oriented, etc. Apple and IBM together, to make a NeXTStep for the rest of us, perhaps? Except instead of a dynamic language, they decided to go for C++. But they apparently had to pump in a lot of work to overhaul the C++ runtime and try to provide some of the dynamic loading options (of Smalltalk, NeXTStep/Objective C, etc). It was a lot of time wasted, I&amp;#8217;m sure. And they eventually had to pull back from the all-new operating system plan. That was probably wise, considering the environment of the time. Apple never was able to complete Copland and Gershwin, and Microsoft never got Cairo finished; BeOS never found a substantial market; and even early NeXT-era Apple wasn&amp;#8217;t able to sell the idea of a NeXTStep based Mac OS until they provided the Carbon migration path for the classic Mac APIs.&lt;/p&gt;

&lt;p&gt;So Taligent shifted to providing, like OpenStep, differing layers that would provide these object features on top of differing host operating systems. Still never happened. Which is a bit of a bummer - they had some paradigms that would have been interesting to see.&lt;/p&gt;

&lt;p&gt;In 1994, Jon Udell wrote a short article titled &amp;#8220;&lt;a href="http://web.archive.org/web/20020609014601/http://www.d.kth.se/~d95-aeh/taligenc.html"&gt;A Taligent Update&lt;/a&gt;,&amp;#8221; subtitled &lt;em&gt;Will systemwide object frameworks reinvent programming?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, while Taligent never delivered; and OpenStep faded into WebObjects (providing the OpenStep developer tools on NT, NeXTStep Mach, and Mac OS X Server 1.x, aka Rhapsody); this seems to have actually, finally, come to pass. Cocoa is a &lt;em&gt;killer&lt;/em&gt; framework for Mac OS X, with many fans. There are bridges to many other languages (Ruby, Perl, Python, among others). It&amp;#8217;s not quite the pervasive system-wide framework that it was in the NeXTStep days, but in Mac OS X Leopard Cocoa looks as though it&amp;#8217;s reclaiming its position as king of the hill. (For a while, there were many Carbon APIs that were a bitch to use from Cocoa; or at least those used to the comparative ease of Cocoa programming).&lt;/p&gt;

&lt;p&gt;And Microsoft&amp;#8217;s .NET framework has delivered similar in the Windows market. Of course, it doesn&amp;#8217;t have anything like Interface Builder; but it still seems to have a much better share-and-reuse model than anything that&amp;#8217;s come before it in Windows programming. And it&amp;#8217;s built on: dynamic object systems. Unlike Java (which I&amp;#8217;ll get to in a minute), the .NET framework and core languages (C#) appear to be taking cues from Objective C and purely dynamic languages/systems like Smalltalk: &lt;a href="http://community.bartdesmet.net/blogs/bart/archive/2006/12/06/C_2300_-3.0-Feature-Focus-_2D00_-Part-4-_2D00_-Extension-Methods.aspx"&gt;dynamic class extension&lt;/a&gt;, for example, is a new feature in C# 3.0. It&amp;#8217;s also been possible in &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_4_section_7.html#//apple_ref/doc/uid/TP30001163-CH7-TPXREF139"&gt;Objective C&lt;/a&gt;. This can be a dangerous feature; but also quite useful and usable. But it&amp;#8217;s nice to see this in languages and systems that try to combine C, which has the benefits of familiarity, with the power of dynamic object-filled worlds.&lt;/p&gt;

&lt;p&gt;And it&amp;#8217;s much better than the heavy and strained world of COM and CORBA.&lt;/p&gt;

&lt;p&gt;So anyways - NeXT, and now Apple, has been ahead of this game for quite some time. Granted, if it weren&amp;#8217;t for Apple, NeXT would be another blip like Taligent. Except with a shipping product. But still - they survived. And their system wide dynamic object framework idea seems to have been vindicated.&lt;/p&gt;

&lt;p&gt;So what of Java?&lt;/p&gt;

&lt;p&gt;Java is the bastard child here. I&amp;#8217;ve never been comfortable with it. It&amp;#8217;s not cross platform: Java IS the platform. And it&amp;#8217;s awkward. Even in its best desktop guise - Eclipse - it&amp;#8217;s still a foreign environment on Mac OS X. Even Firefox is starting to feel more natural (and Firefox 3 looks to be trying even harder in this area). Why would we want it? Sun has never seemed to care that much about Java on Macs, except to try to showcase their &amp;#8220;see, multi-platform!&amp;#8221; message. But Windows has always gotten the lions share of the attention, even though Microsoft long ago stopped caring about Java.&lt;/p&gt;

&lt;p&gt;On a side note, we&amp;#8217;re seeing the same thing happen now with Flash. Ugh. It&amp;#8217;s a memory hog on Mac OS X. Makes poor use of 
resources. If Adobe and Sun don&amp;#8217;t seem to care enough about providing a truly killer Mac experience, is it any wonder that they&amp;#8217;re being kicked off of the island? Apple&amp;#8217;s got the dynamic object system language and frameworks (Objective C, Cocoa); and it&amp;#8217;s got an increasingly impressive web environment (WebKit, with Canvas support); it has bridges into and out of AppleScript, Python, Ruby, and Perl, all included with Leopard - bridges too!&lt;/p&gt;

&lt;p&gt;One just has to look at how huge the &amp;#8220;Java in a Nutshell&amp;#8221; books have become to know that Java is no small undertaking. And again, I think that Apple probably has stopped caring. They&amp;#8217;ve tried to be good Java citizens - from the Java - Objective C bridge to the all-Java implementation of WebObjects; they&amp;#8217;ve tried to be make the Cocoa framework appealing to Java developers and probably tried to make Java appealing to Cocoa developers. But it must not have ever happened. It&amp;#8217;s all deprecated now.&lt;/p&gt;

&lt;p&gt;And I don&amp;#8217;t know what&amp;#8217;s going on, really. I just see Apple as having other priorities. It&amp;#8217;s not like they&amp;#8217;re (purely) a not-invented-here company. They have, after all, built in &lt;a href="http://www.sun.com/bigadmin/content/dtrace/"&gt;Sun&amp;#8217;s DTrace technology&lt;/a&gt;. And Apple builds on and gives back to Open Source, with projects like &lt;a href="http://launchd.macosforge.org/"&gt;launchd&lt;/a&gt;, the new &lt;a href="http://trac.calendarserver.org/projects/calendarserver"&gt;calendar server&lt;/a&gt;, &lt;a href="http://trac.macosforge.org/projects/bridgesupport/"&gt;bridge support&lt;/a&gt;, &lt;a href="http://www.webkit.org/"&gt;WebKit&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;But Java&amp;#8230;? Apple has no real stake in it any more. The last Java application I ran was Eclipse, months ago, just trying to see what life in a fancy IDE would be like. It was disappointing. Desktop Java just doesn&amp;#8217;t figure into a Mac user&amp;#8217;s life all that much. I&amp;#8217;d rather see Apple focus on improving their primary object language (which inspired Java), focus on improving their APIs and offering more features for programmers (all done handily in Mac OS X 10.5 - from a programmer&amp;#8217;s standpoint, it&amp;#8217;s extremely impressive) and providing a smooth, fast, and natural platform experience (again done handily in Mac OS X 10.5 - see the still-unequaled Interface Builder 3.0; see CoreAnimation; see a &lt;a href="http://mattgemmell.com/2007/10/28/get-rid-of-your-code-with-leopard"&gt;sea of new UI object offerings from Apple&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Why would they spend their time fighting uphill to support a platform whose chief aim is to be an anti-platform? At best, desktop Java on the Mac could mean &amp;#8220;runs a windows-like-application-almost-as-good-as-windows, maybe.&amp;#8221; Well, we now have Boot Camp and Parallels/VMWare for that. Apple wants to provide a killer alternative platform, and they&amp;#8217;ve learned that the best way to do that is to be in control. When Mac browsers were suffering - IE on Mac OS X was slow and strange (compared to near excellent behavior in OS 9), Camino and Firefox were big and slow and non-native (Camino did a decent job, but it had different widget implementations for browser skin and in-page rendering), OmniWeb looked beautiful but its support for new HTML and Javascript was far behind, etc - Apple took control of their destiny by building Safari. And they built in on a toolkit that would let them plug in the right widgets and behavior for a native experience. Hence, all Safari users have long enjoyed having spell checking support in their TextAreas. We get that from Cocoa. As of Mac OS X 10.5, we can turn on grammar checking as well. And now, WebKit is &lt;em&gt;leading&lt;/em&gt; much of the HTML 5 charge, recently announcing preliminary support for &lt;a href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/"&gt;client side database storage&lt;/a&gt;, and were among the first (if not THE first) to put forward tags like &lt;strong&gt;canvas&lt;/strong&gt; which may make SVG usable and make ultimately take care of many uses of Flash (remember when Flash was purely an animation tool?). Apple has all of this in their control. They don&amp;#8217;t have to put up with lackluster players / viewers from Adobe.&lt;/p&gt;

&lt;p&gt;And I think it&amp;#8217;s become pretty clear that Apple&amp;#8217;s preferred solution at this time for rich cross-platform(ish) UI and Code is - the web. HTML, CSS, Javascript. It powers Dashboard; it&amp;#8217;s been a big selling point of the iPhone (although it is admittedly laughable that Apple said &amp;#8220;Web 2.0 apps are your iPhone API!&amp;#8221;, but it&amp;#8217;s still impressive; people have built some very impressive apps with that very system).&lt;/p&gt;

&lt;p&gt;Why does AJAX / DHTML succeed where Applets have failed? And even Flash does poorly? It&amp;#8217;s not just because it&amp;#8217;s &amp;#8220;everywhere&amp;#8221;, without a need to install and deal with a JRE. It&amp;#8217;s because AJAX is part of the web page. It&amp;#8217;s not a self contained rectangle that can do really cool things - within the realm of that rectangle. It&amp;#8217;s because AJAX leverages the browser&amp;#8217;s toolkit, so that a text field in IE behaves like a text field in IE; and a text field on a Mac behaves like a text field on a Mac. Java performance has never been that great on the Mac. Which must mean that no one cared enough to really try to make it shine, or that the technology is really heavy and inferior. I remember groaning every time I used to check the snow report page at one of the ski resorts because of the extra amount of time taken to load up Java and all that accompanies it just to render some scrolling-headlines; scrolling headlines whose text didn&amp;#8217;t match (or even anti-alias with) the surrounding text. It&amp;#8217;s absolutely useless and pointless. Granted - I have seen some impressive Java applets in the science arenas, and IBM had some cool chess ones in their old Deep Blue v Kasparov (?) challenge. But again, those have been few and far between.&lt;/p&gt;

&lt;p&gt;The two desktop Java apps that I&amp;#8217;ve used heavily at points in the past, besides my experiments with Eclipse, were with a UML tool, and then LimeWire. Both of these used on Macs. The UML tool was tolerable, but barely. Limewire was terribly slow - click and wait instead of click and point. Desktop Java is dead to me. I don&amp;#8217;t know why you&amp;#8217;d want to write in it. Cocoa is just an all out balls out better environment, especially for UI programming as (again) Interface Builder remains peerless. And .NET, especially with the Mono implementation, is a far more interesting playground that seems keen on taking in new dynamic, declarative, and functional features, (LINQ, F#, etc), while Java just feels like a big stack of alphabet soup and static typing and not much else. (Although I do understand that Java 6 has started to break this mold).&lt;/p&gt;

&lt;p&gt;And as far as languages go: please. Python, Perl, and Ruby alone offer better cross platform capabilities than Java: especially on the server side where Java is supposed to shine. I didn&amp;#8217;t have to wait for Apple&amp;#8217;s blessing to use Python 2.5 on my desktop Mac. I didn&amp;#8217;t have to wait for Apple&amp;#8217;s blessing to draw native widgets with it either. I didn&amp;#8217;t have to wait for Apple&amp;#8217;s blessing to use Python 1.x to control other applications across the scripting bridges of Mac OS 7, 8, and 9.&lt;/p&gt;

&lt;p&gt;Now that Java is Open Source (it is, isn&amp;#8217;t it?), maybe the Java community can look into what it would take to provide a good Java experience on Mac OS X. I think that is its only hope. It has to become leaner. The dynamic &amp;#8220;scripting&amp;#8221; language crowd have all been able to find ways to take advantage of different platforms. Why is it on Apple&amp;#8217;s head to provide Mac Java? Going back to what I asked earlier - is Sun going to try to get OpenStep going again on Solaris? Is Microsoft going to provide Java 6 for Windows? Is Apple going to provide .NET 3.5 for the Mac?&lt;/p&gt;

&lt;p&gt;A response I&amp;#8217;ve seen in the Java community is that Apple is arrogant for not shipping Java 6 with Leopard, and for withdrawing any development downloads and many topics related to Java on the Mac. I think that it&amp;#8217;s arrogant of the Java community to think that they matter enough for Apple to continue to sink engineering resources into the platform. They&amp;#8217;ve sunk a lot in over the years, and there&amp;#8217;s never been a huge payoff. I see no reason for them to continue. They have far better alternatives.&lt;/p&gt;

&lt;p&gt;IBM or Sun or anyone else out in the Java / Open Source community should take it upon themselves to provide a good platform if they really care. They&amp;#8217;re obviously doing it for Linux and Windows.&lt;/p&gt;

&lt;p&gt;Sorry, this is a long and rambling post and now it&amp;#8217;s quite late at night when I swore I would be going to bed early. But seriously - Java has not mattered to me as a developer or Mac user for years. It&amp;#8217;s a dead weight for Apple. Support for Mac OS &amp;#8220;Classic&amp;#8221; got the boot in Leopard, and even Carbon is looking like its days are numbered. If those two can be cut off, what the hell chance would Java have?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-4868037104070497659?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4868037104070497659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4868037104070497659'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/10/java-crybabies.html' title='Java Crybabies'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-8783158614436935637</id><published>2007-10-12T14:50:00.000-06:00</published><updated>2007-10-12T14:51:25.707-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='mochikit'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='coding style'/><category scheme='http://www.blogger.com/atom/ns#' term='sqlalchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='toolkits'/><title type='text'>Catching Up</title><content type='html'>&lt;p&gt;These periods between posts keep getting longer, don&amp;#8217;t they?&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve got nothing earth-shattering to talk about. Work&amp;#8217;s been very busy, and we continue to be served well by &lt;a href="http://wiki.zope.org/zope3/Zope3Wiki"&gt;Zope 3&lt;/a&gt;. I&amp;#8217;m still royally confused by things like &lt;a href="http://peak.telecommunity.com/DevCenter/setuptools"&gt;setuptools and eggs&lt;/a&gt;, mostly in regards to how they work in a Zope 3 world when you&amp;#8217;ve already got long entrenched ways of doing software. I could not get a good answer from anyone I asked (in fact, I often got wildly competing opinions). So I&amp;#8217;m sticking with our internal make-rake-like-ish toolkit which is primarily helpful for automating checkouts from internal and external repositories. I did have some success with &lt;a href="http://cheeseshop.python.org/pypi/zc.buildout"&gt;zc.buildout&lt;/a&gt;, but I don&amp;#8217;t yet foresee a time when I can use it to deploy whole sites/applications. I can barely see a time when I can use it on anything but small projects that are relatively stand-alone. There&amp;#8217;s just a big gap between The Way Things Have Been Done and The Way That It Seems That Maybe Things Should Be Done In The Future.&lt;/p&gt;

&lt;p&gt;Of course, neither setuptools nor zc.buildout seem to have &amp;#8220;proper&amp;#8221; releases. &lt;em&gt;zc.buildout&lt;/em&gt; is in an endless 1.0 beta (beta-30 at this point), and &lt;em&gt;setuptools&lt;/em&gt; is at 0.6c7. Does that mean that it&amp;#8217;s not even at release 0.6 quality yet? None of this instills confidence in this hurried developer.&lt;/p&gt;

&lt;p&gt;The big problem is the legacy code, which is in CVS. Some of it is being extracted out into individual packages that have the proper &amp;#8216;setup.py&amp;#8217;, &amp;#8216;buildout.cfg&amp;#8217;, etc. Finally. But I have no idea how to apply it to the bigger picture, and I&amp;#8217;ve found very little written words that target our situation.&lt;/p&gt;

&lt;p&gt;The biggest downside of being so busy with customer related work is that it&amp;#8217;s very difficult to keep up with discussions, conversations, plans, etc. And I&amp;#8217;m sure that my frustrations with lack of documentation, seemingly unfinished releases, and so on, are really the fruit of other hurried developers. I admire them for at least releasing something. It&amp;#8217;s more than I&amp;#8217;ve done in a long time. It&amp;#8217;s more than I see myself being able to do for quite some time.&lt;/p&gt;

&lt;p&gt;Anyways, the revolving door of Javascript toolkits keeps turning. I&amp;#8217;m now deeply enamored with &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;. &amp;#8220;Write less, do more&amp;#8221;. I like it. I like that it doesn&amp;#8217;t trample all over Javascript, and thus plays well with others (especially others that play well with others, like &lt;a href="http://mochikit.com/"&gt;MochiKit&lt;/a&gt;). MochiKit is just so big&amp;#8230; I think I might make a stab at writing, at least for internal use, a lightweight version that brings many of its best concepts out without overlapping jQuery&amp;#8217;s functionality. MochiKit brings many wonderful Python-ic functions and tools to the Javascript table that make general development much easier.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m also deeply enamored with &lt;em&gt;zc.resourcelibrary&lt;/em&gt; which is a Zope 3 add-on that makes it much easier to manage javascript and CSS resources and their relations to each other. Among other things, it helps save resources when they&amp;#8217;re not needed. For example::&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if len(rendered_boxes) &amp;lt;= 3:
    return self.just_render_the_damn_boxes(rendered_boxes)
else:
    zc.resourcelibrary.need('fancy.scrolling.library')
    return self.render_the_advanced_widget(rendered_boxes)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#8217;ve also adjusted my coding style, returning to the &lt;code&gt;underscore_separated_words&lt;/code&gt; style instead of the &lt;code&gt;camelCasedWords&lt;/code&gt; style, at least for functions, attributes, and methods. This is closer in style to &lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt; (the main style guide for Python code). The Zope style guide differs on this point, using camelCased instead. And PEP 8 does say that it&amp;#8217;s OK, if not downright preferred, to stay true to the style around you.&lt;/p&gt;

&lt;p&gt;But one thing I learned from looking through Rails code was that the underscore_style was easier to read, since the underscore acts like a space. And I&amp;#8217;ve become a big fan of writing code that communicates intent; that reads like a story (somewhat). &lt;em&gt;Extract Method&lt;/em&gt; is your friend. I&amp;#8217;ve grown very distrustful of excessive nesting, or of having very long bodies inside of a &amp;#8216;for&amp;#8217; or &amp;#8216;if&amp;#8217; block.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s about it. Hell of an update, huh? Well, work&amp;#8217;s really started to become &lt;em&gt;work&lt;/em&gt;, and is quite enjoyable. I&amp;#8217;ve got a good flow going and don&amp;#8217;t feel I have as much need (nor place) to be an advocate or crank. As I&amp;#8217;ve mentioned before, we&amp;#8217;ve gotten incredible levels of code re-use by building our internal libraries and applications on top of Zope 3, and we&amp;#8217;ve been able to grow them so much that they&amp;#8217;re really the first level of framework. It was such a struggle to do this in Zope 2, but in Zope 3 it does fall (fairly) neatly into place. Nothing else in the Python web-framework-whatsit world comes close.&lt;/p&gt;

&lt;p&gt;The only toolkit that&amp;#8217;s even better? &lt;a href="http://sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. It&amp;#8217;s pretty much the only way I&amp;#8217;ll interact with RDBMS systems in Python from this point out. And I don&amp;#8217;t mean I&amp;#8217;ll be writing every RDBMS interaction as an object-relational mapping. SQLAlchemy is great because it provides a good connection / pooling infrastructure; a good Pythonic query building infrastructure; and then a good ORM infrastructure that is capable of complex queries and mappings (as well as some pretty stone-simple ones).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-8783158614436935637?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8783158614436935637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8783158614436935637'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/10/catching-up.html' title='Catching Up'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1428092880014750406</id><published>2007-08-16T07:18:00.000-06:00</published><updated>2007-08-16T08:23:15.289-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iwork'/><category scheme='http://www.blogger.com/atom/ns#' term='spreadsheets'/><category scheme='http://www.blogger.com/atom/ns#' term='numbers'/><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Numbers</title><content type='html'>&lt;p&gt;I don&amp;#8217;t know when I last used a spreadsheet for its actual spreadsheet capabilities, on a sheet I designed myself. I think it may go back to AppleWorks (on the Apple II)! Sure, I&amp;#8217;ve used sheets like time cards and travel requests that others had made where I just had to fill in the holes. And I&amp;#8217;ve received more than my fair share of spreadsheets used like an outliner / lightweight database / structured note list. But I don&amp;#8217;t remember how long it&amp;#8217;s been since I used a spreadsheet to figure out a budget, to track expenses, or any other dumb mundane thing like that. Until last night.&lt;/p&gt;

&lt;p&gt;I was getting ready to pay my mid-month bills, and I was trying to figure out how much I could pay towards one of my credit cards and still have enough cash to cover the expenses remaining in the month. I also realized that I&amp;#8217;ve been spending quite a bit at the iTunes Music Store and hadn&amp;#8217;t been tracking any of it. I decided that this would be an excellent time to try out Apple&amp;#8217;s new spreadsheet application, &lt;a href="http://www.apple.com/iwork/numbers/"&gt;Numbers&lt;/a&gt;. I found a downloadable time trial of Apple&amp;#8217;s &lt;a href="http://www.apple.com/iwork/"&gt;iWork &amp;#8216;08&lt;/a&gt; suite, and immediately got to work.&lt;/p&gt;

&lt;p&gt;Numbers is pretty damn cool. I don&amp;#8217;t know if there are other spreadsheets that behave like this, but in modern times, it seems so obvious: instead of having the big set of cells in one large table, you work in small floating spreadsheets / tables. This is a big deal for so many reasons, with the most obvious being layout. Another great reason is that each table/spreadsheet can be more focused on its job. Already, Numbers felt a lot more intuitive than anything I had used in a long time.&lt;/p&gt;

&lt;p&gt;When doing my simple rest-of-the-month budget, my main question was &amp;#8220;how much can I pay on this card and still have enough cash on hand for the rest of the month?&amp;#8221; Numbers made it easy with its slider option. For just this one cell, I was able to quickly configure it to give me a slider with a range of -700 to -500. When I got the rest of the budget entered, I could then play with the slider and watch its impact on the total-leftover cell. In previous months, I&amp;#8217;ve generally done this calculation in my head, or compared where I stood the prior month after paying this particular bill. It was much nicer to whip up a simple spreadsheet where I could make this one particular number interactive and see the results immediately.&lt;/p&gt;

&lt;p&gt;So I was able to get a couple of simple but nice looking spreadsheets together quickly that gave me actual data. I could easily play with this data, or just be embarrassed by it (I have spent quite a bit on the iTunes Music Store).&lt;/p&gt;

&lt;p&gt;There are still a lot of old-style spreadsheet rules in play, at least in formulas and the like. That&amp;#8217;s made a bit easier by being able to use header names (ie, &lt;code&gt;=SUM(Total)&lt;/code&gt; or &lt;code&gt;=MINA(Date Purchased)&lt;/code&gt;). I think it was Lotus&amp;#8217; Improv, which first appeared on NeXTStep, that worked this way. In fact, I think with Improv, it was the only way you could work: there were no A/B/C/D columns or rows. This was part of a cool feature of Improv wherein you could drag and drop header representations and regroup the data visually without impact on the calculations. I still think that was one of the most forward-thinking spreadsheet applications. But, it&amp;#8217;s gone. I believe there&amp;#8217;s some open source variation on the idea, possibly written just for GNUStep&amp;#8230;?&lt;/p&gt;

&lt;p&gt;Still, &lt;a href="http://www.apple.com/iwork/numbers/"&gt;Numbers&lt;/a&gt; is pretty decent. I love the free-floating tables. It does make it much easier to compose complex spreadsheet pages out of multiple tables and data types. It&amp;#8217;s pretty easy to refer to other tables as well. And it&amp;#8217;s nice to have non-tabular data (text, graphics, etc) floating free from those numbers, making it easier to adjust layouts without impacting cells.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m impressed enough that I&amp;#8217;m quite likely to buy &lt;a href="http://www.apple.com/iwork/"&gt;iWork &amp;#8216;08&lt;/a&gt;, just for Numbers alone. I have a small need for &lt;a href="http://www.apple.com/iwork/pages/"&gt;Pages&lt;/a&gt; and almost no need for Keynote, but I do find myself needing to get on top of my finances and similar data. Numbers is the first tool I&amp;#8217;ve encountered that I think will let me handle my odd needs without requiring a degree or summer course in spreadsheets.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1428092880014750406?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1428092880014750406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1428092880014750406'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/08/numbers.html' title='Numbers'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-3007085774174010572</id><published>2007-07-18T20:26:00.000-06:00</published><updated>2007-07-18T20:31:13.109-06:00</updated><title type='text'>Yahoo TV Is Now Useless</title><content type='html'>&lt;p&gt;So, I used to use &amp;#8220;My Excite&amp;#8221; as my little personal portal. It had good TV listings, which is always important. But many years ago, as Excite was was burying its content under more and more ads, I switched to &amp;#8220;My Yahoo!&amp;#8221;. Which was even better. Great TV listings. So even now, when I don&amp;#8217;t have cable or satellite, I found it valuable.&lt;/p&gt;

&lt;p&gt;But then they changed. They upgraded to super fancy TV listings full of AJAX-y action.&lt;/p&gt;

&lt;p&gt;But do you know what sucks?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;THEY CAN&amp;#8217;T GET TIMEZONES RIGHT!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s been quite a few months now, &lt;strong&gt;and they still can&amp;#8217;t get my timezone right&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For seven or eight years, I had no problem with localized listings. Although for a few of those years I was in the blessed Eastern Time Zone. But even when I moved out west - no problem.&lt;/p&gt;

&lt;p&gt;But now, apparently Yahoo! has invested all of their resources into flashy features but they can&amp;#8217;t tell me &lt;strong&gt;when a tv show is on according to the time in my area&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Absolutely &lt;strong&gt;useless&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a while, I&amp;#8217;ve gotten by with using the TV listings on the &amp;#8220;My Yahoo!&amp;#8221; page. It didn&amp;#8217;t have all of the fancy features, &lt;strong&gt;so somehow it managed to get the times right&lt;/strong&gt;. But as of today, I&amp;#8217;m told that I have to use the new fancy-ass &amp;#8220;My Yahoo! Beta&amp;#8221;.&lt;/p&gt;

&lt;p&gt;First thing that happens when I visit the My Yahoo! beta?&lt;/p&gt;

&lt;p&gt;&amp;#8220;&lt;strong&gt;We don&amp;#8217;t support Safari&lt;/strong&gt;&amp;#8230;.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Goddammit&lt;/strong&gt;. Many of their other upgraded YUI based sites &lt;strong&gt;work fine in Safari&lt;/strong&gt;. I can understand them saying this months ago, which was the last time I looked at the new beta. But to still be having an issue? While trying to be a shiny partner of the lovely iPhone? What&amp;#8217;s up?&lt;/p&gt;

&lt;p&gt;Anyways, I clicked the &amp;#8220;live on the edge&amp;#8221; button to see the new page. There were the TV listings. &lt;strong&gt;In the wrong time zone!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I submitted an email months ago about this and got the &amp;#8220;yeah, we know, we&amp;#8217;re working on this&amp;#8221; response.&lt;/p&gt;

&lt;p&gt;I know that time zones are a bitch to work with, but come on: this shit has worked for years. And now it&amp;#8217;s been how long since the launch of the fancy new Yahoo TV section? Six months? Seven? Surely someone could have worked this out by now.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m so disappointed. Yahoo! was always one of the most reliable web sites. And I appreciate what they&amp;#8217;ve given to the developer community with YUI! and other tools. But this little TV listing issue just takes the cake. It makes it absolutely useless, and now &amp;#8220;My Yahoo!&amp;#8221;, which has been my &amp;#8216;home page&amp;#8217; for years, is all but useless as this became such a valued resource as their other sources stopped working.&lt;/p&gt;

&lt;p&gt;Very frustrating.&lt;/p&gt;

&lt;p&gt;And I&amp;#8217;m still looking for a good TV listing site. But all I&amp;#8217;ve come up with, so far, is pretty much bullshit. Wrong channels, inability to properly remember channels, too many ads, hard to access listings, slow display&amp;#8230;. Augh.&lt;/p&gt;

&lt;p&gt;Pissed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-3007085774174010572?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/3007085774174010572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/3007085774174010572'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/07/yahoo-tv-is-now-useless.html' title='Yahoo TV Is Now Useless'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1230647787449358105</id><published>2007-05-08T14:29:00.000-06:00</published><updated>2007-05-08T14:43:17.051-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python3000'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='interfaces'/><title type='text'>Traits / Roles as Alternative to Abstract Base Classes</title><content type='html'>&lt;p&gt;While digging through the Python-3000 development list archives, trying to figure out the state of thought circling PEP&amp;#8217;s &lt;a href="http://www.python.org/dev/peps/pep-3119/"&gt;3119&lt;/a&gt; and &lt;a href="http://www.python.org/dev/peps/pep-3124/"&gt;3124&lt;/a&gt;, I came across this gem:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://mail.python.org/pipermail/python-3000/2007-April/007026.html"&gt;&amp;#8220;Traits/roles instead of ABCs&amp;#8221;&lt;/a&gt;,  by Collin Winter.&lt;/p&gt;

&lt;p&gt;With ABCs refererring to Abstract Base Classes (pep 3119).&lt;/p&gt;

&lt;p&gt;Winter&amp;#8217;s proposal is similar to my &lt;a href="http://griddlenoise.blogspot.com/2007/05/abc-may-be-easy-as-123-but-it-cant-beat.html"&gt;recent post&lt;/a&gt;, which is that this sort of &amp;#8220;capability inference&amp;#8221; should be dynamic, and not bound to the rigid nature of the class hierarchy. In my post on this subject, I showed a number of different implementations of a single interface (specification, role, whatever) - only one implementation followed the basic class-instance scenario. All others provided the exact same outward appearance, while internally they were implemented as module-level functions, class or static methods, or a dynamically composed single-use object (a brainless instance was made and had methods dynamically attached).&lt;/p&gt;

&lt;p&gt;Winter&amp;#8217;s roles/traits system, which refers to roles in Perl 6 and traits in Squeak, is along the same lines. I hope to hell it gains traction.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1230647787449358105?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1230647787449358105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1230647787449358105'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/05/traits-roles-as-alternative-to-abstract.html' title='Traits / Roles as Alternative to Abstract Base Classes'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2864027387328317986</id><published>2007-05-04T10:45:00.000-06:00</published><updated>2007-05-04T14:04:32.362-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python3000'/><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='interfaces'/><title type='text'>ABC may be easy as 123, but it can't beat zope.interface</title><content type='html'>&lt;p&gt;I guess the deadline may have come and gone for getting in &lt;a href="http://www.python.org/dev/peps/"&gt;PEPs&lt;/a&gt; for &lt;a href="http://www.python.org/dev/peps/pep-3000/"&gt;Python 3000&lt;/a&gt;. Guido&amp;#8217;s already written up a &lt;a href="http://mail.python.org/pipermail/python-3000/2007-May/007178.html"&gt;PEP Parade&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of particular interest to me has been the appearance of PEPs for &lt;a href="http://www.python.org/dev/peps/pep-3119/"&gt;Abstract Base Classes&lt;/a&gt; (PEP 3119) and the more exhaustive &lt;a href="http://www.python.org/dev/peps/pep-3124/"&gt;PEP 3124&lt;/a&gt; which covers &amp;#8220;Overloading, Generic Functions, Interfaces, and Adaptation.&amp;#8221;&lt;/p&gt;

&lt;p&gt;Both of these aim to provide ways of saying &amp;#8220;this is file-ish&amp;#8221;, &amp;#8220;this is string-ish,&amp;#8221; without requiring subclassing from a concrete &amp;#8220;built-in&amp;#8221; type/class. But I think they both fall short a little bit, while &lt;code&gt;zope.interface&lt;/code&gt; (from the Zope 3 family) provides the best solution.&lt;/p&gt;

&lt;p&gt;PEP 3119 (Abstract Base Classes) has a section covering &lt;a href="http://www.python.org/dev/peps/pep-3119/#abcs-vs-alternatives"&gt;comparisons to alternative techniques&lt;/a&gt;, and it specifically mentions &amp;#8220;For now, I&amp;#8217;ll leave it to proponents of Interfaces to explain why Interfaces are better.&amp;#8221; So this is my &lt;del&gt;brief&lt;/del&gt; attempt at explaining why.&lt;/p&gt;

&lt;p&gt;A quote from PEP 3119 that I particularly like is &amp;#8220;Like all other things in Python, these promises are in the nature of a gentlemen&amp;#8217;s agreement&amp;#8230;&amp;#8221; The Interfaces as specified and used in Zope 3 and some other systems are the same way. They are not &amp;#8220;bondange and discipline&amp;#8221; Interfaces. They are not the ultra-rigid Eiffel contracts, nor are they the rigid and limited Interfaces as used by Java. They are basically a specification, and they can be used (as mentioned in PEP 3119) to provide additional metadata about a specification. There are some simple tools in &lt;code&gt;zope.interface.verify&lt;/code&gt; to check an implementation against a specification, but those are often used in test suites; they&amp;#8217;re not enforced hard by any system. The agreement might be &amp;#8220;I need a seekable file&amp;#8221;, which might mean it expects the methods/messages &amp;#8216;read&amp;#8217;, &amp;#8216;seek&amp;#8217;, and &amp;#8216;tell&amp;#8217;. If you only provide &amp;#8216;read&amp;#8217; and &amp;#8216;seek&amp;#8217;, then it&amp;#8217;s your fault for not living up to the agreement. That&amp;#8217;s no different than the Python of today. What Interfaces and Abstract Base Classes aim to provide is a better clarification of what&amp;#8217;s expected. Sometimes &amp;#8220;file-like&amp;#8221; in Python (today) means it just needs a &amp;#8216;read&amp;#8217; method. Sometimes it means the full suite of file methods (read, readlines, seek, tell). Same thing with sequences: sometimes it just means &amp;#8220;something iterable&amp;#8221;. Other times it means &amp;#8220;support append and extend and pop&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Another side benefit of Interfaces as specification is that they provide a common language for, well, specifications. Many &lt;a href="http://www.python.org/dev/peps/"&gt;PEPs&lt;/a&gt; propose some sort of API, especially informational PEPs like &lt;a href="http://www.python.org/dev/peps/pep-0333/"&gt;WSGI (PEP 333)&lt;/a&gt; or &lt;a href="http://www.python.org/dev/peps/pep-0247/"&gt;API for Cryptographic Hash Functions (PEP 247)&lt;/a&gt;. I&amp;#8217;ll use PEP 247 as an example for &lt;em&gt;my attempt at explaining why Zope 3&amp;#8217;s Interfaces are Better&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A problem with Abstract Base Classes is this: they&amp;#8217;re limited to classes. Even when PEP 3119 mentions Interfaces, it does so like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&amp;#8220;Interfaces&amp;#8221; in this context refers to a set of proposals for additional metadata elements attached to a class which are not part of the regular class hierarchy&amp;#8230;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It then goes on to mention that such specifications (in some proposals and implementations) may be mutable; and then says that&amp;#8217;s a problem since classes are shared state and one could mutate/violate intent. That&amp;#8217;s a separate discussion that I&amp;#8217;m not going to go into here.&lt;/p&gt;

&lt;p&gt;What is important is this &lt;strong&gt;severely limited focus on classes&lt;/strong&gt;. &lt;code&gt;zope.interface&lt;/code&gt; works on objects as well, and not just normal &amp;#8216;instances of a class&amp;#8217; object, but on classes themselves, &lt;strong&gt;and also modules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are two important verbs in &lt;code&gt;zope.interface&lt;/code&gt;: &lt;em&gt;implements&lt;/em&gt; and &lt;em&gt;provides&lt;/em&gt;. &lt;em&gt;provides&lt;/em&gt; is the most important one - it means that this Object, whatever that object may be, provides the specified interface directly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;implements&lt;/em&gt; is often used in class definitions. It means &amp;#8220;instances of this class will provide the specified interface&amp;#8221;. It can also be thought of in terms of Factories and/or Adaptation - &amp;#8220;calling this object will give you something that provides the desired interface.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&amp;#8220;What does that matter?&amp;#8221; you might ask. Well, there are all sorts of ways to compose objects in Python. A module is an object. It has members. A class is an object. An instance of a class is, of course, an object. Functions and methods are also objects in Python, but for the most part what we care about here are Modules, Classes, and Instances.&lt;/p&gt;

&lt;p&gt;Because when it comes down to actual usage in code, it doesn&amp;#8217;t particularly matter what an object is. In &lt;a href="http://www.python.org/dev/peps/pep-3124/"&gt;PEP 3124&lt;/a&gt;, the author (Phillip J Eby) shows the following interface:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class IStack(Interface):
    @abstract
    def push(self, ob)
        """Push 'ob' onto the stack"""

    @abstract
    def pop(self):
        """Pop a value and return it"""
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ignore the &lt;code&gt;@abstract&lt;/code&gt; decorators, as they&amp;#8217;re artifacts of the rest of his PEP and/or related to &lt;a href="http://www.python.org/dev/peps/pep-3119/"&gt;PEP 3119&lt;/a&gt;. What is important is the use of &lt;strong&gt;self&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;#8220;self&amp;#8221; is an artifact of implementation that is invisible to use&lt;/strong&gt;. Sure, you can write a Stack implementation like this. (Note: I&amp;#8217;m going to use &lt;code&gt;zope.interface&lt;/code&gt; terminology and style from here on out):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import zope.interface

class Stack(object):
    zope.interface.implements(IStack)

    def __init__(self):
        self._stack = []

    def push(self, ob):
        self._stack.append(ob)

    def pop(self):
        return self._stack.pop()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But when it&amp;#8217;s being used, it&amp;#8217;s used like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def do_something_with_a_stack(stack):
    stack.push(1)
    stack.push(2)
    # ...
    top = stack.pop()

stack_instance = Stack()
IStack.providedBy(stack_instance)
# True
IStack.providedBy(Stack)
# False

do_something_with_a_stack(stack_instance)
# works fine
do_something_with_a_stack(Stack)
# raises an exception because `Stack.push(1)` is passing `1` 
# to `self`.. unbound method, bla bla bla.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that &lt;strong&gt;there is no &amp;#8216;self&amp;#8217; reference visibly used when dealing with the IStack implementation&lt;/strong&gt;. This is an extremely important detail. What are some other ways that we may provide the IStack interface.&lt;/p&gt;

&lt;p&gt;One way is to do it with class methods and properties, effectively making a singleton. (This isn&amp;#8217;t a good way to do it, and is just here as an example).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import zope.interface

class StackedClass(object):
    zope.interface.classProvides(IStack)

    _stack = []

    @classmethod
    def push(class_, ob):
        class_._stack.append(obj)

    @classmethod
    def pop(class_):
        return class_._stack.pop()

IStack.providedBy(StackedClass)
# True

do_something_with_a_stack(StackedClass)
# this time it works, because `StackedClass.push(1)` is a class method,
# and is passing `StackedClass` to the `class_` parameter, and `1` 
# to `ob`.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another variation of the above is using Static Methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import zope.interface

class StaticStack(object):
    zope.interface.classProvides(IStack)

    _stack = []

    @staticmethod
    def push(ob):
        StaticStack._stack.append(ob)

    @staticmethod
    def pop():
        return StaticStack._stack.pop()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, &lt;code&gt;StaticStack.push(1)&lt;/code&gt; and &lt;code&gt;StaticStack.pop()&lt;/code&gt; work fine. Now lets try a third way - in a module! Let&amp;#8217;s call this module &lt;code&gt;mstack&lt;/code&gt; (file - &lt;code&gt;mstack.py&lt;/code&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import zope.interface

zope.interface.moduleProvides(IStack)

_stack = []

def push(ob):
    _stack.push(ob)

def pop():
    return _stack.pop()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then in other code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import mstack

IStack.providedBy(mstack)
# True
mstack.push(1)
mstack.push(2)

print mstack.pop()
# 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So whether we&amp;#8217;re dealing with the instance in the first example (&lt;code&gt;stack_instance&lt;/code&gt;), the classes in the second two examples (&lt;code&gt;StackedClass&lt;/code&gt; and &lt;code&gt;StaticStack&lt;/code&gt;), or the module in the last example (&lt;code&gt;mstack&lt;/code&gt;), they&amp;#8217;re all objects that live up to the &lt;code&gt;IStack&lt;/code&gt; agreement. So having &lt;code&gt;self&lt;/code&gt; in the Interface is pointless. &lt;strong&gt;self is a binding detail.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Jim Fulton, the main author of &lt;code&gt;zope.interface&lt;/code&gt;, taught me this a long time ago. Because in Zope 2, you could also make an &lt;code&gt;IStack&lt;/code&gt; implementation using a Folder and a pair of Python scripts. Well, those Python scripts (as used in Zope 2 &amp;#8220;through-the-web&amp;#8221; development) have at least &lt;strong&gt;4 binding arguments&lt;/strong&gt;. Instead of &amp;#8216;self&amp;#8217;, the initial arguments are &lt;code&gt;context, container, script, traverse_subpath&lt;/code&gt;. Just like &lt;code&gt;self&lt;/code&gt; is automatically taken care of by the class-instance binding machinery, the four Zope Python Script binding arguments are automatically taken care of by Zope 2&amp;#8217;s internal machinery. You never pass those arguments in directly, you just use it like &lt;code&gt;push(ob)&lt;/code&gt; and &lt;code&gt;pop()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So there it is - many ways to provide this simple &amp;#8220;Stack&amp;#8221; Interface. And I believe that both [PEP 3119] and [PEP 3124] are short sighted by focusing on the class-instance relationship exclusively (or so it appears).&lt;/p&gt;

&lt;p&gt;And since many objects, particularly instances, are mutable, one could compose an IStack implementation on the fly.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Prototype(object):
    """ Can be anything... """

pstack = Prototype()
pstack._stack = []

def pstack_push(ob):
    pstack._stack.append(ob)

def pstack_pop():
    return pstack._stack.pop()
pstack.push = pstack_push
pstack.pop = pstack_pop

# Now we can say that this particular instance provides the IStack
# interface directly - has no impact on the `Prototype` class
zope.interface.directlyProvides(pstack, IStack)

pstack.push(1)
pstack.push(2)
print pstack.pop()
2

# We can remove support as well
del pstack.push
zope.interface.noLongerProvides(pstack, IStack)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Examples of dynamically constructed objects in the real world - a network services client, particularly one that&amp;#8217;s in an overwraught distributed object system (CORBA, SOAP, and other things that make you cry in the night). Dynamic local &amp;#8216;stub&amp;#8217; objects may be created at run time, but those could still be said to provide a certain interface.&lt;/p&gt;

&lt;p&gt;So now let&amp;#8217;s look at whether it matters that you&amp;#8217;re dealing with a class or not:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@implementer(IStack)
def PStack():
    pstack = Prototype()
    pstack._stack = []

    def pstack_push(ob):
        pstack._stack.append(ob)

    def pstack_pop():
        return pstack._stack.pop()

    pstack.push = pstack_push
    pstack.pop = pstack_pop
    zope.interface.directlyProvides(pstack, IStack)

    return pstack

@implementer(IStack)
def StackFactory():
    # Returns a new `Stack` instance from the earlier example
    return Stack()

import mstack
import random

@implementer(IStack)
def RandomStatic():
    # chooses between the two class based versions and module
    return random.choice([StackedClass, StaticStack, mstack])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All three are factories that will return an object that provides an IStack implementation, which is exactly the same as the &lt;code&gt;Stack&lt;/code&gt; class in the first example. That also claimed that it &lt;code&gt;implements(IStack)&lt;/code&gt;. When the class is instantiated / called, a new object is made that provides the IStack interface. In Python, another thing that doesn&amp;#8217;t really matter is whether something is a class or function. All of the following lines of code yield a result that is the same to the consumer. The internal details of what is returned may vary, but the IStack interface works on all of them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Stack()         # class
PStack()        # 'Prototype' dynamically constructed object
StackFactory()  # Wrapper around basic class
RandomStatic()  # Chooses one of the class/static method implementations.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And whether we&amp;#8217;re looking at the class implementation, or any of the factory based implementations, the result should be the same:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IStack.implementedBy(Stack) # class
# True
IStack.providedBy(Stack)
# False
IStack.providedBy(Stack())
# True

IStack.implementedBy(PStack)    # Factory
# True
IStack.providedBy(PStack)
# False
IStack.providedBy(PStack())
# True
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No matter which method of instantiation is used, they should all pass the &lt;code&gt;verifyObject&lt;/code&gt; check, which checks to see whether all of the specified members are provided and that the method/function signatures match the specification&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from zope.interface import verifyObject
verify_stack = partial(verifyObject, IStack)

all(verify_stack, [Stack(), PStack(), StackFactory(), RandomStatic()])
# True
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the class-based options will fail on the &lt;code&gt;implementedBy&lt;/code&gt; check, because it&amp;#8217;s the Class that provides the implementation, not an instance like with &lt;code&gt;Stack&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IStack.implementedBy(StackedClass)
# False
IStack.providedBy(StackedClass)
# True
IStack.providedBy(StackedClass())
# False
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#8220;OK&amp;#8221;, you might say, &amp;#8220;but still, why does it matter? Why might we really care about whether these abstract specifications work only with classes? It seems smaller, simpler.&amp;#8221;&lt;/p&gt;

&lt;p&gt;The main advantage is that &lt;strong&gt;specification should (generally) make no assumptions about implementation&lt;/strong&gt;. If the specification, aka &amp;#8220;gentlemen&amp;#8217;s agreement&amp;#8221; is generally met, it shouldn&amp;#8217;t matter whether it&amp;#8217;s provided by a Class, an instance, a module, an extension module, or some dynamically constructed object. &lt;strong&gt;The specification language should be the same&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Going back to &lt;a href="http://www.python.org/dev/peps/pep-0247/"&gt;PEP 247&lt;/a&gt;, the &amp;#8220;cryptographic hash API&amp;#8221;: there is a specification in that module about what the &amp;#8216;module&amp;#8217; must provide, and for what the hash objects must provide. Consider also the WSGI spec, the DB-API specs, and all of the other formal and informal specs that are floating around just in the PEPs. Using &lt;code&gt;zope.interface&lt;/code&gt;, those specifications can be spelled out in the same fashion. WSGI just cares about a particular function name signature. It can be provided by a single function in a simple module, or as a method from an object put together by a large system like the full Zope 3 application framework and server. It just wants a callable. This is a little bit ugly in &lt;code&gt;zope.interface&lt;/code&gt;&amp;#8230; but in reality, actually, I think it works. Here&amp;#8217;s how it could be specified:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class IWSGIApplication(Interface):
    def __call__(environ, start_response):
        """ Document the function """
    # and/or use tagged values to set additional metadata
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This just means that a WSGIApplication must be a callable object taking &lt;code&gt;environ&lt;/code&gt; and &lt;code&gt;start_response&lt;/code&gt; arguments. A callable object may be a function (taken from &lt;a href="http://www.python.org/dev/peps/pep-0333/"&gt;PEP 333&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or a class (the &lt;code&gt;__init__&lt;/code&gt; is what is callable here). Maybe the WSGI spec might also state that the result &amp;#8220;should be iterable (support &lt;code&gt;__iter__&lt;/code&gt;)&amp;#8221; Maybe that&amp;#8217;s loosely enforced, but the following example shows how the class can make separate declarations about what the class directly provides, and what its instances implement. Instead of using any decorators or magic-ish &amp;#8220;class decorators&amp;#8221; (the &lt;code&gt;implements&lt;/code&gt;, &lt;code&gt;classProvides&lt;/code&gt; calls above), we&amp;#8217;ll make the declarations for both &lt;code&gt;AppClass&lt;/code&gt; and &lt;code&gt;simple_app&lt;/code&gt; in the same manner, which matches the style in &lt;a href="http://www.python.org/dev/peps/pep-3124/"&gt;PEP 3124&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AppClass(object):
    def __init__(self, environ, start_response):
        self.environ = environ
        self.start = start_response

    def __iter__(self):
        status = '200 OK'
        response_headers = [('Content-type','text/plain')]
        self.start(status, response_headers)
        yield "Hello world!\n"

from zope.interface import directlyProvides, classImplements

# Both 'simple_app' and 'AppClass' are callable with the same arguments,
# so they both *provide* the IWSGIApplication interface

directlyProvides(simple_app, IWSGIApplication)
directlyProvides(AppClass, IWSGIApplication)

# And we can state that AppClass instances are iterable by supporting
# some phantom IIterable interface
classImplements(AppClass, IIterable)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What are the benefits of this, beyond just having a common way of spelling specifications? Instead of, or in addition to, abstract base classes, the core Python libraries can include all of these specs, even if they don&amp;#8217;t provide any concrete implementation. Then I could have a unit test in my code that uses &lt;code&gt;verifyClass&lt;/code&gt; or &lt;code&gt;verifyObject&lt;/code&gt; to ensure I stay inline with the specification.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def test_verifySpec(self):
    verifyClass(ICryptoHash, MyHashClass)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, if the specification changes in a new version of Python or in a new version of someone elses library or framework, I can be notified.&lt;/p&gt;

&lt;p&gt;Of if the specification undergoes a big change, a new spec could be written, such as &lt;code&gt;IWSGI2Application&lt;/code&gt;. Then by process of adaptation (not covered in this post) or interface querying, a WSGI Server could respond appropriately to implementations of the earlier spec:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if IWSGI2Application.providedBy(app):
    # Yay! We don't have to do anything extra!
    # ... do wsgi 2 work
elif IWSGIApplication.providedBy(app):
    # We have to set up the old `start_response` object
    # ... do wsgi 1 work
else:
    raise UnsupportedOrUndeclaredImplementation(app)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Adaptation could provide a means of doing the above&amp;#8230; (still, not going into the details.. trying not to!)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@implementer(IWSGI2Application)
@adapts(IWSGIApplication)
def wsgi1_to_wsgi2(app):
    return wsgi2wrapper(app)

# And then, replacing the `if, else` above:
wsgi_app = IWSGI2Application(app, None)
if app is None:
    raise UnsupportedOrUndeclaredImplementation(app)
# ... do wsgi2 work
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you have both specification and adaptation, then you can write your code against the spec. In the above example, the main code does &lt;code&gt;IWSGI2Application(app, None)&lt;/code&gt; which means &amp;#8220;for the object &lt;code&gt;app&lt;/code&gt;, give me an object that provides IWSGI2Application, or None if there is no means of providing that interface.&amp;#8221;&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;app&lt;/code&gt; provides that interface directly, then &lt;code&gt;app&lt;/code&gt; is returned directly. Otherwise an adaptation registry is found, and it&amp;#8217;s queried for a callable object (an adapter) that will take &amp;#8216;app&amp;#8217; as its argument and return an object that provides IWSGI2Application.&lt;/p&gt;

&lt;p&gt;Another example: knowing that Python 3000 is going to change a lot of core specifications and implementations, such as the attributes for functions (&lt;code&gt;func_code&lt;/code&gt;, &lt;code&gt;func_defaults&lt;/code&gt;, etc). If an &lt;code&gt;IPy2Function&lt;/code&gt; interface were made (and &lt;code&gt;zope.interface&lt;/code&gt; or something like it was added to Python 2.x), then code that works with function object internals could program against their preferred spec by adding a line of code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;func = IPy2Function(func)
if my_sniffer(func.func_code):
    raise Unsafe(func)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On Python 2, you&amp;#8217;d get the regular function straight through. In Python 3000 / 3.0, an adapter would translate &lt;code&gt;__code__&lt;/code&gt; into &lt;code&gt;func_code&lt;/code&gt;, for example. I don&amp;#8217;t expect this to happen in reality, but it&amp;#8217;s an example of how migration paths &lt;em&gt;could&lt;/em&gt; be made between two major software versions, allowing code to run in both.&lt;/p&gt;

&lt;p&gt;By taking advantage of this system, my company &lt;a href="http://griddlenoise.blogspot.com/2007/04/reuse-and-non-use.html"&gt;has seen more re-use with Zope 3&lt;/a&gt; than at any time in our company history. And because (most of) Zope 3 is programmed against specification, we&amp;#8217;ve been able to plug in or completely make over the whole system by providing alternative implementations of core specs. This is very hard to do in native Zope 2 (the CMF, on which &lt;a href="http://plone.org"&gt;Plone&lt;/a&gt; is based, was probably the first Zope system that started these concepts, which Plone and others were able to take advantage of by providing new tools that matched the provided spec).&lt;/p&gt;

&lt;p&gt;At the heart of it, again, is the gentlemen&amp;#8217;s agreement, but brought out in full: it doesn&amp;#8217;t matter who you are or where you came from (ie, it doesn&amp;#8217;t matter what classes are in your family tree or if you are a simple module), as long as you get the job done. There&amp;#8217;s a simple contract, and as long as the contract is fulfilled, then everybody is happy.&lt;/p&gt;

&lt;p&gt;But if the gentlemen involved can only come from the class system, then there&amp;#8217;s still a nasty aristocracy that excludes a large chunk of the populace, all of whom can potentially fulfill the contract. Let&amp;#8217;s not cause an uprising, OK?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-2864027387328317986?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2864027387328317986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2864027387328317986'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/05/abc-may-be-easy-as-123-but-it-cant-beat.html' title='ABC may be easy as 123, but it can&apos;t beat zope.interface'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-9208107548001112313</id><published>2007-04-30T11:32:00.000-06:00</published><updated>2007-04-30T11:34:03.170-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>plispy</title><content type='html'>&lt;p&gt;Sometimes, it just happens...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&gt;&gt;&gt; pprint(
...     sorted(
...         map(
...             linecount,
...             path('.').walkfiles('*.py')
... )))&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-9208107548001112313?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9208107548001112313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9208107548001112313'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/plispy.html' title='plispy'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-7243230097062498826</id><published>2007-04-24T23:33:00.000-06:00</published><updated>2007-04-27T08:26:58.113-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='scons'/><category scheme='http://www.blogger.com/atom/ns#' term='buildout'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='setuptools'/><category scheme='http://www.blogger.com/atom/ns#' term='rake'/><category scheme='http://www.blogger.com/atom/ns#' term='make'/><category scheme='http://www.blogger.com/atom/ns#' term='distutils'/><title type='text'>Python's Make Rake and Bake, another and again</title><content type='html'>&lt;p&gt;Ian Bicking wrote a post recently titled &lt;a href="http://blog.ianbicking.org/pythons-makefile.html"&gt;&amp;#8220;Python&amp;#8217;s Makefile&amp;#8221;&lt;/a&gt;. He advocates using / re-using &lt;a href="http://docs.python.org/lib/module-distutils.html"&gt;distutils&lt;/a&gt;&amp;#8230; er&amp;#8230; &lt;a href="http://peak.telecommunity.com/DevCenter/setuptools#creating-distutils-extensions"&gt;setuptools&lt;/a&gt;. (I can&amp;#8217;t keep them straight - they&amp;#8217;ve both become absolute nightmares in my opinion). He then goes off about entry points, separate &lt;code&gt;setup.cfg&lt;/code&gt; files, and other things that still go way over my head. The example he shows is convoluted, and I&amp;#8217;m ultimately not entirely sure what he&amp;#8217;s really advocating (besides the idea - which isn&amp;#8217;t bad - of using the near-standard &lt;code&gt;setup.py&lt;/code&gt; file/system instead of re-inventing).&lt;/p&gt;

&lt;p&gt;But he mentions, earlier:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Because really people are talking about something more like &lt;a href="http://rake.rubyforge.org/"&gt;rake&lt;/a&gt; &amp;#8212; something where you can put together a bunch of code management tools. These aren&amp;#8217;t commands provided by the code, these are commands used on the code.&lt;/p&gt;
  
  &lt;p&gt;We do have the infrastructure for this in Python, but no one is really using it. So I&amp;#8217;m writing this to suggest people use it more: the setup.py file. So where in another environment someone does &lt;code&gt;rake COMMAND&lt;/code&gt;, we can do &lt;code&gt;python setup.py COMMAND&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For me, having an easy way to say &lt;code&gt;bla bla COMMAND&lt;/code&gt; isn&amp;#8217;t as important as having a good system for automating common tasks that I and/or my colleagues do frequently. As we started to depend on more and more code from internal and external repositories, due to our &lt;a href="http://griddlenoise.blogspot.com/2007/04/reuse-and-non-use.html"&gt;increased re-use when building on Zope 3&lt;/a&gt;, I really needed to automate checkouts and exports. Not everything was neatly packaged as an egg, or the released egg didn&amp;#8217;t have a bugfix applied, and I still don&amp;#8217;t understand how to make eggs work well with Zope 3 in a manner that I&amp;#8217;m comfortable with.&lt;/p&gt;

&lt;p&gt;I was initially excited about &lt;a href="http://cheeseshop.python.org/pypi/zc.buildout"&gt;zc.buildout&lt;/a&gt; as a way to automate the monotonous but important tasks that revolve around setting up both deployment and development environments. But I didn&amp;#8217;t like how &lt;code&gt;zc.buildout&lt;/code&gt; specified its tasks/commands in INI format. It was relatively easy to write new &amp;#8216;recipes&amp;#8217;, so I wrote some recipes to do Subversion and CVS checkouts/exports.&lt;/p&gt;

&lt;p&gt;But the INI format just pissed me off. It didn&amp;#8217;t fit my needs, basically, wherein I needed more conditional control. More code control. And managing complex sets of parameters required making new top-level sections instead of nesting. Before long I was staring at a very long and very narrow file. And in the end, it was building Zope in a way that wouldn&amp;#8217;t work for us. So I abandoned it.&lt;/p&gt;

&lt;p&gt;I briefly looked at some tools that let you write these task files in &amp;#8220;pure&amp;#8221; Python. In this way, &lt;a href="http://www.scons.org/"&gt;Scons&lt;/a&gt; appeared to be the closest thing in Python to &lt;a href="http://rake.rubyforge.org/"&gt;Rake&lt;/a&gt;, which uses Ruby. But &lt;em&gt;Scons&lt;/em&gt; seemed far more focused on general compilation issues (compiling C, Java, etc), but that&amp;#8217;s never a problem that crosses my path.&lt;/p&gt;

&lt;p&gt;I just wanted something like &lt;a href="http://rake.rubyforge.org/"&gt;rake&lt;/a&gt;. What I liked about &lt;em&gt;every&lt;/em&gt; Rakefile that I&amp;#8217;ve seen is that it&amp;#8217;s been quite readable. Rake makes common file / path commands readily available as Ruby methods, classes, and objects. Rake takes advantage of Ruby&amp;#8217;s syntax, particularly blocks (and optional parenthesis) in a way that makes it not seem like, well, Ruby. It looks like something makefile-ish, something shell-scripting-ish, etc. That&amp;#8217;s what I wanted; but, of course, in Python.&lt;/p&gt;

&lt;p&gt;So I came up with a system. It&amp;#8217;s not yet released to the world - far from finished, and there are many competing ideas out there that I don&amp;#8217;t feel like competing with - but it&amp;#8217;s already proven to be very useful internally. Generally, it&amp;#8217;s been used to automate what I mentioned above: retrieving software from multiple repositories, both Subversion and CVS, and placing them in the proper directories. In particular, we try to stick with certain revisions for third party dependencies, and I got tired of trying to capture this information in READMEs and other files that we could refer to when installing certain configurations. It&amp;#8217;s even been useful for downloading such software and applying internal patches::&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;patch = Command('patch')

@task('mysqldbda')
def mysqldbda():
    """ Installs mysqldbda from subversion and applies patch """
    svn = Subversion('svn://svn.zope.org/repos/main')
    svn.co('mysqldbda/tags/mysqldbda-1.0.0', target='mysqldbda')

    # patch mysqldbda
    log.info("patching mysqldbda")
    patchfile = path('fixes/mysqlda.1-5-07.patch')
    if patchfile.exists():
        print patch.read('-p1', '-i', patchfile)

@task('formencode')
def formencode():
    svn = Subversion('http://svn.colorstudy.com/FormEncode')
    svn.co('tags/0.6/formencode')

task('install', ['mysqldbda', 'formencode'])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s also been useful for tasks like getting &lt;a href="http://mochikit.com/"&gt;MochiKit&lt;/a&gt; and generating all sorts of packed versions. A lot of what makes this possible is the &lt;a href="http://www.jorendorff.com/articles/python/path/"&gt;path.py&lt;/a&gt; module, which provides a more object-oriented interface over &lt;code&gt;os&lt;/code&gt;, &lt;code&gt;os.path&lt;/code&gt;, and other Python file utilities.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ROCKFILEPATH = globals().get('ROCKFILEPATH', path('.'))
MOCHIKIT_LIB = ROCKFILEPATH/'libs'/'mochikit'
MOCHIKIT_DL = ROCKFILEPATH/'mochikit_dl'
MOCHIKIT_SRC = MOCHIKIT_DL/'MochiKit'
SCRATCH = MOCHIKIT_LIB/'_scratch.js'
mochikit = namespace('mochikit')

@mochikit.task('get')
def getmochikit():
    if MOCHIKIT_DL.exists() and bool(MOCHIKIT_DL.listdir()):
        return
    svn = Subversion('http://svn.mochikit.com/mochikit')
    svn.co('trunk', target=MOCHIKIT_DL)

@mochikit.task('clearmochilib')
def clearmochilib():
    for jscript in MOCHIKIT_LIB.files('*.js'):
        jscript.remove()

@mochikit.task('make-noexport')
def makenoexport():
    info = Subversion().info(MOCHIKIT_DL)
    src = NOEXPORT.safe_substitute(**info)
    file(MOCHIKIT_LIB/'NoExport.js','w').write(src)

@mochikit.task('build', ['get', 'clearmochilib', 'make-noexport'])
def mochi_install():
    for source in MOCHIKIT_SRC.files('*.js'):
        log.info('copy %s -&amp;gt; %s' % (source, MOCHIKIT_LIB))
        source.copy(MOCHIKIT_LIB)

# Javascript Packing tools (JSPack not shown - essentially it's a wrapper
# around combining and piping Javascript through Dojo's custom_rhino.jar
# to use its compression system)
def packmodules(sourcedir, modules, target):
    mods = [ (sourcedir/mod) for mod in modules ]
    log.info('Packing %s modules', path(target).name)
    JSPack(mods, target).run()

    if SCRATCH.exists():
        SCRATCH.remove()

def jsmin(sources, target):
    packmodules(MOCHIKIT_LIB, sources, MOCHIKIT_LIB/'min'/target)

@mochikit.task('minimize')
def mochiMinimize():
    """
    Generates packed versions of most individual MochiKit files, while
    combining a few core ones together.
    """
    mindir = MOCHIKIT_LIB/'min'
    for jscript in mindir.files('*.js'):
        jscript.remove()
    jsmin(['NoExport.js', 'Base.js', 'Iter.js', 'DOM.js'], 'base-iter-dom.js')
    jsmin(['Style.js', 'Signal.js'], 'style-signal.js')
    jsmin(['Async.js'], 'async.js')
    jsmin(['Color.js'], 'color.js')
    # ...

mochikit.task('install', ['build', 'minimize']).comment('INSTALL!')
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I don&amp;#8217;t think this falls under the jurisdiction of &lt;code&gt;setup.py&lt;/code&gt; (distutils/setuptools). Nor would I want to specify these as &lt;code&gt;zc.buildout&lt;/code&gt; recipes and have a separate configuration file to then name all of the files and directories. And, being Python, I don&amp;#8217;t really have to deal with compilation steps so I don&amp;#8217;t need wrappers around &lt;code&gt;gcc&lt;/code&gt; and friends. I&amp;#8217;m not (yet) specifying how to build large deployment scenarios. I just need to automate some development tasks, and I need to be able to write them easily. I want to write them in Python, but I want to ensure that they don&amp;#8217;t accidentally get imported into normal projects (hence, the files above don&amp;#8217;t have a &lt;code&gt;.py&lt;/code&gt; extension). And as this is a specialized task, I&amp;#8217;ll allow myself to get away with Python shortcuts that I would never touch in normal development, such as &lt;code&gt;import *&lt;/code&gt;. In fact, it&amp;#8217;s the &lt;code&gt;import *&lt;/code&gt; that gives me a lot of the common commands/tools, such as the classes for interacting with Subversion and CVS, managing working directories, etc.&lt;/p&gt;

&lt;p&gt;This really stemmed from reading &lt;a href="http://martinfowler.com/bliki/JRake.html"&gt;this article by Martin Fowler&lt;/a&gt; about people wanting to replace &lt;a href="http://ant.apache.org/"&gt;ant&lt;/a&gt; with Rake with the advent of JRuby. In the post, Martin states:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The thing with build scripts is that you need both declarative and procedural qualities. The heart of a build file is defining tasks and the dependencies between them. This is the declarative part, and is where tools like ant and make excel. The trouble is that as builds get more complex these structures aren&amp;#8217;t enough. You begin to need conditional logic; in particular you need the ability to define your own abstractions. (See &lt;a href="http://www.martinfowler.com/articles/rake.html"&gt;my rake article&lt;/a&gt; for examples.)&lt;/p&gt;
  
  &lt;p&gt;Rake&amp;#8217;s strength is that it gives you both of these. It provides a simple declarative syntax to define tasks and dependencies, but because this syntax is an internal DomainSpecificLanguage, you can seamlessly weave in the full power of Ruby.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that point, I decided that this was the way to go: use Python decorators to wrap &amp;#8216;task&amp;#8217; functions. The wrapper maintains dependency links, comments, and other things of interest to the internal system; and the wrapper allows the task name to be independent of the function name, allowing easier-to-type tasks for use from the file system. But the &amp;#8216;task&amp;#8217; function is plain Python. Or, like some of the examples above show, &lt;code&gt;task&lt;/code&gt; can be called without the &lt;code&gt;@&lt;/code&gt; symbol that makes it a decorator. Multiple callable actions can be added to a task, potentially allowing for more &amp;#8216;declarative&amp;#8217; style:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mochikit.task('minimize').using_action(
  JSMinMap(
    {'style-signal.js': ['Style.js', 'Signal.js']},
    {'async.js': ['Async.js']},
  ))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Useful, I imagine, for very common patterns. Er. &amp;#8220;Recipes&amp;#8221;. In any case, it&amp;#8217;s a very useful kind of tool. Beats &lt;code&gt;setup.py&lt;/code&gt;, &lt;code&gt;INI&lt;/code&gt;, or XML based automation language any day.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-7243230097062498826?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/7243230097062498826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/7243230097062498826'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/pythons-make-rake-and-bake-another-and.html' title='Python&apos;s Make Rake and Bake, another and again'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2146239670088514101</id><published>2007-04-18T11:41:00.000-06:00</published><updated>2007-04-18T12:12:37.208-06:00</updated><title type='text'>Cock Radio</title><content type='html'>&lt;p&gt;This whole &lt;em&gt;Don Imus&lt;/em&gt; issue has confused the shit out of me. Talk radio is full of that kind of, um, talk. Anyways, it all feels like the &lt;a href="http://www.southparkstudios.com/show/display_episode.php?season=11&amp;amp;id1=1101&amp;amp;id2=158"&gt;first episode of the latest season of South Park&lt;/a&gt;. Sometimes, South Park can crank out a new episode in response to a very recent event, but that didn&amp;#8217;t happen here. This episode aired weeks earlier.&lt;/p&gt;

&lt;p&gt;As for how or why this Don Imus issue exploded in the way that it did - I just don&amp;#8217;t understand (and now I feel like Stan Marsh at the end of that South Park episode). There are so many similar things said all the time by many radio &amp;#8220;personalities.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://mediamatters.org/"&gt;Media Matters&lt;/a&gt; has an excellent post up chronicling the many slurs of Glenn Beck, O&amp;#8217;Reilly, and more: &lt;a href="http://mediamatters.org/items/200704120010"&gt;It&amp;#8217;s not just Imus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The response to the whole Imus situation just seems wrong: a cause celeb on which everyone can jump. The latest distraction. How the hell did it get so out of hand? Who did it &lt;em&gt;really&lt;/em&gt; offend? Why this &amp;#8220;nappy headed ho&amp;#8217;s&amp;#8221; statement? Why not &amp;#8220;ghetto slut&amp;#8221; (Boortz)? &amp;#8220;Turbanned hoodlums&amp;#8221; (Savage)?&lt;/p&gt;

&lt;p&gt;Imus is probably far less offensive than many of these other radio people, and neither his firing nor all of this special attention is going to make anything better. Nor did it solve anything. It just provided everybody with some bullshit theater.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-2146239670088514101?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2146239670088514101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2146239670088514101'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/cock-radio.html' title='Cock Radio'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1678945150042190166</id><published>2007-04-17T16:06:00.000-06:00</published><updated>2007-04-17T16:08:27.489-06:00</updated><title type='text'>What about search?</title><content type='html'>&lt;p&gt;From my tumblog: &lt;a href="http://dirtymodern.tumblr.com/post/1006448"&gt;but I don't want my search engine to be a slide show!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Google - remember that search engine of yours? How about making it better by offering some options like result filtering ("I don't feel like shopping right now, I'm trying to research")?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1678945150042190166?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1678945150042190166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1678945150042190166'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/what-about-search.html' title='What about search?'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114195265668189680</id><published>2007-04-17T11:55:00.000-06:00</published><updated>2007-04-17T14:50:53.593-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><title type='text'>Reuse and non use</title><content type='html'>&lt;p&gt;We&amp;#8217;ve been using &lt;a href="http://wiki.zope.org/zope3/FrontPage"&gt;Zope 3&lt;/a&gt; in earnest for just over a year and a half now. I would like to report that in that year and a half &lt;strong&gt;our little company has achieved more re-use than at any time in our history&lt;/strong&gt;. This is real re-use too: libraries of tools and objects that are easily shared among both horizontal and vertical markets, yet customized for each customer as needed. Benefits for one are fairly easily shared with all.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="http://www.zope.org/Products/"&gt;Zope 2&lt;/a&gt; days, we tried hard to achieve this. But we were constantly having to re-invent the kind of architecture that I believe really makes this work: adaptation, which also brings dynamic view binding, dynamic UI generation (ie - registering a &amp;#8216;tab&amp;#8217; for a particular object / interface and having it show up in the UI as necessary, etc. We had to spend a lot of time making the frameworks that would let us make frameworks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;#8220;Frameworks for making frameworks?&amp;#8221;&lt;/em&gt; - you heard right. Let&amp;#8217;s face it: most web work is custom development. Sometimes custom development is best served by tools like &lt;a href="http://www.rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; or &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;, or even by plain old PHP. But sometimes you know you&amp;#8217;re going to have at least five customers all needing variations on the same thing in the coming months; and potentially more after that. You&amp;#8217;re going to need to at least make a library or two.&lt;/p&gt;

&lt;p&gt;See, &lt;strong&gt;Model-View-Controller&lt;/strong&gt; isn&amp;#8217;t just about &amp;#8220;separating business logic from presentation&amp;#8221;. It&amp;#8217;s about separating it in a way that you can take business objects and logic (the &amp;#8216;model&amp;#8217; layer; or models and services) and put more than one view on them. And by &amp;#8220;more than one view&amp;#8221;, I don&amp;#8217;t mean &amp;#8220;more than one template.&amp;#8221; I mean putting wholly different user interfaces on it. I mean being able to take a base library and override a few select options (or many select options) as they appeal to a customer.&lt;/p&gt;

&lt;p&gt;We tried to achieve this on some of our Zope 2 products, but it was hard to extract frameworks. We did OK, however, but I think that the most re-use we ever got was about three or four customers on one toolkit. That was over a three or four year span. We re-used patterns and snippets quite often, but it took a lot of work to extract an e-commerce toolkit from a particular customer&amp;#8217;s site, and more work still to make it adaptable and workable for different customer requirements. &lt;/p&gt;

&lt;p&gt;In the year and a half since using &lt;strong&gt;Zope 3&lt;/strong&gt; full time, we&amp;#8217;ve had double that - and with far greater results. It&amp;#8217;s not an easy system to just start using from scratch, but it can be quite worth it.&lt;/p&gt;

&lt;p&gt;Being back at work on some legacy &lt;strong&gt;Zope 2&lt;/strong&gt; projects has made me all the more appreciative.&lt;/p&gt;

&lt;p&gt;By the way: for a simpler Zope 3 development experience, check out &lt;a href="http://grok.zope.org/"&gt;Grok&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/13463691-114195265668189680?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114195265668189680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114195265668189680'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/reuse-and-non-use.html' title='Reuse and non use'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-8655037986488038974</id><published>2007-04-16T16:19:00.000-06:00</published><updated>2007-04-16T16:22:19.309-06:00</updated><title type='text'>Tumbling Dirty</title><content type='html'>&lt;p&gt;Oh yeah: &lt;a href="http://dirtymodern.tumblr.com/"&gt;Dirty Modern&lt;/a&gt;. My tumblelog, generally more focused on design, music, etc.. We'll see.&lt;/p&gt;
&lt;p&gt;I haven't posted too much in &lt;em&gt;Griddle Noise&lt;/em&gt; because it's quite hard, sometimes, to write short entries. I always liked the tumblelog format for being explicitly simple. And &lt;a href="http://tumblr.com/"&gt;Tumblr&lt;/a&gt; has an excellent bookmarklet for posting entries.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-8655037986488038974?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8655037986488038974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/8655037986488038974'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/tumbling-dirty.html' title='Tumbling Dirty'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-6783398237748614690</id><published>2007-04-13T18:52:00.000-06:00</published><updated>2007-04-13T20:37:51.987-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='flex'/><category scheme='http://www.blogger.com/atom/ns#' term='professional'/><category scheme='http://www.blogger.com/atom/ns#' term='desktop'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><category scheme='http://www.blogger.com/atom/ns#' term='applications'/><title type='text'>The Web Will Not Replace the Desktop</title><content type='html'>&lt;blockquote&gt; Web 2.0 has excited us because we lowered our expectations so much. Of course web apps will get better, and one day will deliver the functionality we currently get from desktop software. They may even do more than our desktop applications one day. But isn’t it a tad strange that we think this is all a huge leap forward? - &lt;a href="http://www.loosewireblog.com/2007/04/its_not_the_dea.html"&gt;loose wire blog: It's Not the "Death" of Microsoft, it's the "Death" of Software&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;The author's main point is that while it's cool that people are making Mind Mapping tools in DHTML, they're still a long ways behind desktop apps like MindManager. He goes on to contend that there's just nothing exciting in the "offline" world in recent years.&lt;/p&gt;

&lt;p&gt;While it's true that the web has made for some neat and very useful online tools, there are classes of software missed. There's a reason why we'll never get to the "every computer is just a web browser / flash player" ideal: &lt;strong&gt;professional software&lt;/strong&gt;. It's a world I'm entering again as I'm finally getting my home studio together.&lt;/p&gt;

&lt;p&gt;I'm talking about apps like &lt;strong&gt;Pro Tools&lt;/strong&gt;, &lt;strong&gt;Reaktor&lt;/strong&gt;, &lt;strong&gt;Final Cut&lt;/strong&gt;, &lt;strong&gt;DVD Studio&lt;/strong&gt;, &lt;strong&gt;Aperture&lt;/strong&gt;, &lt;strong&gt;Lightroom&lt;/strong&gt;, &lt;strong&gt;InDesign&lt;/strong&gt;, &lt;strong&gt;Quark XPress&lt;/strong&gt;, etc.&lt;/p&gt;

&lt;p&gt;Granted, most people don't use those applications, but I think that it's a growing market. As technology grows and commodifies, we need tools to deal with it. The gap between pretty-good consumer gear and pretty-good entry level professional gear is pretty small now in many areas: digital photography, digital video, music, etc.&lt;/p&gt;

&lt;p&gt;Now that I think about it, &lt;strong&gt;Apple&lt;/strong&gt; has realized this for some time. They have a pretty good upgrade path. For those who get hooked playing with video in &lt;a href="http://www.apple.com/ilife/imovie/"&gt;iMovie&lt;/a&gt;, there's &lt;a href="http://www.apple.com/finalcutexpress/"&gt;Final Cut Express&lt;/a&gt; at a rather reasonable price. Those who really start to do well with that can go up to the full &lt;a href="http://www.apple.com/finalcutstudio/finalcutpro/"&gt;Final Cut Pro&lt;/a&gt;. For Music, there's &lt;a href="http://www.apple.com/ilife/garageband/"&gt;Garage Band&lt;/a&gt;, &lt;a href="http://www.apple.com/logicexpress/"&gt;Logic Express&lt;/a&gt;, and &lt;a href="http://www.apple.com/logicpro/"&gt;Logic Pro&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Within those realms, there's a huge array of plug-ins, virtual instruments, specialized sound tools and environments (&lt;a href="http://www.ableton.com/"&gt;Ableton Live&lt;/a&gt;, &lt;a href="http://www.nativeinstruments.de/index.php?reaktor_us"&gt;Reaktor 5&lt;/a&gt;, Max/MSP, etc). I am amazed at the sounds I get out of Reaktor, and that's only a single product in a single company's impressive set of offerings.&lt;/p&gt;

&lt;p&gt;Perhaps the new web applications are freeing up resources on our own machines so that it no longer feels like some dreadful work environment, just at home. There are plenty of useful and usable online tools for doing quick writing, sharing, interacting, thinking, and planning. Typically they offer enough to be usable for those small (or even medium) jobs we occasionally encounter, while freeing us from having something overkill like &lt;strong&gt;Office&lt;/strong&gt; for casual, personal writing. It's easier to specialize a computer for audio work by fine tuning system settings, throwing away silly applications, etc, without making that computer into an island. As long as you have a web browser, you can still check email, contribute to a planning document, etc.&lt;/p&gt;

&lt;p&gt;But honestly, I don't think the Desktop is going to die - ever. It's great that we can do so much on the web, but I don't think the native experience is going to die, ever.&lt;/p&gt;

&lt;p&gt;And even if &lt;a href="http://www.37signals.com/svn/posts/347-youre-not-on-a-fucking-plane-and-if-you-are-it-doesnt-matter"&gt;you're not on a fucking plane&lt;/a&gt;, it does matter: when I moved into this loft, it took me a couple of months to get internet access down here. I was working on a lot of things for the office at the time, and I was able to take it home by just using my laptop: at work, I'd synchronise source code, copy stuff to my laptop and/or sync with .Mac's iDisk, and sync with .Mac for my calendar, etc; as such, even though I was offline, I could work. It was then and there, however, that I decided that although I liked &lt;a href="http://backpackit.com"&gt;Backpack&lt;/a&gt;, it wasn't worth paying for: I needed offline access. I needed, well, &lt;a href="http://www.omnigroup.com/applications/omnioutliner/"&gt;OmniOutliner&lt;/a&gt; and &lt;a href="http://www.eastgate.com/Tinderbox/"&gt;Tinderbox&lt;/a&gt;. My personal project files and note-taking documents are just too precious to be left online (this is why I don't and won't use &lt;a href="http://www.stikkit.com/"&gt;Stikkit&lt;/a&gt;). If the occasional monster storm comes along and takes away the Internet for a few days, the worst feeling in the world would be being disconnected from my notes.&lt;/p&gt;

&lt;p&gt;Strangely enough, these online note-takers, organizers, etc, all solve a problem that has plagued me until quite recently: how to do &lt;em&gt;effective&lt;/em&gt; sharing of data between home, work, and laptop? How to not get out of sync? I love Tinderbox and I have a couple of big Tinderbox files that I keep on .Mac's iDisk. This means I &lt;em&gt;usually&lt;/em&gt; have access to it. But sometimes, I forget to sync or close or save the document when I leave work or close the laptop. What about the little bits of random data, not yet filed, or not really worth filing into that larger document? How can I quickly enter, find, and share that info?&lt;/p&gt;

&lt;p&gt;The answer didn't come from any web service, although lord knows I tried a few. The answer came when Tinderbox's developer, &lt;a href="http://eastgate.com/"&gt;Eastgate&lt;/a&gt;, ingeniously started bundling &lt;a href="http://www.barebones.com/products/yojimbo/"&gt;Barebones' Yojimbo&lt;/a&gt; with Tinderbox. I had looked at Yojimbo in the past, but I'd gone through so many personal note taking / note capturing / note filing systems (Mac OS X has MANY). I didn't want to look at another such product and be fighting between "do I file it in Yojimbo? In Tinderbox? DEVONThink? Can I get to it from home?"&lt;/p&gt;

&lt;p&gt;But Yojimbo has a killer feature: &lt;strong&gt;it syncs with .Mac&lt;/strong&gt;! The same tool that I've used to keep calendars and contacts and Safari bookmarks transparently shared between three machines, finally someone made one of these note tools that took advantage. Now I have my enter-a-quick-note, file-it-later system that gets updated and merged automatically. No worries about having an out-of-date iDisk, about forgetting to save and sync. And best of all - it's 100% native and usable offline. And it doesn't get lost in the army of tabs since every goddamn web "app" is now just something that gets lost in a browser window (for those who wonder why I take so long to reply to mail sent to my GMail account, well, GMail sucks as an application compared to a native mail app. I just don't watch it regularly enough to stay on top of things).&lt;/p&gt;

&lt;p&gt;So, anyways, I love a lot of the new web apps. But people need to get a grip. I've been hearing about "the death of the desktop" for eleven or so years now. Stop tricking yourself into thinking you're that high and mighty. If you don't understand the true value of native applications, professional applications, personal data, then you don't understand the desktop's power. As such, you're not going to kill it. Yes, please focus on tools that take work well on the web, tools that are simple yet useful. But don't think for a second that I want to spend every second of my computing day in a web browser, nor do I want to spend every second in an Apollo client. It's not going to replace everything, any more than Java, &lt;a href="http://www.byte.com/art/9703/sec6/art3.htm"&gt;Netscape Constellation&lt;/a&gt;, or even Active Desktop did.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-6783398237748614690?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6783398237748614690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6783398237748614690'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/04/web-will-not-replace-desktop.html' title='The Web Will Not Replace the Desktop'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-4194173936998893453</id><published>2007-02-23T11:55:00.000-07:00</published><updated>2007-02-23T11:56:58.436-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='movie'/><title type='text'>The Saddest Music in the World</title><content type='html'>&lt;p&gt;&lt;a href="http://us.imdb.com/title/tt0366996/"&gt;The Saddest Music In The World&lt;/a&gt; just joined the list of favorites-among-favorites-of-movies.&lt;/p&gt;

&lt;p&gt;Surreal, beautiful, soft, and fuzzy, like &lt;em&gt;&lt;a href="http://us.imdb.com/title/tt0113429/"&gt;Institute Benjamenta&lt;/a&gt;&lt;/em&gt;; but with a classic old showbiz quality and language like &lt;em&gt;&lt;a href="http://us.imdb.com/title/tt0158371/"&gt;Sweet and Lowdown&lt;/a&gt;&lt;/em&gt;; and a bit of melancholy [even a bit of brutality] like &lt;em&gt;&lt;a href="http://us.imdb.com/title/tt0276919/"&gt;Dogville&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href="http://us.imdb.com/title/tt0105378/"&gt;Shadows and Fog&lt;/a&gt;&lt;/em&gt;, and &lt;em&gt;&lt;a href="http://us.imdb.com/title/tt0074486/"&gt;Eraserhead&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It fits in so comfortably with these other films that I love; yet stands on its own in a way that makes me &lt;em&gt;terribly&lt;/em&gt; happy as it feels like it glues them all together. It's this one piece that makes all of the above and more (&lt;em&gt;2046&lt;/em&gt;, &lt;em&gt;City of Lost Children&lt;/em&gt;, etc) all the more lovable.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://us.imdb.com/name/nm0000618/"&gt;Isabella Rossellini&lt;/a&gt;'s beer baroness with the platinum wig is beyond hot. Especially when she shows up with beer filled glass legs.&lt;/p&gt;

&lt;p&gt;And &lt;a href="http://us.imdb.com/name/nm0210218/"&gt;Maria de Medeiros&lt;/a&gt; is beyond cute as the depression era dark bobbed amnesiac singer and dancer. I guess she's probably best known in the U.S. (if at all) as the wife of Bruce Willis's character in &lt;em&gt;Pulp Fiction&lt;/em&gt;. Here, she seems straight out of a Chaplin or Keaton film, while capably leading a spectacle performance of &lt;em&gt;The Song Is You&lt;/em&gt; mid film.&lt;/p&gt;

&lt;p&gt;I love getting lost in spectacle.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-4194173936998893453?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4194173936998893453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/4194173936998893453'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/02/saddest-music-in-world.html' title='The Saddest Music in the World'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-2570456782697434027</id><published>2007-02-23T00:51:00.000-07:00</published><updated>2007-02-23T13:43:10.747-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='flex'/><category scheme='http://www.blogger.com/atom/ns#' term='gui'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><category scheme='http://www.blogger.com/atom/ns#' term='dojo'/><category scheme='http://www.blogger.com/atom/ns#' term='toolkits'/><title type='text'>Flex my Dojo</title><content type='html'>&lt;p&gt;OK. I don&amp;#8217;t get &lt;a href="http://www.flex.org/"&gt;Flex&lt;/a&gt;. By my understanding, &lt;strong&gt;Flex&lt;/strong&gt; is the components / widgets from or for Flash. Actually, I can&amp;#8217;t find a definition. I&amp;#8217;m hitting the main pages, and they all treat me like I already know what Flex is and why I need it. But I don&amp;#8217;t. From the buzz I see around the web, it smells a lot like the promises of Java Applets circa 1996. It&amp;#8217;s the universal platform - rich internet applications! cross platform! run everywhere! It&amp;#8217;s in the browser, so you lose yet another tab / window to some application that&amp;#8217;s not quite a full application!&lt;/p&gt;

&lt;p&gt;As a life long Mac user, I&amp;#8217;m dubious of any cross platform promise. Java with some cross platform toolkit or another has never been a great experience on the Mac. Eclipse fares fairly well, but I&amp;#8217;m still very aware that I&amp;#8217;m in a different environment. This has something to do with look, but really it&amp;#8217;s about feel. There&amp;#8217;s a way that I expect my widgets to feel: ways that I can move around in a text field, responsiveness of a button, and so on. Cocoa&amp;#8217;s text fields benefit from their NeXTStep ancestry which has provided some powerful and extensible features: basic EMacs keys (ctrl-a and ctrl-e to get to begin and end of line, ctrl-k and ctrl-y for kill and yank to a separate copy/paste buffer); spell checking; in place dictionary lookup; often, a common set of search/replace features including &amp;#8216;use selection for find&amp;#8217;; word completion; etc. Input Managers can be installed for even more control. I used an Input Manager to get word completion in early versions of Mac OS X, before it was a built in feature. Now I use &amp;#8220;Edit in TextMate&amp;#8221; to edit HTML TextAreas, emails (from both GMail and Mail.app), even to tweak a filename using TextMate&amp;#8217;s editing tools. Any Cocoa text field, whether it&amp;#8217;s a single line or a large block, can be wired this way without the application&amp;#8217;s knowledge.&lt;/p&gt;

&lt;p&gt;In cross platform toolkits (as well as most Carbon apps), I lose these features. XUL (Firefox/Mozilla); Java AWT, Swing, and whatever the hell Eclipse&amp;#8217;s toolkit is called; and now: Flex. Don&amp;#8217;t get me wrong: I like that these toolkits enable some apps to exist on the Mac at all; but I&amp;#8217;ve seldom been as productive in them as I have been with native apps.&lt;/p&gt;

&lt;p&gt;I took a look at a Flex Quick Start page covering &lt;a href="http://www.adobe.com/devnet/flex/quickstart/using_controls/"&gt;&amp;#8220;Building a simple user interface&amp;#8221;&lt;/a&gt; to see basic Flex in action. As I feared, the controls followed a different set of rules than those I expect. Since the tutorial covered only basic UI, there wasn&amp;#8217;t much that was terribly impressive. I didn&amp;#8217;t see anything that stood out from what I had seen in rich JavaScript/DHTML toolkits like &lt;a href="http://dojotoolkit.org/"&gt;Dojo&lt;/a&gt; and &lt;a href="http://developer.yahoo.com/yui/"&gt;YUI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I decided to do a quick comparison - how did some of the basic Dojo widgets compare to the basic Flex ones? I went to Dojo&amp;#8217;s &amp;#8220;See it in action&amp;#8221; tab and looked at the FormTour, which housed some basic widgets including one of the few &amp;#8220;rich text editors&amp;#8221; that works in Safari. And sure enough, even though some of these widgets had some extra behavior wired in, they were still built on browser native elements. All of my usual keyboard behavior worked as expected in text fields - even in the rich editor.&lt;/p&gt;

&lt;p&gt;I can see how &lt;strong&gt;Flex&lt;/strong&gt; may be useful for fast dynamic graphical components, such as charts. Beyond that, I feel like it&amp;#8217;s another round of the magical cross platform kool-aid; another round of trying to shoehorn a sub-universe within the sub-universe of the web browser. I think it has its uses, but some people seem to think that it&amp;#8217;s the new holy grail of rich internet applications.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve heard this song before, and I&amp;#8217;ve been horribly disappointed almost every time. So far, all I&amp;#8217;ve seen of Flex is a retread of the promises of Java Applets. I would like to see statements about what makes Flex different. Has it learned from Java Applets and the various &amp;#8220;abstract&amp;#8221; Java toolkits that promised a common UI everywhere? Does it have a focus, or will it devolve into servlets and enterprise architecture? Is Flash still an animation platform, a movie player platform, or a GUI/Form platform? Can it handle all of the above? Will Adobe be wiser than Sun and avoid big clashes with Microsoft? &lt;/p&gt;

&lt;p&gt;My gut says not to trust it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-2570456782697434027?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2570456782697434027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/2570456782697434027'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/02/flex-my-dojo.html' title='Flex my Dojo'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-9075917892521757862</id><published>2007-02-13T08:37:00.000-07:00</published><updated>2007-02-13T08:39:02.639-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='soap'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='webservices'/><title type='text'>An update on Python SOAP toolkits</title><content type='html'>&lt;p&gt;Last week, I &lt;a href="http://griddlenoise.blogspot.com/2007/02/soap-web-services-flash-waaa.html"&gt;struggled with implementing a rough SOAP service&lt;/a&gt; in Zope 3 and Python. At the time, the state of SOAP libraries and toolkits for Python appeared to be in rough shape. The only toolkit that seemed to cover enough ground was &lt;a href="http://pywebsvcs.sourceforge.net/"&gt;ZSI&lt;/a&gt;, which also had a recent 2.0 release. ZSI, however, is a sprawling and incoherant mess. Given the SOAP, WSDL, and WS-* specs, who could expect anything more? It was a difficult system to work with as I had to do some brutal massaging of typecodes in order to get my client application to respond.&lt;/p&gt;

&lt;p&gt;At the end of last week, &lt;a href="http://tgwebservices.python-hosting.com/wiki"&gt;TGWebServices&lt;/a&gt; appeared on the scene. TGWebServices brings XML-RPC and SOAP to the &lt;a href="http://turbogears.org/"&gt;TurboGears&lt;/a&gt; web framework. It looked like it was much easier to use than what I had to cobble together.&lt;/p&gt;

&lt;p&gt;And this week, &lt;a href="http://trac.optio.webfactional.com/"&gt;soaplib&lt;/a&gt; showed signs of life with a new release. Soaplib appears to be easier to comprehend than ZSI, and it feels more modern. I wish it had been available a week ago.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-9075917892521757862?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9075917892521757862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/9075917892521757862'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/02/update-on-python-soap-toolkits.html' title='An update on Python SOAP toolkits'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-6099319719284353266</id><published>2007-02-10T09:26:00.000-07:00</published><updated>2007-02-13T08:38:20.193-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='zope3'/><category scheme='http://www.blogger.com/atom/ns#' term='soap'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='flash'/><category scheme='http://www.blogger.com/atom/ns#' term='webservices'/><title type='text'>SOAP. Web Services. Flash. Waaa.</title><content type='html'>&lt;p&gt;As a result of a peculiar chain of events, we&amp;#8217;ve been stuck with a compiled Flash file requiring data off of a web service. The old database is gone. The old server is gone. We have been unable to get much information about the data required. We don&amp;#8217;t have the Flash source. All we have is a single ColdFusion Component that is used a web service via WSDL and SOAP.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve never used ColdFusion. Fortunately, Allaire, er, Macromedia, er, Adobe makes demos available. ColdFusion even comes with a developer version that can live beyond the typical 30 days. So using that, I was able to re-generate the WSDL. I didn&amp;#8217;t understand it, but I had it. Then I installed a demo of Flash Professional. I made a quick document and put some web service links in it by stumbling around, and watched the HTTP/SOAP communication between Flash and Apache/ColdFusion.&lt;/p&gt;

&lt;p&gt;I tried looking at the specs for SOAP, and recoiled. Then I naively thought I could emulate the response as a Zope Page Template emitting XML, looping over the little bit of data that the Flash client wanted. But then I realized that the SOAP style in use was RPC style, and the &amp;#8216;method&amp;#8217; was buried in the posted XML, so I couldn&amp;#8217;t even easily answer the incoming requests.&lt;/p&gt;

&lt;p&gt;Since there&amp;#8217;s no standard SOAP toolkit available for Python, &lt;a href="http://dev.zope.org/Zope3"&gt;Zope 3&lt;/a&gt; only holds a skeleton off which one can hang a SOAP handling REQUEST/RESPONSE pair. I&amp;#8217;m too dumb, or perhaps just too busy, to wrestle with XML parsing myself, and I quickly realized that I needed some kind of toolkit. The data that I saw in the WSDL and SOAP communications appeared far too complicated for me to read and write on my own. Again I tried going to the specs, and again I ran rapidly away as I couldn&amp;#8217;t even figure out how the WSDL connected to the SOAP requests and responses.&lt;/p&gt;

&lt;p&gt;Now, obviously this stuff must work out for somebody. When we first approached this problem, the advice that we got was along the lines &amp;#8220;just put up an XML gateway.&amp;#8221; Um, what? I then realized that the tools were probably doing everything and the developers with whom we were communicating never gave much thought to what was going on. Data format? There is no data format - just put up an XML gateway!&lt;/p&gt;

&lt;p&gt;I can&amp;#8217;t fault anyone for this, per se. We all get abstracted away from something. Many web developers plug along happily without knowing too many details about HTTP. Even when one knows quite a bit about the more advanced or nuanced details of HTTP, one&amp;#8217;s not likely to know much about what&amp;#8217;s going on at the TCP/IP layer.&lt;/p&gt;

&lt;p&gt;While stumbling around Flash Professional, I was a wee bit impressed with how quickly I could make a web service connector, wire it to a table widget, write a quick button-click handler, and could see the results in the table. The ColdFusion Component had its WSDL generated by merely adding &lt;code&gt;?wsdl&lt;/code&gt; to the end of the URL. Since both tools are maintained by Macromedia, er, Adobe, the SOAP messages actually seem to work together.&lt;/p&gt;

&lt;p&gt;But my gods, it sucks.&lt;/p&gt;

&lt;p&gt;I have been so spoiled by HTML and Python, and by Javascript, CSS, Zope, etc. There&amp;#8217;s no end to the value of the web browser&amp;#8217;s &amp;#8220;View Source&amp;#8221; command. With Python, I can read the source of almost any library and figure out its innards if I can&amp;#8217;t get answers from the documentation. CSS and JavaScript are equally open to public viewing. One can easily send plain text as results of HTTP calls - I think that if we had designed the system we&amp;#8217;re wresting with right now, we would have served some kind of delimited text that any tool could read - even human eyes. This week I realized just how hard it is to make a simple SOAP request by hand, leaving me to use a TCP watcher/proxy to test requests and responses.&lt;/p&gt;

&lt;p&gt;Using ZSI from the &lt;a href="http://pywebsvcs.sourceforge.net/"&gt;Python Web Services&lt;/a&gt; project, I was able to mash together a basic SOAP Publisher for &lt;a href="http://dev.zope.org/Zope3"&gt;Zope 3&lt;/a&gt;. It doesn&amp;#8217;t deal with multipart messages, WS-Addressing or whatever the hell that is, &amp;#8220;document/literal&amp;#8221;, or even Request argument processing. Well, that&amp;#8217;s made available on the Parsed Soap instance from ZSI that&amp;#8217;s put on the request. The handlers - the remote procedures / &amp;#8220;controllers&amp;#8221; / &amp;#8220;views&amp;#8221; / whatever you want to call them, still have to do quite a bit of work themselves, at least with the Parsed Soap message. This is because, as far as I can tell, one can&amp;#8217;t do much without using explicitly build custom types, generated from tools like &lt;code&gt;wsdl2python&lt;/code&gt;. Ahhh, this takes me back to all of the crap I had to deal with in ILU/CORBA - baroque generated code that one couldn&amp;#8217;t live without, nor was likely to understand.&lt;/p&gt;

&lt;p&gt;Even after all of that, I had to do a lot of ZSI typecode wrangling in said generated code before I even began to get results like what was generated from ColdFusion. And these are simple calls, really - no request arguments, and the returns are just lists of dictionaries. I stand amazed at just how much work is involved with getting &lt;em&gt;these little details right&lt;/em&gt;, even with a toolkit.&lt;/p&gt;

&lt;p&gt;Even with that toolkit&amp;#8217;s aid, the status line in FireFox would read &amp;#8220;Waiting for data from&amp;#8230;&amp;#8221; This was puzzling, as I thought had finally mangled a seemingly proper Map and Array typecode / values together from the available tools. I started to worry - is there something at the HTTP level that SOAP is doing differently? Does it want chunked results? Is it not closing the connections? I started crawling deep in the networking guts of Zope and Twisted, trying different transfer encodings, verifying that the content-length header matched the content length in the response &amp;#8230; nothing.&lt;/p&gt;

&lt;p&gt;Then, on a whim, I decided to try dimensioning my array. ZSI&amp;#8217;s array, by default, doesn&amp;#8217;t seem to handle specifying some kind of variable length in the array type. So it was generating &lt;code&gt;xsd:anyType[]&lt;/code&gt;. The ColdFusion results had &lt;code&gt;xsd:anyType[n]&lt;/code&gt; with &lt;code&gt;n&lt;/code&gt; being the length of the array. I finally got this working by dynamically altering half of a tuple on a typecode that descended from the strange Result type/typecode that I was building. I&amp;#8217;m not even sure if this is thread safe, come to think of it. But by finally getting that dimension in there, Flash started to respond again.&lt;/p&gt;

&lt;p&gt;Ugh. Remember, &lt;a href="http://wanderingbarque.com/nonintersecting/2006/11/15/the-s-stands-for-simple/"&gt;The S Stands For Simple&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That kind of development - closed, compiled, heavily dependent on tools like Flash that work on few desktops and cost a good chunk of money - is just so foreign to me. I&amp;#8217;m no die-hard open source zealot: I love a lot of the commercial tools and applications for Mac OS X, and would rather use it than any of the &amp;#8220;free desktops&amp;#8221;. But when it comes to web development, I&amp;#8217;m used to dynamic languages and source code that is often readily available or shareable without the need of heavy tools. This is (usually) code that I can read, which can teach me new techniques by real implementation and not vague &amp;#8220;hello world&amp;#8221; examples followed by nightmare specs. I&amp;#8217;m used to the layers below that being either so lightweight or established that I don&amp;#8217;t have to think about them much. I&amp;#8217;m grateful that I still seldom have to think in XML. I&amp;#8217;m glad that I have next to none of the endless Java acronyms memorized. Sure, I guess there&amp;#8217;s a place for them all, but I&amp;#8217;m happy that I&amp;#8217;ve been able to make a living for the past ten years without all of that. And I&amp;#8217;ll be happier still when this particular problem is behind us.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-6099319719284353266?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6099319719284353266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/6099319719284353266'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/02/soap-web-services-flash-waaa.html' title='SOAP. Web Services. Flash. Waaa.'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-1156232976437344368</id><published>2007-02-07T10:28:00.000-07:00</published><updated>2007-02-07T10:31:34.182-07:00</updated><title type='text'>Damn Fine Coffee</title><content type='html'>&lt;p&gt;My &lt;a href="http://davidlynch.com/coffee"&gt;David Lynch Coffee&lt;/a&gt; arrived today. I won't get a chance to try it until tomorrow. But damn! I'm excited.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-1156232976437344368?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1156232976437344368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/1156232976437344368'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2007/02/damn-fine-coffee.html' title='Damn Fine Coffee'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-116303055126943099</id><published>2006-11-08T15:41:00.000-07:00</published><updated>2006-11-08T17:02:31.370-07:00</updated><title type='text'>Zope 3 drives me back to smoking; Pylons may be the sleeper hit of Python web systems</title><content type='html'>&lt;p&gt;So, my &lt;a href="http://griddlenoise.blogspot.com/2006/11/looks-like-i-picked-wrong-week-to-stop.html"&gt;recent problems with Zope 3&lt;/a&gt; that were making me want to resume smoking? Yeah, I&amp;#8217;m a smoker again. Two months clean. The stress just got to be too much.&lt;/p&gt;

&lt;p&gt;I reported my problems to the community, with long and detailed explanations and explorations and pleas for help. The responses? Very few. Far fewer than I would have hoped. I had to scrap upgrading a customer to &lt;strong&gt;Zope 3.3&lt;/strong&gt; after losing a day of work trying to upgrade their database, unsuccessfully. Back to 3.1 they go. And now maybe we&amp;#8217;ll forget about this for another year and have an even harder time upgrading &lt;em&gt;next&lt;/em&gt; year.&lt;/p&gt;

&lt;p&gt;Combined with another day lost chasing an obscure bug (moral of the story - sometimes saying that you implement the interface you implement can be bad, at least in cases where people do identity checks against &lt;em&gt;self&lt;/em&gt; when attempting to retrieve keys out of a system), I&amp;#8217;m pretty pissed. I really want to leave it all behind. I can&amp;#8217;t. But right now, I&amp;#8217;d like to. Even when Zope 3 is working, there are some common activities that seem to take way too long to accomplish. I feel like I&amp;#8217;ve been spending a vast chunk of my time in recent months focusing on building tools and classes on top of Zope 3 that could bring at least &lt;em&gt;some&lt;/em&gt; of what I see and like in Rails and &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; while taking advantage of Zope 3&amp;#8217;s strengths.&lt;/p&gt;

&lt;p&gt;I think Zope 3 can be good for CMS type applications. And even for big business and public applications, it can be a good system. The so-called &amp;#8220;MVC&amp;#8221; stack of the new breed of systems bugs me. I have mixed feelings on templates these days. I think that with good objects, one can generate simple HTML out of Python (or any other programming language) which can then be styled up with CSS. It&amp;#8217;s not appropriate for all situations, but it can be a great tool.&lt;/p&gt;

&lt;p&gt;But, I must admit, I like what I&amp;#8217;ve seen of &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;. I installed it yesterday and ran through a couple of the tutorials (not even getting to the Wiki tutorial). Last night, I decided to convert the &lt;a href="http://euc.cx/toulouse/archives/simple_todo_application/"&gt;Basic To-do Application&lt;/a&gt; that I wrote up last year to Pylons, using &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; as the storage mechanism. Fortunately I had some recent (and inspired, if I do say so) SQLAlchemy work done for Zope 3 whose ideas I was able to borrow to get the basic Alchemy session and engine management working in my application. I had just a single table and thus a single model class (keys: &amp;#8216;id&amp;#8217;, &amp;#8216;description&amp;#8217;, and &amp;#8216;done&amp;#8217;).&lt;/p&gt;

&lt;p&gt;I decided to go for the same minimum of functionality that I had gone for in the &lt;a href="http://euc.cx/toulouse/archives/simple_todo_application/"&gt;Basic To-do&lt;/a&gt; scenario: have a single page that lists completed and incomplete items, with a small form to add new items to the system.&lt;/p&gt;

&lt;p&gt;I got this done - including the writing of the simple SQLAlchemy bridge - in about an hour or hour and a half. No time wasted writing ZCML. No time wasted turning off the ZMI. It was generally quite easy. I made a few faltering steps along the way, but not many.&lt;/p&gt;

&lt;p&gt;I think &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; may be the sleeper hit out of all of the Python &amp;#8220;web frameworks&amp;#8221;. &lt;a href="http://www.turbogears.org/"&gt;TurboGears&lt;/a&gt; got to be overwhelming, immediately. I think that I&amp;#8217;ve just never been a fan of its core components. No offense to their authors. &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; is also a bit overwhelming. It&amp;#8217;s more like Zope: more of a complete environment. That can be great for many uses, but it can be a hindrance for others. I think Django is a terrific system from what I&amp;#8217;ve seen of it, but it&amp;#8217;s too big for me. I have one big system in my life already.&lt;/p&gt;

&lt;p&gt;I have a bit more admiration for the core bits of &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;. While I&amp;#8217;m not a big fan of its syntax, I do think that &lt;a href="http://www.myghty.org/"&gt;Myghty&lt;/a&gt; (a port of Mason) has a substantial amount to offer beyond just being a templating language: namely lots of caching options and intelligence. SkunkWeb was the only other Python web system that I&amp;#8217;ve seen that seems to make caching such a priority. The alternate templating languages one can use in Pylons - &lt;a href="http://kid.lesscode.org/"&gt;Kid&lt;/a&gt; and &lt;a href="http://www.cheetahtemplate.org/"&gt;Cheetah&lt;/a&gt; - are not at all appealing to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.pylonshq.com/WebHelpers/module-index.html"&gt;WebHelpers&lt;/a&gt; are alright as a collection of useful functions for use in templates and controllers. I&amp;#8217;ve had a blast taking the &lt;em&gt;helpers&lt;/em&gt; concept and implementing it in our new Zope 3 based sites. It makes a big difference. With a good base set of helpers that are easy to expand on, it becomes much more desirable to use Python expressions straight up in templates. When I saw the ERB code in many Rails projects, I was impressed - it didn&amp;#8217;t look like the typical mess of common PHP / Classic ASP style development; nor did it have to create yet-another-language on top of its base with hard to learn bind / call semantics. One doesn&amp;#8217;t have to translate::&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;% h.text_field(name='description', size=35, maxlength=100) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;into &amp;#8220;what Python or template or other thing does that there code call?&amp;#8221; compared to::&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;f:text name=quest label="Question:" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The latter coming from &lt;a href="http://spyce.sourceforge.net/"&gt;Spyce&lt;/a&gt;, from an entry on the &lt;a href="http://spyced.blogspot.com/2006/08/spyce-will-not-waste-your-time-code.html"&gt;Spyced Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Actually, I was starting to want to use Spyce in my Zope projects in spaces where we had Helpers doing many common tasks (like seen above) and ZPT was way way way too verbose:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;input tal:replace="structure python:view.h.text_field(...)" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But Spyce has grown up into a richer system, where all I really want is a good basic &lt;em&gt;Python Server Pages&lt;/em&gt; style system. But I&amp;#8217;ve never come across one that I&amp;#8217;ve liked: something small, simple, fast, easy to bind, meant to work with others (ie - not meant to be standalone pages with big blocks of Python, but rather to work with a view/controller class and helpers).&lt;/p&gt;

&lt;p&gt;Back to what I like about &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; - the last two are &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt;, which does the URL dispatch (writing maps like in Rails and Django); and the aggressive use of &lt;a href="http://wsgi.org/"&gt;WSGI&lt;/a&gt; / &lt;a href="http://pythonpaste.org/"&gt;Paste&lt;/a&gt;. These seem to be bringing the &lt;em&gt;Component Architecture&lt;/em&gt; dream of Zope 3 closer to reality as there are additional &lt;a href="http://wsgi.org/wsgi/Middleware_and_Utilities"&gt;filters and middleware&lt;/a&gt; one can put around one&amp;#8217;s application. Paste provides all sorts of cool features. There seem to be a lot of options for interchangeability.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m hoping that Zope 3&amp;#8217;s &amp;#8220;eggification&amp;#8221; will make it easy to write Zope 3 style applications without having to use Zope 3. There are a lot of great libraries and toolkits in the heart of Zope 3 whose liberation would be most welcome. Even without that, I hope to look into what might happen if Zope 3&amp;#8217;s libraries were just added to the Python path so that a &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; application might be written up, using Zope 3&amp;#8217;s concept of Views (Multi-adapters) and Transactions with objects pulled from SQLAlchemy without all of Zope&amp;#8217;s security and nonsense.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-116303055126943099?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116303055126943099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116303055126943099'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/11/zope-3-drives-me-back-to-smoking.html' title='Zope 3 drives me back to smoking; Pylons may be the sleeper hit of Python web systems'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-116257905271459120</id><published>2006-11-03T11:28:00.000-07:00</published><updated>2006-11-03T11:37:32.736-07:00</updated><title type='text'>Looks like I picked the wrong week to stop ...</title><content type='html'>&lt;p&gt;There&amp;#8217;s a great set of lines delivered by Lloyd Bridges in &lt;a href="http://us.imdb.com/title/tt0080339/"&gt;Airplane&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looks like I picked the wrong week to quit drinking. &lt;/li&gt;
&lt;li&gt;Looks like I picked the wrong week to quit smoking.&lt;/li&gt;
&lt;li&gt;Looks like I picked the wrong week to quit sniffing glue.&lt;/li&gt;
&lt;li&gt;Looks like I picked the wrong week to quit amphetamines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes I love Zope 3. Other times, it makes me start to sound like McCroskey. I haven&amp;#8217;t smoked now in two months, but I just smashed my head into another foolish and crappy scenario in Zope 3 (after discovering an incredibly crappy scenario earlier this week). Too stressed and confused to think clearly and engineer / hack my way around this latest situation, I just want to grab a fresh pack of Lucky Strikes (unfiltered, of course).&lt;/p&gt;

&lt;p&gt;Waaa.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-116257905271459120?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116257905271459120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116257905271459120'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/11/looks-like-i-picked-wrong-week-to-stop.html' title='Looks like I picked the wrong week to stop ...'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-116230664548133040</id><published>2006-10-31T07:22:00.000-07:00</published><updated>2006-10-31T07:57:26.003-07:00</updated><title type='text'>Namespace Packages in Python</title><content type='html'>&lt;p&gt;Ian Bicking wrote a &lt;a href="http://blog.ianbicking.org/zope-3-critique.html"&gt;Zope 3 Critique&lt;/a&gt; a couple of weeks or so ago, partially in response to a critique by &lt;a href="http://www.z3lab.org/sections/blogs/jean-marc-orliaguet/2006_09_23_times-they-changin"&gt;Jean-Marc Orliaguet&lt;/a&gt;. I&amp;#8217;ve wanted to write a response of my own, but time has not allowed it. Now, I&amp;#8217;d like to use a few posts to post my own responses to a few items.&lt;/p&gt;

&lt;p&gt;The first point I&amp;#8217;d like to address comes under headline 3, &lt;em&gt;The importance of standards:&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I personally don&amp;#8217;t care much about namespaces. Is zope.formlib any more &amp;#8220;right&amp;#8221; than zope_formlib? Is it any more hierarchical? I don&amp;#8217;t think so. I have one namespace package, but it&amp;#8217;s kind of a historical accident. I wouldn&amp;#8217;t (and don&amp;#8217;t) put any more libraries under that namespace. Each library should stand on its own, so why create these hierarchies? People read too much into those namespaces, which is happening right here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ugh. &lt;code&gt;zope.formlib&lt;/code&gt; is far more &amp;#8220;right&amp;#8221; than zope_formlib. Granted, this is largely opinion. But man, do I love namespaces. &lt;code&gt;zope_formlib&lt;/code&gt; looks like one of those crap-ass hacks and tricks used by the litany of languages who have no namespaces and have to fake it.&lt;/p&gt;

&lt;p&gt;First off - I hate the underscore, and believe it should never enter package / module names. Mixed case package/module names are also evil. &lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt; recommends this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Modules should have short, lowercase names, without underscores.
  &amp;#8230;
  Like modules, Python packages should have short, all-lowercase names, without underscores.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I don&amp;#8217;t follow PEP 8 too religiously, I&amp;#8217;ve found my life to be generally better by trying to stay close to it. I believe that short lowercase names without underscores are a nice constraint, requiring one to think a little bit about what a module/package will entail and how it will be used. If it&amp;#8217;s a module that will be reused frequently, it&amp;#8217;s good to have a name that&amp;#8217;s easy to remember and type.&lt;/p&gt;

&lt;p&gt;At least we don&amp;#8217;t see as much of the following any more:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from DocumentTemplate.DocumentTemplate import DocumentTemplate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ugh.&lt;/p&gt;

&lt;p&gt;Finally, Zope 3 is a large system. I make fairly large systems using many of its pieces, some more than others. Some of those are quite nice to use from an import standpoint when one just imports the sub-package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from zope import component, interface

from interfaces import IBar

class IFoo(interface.Interface):
    def newbar():
        """ returns 'ha!' """

class BarAdapter(object):
    interface.implements(IFoo)
    component.adapts(IBar)

    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#8217;s a trivial and nearly pointless example, but it&amp;#8217;s a pattern I find myself using more and more. I&amp;#8217;d be a much less happy mac if I had to do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import zope_component
import zope_interface
import sqlalchemy_sql
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ugh. Why not just introduce crap like &amp;#8216;require&amp;#8217; and &amp;#8216;use&amp;#8217; and leave this modularism behind?&lt;/p&gt;

&lt;p&gt;There has been one problem, historically, with Python&amp;#8217;s packages: unlike Perl, Ruby, Java, etc, the namespaces in Python are based exclusively on filenames and file system hierarchies. That has meant that a &amp;#8220;namespace package&amp;#8221; like &lt;code&gt;zope.*&lt;/code&gt; would have to include everything. It couldn&amp;#8217;t be distributed and used as smaller chunks easily, whereas if this were Java the packages/modules would use the &amp;#8216;package&amp;#8217; keyword:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;package org.zope.component;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But now &lt;a href="http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages"&gt;SetupTools&lt;/a&gt; allows one to break these pieces up and distribute them separately while still getting the organizational and conceptual benefits of big hierarchical namespaces.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-116230664548133040?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116230664548133040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116230664548133040'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/10/namespace-packages-in-python.html' title='Namespace Packages in Python'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-116222355638603089</id><published>2006-10-30T07:33:00.000-07:00</published><updated>2006-10-30T13:16:48.560-07:00</updated><title type='text'>Simple Nuggets - Recent Interests in Seaside, Io, and more</title><content type='html'>&lt;p&gt;I know that I haven&amp;#8217;t posted much lately. I do have a couple of long draft pieces saved that I haven&amp;#8217;t had time to finish. I don&amp;#8217;t know if I&amp;#8217;ll get back to them, but I&amp;#8217;ll try.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been looking at a lot of different things recently, looking for new inspirations, tools, and/or chances to widen my understanding. I find myself growing increasingly fond of a couple of things in particular: &lt;a href="http://seaside.st/"&gt;Seaside&lt;/a&gt; on the web development side, and &lt;a href="http://www.smalltalk.org/"&gt;Smalltalk&lt;/a&gt;, &lt;a href="http://www.schemers.org/"&gt;Scheme&lt;/a&gt;/LISP, &lt;a href="http://iolanguage.com/"&gt;Io&lt;/a&gt;, and &lt;a href="http://developer.mozilla.org/en/docs/JavaScript"&gt;Javascript&lt;/a&gt; (particularly with the &lt;a href="http://prototype.conio.net/"&gt;Prototype.js&lt;/a&gt; library) on the programming language side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seaside&lt;/strong&gt; interests me on many levels. I&amp;#8217;ve been staring at it with a lustful eye for some time now. There is definitely a place for heavily stateful web apps. &lt;strong&gt;Seaside&lt;/strong&gt; and &lt;a href="http://www.apple.com/webobjects/"&gt;WebObjects&lt;/a&gt; make this a part of their core, where a developer can make an application in a style that is more like a desktop application: less dealing with &lt;em&gt;sessions&lt;/em&gt;, freedom from the typical &lt;em&gt;request-response&lt;/em&gt; cycle, etc.&lt;/p&gt;

&lt;p&gt;But Seaside is more than continuations and callbacks. I love how you generate HTML in it: &lt;strong&gt;NO TEMPLATES!!!&lt;/strong&gt; In a post titled &lt;a href="http://onsmalltalk.com/programming/smalltalk/turtles-all-the-way-down/"&gt;&amp;#8220;Turtles All The Way Down&amp;#8221;&lt;/a&gt;, Ramon Leon writes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Seaside lets me work in Smalltalk, at every level, all the way from programmatic generation of the HTML and Javascript to configuration of the application. No HTML, XML, XSLT, or SQL is necessary to build a web application, just simple, pure Smalltalk. Programming’s never been more fun!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I&amp;#8217;ve made some in-house tools that get us closer to that goal when using Zope 3 and Python. I&amp;#8217;ve started to hate template languages again. Well - I don&amp;#8217;t mind using them for layout intensive work. But as I get more proficient with CSS, even that is changing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[Edit: Moved side rant about Zope and Views and Templates out... This isn't the post for it]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It still stare lustfully at Seaside code, especially things like this very basic example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;renderContentOn: html
    html heading: count.
    html anchor callback: [self increase]; text: '++'.
    html space.
    html anchor callback: [self decrease]; text: '--'.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ooo. Two links are made with anonymous functions that call &lt;code&gt;self increase&lt;/code&gt; and &lt;code&gt;self decrease&lt;/code&gt; respectively. There&amp;#8217;s no &amp;#8220;absolute URL&amp;#8221;-ness going on. There&amp;#8217;s no &amp;#8220;how do I make it so that increase can be called through the web?&amp;#8221;. No exposure decorator. No seven lines of XML code each for &amp;#8216;increase&amp;#8217; and &amp;#8216;decrease&amp;#8217; to be made into separate views. And no template. Just a solid binding between a link on a form and real code.&lt;/p&gt;

&lt;p&gt;Seaside is a testament to the power of Smalltalk. People think that Seaside is all about continuations, and if they get just that part down, they&amp;#8217;ve made something to compete. But it&amp;#8217;s more than that: Seaside is a tool for building web applications in pretty much the same way one makes a desktop application. It&amp;#8217;s not the tool or style for every job, but it definitely has its place.&lt;/p&gt;

&lt;p&gt;In a recent bit of work we've done in Zope 3, I would have loved to have something like Seaside, especially for the checkout process. I've tried to engineer that process as well as I could, with extra preconditions and redirectors on pages to ensure that all desired information is supplied (ie - so that one can't jump from step 1 to step 4). With Seaside I could have encompassed the in a &lt;code&gt;WATask&lt;/code&gt; component, expressing the checkout workflow as normal Python code: &lt;code&gt;while shippingAddressRequired and (not order.shippingAddress): yield self.askForShippingAddressForm()&lt;/code&gt; (or something like that). The shopper could never accidentally (or purposefully) get past that point without supplying the right information. Doing this with preconditions, sessions, hidden form fields, cookies, etc, is all possible. But it can be a lot more code overhead.&lt;/p&gt;

&lt;p&gt;Back to the other interests listed, really quickly: I&amp;#8217;ve used &lt;a href="http://www.lisp.org/"&gt;LISP&lt;/a&gt; on very rare occasions (for customizing EMacs, basically, back in the day). I&amp;#8217;ve never quite understood the appeal that LISP / &lt;a href="http://www.schemers.org/"&gt;Scheme&lt;/a&gt; have for some people until recently. While I enjoy and will probably continue to work in general purpose languages like &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt;, I&amp;#8217;ve started to grow fond of these languages that are built on very simple precepts. &lt;a href="http://www.smalltalk.org/"&gt;Smalltalk&lt;/a&gt; has practically no syntax: it&amp;#8217;s all messages. And I really like that &lt;a href="http://www.squeak.org/"&gt;Squeak&lt;/a&gt; is written in itself - there&amp;#8217;s just something impressive about that. On a related topic, I checked on the progress of &lt;a href="http://codespeak.net/pypy/"&gt;PyPy&lt;/a&gt; and was very impressed. Like Squeak, which has a small subset-of-smalltalk-to-C translator for generating the core pieces from Smalltalk itself, PyPy is Python written in Python, with translators to lower-level languages. &lt;/p&gt;

&lt;p&gt;Regarding Scheme, I found a Scheme translator for Smalltalk and have spent a small amount of time playing with it this weekend. I came away impressed with how easy it is to parse and process Scheme, and how easy it is to implement it and its primitives in quite easily readable Smalltalk. The &amp;#8220;everything is a list&amp;#8221; (&amp;#8216;car&amp;#8217; and &amp;#8216;cdr&amp;#8217;) power finally came through to me as I browsed through the Smalltalk code to see how things that are keywords and operators in other languages (&amp;#8216;+&amp;#8217;, &amp;#8216;if&amp;#8217;, etc) were implemented by just using car and cdr (the head and remainder of any list/pair, on which all things are based).&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve also become very interested in prototype-based programming. With prototype based programming, one has Objects but without classes and metaclasses and on and on. I&amp;#8217;ve known about prototype based programming for some time, but I&amp;#8217;ve only recently started to appreciate it. It&amp;#8217;s radically simple. Looking around at Prototype based languages, I came across the relative newcomer &lt;a href="http://iolanguage.com/"&gt;Io&lt;/a&gt;. Io has no keywords - which, again, I find quite interesting and provocative. And powerful. It&amp;#8217;s message based, which I like, and it has no classes. You just clone something to make something else. A simple object example from the &lt;a href="http://iolanguage.com/about/samplecode/"&gt;sample code&lt;/a&gt; page:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Account := Object clone do(
    balance := 0
    deposit  := method(v, balance = balance + v)
    withdraw := method(v, balance = balance - v)
    show := method(writeln("Account balance: $", balance))
)

myAccount := Account clone
myAccount show
"Depositing $10\n" print
myAccount deposit(10)
myAccount show
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh yeah - and the minimalist in me swoons over its web site.&lt;/p&gt;

&lt;p&gt;There it is - a scattering of a portion of the thoughts that occupy my brain when I have the chance to take a breath at work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-116222355638603089?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116222355638603089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/116222355638603089'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/10/simple-nuggets-recent-interests-in.html' title='Simple Nuggets - Recent Interests in Seaside, Io, and more'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115930182382938800</id><published>2006-09-26T14:06:00.000-06:00</published><updated>2006-09-26T14:17:13.006-06:00</updated><title type='text'>Browser Side</title><content type='html'>&lt;p&gt;I&amp;#8217;ve surprised myself by starting to enjoy doing browser-side development in CSS and JavaScript more than I enjoy the server side. &lt;a href="http://prototype.conio.net/"&gt;Prototype&lt;/a&gt;, &lt;a href="http://script.aculo.us/"&gt;Scriptaculous&lt;/a&gt;, &lt;a href="http://www.danwebb.net/2006/9/3/low-pro-unobtrusive-scripting-for-prototype"&gt;LowPro&lt;/a&gt;, and a comfortably growing in-house library have gone a long way towards helping with this shift, along with finally getting down into the guts of CSS and learning about the box model. Tools like &lt;a href="http://www.joehewitt.com/software/firebug/"&gt;FireBug&lt;/a&gt; and the &lt;a href="https://addons.mozilla.org/firefox/60/"&gt;Web Developer Toolbar&lt;/a&gt; for &lt;a href="http://www.mozilla.com/firefox/"&gt;Firefox&lt;/a&gt; have helped out tremendously, as well as native Mac OS X tools like &lt;a href="http://culturedcode.com/xyle/"&gt;XyleScope&lt;/a&gt; and direct linking to the CSS specs from within &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; (very helpful when wanting to learn the real details about any given property).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115930182382938800?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115930182382938800'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115930182382938800'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/09/browser-side.html' title='Browser Side'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115574373084477076</id><published>2006-08-16T09:14:00.000-06:00</published><updated>2006-08-16T09:55:30.930-06:00</updated><title type='text'>Iterators, Generators, Array Comprehensions, and More for JavaScript 1.7</title><content type='html'>&lt;p&gt;I saw a link today from &lt;a href="http://wmf.editthispage.com/2006/08/15"&gt;Hack The Planet&lt;/a&gt; titled &lt;em&gt;&amp;#8220;What&amp;#8217;s new in JavaScript 1.7: Lisp/Python!&amp;#8221;&lt;/em&gt;, pointing to &lt;a href="http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7"&gt;a &amp;#8220;new in JavaScript 1.7&amp;#8221; page at developer.mozilla.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, of course I had to follow this and see what he meant. Sure enough, JavaScript 1.7 starts to look a bit more like Python in some places. From the &amp;#8220;What&amp;#8217;s new&amp;#8221; document, this is an &lt;a href="http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Array_comprehensions"&gt;Array Comprehensions&lt;/a&gt; example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var ten_squares = [i * i for (i in range(0, 10))];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Take out the word &lt;code&gt;var&lt;/code&gt;, and that&amp;#8217;s 100% valid Python (although Python can get by here with less parentheses and without the semicolon).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Iterators"&gt;Iterators in JavaScript 1.7&lt;/a&gt; are also very similar to Python&amp;#8217;s, with objects providing an optional &lt;code&gt;__iterator__&lt;/code&gt; slot. Iterators just implement a &lt;code&gt;next()&lt;/code&gt; method, and raise &lt;code&gt;StopIteration&lt;/code&gt; when done. &lt;a href="http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7#Generators"&gt;Generators&lt;/a&gt; turn functions into iterators by using the &lt;code&gt;yield&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Very interesting. For a while, I was a fan of the &lt;a href="http://mochikit.com/"&gt;MochiKit&lt;/a&gt; JavaScript libraries. MochiKit takes a lot of inspiration from Python and some Python toolkits like &lt;a href="http://twistedmatrix.com/"&gt;Twisted&lt;/a&gt;. Among other things, it provides &lt;a href="http://mochikit.com/doc/html/MochiKit/Iter.html"&gt;MochiKit.Iter&lt;/a&gt;, which brings a lot of the Python &lt;code&gt;itertools&lt;/code&gt; functions as well as basic Iterator concepts to current JavaScript, if desired.&lt;/p&gt;

&lt;p&gt;I must admit, however, that while I like MochiKit for its general philosophy and the fact that it&amp;#8217;s one of the best documented &amp;#8216;New Age&amp;#8217; JavaScript libraries/frameworks/toolkits around, I&amp;#8217;ve gone back to using &lt;a href="http://prototype.conio.net/"&gt;Prototype.js&lt;/a&gt; for most of my work. MochiKit is big. It&amp;#8217;s powerful, but big. Yet I found myself straining to copy over some really useful little functions from Prototype, some done while trying to make the Ajax calls a little easier to work with. Ultimately, I find that my Prototype.js based code tends to be easier to read, write, and comprehend. I&amp;#8217;m a JavaScript outsider, and Prototype.js pulls enough tricks to make programming much more familiar and convenient. While it&amp;#8217;s not well documented, its source code is actually quite easy to read. Both toolkits are nice, but I now reserve MochiKit for heavy-lifting situations only.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115574373084477076?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115574373084477076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115574373084477076'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/08/iterators-generators-array.html' title='Iterators, Generators, Array Comprehensions, and More for JavaScript 1.7'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115515653045163727</id><published>2006-08-09T14:48:00.000-06:00</published><updated>2006-08-09T14:48:50.463-06:00</updated><title type='text'>Congratulations, TextMate!</title><content type='html'>&lt;p&gt;Congratulations to Allan Odgaard and everyone else involved with &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; on winning an &lt;a href="http://developer.apple.com/ada/"&gt;Apple Design Award&lt;/a&gt; for &lt;strong&gt;Best Mac OS X Developer Tool&lt;/strong&gt;. TextMate has so greatly improved my development life, finally allowing me to (where possible) work on my desktops / laptop instead of on a development server as I&amp;#8217;ve done for so many years.&lt;/p&gt;

&lt;p&gt;A little bit of my development day today: Using Mac OS X terminal to test a new date-range formatting function. The results were clipped directly into a Circus Ponies &lt;a href="http://www.circusponies.com/"&gt;Notebook&lt;/a&gt; page without leaving Terminal via Mac OS X Services. All of those clippings were then brought into Hog Bay Software&amp;#8217;s excellent &lt;a href="http://www.hogbaysoftware.com/product/writeroom"&gt;WriteRoom&lt;/a&gt; where I went into full screen mode to turn the test results into documentation that could run via Python&amp;#8217;s super-cool &lt;a href="http://docs.python.org/lib/module-doctest.html"&gt;Doctest&lt;/a&gt; tool. Using &lt;em&gt;WriteRoom&lt;/em&gt; for this allowed me to focus on writing the documentation without distractions: it was like being back in the old old 70&amp;#8217;s terminals: green text, black screen. No syntax coloring, no modes, nothing.&lt;/p&gt;

&lt;p&gt;A couple of times while &lt;em&gt;writing&lt;/em&gt; the documentation, I was able to use the globally installed &lt;strong&gt;Edit in TextMate&amp;#8230;&lt;/strong&gt; command that lets just about any Cocoa text field / area / etc be editable in a TextMate window. I used this during the main &lt;em&gt;writing&lt;/em&gt; to do some big find/replace runs (some names that I had imported in the terminal were redundant in the test documentation). So, from WriteRoom, I hit &lt;strong&gt;Edit in TextMate&amp;#8230;&lt;/strong&gt; (actually, I just hit &lt;em&gt;control-command-e&lt;/em&gt;) and a new TextMate window opens up with the contents of my WriteRoom document. I used TextMate&amp;#8217;s nicer search/replace tools to do some mass fixing, hit &amp;#8216;save&amp;#8217; to send the results back to WriteRoom, and closed the window - which caused a direct return to WriteRoom.&lt;/p&gt;

&lt;p&gt;Again, this was nice for this situation since I could use a specialized no-frills tool to focus on the words I wanted to write. When I was done with the writing, I copied everything out of WriteRoom and went back to TextMate to paste the documentation in the docstring of this function. At that point I could use TextMate&amp;#8217;s tools and powers to format the results (wrap / indent properly, apply some reStructuredText styling, etc).&lt;/p&gt;

&lt;p&gt;What a cool little collection of tools.&lt;/p&gt;

&lt;p&gt;And happily, when the documentation test was executed, it ran on the first pass.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115515653045163727?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115515653045163727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115515653045163727'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/08/congratulations-textmate.html' title='Congratulations, TextMate!'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115464636481928918</id><published>2006-08-03T17:06:00.000-06:00</published><updated>2006-08-03T17:06:26.643-06:00</updated><title type='text'>Leopard, Fake Screenshot Winners, and Dreams</title><content type='html'>
&lt;p&gt;
&lt;a href="http://phillryu.com/2006/07/26/fake-leopard-screenshot-contest-winners-better-than-the-real-thing/"&gt;These are absolutely amazing&lt;/a&gt;. Phill Ryu held a &lt;em&gt;Fake Leopard Screenshot Contest&lt;/em&gt; in anticipation of next week’s &lt;a href="http://developer.apple.com/wwdc/"&gt;Apple Developer Conference&lt;/a&gt; which will unveil the next version of &lt;strong&gt;Mac OS X&lt;/strong&gt;. Some of these people put a lot of time into these designs and some of theme are quite interesting. The &lt;a href="http://phillryu.com/leopard.php?person=eric"&gt;winning shots&lt;/a&gt; by Eric Patterson are quite nice, going for user experience: more views of data “your way”, nice collections of information. Some of it reminds me of the pie-in-the-sky Longhorn screen shots showcasing all of the power of Windows Vista.. well, all the power that was hoped… And Eric’s &lt;em&gt;tabbed finder&lt;/em&gt; is about the only mock-up that I’ve seen that I would use.&lt;/p&gt;

&lt;p&gt;Honestly - why are people so obsessed with a tabbed Finder? I like the Finder browser (metal) windows, I like Column view, but I don’t want tabs. What I do want is “Open Folder in New Browser Window” so I can branch off at any time. What I would like - a shelf. The sidebar in the Finder is nice. I use it like Tabs anyways, but it’s better. It’s so easy to throw folders on there for one time use for easy copying. And it’s useful when working on long-term projects for rapid access to documents. But it doesn’t deal with drives going away and coming back very well.&lt;/p&gt;

&lt;p&gt;Anyways, back to the fake screenshots. The final runner-up is acknowledged as being the most out there, and the most controversial. I like this guy for - &lt;em&gt;ahem&lt;/em&gt; - thinking differently. Stephen Sciliano &lt;a href="http://phillryu.com/leopard.php?person=stephen"&gt;wraps everything up into a single window interface&lt;/a&gt;, with multiple panes. I’ve seen some Unix window managers that do similar, with a heavy focus on being text-only. I think I know some people who are big fans of it. Sciliano’s mock-up reminds me a bit of OpenDoc gone wild, and reminds me of Microsoft’s new UI for &lt;a href="http://www.microsoft.com/office/preview/ui/highlights.mspx"&gt;Office 2007&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another runner-up, &lt;a href="http://phillryu.com/leopard.php?person=nathan"&gt;Nathan Ziarek&lt;/a&gt;, focuses heavily on metadata - particularly on making metadata easy and obvious. Among other things, his shots showcase being able to associate files and other items with To Do items in iCal, and associating files with contacts so that viewing them from the contact view can link to associated files and other objects.&lt;/p&gt;

&lt;p&gt;And that brings me back to one of my favorite Longhorn images (which I haven’t been able to find) was one that showed a Contact. Well, not a contact, but everything associated with that contact: IM chats, phone calls, files, events, etc. In one window, nice and clean. I think it was a WinFS showcase item. I haven’t seen anything like it in Longhorn / Vista screen shots over the past couple of years. That’s something I would like: ways to just group a lot of different information together without requiring a third party app. &lt;/p&gt;

&lt;p&gt;I want this most in the home studio. I have lots of audio files and (now) a rapidly growing iPhoto library. The audio files at home that I’m concerned about are not the songs in my iTunes library, but all of the work for &lt;em&gt;Eucci&lt;/em&gt;, &lt;em&gt;aodl&lt;/em&gt;, etc. Most of them are raw little audio bits, not fit for a loop library or management through a dedicated audio program: they’re AIFF’s of various lengths in various states of processing. I use labels (the little color codes in the Finder) to highlight some of them, such as completed pieces or raw sources (usually the two kinds worth keeping around), but they still tend to get lost, especially if I’ve been away for a while. It would be nice if it were easier to tag those files, to group them dynamically, to associate them with a particular contact to whom I’ve promised an album, to associate them with a to-do so that I have a better sense of what I was doing if I have been away for a while. “Oh yeah, I need to just finalize the levels on that track and I can send it to …”.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115464636481928918?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115464636481928918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115464636481928918'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/08/fake-leopard-screenshot-contest.html' title='Leopard, Fake Screenshot Winners, and Dreams'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115402284178834190</id><published>2006-07-27T11:54:00.000-06:00</published><updated>2006-07-27T11:54:01.943-06:00</updated><title type='text'>Scope, Hog Bay Software, and Knowing Your Place</title><content type='html'>&lt;p&gt;The staggering array of personal shit management (PSM) tools for Mac OS X seems to be growing, constantly. There are Outliners, Notebooks, personal hierarchical databases, and so on.&lt;/p&gt;

&lt;p&gt;Many of the tools may look similar on the surface. Besides downloading all of the trials or crawling through the archives of &lt;a href="http://www.atpm.com/Back/atpo.shtml"&gt;About This Particular Outliner&lt;/a&gt;, how can you decide which tool may be right for you? Many companies do nothing but expound on their particular feature set, but when there are many similar features between applications, it&amp;#8217;s not always easy to filter out the two or three items that make a particular application different from substantially different from its competitors. Some companies have comparison tables between their product and one or two (usually popular) competitors. But these tables often show the main company&amp;#8217;s product as doing more! more! more! for the same or lower price. And while that can be helpful when evaluating your options, it&amp;#8217;s not exactly unbiased research that you&amp;#8217;re reading.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s why I was impressed yesterday when I took a glance at the page for Hog Bay Software&amp;#8217;s &lt;a href="http://www.hogbaysoftware.com/product/mori"&gt;Mori&lt;/a&gt;. The lead-in paragraph and accompanying screen shot didn&amp;#8217;t sell me on it. I have too many &amp;#8220;digital notebooks&amp;#8221; as it is, and the screen shot reminded me of &lt;a href="http://www.devon-technologies.com/products/devonthink/"&gt;DEVONThink&lt;/a&gt;. But I scrolled down the page, skimming the text and looking at screen shots, and at the bottom of the page I found a paragraph with a lead-in &lt;strong&gt;Is Mori the best choice for you?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Buying a note manager can be a daunting process with many choices. On one hand you have great outlining programs. If your goal is lists and outlines, try &lt;a href="http://www.omnigroup.com/omnioutliner/"&gt;OmniOutliner&lt;/a&gt;. On the other hand you have powerful and complex note databases. If your goal is to create reference database of &amp;#8220;everything&amp;#8221; try &lt;a href="http://www.devon-technologies.com/products/devonthink/"&gt;DevonThink&lt;/a&gt;. But if you need something in-between, give Mori a try. We think it&amp;#8217;s the ideal place for your day to day notes, projects, and activities.&lt;/p&gt;
  
  &lt;p&gt;&lt;a href="http://www.hogbaysoftware.com/product/mori"&gt;Mori Product Information Page, Hog Bay Software, viewed July 26 2006&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Wow. I think that&amp;#8217;s refreshingly honest. It gives Mori a good scope, and it differentiates itself by saying &amp;#8220;if you need more than lists, but less than a database of everything, we&amp;#8217;re your app. But if you need those things, by all means, go next door and get them.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.hogbaysoftware.com/"&gt;Hog Bay Software&lt;/a&gt; now has my attention. Looking at their other offerings I noticed the application &lt;a href="http://www.hogbaysoftware.com/product/clockwork"&gt;Clockwork&lt;/a&gt;, a computer timer program. You know, the buzz-me with an alarm, remind of this, etc, kind. Its page also has a &amp;#8220;right choice for you?&amp;#8221; paragraph. They also are the developers of &lt;a href="http://www.hogbaysoftware.com/product/writeroom"&gt;WriteRoom&lt;/a&gt;, a &amp;#8220;distraction free full screen writing environment.&amp;#8221; WriteRoom is one of those applications like 37Signals&amp;#8217; &lt;a href="http://www.writeboard.com/"&gt;Writeboard&lt;/a&gt;. Simple plain text writing, no formatting toolbars, no wysiwyg (which is still painful in most browsers), just words. 37Signals has a nice post about the &lt;a href="http://37signals.com/svn/archives2/a_world_of_difference_between_writing_and_word_processing.php"&gt;difference between word processing and writing&lt;/a&gt;. They are different tools with different scopes. For the time in writing when the words matter more than layout and formatting, it&amp;#8217;s wonderful to be distraction free.&lt;/p&gt;

&lt;p&gt;And it&amp;#8217;s refreshing to look at a software page and wonder &amp;#8220;but why would I use that if there&amp;#8217;s this tool and that tool and that other tool available?&amp;#8221; only to find an answer that says &amp;#8220;hey, that other tool might work better for you if you&amp;#8217;re looking for something that does feature X really well.&amp;#8221;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115402284178834190?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115402284178834190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115402284178834190'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/07/scope-hog-bay-software-and-knowing.html' title='Scope, Hog Bay Software, and Knowing Your Place'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115389319302246918</id><published>2006-07-25T21:02:00.000-06:00</published><updated>2006-07-25T23:53:13.080-06:00</updated><title type='text'>Typography, languages, beauty, ramble ramble ramble</title><content type='html'>&lt;p&gt;A post that&amp;#8217;s been making the rounds lately, it seems, is Tim Bray&amp;#8217;s &lt;a href="http://www.tbray.org/ongoing/When/200x/2006/07/24/Ruby"&gt;&amp;#8220;On Ruby&amp;#8221;&lt;/a&gt;. Bray praises Ruby as being &amp;#8220;remarkably, perhaps irresistibly, attractive,&amp;#8221; especially for people (like Bray) who are proficient in Perl and Java. As some see Bray&amp;#8217;s post as a pro-dynamic-language post as much as (or more than) a pro-Ruby post, I finally decided to take a read.&lt;/p&gt;

&lt;p&gt;As I was reading, this paragraph jumped out at me:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Maybe the single biggest advantage is readability. Once you’ve got over the hump of the block/yield idiom, I find that a chunk of Ruby code shouts its meaning out louder and clearer than any other language. Anything that increases maintainability is a pearl beyond price.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I&amp;#8217;ve still done very little actual coding in Ruby, I have found the above to be true with &lt;em&gt;most&lt;/em&gt; code that I&amp;#8217;ve come across. I love reading source. Well, perhaps &lt;strong&gt;read&lt;/strong&gt; is not the right term. I love to look at it, just as I love to look at screen shots when reading about any particular piece of desktop software. I have a deep love for design, and much of my own personal artwork is grounded more in design aesthetics than conventional art aesthetics, so I often take a visual approach to code. And what appeals to me at any given moment often shifts. &lt;/p&gt;

&lt;p&gt;Ruby code tends to be quite attractive to me these days. I&amp;#8217;m not sure why, entirely. But I think Bray hits it on the head in his next paragraph. Funny thing: when I was reading the paragraph quoted above - regarding readability - the thought &amp;#8220;hmm, what about Python?&amp;#8221; ran through my head. That, too, is answered in the following.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In theory, Python ought to do better, lacking all those silly end statements cluttering up the screen. But in practice, when I look at Python code I find my eyes distracted by a barrage of underscores and double-quote marks. Typography is an important component of human communication, and Ruby’s, on balance, is cleaner.
  &lt;a href="http://www.tbray.org/ongoing/When/200x/2006/07/24/Ruby"&gt;Tim Bray, &amp;#8220;On Ruby&amp;#8221;, Jul 24 2006&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Typography. Could that really be it? You know, he may be right. Phillip Eby recently had a post about &lt;a href="http://dirtsimple.org/2006/07/schema-analysis-and-need-for-python.html"&gt;Python Based DSLs&lt;/a&gt;. He brings up a couple of the elements that seem to give Ruby the power to make nice little domain-specific-languages in, which projects like Rails use to great advantage.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;However, Ruby&amp;#8217;s advantage in this area basically boils down to two things: being able to apply functions without parentheses, and having code blocks. The first is nice because it makes it possible to create commands or pseudo-statements, and the second is a necessity because it allows those pseudo-statements to encompass code blocks. Without at least the second of these features, Python is never going to be suitable for heavy-duty DSL construction.
  &lt;a href="http://dirtsimple.org/2006/07/schema-analysis-and-need-for-python.html"&gt;Phillip J Eby, &amp;#8220;Schema Analysis and the need for Python-based DSLs&amp;#8221;, Jul 15 2006&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think Eby captures a couple of the more common elements that make this work for Ruby. However, I think there are a couple of other elements that make Ruby look particularly good in this area. The first is Ruby&amp;#8217;s use of &lt;em&gt;Symbols&lt;/em&gt;. One description I found for Symbols (I forget the source) is that they&amp;#8217;re like Strings that you&amp;#8217;ll never show to the user. Therefor they don&amp;#8217;t need to be printed. They also seem to work with the Ruby&amp;#8217;s equivalent (as far as I understand it) of Python&amp;#8217;s &lt;em&gt;identity comparison&lt;/em&gt; (in python: &lt;code&gt;obj is None&lt;/code&gt;, &lt;code&gt;foo is marker&lt;/code&gt;). I&amp;#8217;d always seen Symbols in Ruby code, but it was Rails that really made me take notice, as they&amp;#8217;re used all over the place. Symbols in Ruby are those things that begin with a colon:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;finished = Todo.find :all, :include =&amp;gt; [:something]
render :action =&amp;gt; 'error'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is something about that that just looks kindof&amp;#8230; nice. &lt;code&gt;:all&lt;/code&gt;. In my editor, Symbols are colorized differently than strings, which helps them stand out even more. &lt;code&gt;find :all&lt;/code&gt;. Not &lt;code&gt;findAll()&lt;/code&gt; or &lt;code&gt;find(all=True)&lt;/code&gt; or &lt;code&gt;find('all')&lt;/code&gt; like one &lt;em&gt;might&lt;/em&gt; have in Python (all of which are OK solutions, but man.. those Symbols).&lt;/p&gt;

&lt;p&gt;Now as much as the blocks, Symbols, and optional parenthesis seems to help Ruby - it&amp;#8217;s the meta-programming that really seems to stand out. This is some ActiveRecord code from &lt;a href="http://www.rousette.org.uk/projects/"&gt;Tracks&lt;/a&gt;, a GTD-focused task management application written in Rails:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Project &amp;lt; ActiveRecord::Base

  has_many :todos, :dependent =&amp;gt; true
  has_many :notes, :dependent =&amp;gt; true, :order =&amp;gt; "created_at DESC"
  belongs_to :user
  acts_as_list :scope =&amp;gt; :user

  attr_protected :user

  # Project name must not be empty
  # and must be less than 255 bytes
  validates_presence_of :name, :message =&amp;gt; "project must have a name"
  validates_length_of :name, :maximum =&amp;gt; 255, :message =&amp;gt; "project name must be less than %d"
  validates_uniqueness_of :name, :message =&amp;gt; "already exists", :scope =&amp;gt;"user_id"

  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These are statements in the class level that read&amp;#8230; easily. &lt;strong&gt;A project has many todos and notes and belongs to a user. It must have a unique name for an individual user that is less than 255 characters.&lt;/strong&gt; Wow. That is a lot of information in a small space. And you don&amp;#8217;t think of &lt;code&gt;has_many&lt;/code&gt; as a function or method or something that&amp;#8217;s pulling of crazy metaclass trickery: it reads like a statement. I see this done so often in Ruby that writing things like &lt;code&gt;has_many&lt;/code&gt; are not that difficult (I&amp;#8217;m not talking about the implementation behind it, since O-R mapping is always a beast; I&amp;#8217;m talking about how easy it is to operate on the &lt;code&gt;Project&lt;/code&gt; class in-line like that).&lt;/p&gt;

&lt;p&gt;Now this is &lt;em&gt;doable&lt;/em&gt; in Python. Zope 3 has applied similar things, albeit sparingly (and with good cause). You can&amp;#8217;t really monkey with the &lt;code&gt;Project&lt;/code&gt; class in Python while inside the &lt;code&gt;class&lt;/code&gt; statement without resorting (at the least) to execution frame tricks. But one you&amp;#8217;re comfortable with them - you can start doing some nice things. In the early days of Zope&amp;#8217;s Interface system, declaring support for what was implemented by class instances looked like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Project(Base):
    __implements__ = IProject
    __used_for__ = IUser
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it can be this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Project(Base):
    implements(IProject)
    adapts(IUser)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In a SQLAlchemy based system I&amp;#8217;ve worked on for a major project I&amp;#8217;m involved with, I&amp;#8217;ve applied some of these techniques to yield code like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class FeeScale(Base):
    act.baseTable(
        fee_scale, classify='type',
        order_by=fee_scale.c.price_floor,
    )

    @classmethod
    def getFeeForPrice(cls, price, owner, default=None):
        fee = cls.selectFirst(
            (cls.c.price_floor &amp;lt; price)
            &amp;amp; (price &amp;lt;= cls.c.price_ceil)
            &amp;amp; (cls.c.owner_id == owner.id)
        )
        if fee:
            return fee.service_fee
        return default

class RetailerFeeScale(FeeScale):
    act.whenClassified('retailer')
    implements(interfaces.IRetailerFeeScale)
    classProvides(interfaces.IQueryableFeeScale)

    owner = props.One(ILinkedFee['owner'])

class WholesalerFeeScale(FeeScale):
    act.whenClassified('wholesaler')
    implements(interfaces.IWholesalerFeeScale)
    classProvides(interfaces.IQueryableFeeScale)

    owner = props.One(ILinkedFee['owner'])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It doesn&amp;#8217;t read quite as nice as the Ruby example above, and it&amp;#8217;s from a different problem domain. But it&amp;#8217;s not bad&amp;#8230; I had to move my validation and relationship-related items into Zope Schema fields which are about specifying design and contracts. Since I use them heavily in order to do things like form generation, &lt;code&gt;ILinkedFee['owner']&lt;/code&gt; contains the information about the relationship, &lt;code&gt;props.One&lt;/code&gt; is a Python descriptor that uses that field information in conjunction with SQLAlchemy&amp;#8217;s properties to handle relationships between two mapped objects.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class ILinkedFee(Interface):
    owner = schema.HasOne(
        title=u"Owner",
        model=Ref.relative('.base.Owner'),
        options=dict(lazy=True),
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are upsides and downsides to this setup. One really big downside is that there&amp;#8217;s no single place to see everything going on with &lt;code&gt;RetailerFeeScale&lt;/code&gt;. Earlier versions of this code had functions that played tricks inside of a class suite to spell things like &lt;code&gt;hasOne(...)&lt;/code&gt; without assignment or using a second mechanism such as Interface schemas. That code, however, was playing too many tricks and causing too much trouble. And this setup works well with Zope 3.2 and the latticework I&amp;#8217;ve put in place to support it.&lt;/p&gt;

&lt;p&gt;But it seems like a lot of work, learning metaclasses and descriptors and decorators and getframe() trickery. However, looking at this mammoth project&amp;#8217;s code tonight, I&amp;#8217;m impressed by how concise and readable most of it is. Ruby and Smalltalk have both been major influences on me lately, even if I seldom get to actually use those languages directly. God I wish for blocks though. I think that the &lt;code&gt;with&lt;/code&gt; statement in Python 2.5 will help. A place where Blocks seem especially powerful is their ability to construct an object, yield it to the block, let the block do things with it (set attributes, etc), and then the thing which yielded control can do more things with the object. Hmm. That&amp;#8217;s vague. Here&amp;#8217;s one case: explicitly saving (flushing) a SQL Alchemy object after doing a bunch of updates. It&amp;#8217;s one of those lines that bugs me: it&amp;#8217;s something important (it should happen), but it&amp;#8217;s not necessarily important to the business logic. It&amp;#8217;s small, and it often blends in with its surroundings:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fee = Fee.get(1)
fee.floor = 0.0
fee.ceil = 10.0
fee.price = 1.25
fee.save()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Small annoyance, really. But it does bug me. I &lt;em&gt;believe&lt;/em&gt; that the &lt;code&gt;with&lt;/code&gt; statement might help out, ensuring that the save happens immediately:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;with savable(Fee.get(1)) as fee:
    fee.floor = 0.0
    fee.ceil = 10.0
    fee.price = 1.25
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And with that, I put to bed this evening&amp;#8217;s incredibly long and pointless rambling, whose beginnings I scarcely remember. Oh yeah. Ruby&amp;#8217;s punctuation and typography &lt;em&gt;is&lt;/em&gt; beautiful. It really is. And I envy it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115389319302246918?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115389319302246918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115389319302246918'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/07/typography-languages-beauty-ramble.html' title='Typography, languages, beauty, ramble ramble ramble'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115376712066868198</id><published>2006-07-24T12:23:00.000-06:00</published><updated>2006-07-24T12:53:37.253-06:00</updated><title type='text'>OmniPlan Approaching</title><content type='html'>&lt;p&gt;I&amp;#8217;m not sure what this indicates about me, but I felt such an overwhelming air of excitement and relief that I almost - &lt;em&gt;almost!&lt;/em&gt; - had a little tear in my eye when I saw &lt;a href="http://blog.omnigroup.com/2006/07/21/brand-new-secret-product-no-longer-a-secret/" title="Brand New Secret Product No Longer a Secret"&gt;this announcement from the OmniGroup&lt;/a&gt;. Omni&amp;#8217;s new secret product that&amp;#8217;s no longer a secret is (oh boy oh boy oh boy!): &lt;a href="http://www.omnigroup.com/omniplan/" title="OmniPlan"&gt;OmniPlan&lt;/a&gt;. Project management software.&lt;/p&gt;

&lt;p&gt;Why am I so excited about project management software? Because there&amp;#8217;s very little project management software for the Mac. I know this, because I recently looked for some. We were using an &lt;a href="http://www.omnigroup.com/omnioutliner/" title="OmniOutliner"&gt;OmniOutliner&lt;/a&gt; document to try to capture all of the known things that we needed to do to get this big enormous project out the door, and to come up with some estimations on the time involved. OmniOutliner was OK for this, to some extent: it can have multiple columns, and the columns can be different types including durations. The duration column can be configured to calculate things in working days or 24 hour days, so you can say &amp;#8220;that&amp;#8217;s going to take 10 hours&amp;#8221; and the document can turn that into &amp;#8220;1 day 2 hours&amp;#8221;. You can also have summaries, where a parent outline element can add (or average or mean) the values of the child nodes. However, with the way that we were entering data, we couldn&amp;#8217;t take advantage of this.&lt;/p&gt;

&lt;p&gt;As we were fleshing out the development plan, we were unable to easily spell dependencies. We got around this by adding another column, but it was just plain text. One couldn&amp;#8217;t look at the list of things to be done and easily decide to do &amp;#8220;that big scary thing that needs to be done so we can do these four other things.&amp;#8221;&lt;/p&gt;

&lt;p&gt;Turning that into a calendar so we could plan time and other commitments appropriately didn&amp;#8217;t work out either. We did it manually, on paper, and then turned some of the big milestones into milestone entries in &lt;a href="http://www.basecamphq.com/"&gt;Basecamp&lt;/a&gt;. And while Basecamp excels at communication (insofar as everyone involved actually uses it), this level of task / timeline / dependency management is outside of its scope. And I&amp;#8217;m glad for it. We seldom need this kind of MS Project style project management&amp;#8230; Until this project came along.&lt;/p&gt;

&lt;p&gt;So I downloaded a couple of demo versions of different Mac OS X project managers to see how easily I could turn our Plan into something that could better display time estimates, dependencies, and so on.&lt;/p&gt;

&lt;p&gt;How easy was it? Not very. I didn&amp;#8217;t want deep project management features. I wanted to be able to enter tasks as quickly and easily as I had with OmniOutliner and have the Plan start coming together on its own. But in everything that I tried, there were too many steps, too many dialog boxes, and so on. I don&amp;#8217;t mind dealing with inspectors and details later, but I hate when they get in the way of doing simple data entry. And I also hate the tools whose simple data entry is too simple, so that if you enter a lot of items rapidly you then have to spend a lot of time in dialog boxes, tabs, etc, turning it into something real.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t know what &lt;a href="http://www.omnigroup.com/omniplan/" title="OmniPlan"&gt;OmniPlan&lt;/a&gt; is going to look like, or cost, or anything. But Omni&amp;#8217;s record of building good solid NeXTStep and Mac OS X applications that are fast, fun, intuitive, and flexible is nearly unbroken. I wish this application had been available a month or two ago, but better now than never. I expect we&amp;#8217;ll see a tool that humble programmers such as myself can use without a degree in business or project management.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115376712066868198?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115376712066868198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115376712066868198'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/07/omniplan-approaching.html' title='OmniPlan Approaching'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115151310788364010</id><published>2006-06-28T10:45:00.000-06:00</published><updated>2006-06-28T10:45:07.956-06:00</updated><title type='text'>Desecration Sale Spectacular</title><content type='html'>&lt;p&gt;If you ban the burning of the American Flag because it supposedly desecrates what our soldiers have died to protect (funny - I don&amp;#8217;t see soldiers out protecting the flag over the supermarket from lightning), shouldn&amp;#8217;t there also be a ban on using the flag to bring everyone down to &amp;#8220;celebrate their independence from high prices at your local car dealer and/or furniture warehouse Fourth of July Independence Day Sale Spectacular&amp;#8221;?&lt;/p&gt;

&lt;p&gt;How about a ban on Memorial Day sales pitches? &amp;#8220;Remember all those who have actually died in the service of this country, often in hostile environments most of you would have a heart attack in, by getting a Free Hot Dog and a chance to win a new sofa set on us!&amp;#8221;&lt;/p&gt;

&lt;p&gt;I know that this kind of commercialism is here to stay. Personally, I think that it really does cheapen the meaning behind some of our holidays. Why aren&amp;#8217;t more people up in arms about big business&amp;#8217;s war on memorial day? Unlike the bullshit crusades against the so-called &amp;#8220;war on Christmas&amp;#8221;, some of these holidays actually have a potentially good national meaning that is completely - COMPLETELY - washed over. &amp;#8220;Support our troops and celebrate your freedom by getting a new Honda at Zero Percent Financing, this weekend only!&amp;#8221;&lt;/p&gt;

&lt;p&gt;These proposed constitutional amendments to protect the flag and protect marriage do nothing of the sort. They&amp;#8217;re stupid ass wedge issues. If you want to really protect marriage, do something about the divorce rate in this country; shut down the 24 Hour shotgun chapels in Vegas (does that not make more of a mockery of this &amp;#8220;blessed institution&amp;#8221; (cough) than anything?); boycott Budweiser for cheapening marriage with its image of a man getting married over and over in Vegas for a free case of beer; boycott television sitcoms; get &amp;#8220;Desperate Housewives&amp;#8221; off the air; support federal aid policies that help low income families so that financial stress is less likely to be a factor in separations and divorce; hell, why not make adultery laws with severe punishments like some countries that wobble daily between friend and foe?&lt;/p&gt;

&lt;p&gt;Is a constitutional amendment defining marriage as being a union between a man and a woman really going to do anything to this country&amp;#8217;s divorce rate? Is it going to suddenly put an end to single parent homes? Is it going to cut down on adultery? Murder? Foster care?&lt;/p&gt;

&lt;p&gt;Not one goddamn bit.&lt;/p&gt;

&lt;p&gt;And it&amp;#8217;s the same goddamn thing with the flag burning amendment. I personally believe there are many other ways to desecrate the flag, our troops, and our history, and it&amp;#8217;s all accepted as perfectly legitimate as long as there are free balloons for the kids.&lt;/p&gt;

&lt;p&gt;Stupid, stupid, stupid.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115151310788364010?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115151310788364010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115151310788364010'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/06/desecration-sale-spectacular.html' title='Desecration Sale Spectacular'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115099801138370821</id><published>2006-06-22T11:40:00.000-06:00</published><updated>2006-06-22T11:40:11.453-06:00</updated><title type='text'>Ads - Debugging Matters, and Out of the Box</title><content type='html'>&lt;p&gt;Terrific targeted advertising: The current ad that appears on the main page for Sci-Fi channel&amp;#8217;s excellent new &lt;a href="http://www.scifi.com/battlestar/"&gt;Battlestar Galactica&lt;/a&gt; series is for Microsoft&amp;#8217;s &lt;a href="http://msdn.microsoft.com/vstudio/"&gt;Visual Studio 2005&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The ad? It just says &amp;#8220;Cylons. Why debugging matters.&amp;#8221;&lt;/p&gt;

&lt;p&gt;I think that&amp;#8217;s the first good ad I&amp;#8217;ve seen placed by Microsoft in a long time. For those unfamiliar with Battlestar Galactica, especially the new series, the basic premise is "The Cylons were originally created by man. They evolved. They rebelled." The miniseries that brought the story back to the air (in a much more rich and intelligent flavor than the old series, which had a good idea but had poor execution and network interference) starts with the near annihilation of the human race in a massive coordinated Cylon attack. Yeah, debugging matters. Great placement. Although, of course, you could see variations on this for Terminator: "SkyNet. Why debugging matters." And for The Matrix. Which is not to say that Galactica is anything like those series (I think the nearest it could be compared to is Bladerunner). Just that someday, these robots will come back and kill us all. Sony's cute little QRIO &lt;a href="http://www.sony.net/SonyInfo/QRIO/technology/index3_nf.html"&gt;has its own emotions&lt;/a&gt; and can express them in different ways, including changing eye color. You just know one night you're going to wake up and see this cute little robot at the foot of the bed staring at you with those red eyes... And then you'll never wake up again...&lt;/p&gt;

&lt;p&gt;Sorry, off track.&lt;/p&gt;

&lt;p&gt;While on the concept of ads, I&amp;#8217;ve been enjoying one of the latest from Apple&amp;#8217;s &lt;a href="http://www.apple.com/getamac/ads/"&gt;&amp;#8220;Get a Mac&amp;#8221;&lt;/a&gt; campaign. The commercial is &lt;em&gt;Out of the Box&lt;/em&gt; and features the Mac and PC in their boxes talking about what they&amp;#8217;re going to do. If you haven&amp;#8217;t seen this series, they follow the sparse white backgrounds and straight-on shots of the older &amp;#8220;Switch&amp;#8221; commercials (and, in fact, most of Apple&amp;#8217;s modern non-iPod commercials). Instead of the &amp;#8220;real people&amp;#8221; stories that were the center of &amp;#8220;Switch&amp;#8221;, &amp;#8220;Get a Mac&amp;#8221; features a humanized PC and Mac. The PC is played by John Hodgman (now a Daily Show staple), and the Mac by Justin Long (an actor in &amp;#8220;Dodgeball&amp;#8221;, which is a movie I unexpectedly fell in love with).&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;Out of the Box&lt;/em&gt;, the PC and Mac are sitting in boxes - the PC&amp;#8217;s is plain brown, the Mac&amp;#8217;s is plain white. They introduce themselves as they do in every commercial - &amp;#8220;Hi, I&amp;#8217;m a Mac&amp;#8221; &amp;#8220;And I&amp;#8217;m a PC&amp;#8221;. The Mac starts getting out of his box and says &amp;#8220;ready to get started?&amp;#8221; to which the PC responds &amp;#8220;well, not quite&amp;#8230; what&amp;#8217;s your big plan?&amp;#8221; The Mac sits and says &amp;#8220;well, I might make a movie, create a web site, try out my built in camera.. I can do it all right out of the box. So what about you?&amp;#8221; The PC responds with &amp;#8220;well first I got to download those new drivers and then &lt;strong&gt;erase all the trial software that came on my hard drive&lt;/strong&gt;&amp;#8230;&amp;#8221;&lt;/p&gt;

&lt;p&gt;The ad ends with the Mac getting out of the box and leaving frame while the PC says &amp;#8220;actually I can&amp;#8217;t go yet&amp;#8230; the rest of me is in other boxes.&amp;#8221;&lt;/p&gt;

&lt;p&gt;Now this is a great ad. It&amp;#8217;s short, funny, and quite charming. While the content of the ads is competitively aggressive, the PC and Mac are quite nice to each other (in one ad the Mac even says that the PC is great at business). Overall the series is doing a good job, in very short segments, of highlighting the cultural differences. Some ads play up to the &amp;#8220;if you like the iPod or iTunes, we&amp;#8217;ve got even more of that!&amp;#8221; message, while others cover other differences. This one, however, I particularly enjoyed.&lt;/p&gt;

&lt;p&gt;We recently purchased a new &lt;strong&gt;Dell&lt;/strong&gt; machine at the office to run accounting software. A few days later, there is still a cadre of boxes in our lobby with CDs scattered everywhere. The machine is installed, and it installed fairly quickly. But what I remember most is how much my boss kept yelling at all of the trial software, and how much time he spent un-installing things. &amp;#8220;Something new pops up every time!&amp;#8221;&lt;/p&gt;

&lt;p&gt;I imagine that this is how Dell and the like can offer their machines for such low prices. They stuff it with all sorts of trial software - often very annoying trial software (it bugs you more than it helps you) - which is just more advertising, basically, subsidizing the lower cost.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s amazing. I have a windows machine at my desk that I use on occasion (it&amp;#8217;s actually been off for a couple of months), and I hated having to restart it because there were so many little balloons and bubbles that kept popping up for the first few minutes. &amp;#8220;I did this&amp;#8221; &amp;#8220;You should upgrade to this&amp;#8221; &amp;#8220;Buy this&amp;#8221; &amp;#8220;Your machine is at risk - upgrade to the full version of bla bla antivirus for $79.95 today!&amp;#8221; and on and on. Half of these interrupts were modal, taking away focus from what I was trying to get back to doing. Part of me is amazed that this passes as OK in the Windows world, but part of me looks at advertising today (and through time) and realizes that it&amp;#8217;s just the norm of our society.&lt;/p&gt;

&lt;p&gt;I always get entertained at list once during local coverage of the Utah Jazz at all of the little inserts that get slipped in, and how casually the announcer puts it in. Granted, a lot of these same games are being simulcast on radio (some games are only broadcast on radio), so perhaps it makes a bit more sense. But it&amp;#8217;s just things like &amp;#8220;Malone drives it up the floor and it&amp;#8217;s knocked out of bounds. This portion of the game is brought to you by Bla Bla Bla, reminding you that it&amp;#8217;s always a good time to Bla bla&amp;#8221; or &amp;#8220;brought to you by Bla Bla. Come down and see the professionals at Bla Bla, quality service guaranteed. Stockton takes it inbound&amp;#8230;&amp;#8221;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s all around us.&lt;/p&gt;

&lt;p&gt;Anyways, I just found the &lt;em&gt;Out of the Box&lt;/em&gt; commercial funny, having watched someone just recently go through the experience of spending his time removing all this junk software before he could set the machine up to do its actual job. It&amp;#8217;s not like the Mac is devoid of trial software - a .Mac trial period is pimped, trials for both Apple&amp;#8217;s &lt;a href="http://www.apple.com/iwork/"&gt;iWork&lt;/a&gt; and Microsoft&amp;#8217;s &lt;a href="http://www.microsoft.com/mac/"&gt;Office&lt;/a&gt; are also on board. But to my recollection, no bubbles ever popped up and interrupted my work telling me to use / install / upgrade either of those. In fact, I didn&amp;#8217;t even notice they were on my new iBook. They didn&amp;#8217;t hinder performance any, and - most importantly - &lt;em&gt;never got in the way&lt;/em&gt;. Dragging them to the trash was all that was needed when I did notice they were there.&lt;/p&gt;

&lt;p&gt;So, good ad, sells the point well. I&amp;#8217;ve been impressed with how well all of my Macs have worked out of the box - even discovering that a new laptop had a decent charge in its battery when it arrived!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-115099801138370821?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115099801138370821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115099801138370821'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/06/ads-debugging-matters-and-out-of-box.html' title='Ads - Debugging Matters, and Out of the Box'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-115082676704256125</id><published>2006-06-20T12:06:00.000-06:00</published><updated>2006-06-20T12:06:07.100-06:00</updated><title type='text'>More OmniOutliner Pro Praise, and Other Tools</title><content type='html'>&lt;p&gt;A &lt;a href="http://www.43folders.com/2006/06/20/omni-omni-omni/"&gt;nice post from 43Folders&lt;/a&gt; came across my desk today pointing towards a post by Eric Schmidt about &lt;a href="http://www.maclawstudents.com/product-reviews/omni-outliner-pro-kinkless.php"&gt;Using OmniOutliner Pro and Kinkless GTD in Law School&lt;/a&gt;. Schmidt first covers how he uses OmniOutliner Pro to take and manage notes for his law courses. One significant &lt;em&gt;Pro&lt;/em&gt; feature in OmniOutliner is the ability to have &lt;em&gt;Sections&lt;/em&gt; - a navigable list of top level outline elements. &lt;a href="http://kinkless.com/"&gt;Kinkless GTD&lt;/a&gt; uses these to separate the Inbox, Projects, Actions, Archive, Templates, and Setting portions of the kGTD document. As I&amp;#8217;ve started to work on larger outlines again in OmniOutliner, I&amp;#8217;ve started to make use of this feature in other documents.&lt;/p&gt;

&lt;p&gt;Now, there are numerous outliners available for the Mac OS. A glance through the archives of &lt;a href="http://www.atpm.com/Back/atpo.shtml"&gt;About This Particular Outliner&lt;/a&gt; shows comprehensive coverage of various outlining and mindmapping tools. I&amp;#8217;ve used quite a few of these over the years, often just in evaluation. The only additional ones I&amp;#8217;ve purchased and gotten any real use out of have been Aquaminds &lt;a href="http://www.aquaminds.com/"&gt;NoteTaker&lt;/a&gt;, &lt;a href="http://www.devon-technologies.com/products/devonthink/"&gt;DEVONThink Personal&lt;/a&gt;, and &lt;a href="http://www.eastgate.com/Tinderbox"&gt;Tinderbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.aquaminds.com/"&gt;NoteTaker&lt;/a&gt; is a decent application. I got a lot of great use out of it in a school setting as a math notebook. Using &lt;a href="http://www.esm.psu.edu/mac-tex/EquationService/"&gt;EquationService&lt;/a&gt;, I was able to take notes in a full Notebook paradigm and enter the math formulas in LaTeX and convert them to inline PDFs, with no knowledge of LaTeX or equations being required of NoteTaker. I&amp;#8217;ve also used NoteTaker on a couple of customer projects that had clear releases. NoteTaker&amp;#8217;s structure has many pages, grouped by sections. A section might be &amp;#8220;WebSite 1.6&amp;#8221;, with a page devoted to each feature request made by the customer for that next version. NoteTaker&amp;#8217;s pages are outlines, but it often works best with big blocks of text. No problems - that worked great for these books. But while NoteTaker is steeped in Mac OS X&amp;#8217;s NeXTStep heritage, it has a bit of a strange feel. More NeXTStep-ish still than Mac OS-ish.&lt;/p&gt;

&lt;p&gt;Interestingly, NoteTaker has a very very very similar competitor: &lt;a href="http://www.circusponies.com/"&gt;Circus Ponies NoteBook&lt;/a&gt;. They both have the notebook metaphor - the windows look like ringed notebooks (by default), they have index tabs on the side, and the document is a collection of pages. There are differences between the two, but they both actually share a common ancestry. AquaMinds (NoteTaker) and Circus Ponies (NoteBook) were started by two different principals that had previously made a similar [product for NeXTStep][http://www.simson.net/nextworld/93.2/93.2.ApMay.Notebook.html].&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.devon-technologies.com/products/devonthink/"&gt;DEVONThink Personal&lt;/a&gt; is not so much an outliner as a personal database. NoteTaker and NoteBook position themselves that way too, but DEVONThink is much more like a specialized Finder implementation than an outliner. DEVONThink has a sort-of outline &amp;#8220;mode&amp;#8221;, but it&amp;#8217;s nowhere near as fast or natural as OmniOutliner or NoteTaker. Instead, DEVONThink shines as a place to collect PDFs, web pages/archives, text notes (rich or plain), etc. It has excellent cross-referencing and indexing capabilities so any document can have a &amp;#8220;See Also&amp;#8221; drawer which shows contextually similar documents in the system. This is great for building reference systems, especially since you can drop a new note, text, web archive (great for keeping documentation around), etc, in and then use the classification tools. Classification works similarly to the &amp;#8220;See Also&amp;#8221;, but shows folders instead. Folders are matched based on their contained contents. I use DEVONThink at work to collect odds and ends from various projects, and (more often) to keep and archive web pages containing documentation for tools like SQLAlchemy, Markdown, etc. On my laptop I use it to keep archives of web pages I want to read in my spare time, whether or not I have internet access.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.eastgate.com/Tinderbox"&gt;Tinderbox&lt;/a&gt; is an interesting system. Part of me thinks it could be so much more if only it were modernized. It just doesn&amp;#8217;t feel that natural on Mac OS X. It&amp;#8217;s such a powerful and flexible system, with the ability to think and work in different modes - outline, treemaps, visual maps - with multiple windows open in the same document even! Custom attributes, agents, and rules can make for pretty powerful and personal systems. But using it is like using [Squeak][http://squeak.org/]. It&amp;#8217;s really cool and really powerful, but it&amp;#8217;s also its own self-contained world. I had a hard time integrating Tinderbox into my day-to-day operations as it works less and less like the Mac OS X I know and love. No Services support, changing a font requires using a traditional font menu (which is a nightmare with my sprawling font collection). Hell - you can&amp;#8217;t even save a file with a name longer than 30 characters! I don&amp;#8217;t think I&amp;#8217;m in Tinderbox&amp;#8217;s target market though. If I wrote as much as I often say i&amp;#8217;d like to write, I&amp;#8217;m sure it would be a great tool. I&amp;#8217;ve wanted to use it to start mapping and managing a lot of characters and places from real life and mythic life. But I have a hard time going into Tinderbox land.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.omnigroup.com/applications/omnioutliner/"&gt;OmniOutliner&lt;/a&gt;, on the other hand, is tremendous. Especially as of version 3 (and even more so with version 3.5). It is so deceptively simple. A fresh document is just a basic outline. Start typing, indenting, structuring, etc. Often that&amp;#8217;s all you need to take some notes down or think something through. But it also has excellent multi-column support. The columns can have different value types with the ability to summarize values. In evaluating whether I could afford an impromptu weekend trip, I used OmniOutliner with two columns - Topic (the main outline/text column) and Price, with Price formatted as dollars and with a &amp;#8220;Total&amp;#8221; summary. The top level of the outline was &amp;#8220;San Francisco Trip&amp;#8221;, and then inside of it I had lines for flight, hotel, tickets to an event I wanted to go to, boarding the dog, train, etc. Very quickly I added borders on rows and columns, and within seconds I had a very small and simple document that many people use spreadsheets like Excel for - but with absolutely none of the complexity or long arguments that are involved when I use Excel (or any spreadsheet, for that matter). This was just a quick &amp;#8220;I wonder if I could&amp;#8230;&amp;#8221; experiment - could I make a quick list and see the estimated total? could I afford to go? (The answers were &amp;#8216;yes&amp;#8217; and &amp;#8216;no&amp;#8217;, respectively).&lt;/p&gt;

&lt;p&gt;But &lt;a href="http://www.omnigroup.com/applications/omnioutliner/"&gt;OmniOutliner&lt;/a&gt; does even more, and all naturally. By using Mac OS X&amp;#8217;s text formatting system, it gets access to the Ruler (NoteTaker and NoteBook get this too). The Ruler makes it possible for just about any Rich Text input area to be at least as powerful as a tool like WordPad on Windows. Named styles, tab stops, left / right / justification alignment, paragraph indentation, spacing, and more. OmniOutliner doesn&amp;#8217;t show the &amp;#8216;Lists&amp;#8217; option, but NoteTaker does, so bulleted and numbered lists inside of the text are available just about anywhere.&lt;/p&gt;

&lt;p&gt;This is what amazes me about &lt;a href="http://www.omnigroup.com/applications/omnioutliner/"&gt;OmniOutliner&lt;/a&gt;: it can be such a fast and simple basic outliner, requiring practically no training or documentation to use. It&amp;#8217;s smooth and fast and looks great to boot. But with just a little exploration of the menus, toolbars, and inspectors, it can be unleashed. Some sample documents look closer to a full Word or Pages produced document: the outline handles and checkboxes are hidden, the indention settings are massaged, the fonts and styles applied well. Other sample documents show its usefulness as a simple spreadsheet / database system: the kind where the main text is delightfully easy to enter and formats well against the other columns (spreadsheets do not do this well at all), and the supporting columns can have intelligent value entry and handling. The date support is wonderful - &amp;#8220;tomorrow&amp;#8221;, &amp;#8220;monday&amp;#8221;, &amp;#8220;the 3rd&amp;#8221;, &amp;#8220;last friday&amp;#8221;, are all valid values. Duration columns can be set with how to measure hours - is it a work day? is the work day 8 hours? then a total of 9.5 hours immediately displays as 1 day 1.5 hr.&lt;/p&gt;

&lt;p&gt;The section support in &lt;a href="http://www.omnigroup.com/applications/omnioutliner/pro/"&gt;OmniOutliner Pro&lt;/a&gt; invades some of the territory enjoyed by NoteTaker and NoteBook and the like. Suddenly a single large outline can become very navigable. I exported some of my &lt;a href="http://www.aquaminds.com/"&gt;NoteTaker&lt;/a&gt; books out to OPML and into OmniOutliner Pro and had a system almost as nice up and running within moments (aside from some lost formatting). Nicer still is that a co-worker has started using OmniOutliner pretty heavily and it&amp;#8217;s nice to be able to settle on a single tool and share. I&amp;#8217;m just amazed that this tool can be so simple and useful for the quick-notes while becoming powerful enough to support a system like &lt;a href="http://kinkless.com/"&gt;Kinkless GTD&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/13463691-115082676704256125?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115082676704256125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/115082676704256125'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/06/more-omnioutliner-pro-praise-and-other.html' title='More OmniOutliner Pro Praise, and Other Tools'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114953164796900305</id><published>2006-06-05T12:20:00.000-06:00</published><updated>2006-06-05T12:20:47.993-06:00</updated><title type='text'>My Mac OS X "Priceless" Applications and Tools</title><content type='html'>&lt;p&gt;Can&amp;#8217;t live with &amp;#8216;em, can&amp;#8217;t live without &amp;#8216;em. This is about the Mac OS X applications I can&amp;#8217;t live without, and some mentions of ones that I&amp;#8217;ve still never found use for.&lt;/p&gt;

&lt;h2 id="can8217t_live_without"&gt;Can&amp;#8217;t Live Without&lt;/h2&gt;

&lt;h3 id="quicksilver"&gt;Quicksilver&lt;/h3&gt;

&lt;p&gt;The ultimate quick launch and system control tool, &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt; is like the perfect marriage of graphical and command like control. Before Quicksilver I was an avid user of &lt;a href="http://obdev.at/products/launchbar/"&gt;Launchbar&lt;/a&gt;. At heart, both of these products are just launchers - quick access to applications, bookmarks, etc. Launchbar allowed me to never be bothered by the Mac OS X Dock: I use the Dock to house applications and documents I use frequently, and Launchbar let me quickly get to ones that I use only on occasion. What makes both of these products stand out is that they learn. One might bring up the tool and type the letters &lt;code&gt;A G L&lt;/code&gt;. The first hit might be a bookmark to an agile development article. But hitting the spacebar a couple of times to highlight &lt;a href="http://www.adobe.com/golive/"&gt;Adobe GoLive&lt;/a&gt; will cause both LaunchBar and Quicksilver to increase the weight of that result. Within a couple of uses, &lt;code&gt;CONTROL-SPACE A G L&lt;/code&gt; becomes the fastest way to launch GoLive.&lt;/p&gt;

&lt;p&gt;Both tools offer access to more than just applications and bookmarks. &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt; started to differentiate itself from &lt;a href="http://obdev.at/products/launchbar/"&gt;Launchbar&lt;/a&gt; (as of Launchbar version 3 - it&amp;#8217;s now at version 4.1) as a more thorough system control tool with a lot of AppleScript support and a wide (and growing) range of plug-ins. &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt; could be used to control &lt;a href="http://www.apple.com/itunes/"&gt;iTunes&lt;/a&gt;, to put the computer to sleep, and more.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not sure when or why I made the switch. As Mac OS X matured, I used Launchbar less and less. When Quicksilver came on the scene, I didn&amp;#8217;t pay much attention to it. But I kept hearing good things about it, and eventually got around to checking it out myself as it was a big hit amongst the &lt;a href="http://www.43folders.com/"&gt;43Folders&lt;/a&gt; crowd. As I started to use Quicksilver, I found it insanely useful. I could pause and resume iTunes with a few keystrokes without having to change focus from what I was doing. I could start doing some &amp;#8220;fire and forget until later&amp;#8221; actions, such as emailing a quick note or to-do to a &lt;a href="http://www.backpackit.com/"&gt;Backpack page&lt;/a&gt; or sending an action to my &lt;a href="http://kinkless.com/"&gt;Kinkless GTD&lt;/a&gt; document. I could take quick advantage of Mac OS X services such as &lt;em&gt;Make Sticky&lt;/em&gt; or &lt;em&gt;Take Plain Note in DEVONThink&lt;/em&gt;, even in applications (like &lt;a href="http://www.eastgate.com/Tinderbox/"&gt;Tinderbox&lt;/a&gt;) that don&amp;#8217;t support the Services system.&lt;/p&gt;

&lt;p&gt;This is most handy when doing something very focused, such as a debugging session, when I&amp;#8217;d notice something else I might need to come back and revisit. I don&amp;#8217;t want to take the time to change focus to OmniOutliner or some web project tool or iCal to make the note to &amp;#8220;come back and fix the call to &amp;#8230;&amp;#8221; when I&amp;#8217;m chasing some obscure issue. Quicksilver lets me make that note almost invisibly - I don&amp;#8217;t even have to take my eyes off of the current debugger line. Priceless.&lt;/p&gt;

&lt;p&gt;Small feature that I absolutely love - &lt;em&gt;Large Type&lt;/em&gt;. One of the default text actions in Quicksilver, this is damn handy when making phone calls. Apple&amp;#8217;s Address Book, and some other applications, support this for values they have in the system. But sometimes you need to call a phone number and read off an account number that isn&amp;#8217;t going to be in Address Book. With Quicksilver and a couple of tuning options, you can get this down to a single chord or just a couple of keystrokes, and BAM! Screen-size type. Doesn&amp;#8217;t interfere with anything else - next keystroke or mouse click makes it go away.&lt;/p&gt;

&lt;h3 id="textmate"&gt;TextMate&lt;/h3&gt;

&lt;p&gt;A native Mac OS X text editor, &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; has become my new killer application. For the first time ever, I&amp;#8217;m doing most of my Zope and what-have-you development on my desktop. Historically I&amp;#8217;ve always done my web development on servers, using XEmacs and then VIM as my comprehensive editor of choice. Even when I&amp;#8217;d do development on the desktop, I&amp;#8217;d often use VIM. But TextMate has changed that.&lt;/p&gt;

&lt;p&gt;With support for lots of languages and commands, it&amp;#8217;s become indispensable. The killer feature was the ability to install an &lt;em&gt;Edit in TextMate&amp;#8230;&lt;/em&gt; command in all Cocoa applications. Now I can edit the contents of any textarea in Safari in TextMate - whether it&amp;#8217;s GMail, a bulletin board system, Basecamp, a Zope application, a classic Zope page template, I can pop over to TextMate. Even now, I&amp;#8217;m using &lt;a href="http://ranchero.com/marsedit/"&gt;MarsEdit&lt;/a&gt; to make this post. I&amp;#8217;m writing it in &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; and will convert it to HTML from within &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; before posting it.&lt;/p&gt;

&lt;p&gt;Over the years, I&amp;#8217;ve found long-time Mac staple &lt;a href="http://www.barebones.com/products/bbedit/"&gt;BBEdit&lt;/a&gt; to be too expensive, and ultimately underpowered, for my needs. BBEdit still bears too much of its classic Mac OS heritage, I feel, and some of its keyboard commands and preference screens started to feel really unnatural. Granted, I was still using an old version. But even the newer free &amp;#8216;lite&amp;#8217; version of BBEdit, &lt;a href="http://www.barebones.com/products/textwrangler/"&gt;TextWrangler&lt;/a&gt;, felt uncomfortable. I used it for some development in the past year, but TextMate feels a lot more natural to me in most regards.&lt;/p&gt;

&lt;p&gt;There are some features that TextWrangler / BBEdit has that are still missing from TextMate - integrated FTP support is one, split windows is another. The one feature that I can&amp;#8217;t believe TextMate doesn&amp;#8217;t have yet is the ability to split editing windows! But the number of plug-ins available, the &amp;#8220;Edit in TextMate&amp;#8221; feature, the relative ease with which new syntaxes and commands can be added, far outweigh some of the holes.&lt;/p&gt;

&lt;p&gt;Small feature that I absolutely love - &lt;em&gt;Find in Project&lt;/em&gt;. Any folder can be a project (without all of the project overhead imposed by IDE&amp;#8217;s). In the Zope 3 development that I&amp;#8217;ve been doing, this has made refactoring easy as I could rename or move a class or interface and could quickly find all uses of it. &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; also supports many of the Cocoa find/replace features and commands (and builds on them). One handy command is &amp;#8220;Use Selection for Find (command-E)&amp;#8221;. Safari, Mail, MarsEdit, OmniOutliner, etc, all use this command. Select a word or phrase, hit &amp;#8216;command E&amp;#8217; and then &amp;#8216;command G&amp;#8217; (find again) to search for that word without bringing up the &amp;#8216;Find&amp;#8217; dialog box, without using up the clipboard, etc. This is great with the &lt;em&gt;Find in Project&lt;/em&gt; feature in TextMate when I&amp;#8217;m thinking of renaming or moving a class, or just want to see where it&amp;#8217;s used, such as when exploring other people&amp;#8217;s code (such as the Rails or Zope frameworks themselves).&lt;/p&gt;

&lt;h3 id="darwinports"&gt;DarwinPorts&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://darwinports.opendarwin.org/"&gt;DarwinPorts&lt;/a&gt; has made it possible to do the kinds of development I now do on my desktops / laptop. This is where I get my Python 2.4.x with readline, Ruby 1.8.4, Docutils, subversion, etc.&lt;/p&gt;

&lt;h3 id="omnioutliner_pro_kinkless_gtd"&gt;OmniOutliner Pro / Kinkless GTD&lt;/h3&gt;

&lt;p&gt;OmniOutliner has been in my toolbox since version 1, back in the early Mac OS X days. I&amp;#8217;ve gone through other outliners and information databases, but now I&amp;#8217;m using &lt;a href="http://www.omnigroup.com/"&gt;OmniOutliner Pro&lt;/a&gt; pretty heavily again. Part of this is because it&amp;#8217;s still the fastest, easiest to use, and best looking outliner on Mac OS X. A third party set of AppleScripts turns it into a powerful planning / task management system, as &lt;a href="http://kinkless.com/"&gt;Kinkless GTD&lt;/a&gt;. I&amp;#8217;ve tried some other systems such as GTDRules on Tinderbox, &lt;a href="http://griddlenoise.blogspot.com/2006/05/tinderbox-omnioutliner-and-gtd-again.html"&gt;which I&amp;#8217;ve compared before&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Kinkless GTD features a Quicksilver action called &amp;#8216;Send to kGTD&amp;#8217; which parses text into an action and sends it to the kGTD document. If the document&amp;#8217;s not open, it opens it. The parsing revolves around being able to specify a project and/or context to place an action in. For me, this is useful for that &amp;#8216;fire and forget until later&amp;#8217; moment that comes up from time to time. I capture something that needs to be done, but I don&amp;#8217;t let it consume my mind while I focus on the task at hand. When I have a moment, I can go to Kinkless GTD and file it appropriately or figure out what needs to be done for that note I scribbled off. This shortens the amount of inboxes that I have, and shortens the number of places I have to think about when I want to send myself a &amp;#8220;deal with this later&amp;#8221; note.&lt;/p&gt;

&lt;h3 id="idisk_cvs"&gt;iDisk / CVS&lt;/h3&gt;

&lt;p&gt;Apple&amp;#8217;s iDisk (part of their &lt;a href="http://www.mac.com/"&gt;.Mac&lt;/a&gt; offerings) has a nice feature: the ability to work offline with transparent synchronization. That synchronization can be automatic or manual. This is how I keep track of my &lt;a href="http://kinkless.com/"&gt;Kinkless GTD&lt;/a&gt; document, and any other notes and documents I want to work on without worry of location. No need to have a Lotus Notes size system just to manage a small set of personal information across three machines, especially when one of them spends half of its time offline (and one is spending ALL of that time offline these days). iDisk lets me save any document of any type, synchronize the disk to my laptop, take the laptop home, work on it there (without internet, which hopefully will get fixed soon), come back, synchronize back. I&amp;#8217;ve thought of using USB &amp;#8220;key drives&amp;#8221; to house information like this, but I often fear damaging or forgetting the drive.&lt;/p&gt;

&lt;p&gt;We still use CVS on our development servers at the office. We&amp;#8217;re too small and busy to have time to change to subversion when CVS is doing its job (mostly) well. Some people use CVS to manage their home directories, documents, etc. I just use it to bring code home in case I want / need to work there while I&amp;#8217;m disconnected. It&amp;#8217;s hardly worth mentioning, except for how every work day ends with ensuring the iDisk and source directories are up to date on the laptop.&lt;/p&gt;

&lt;h2 id="can8217t_live_with"&gt;Can&amp;#8217;t Live With&lt;/h2&gt;

&lt;p&gt;There&amp;#8217;s really only one thing I can think of here, and it&amp;#8217;s one thing that&amp;#8217;s always bothered me: &lt;strong&gt;Virtual Desktops&lt;/strong&gt;. I&amp;#8217;m glad Mac OS X doesn&amp;#8217;t support this directly. My main problem with Virtual Desktops is the ease with which important windows get lost. With Mac OS X, I use &amp;#8220;Hide Others&amp;#8221; and window minimization heavily when I need to focus and I have too many distractions on screen. A quick &amp;#8220;Show All&amp;#8221; can bring all the windows back on screen and into the dock (if minimized), and &lt;em&gt;Exposé&lt;/em&gt; is, at that point, the best way to find a particular window when needed. With Virtual Desktops, I was always playing the game of &amp;#8220;is it on 1? nope 2? nope 3?&amp;#8221;. Some people establish systems - web browser always here, email always here, main editor always here - but I never was able to. I&amp;#8217;d just lose things and get frustrated. Between &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt; and Mac OS X&amp;#8217;s native app / window switching features, I have adequate control over my desktop and what populates it, I feel.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114953164796900305?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114953164796900305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114953164796900305'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/06/my-mac-os-x-priceless-applications-and.html' title='My Mac OS X &quot;Priceless&quot; Applications and Tools'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114911775733683491</id><published>2006-05-31T17:22:00.000-06:00</published><updated>2006-05-31T17:22:37.413-06:00</updated><title type='text'>Third Time, Slow Time, Inventing, Revisiting, and Fighting</title><content type='html'>&lt;p&gt;A couple of months ago, we started work on a major rewrite of one of our core sites. What started as a small and specialized e-commerce service a few years ago has grown mightily over those same years. The architecture, however, has hit a limit - especially when compared to the large push for what we want to do (and can do) next. The current site works great and handles its load and duties very well. But there are small annoyances internally with some things, and there is some growth and market potential that it cannot satisfy.&lt;/p&gt;

&lt;p&gt;The first version of the site&amp;#8217;s primary work was done in less than a month. The main focus of that version was the visitor&amp;#8217;s experience. The original HTML mockups drove a lot of the site, and the implementation was primarily done in &lt;strong&gt;Zope 2&lt;/strong&gt;, through the web, using templates, scripts, and SQL Methods. It was a nice enough system for the time - we were very fast with it, we could tweak elements in each other&amp;#8217;s offices, etc. It ended with an all-night debug-and-deploy session, wrought with all sorts of strange problems and angst and fun. But it worked. We continued to work on it over the next few weeks, of course, filling in some major holes that couldn&amp;#8217;t be filled in initial development and responding to site usage.&lt;/p&gt;

&lt;p&gt;The biggest problem with that implementation was the administration side. Since we were the only users of the administration screens, we punted on that issue. There was no form validation. All of the database CRUD statements were entered manually. Zope&amp;#8217;s SQL Methods made this a bit easier, but their main optimization is for read-queries. Any new field required numerous code updates all over the place. The whole business was a little messy back then - requiring us to print out certain reports and delivering them to our providers on time-constrained schedules.&lt;/p&gt;

&lt;p&gt;The site was never empty, but it got perilously close a few times during the lifetime of version 1. But there was enough interest to keep it going. With eyes on expanding and getting new providers, with providing new services (including physical goods), and with running the business side of things better, we went into version 2.&lt;/p&gt;

&lt;p&gt;As I saw all of the HTML forms and database statements I&amp;#8217;d have to change just to accommodate the expanding and changing data requirements, I started looking at options for easing that pain. I ultimately rolled my own system focused primarily on the common CRUD operations. There was no object-relational mapping solution at the time that I liked. A problem, at that time, was that we had many queries in place that would not work in the object-relational tools available. &lt;/p&gt;

&lt;p&gt;What I really wanted was an architecture that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Helped me get important / core business and administration logic out of the ZODB. We wanted to have as much of the core software on disk and under source control as possible.&lt;/li&gt;
&lt;li&gt;Dynamic form and SQL generation for common tasks (primarily in the administration section). I wanted this so that adding new fields to the database schema required only one or two changes.&lt;/li&gt;
&lt;li&gt;Still allowed us to use Zope&amp;#8217;s SQL Methods for generating complex queries.&lt;/li&gt;
&lt;li&gt;Could be introduced in a way that the public application might not even be aware: instead of a folder full of Python scripts in the ZODB, there&amp;#8217;d be a single persistent instance of a class that had many of those scripts as methods.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The resulting framework was essentially a service layer comprised of very rough &lt;a href="http://martinfowler.com/eaaCatalog/tableDataGateway.html"&gt;Table Data Gateways&lt;/a&gt;. You couldn&amp;#8217;t load an object out and do a &lt;code&gt;jeff.hair = 'bleached'&lt;/code&gt; and have it save. The get/create/save statements basically took a dictionary (hash table) of values to save and would flush it out to the database, after harvesting some information. It was expected that the gateways would have the data prepared before passing it off to the lowest level interface, &lt;code&gt;handle_op&lt;/code&gt;, which would perform the requested operation.&lt;/p&gt;

&lt;p&gt;When dealing with fairly set data, such as a form, this didn&amp;#8217;t really matter. I cared about loading and binding the data to the widgets when a page was loaded, and then parsing/validating/converting that data on save. For that, this system worked like a champ. For some other pieces of business logic, it did OK. It wasn&amp;#8217;t great, but it was better than what we had before - especially because it didn&amp;#8217;t require specialized &lt;em&gt;update&lt;/em&gt; SQL to be written for those situations where just a couple of values needed to be changed.&lt;/p&gt;

&lt;p&gt;That site has served us fine, and now the offerings on the site are quite full (many many pages). The content providers have access to their items and reports, so we no longer have to run around town delivering reports and lists.&lt;/p&gt;

&lt;p&gt;Both versions were deployed, in full, and then continuously massaged over time. There was no &amp;#8216;beta&amp;#8217;. Some features sneaked in after the deployment deadlines. Some specialized parts of the system were overhauled a couple of times to deal with scaling issues - ones that we could never have predicted.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve kept laundry lists over the years of the things we wanted to do, but couldn&amp;#8217;t under the first two designs. Some of these came from dealing with some hacks pulled together for a couple of special customers, some came from wishful thinking, some came from complicated set-ups required to make certain rare items available for purchase in the existing system. In a &lt;em&gt;getting real&lt;/em&gt; sense, this was OK, but not great. It limited our ability to start working with larger and more specialized providers.&lt;/p&gt;

&lt;p&gt;Architectures have continued to improve over the past couple of years as well. When &lt;a href="http://dev.zope.org/Zope3/"&gt;Zope 3&lt;/a&gt;, version 3.1 specifically, came out, we were able to do a major rewrite of a content system for one of our oldest customers. We were even able to pick up additional related customers as a result. We&amp;#8217;ve delivered other solutions on top of Zope 3 and the &lt;strong&gt;ZODB&lt;/strong&gt; (Zope Object Database) that have been both impressive and fun to work on, although sometimes Zope 3 can still cause me to go off in a huge screaming match.&lt;/p&gt;

&lt;p&gt;I had hoped (and still wish) that for this particular site&amp;#8217;s version 3 implementation we could ditch the relational database completely and just use the ZODB. Instead of classic Zope ZODB usage, where scripts and templates fill up the database, Zope 3 makes it much easier to keep that stuff OUT, and then easier to keep real data in. This is one of the nicer parts about working with the Zope 3 / ZODB stack: Python is just Python is just Python. There&amp;#8217;s no translation layer, no tricks, trying to fake inheritance. There&amp;#8217;s no real worry about translating statements into a query language - Python is the query language (with tools like the Catalog providing application level indexes for larger queries). I had an application that I was working on in Zope 3 that I thought would be a good testbed for writing as a Rails app - &lt;a href="http://griddlenoise.blogspot.com/2006/03/yay-object-database.html"&gt;until I realized that Active Record&amp;#8217;s inheritance model could never match my object model&lt;/a&gt;, at least as of Rails 1.0. I also played a little bit with Python&amp;#8217;s &lt;a href="http://www.turbogears.org/"&gt;Turbogears&lt;/a&gt; and &lt;a href="http://sqlobject.org/"&gt;SQLObject&lt;/a&gt; stacks, and they had me feeling pissed and frustrated within seconds. No offense to their authors, but they just did NOT work for me.&lt;/p&gt;

&lt;p&gt;But the decision was made that for this site, we would continue with using a relational database. Well, I knew the strengths and limitations of our current systems. And I admit, I was envious of &lt;a href="http://rubyonrails.com/"&gt;Ruby on Rails&lt;/a&gt;. In fact, I even suggested that we ditch Zope for this project and use Rails instead! But it was feared that there was no time on the schedule to learn Ruby. We did, however, agree on wanting a real object-relational system, or at least something more object oriented than what we used for Version 2. Version 3 has richer business logic requirements, and I&amp;#8217;m happiest when that code can look as clean and natural as possible. I also wanted it to be easy to define new pages and views and to have to go through less guess-and-hope work than Zope 3 (as of 3.2) typically requires.&lt;/p&gt;

&lt;p&gt;So we&amp;#8217;ve birthed yet another in-house framework because there&amp;#8217;s little out there that&amp;#8217;s satisfactory. The one thing that &lt;em&gt;is&lt;/em&gt; satisfactory is &lt;a href="http://sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. I built a base storage framework on top of that which allowed us to use SQL Alchemy fairly transparently from within Zope. Fields and properties now let us define and use relationships fairly transparently. Items get bound to their context, are easily traversable, and can even masquerade as Zope containers without interfering with SQLAlchemy&amp;#8217;s on system of managing work. We also birthed a base web framework that provides some useful base classes for constructing the kinds of pages and sub-views that we need with ease. These base classes corral some core Zope 3 features and some other in-house features together to ease our web development.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s all pretty cool, for what it is. But it&amp;#8217;s going so slowly that I can&amp;#8217;t help but wonder if we would have been better off working in Rails. I still haven&amp;#8217;t found anything in the Python world that I&amp;#8217;d leave Zope for, but Zope 3 continues to jump between being insanely cool and powerful and flexible, and being incredibly frustrating and aggravating. That I&amp;#8217;ve been able to pull many of the tricks I&amp;#8217;ve already been able to pull is a testament to the better parts of its design.&lt;/p&gt;

&lt;p&gt;Even with all of my tricks and base classes, it can sometimes still take an entire morning just to get what seems like a simple page together and rendering. On the other hand, once you get pieces in place they&amp;#8217;re pretty sturdy. There&amp;#8217;s low likelihood of accidentally overriding a critical method name or a view/page that applies to a different context or interface layer.&lt;/p&gt;

&lt;p&gt;But as it&amp;#8217;s been going so seemingly slow, this development, I start to wonder why it feels that way. I really was trying to give myself a system where I could enjoy the benefits of &lt;strong&gt;Zope 3&amp;#8217;s Component Architecture&lt;/strong&gt; with an intelligent database / object-relational mapper while also enjoying the benefits of &lt;a href="https://gettingreal.37signals.com/"&gt;Getting Real&lt;/a&gt;. &amp;#8220;Getting Real&amp;#8221; isn&amp;#8217;t anything really new to me (or many people). It just helps give you the OK to say &amp;#8220;no&amp;#8221;. Martin Fowler&amp;#8217;s book, &lt;a href="http://martinfowler.com/books.html#refactoring"&gt;Refactoring&lt;/a&gt;, made me realize that bad smells are OK now, so long as they&amp;#8217;re cleaned up later. In the interest of getting something done, it&amp;#8217;s hard to go for purity. Or in the case of Python&amp;#8217;s &amp;#8220;import this&amp;#8221;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Special cases aren&amp;#8217;t special enough to break the rules.&lt;br /&gt;
  Although &lt;strong&gt;practicality beats purity&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, what is the problem with me then?&lt;/p&gt;

&lt;p&gt;I think it comes down to a &lt;strong&gt;very special case: the major rewrite&lt;/strong&gt;. This is not a new application for us, nor is it a moderate upgrade or maintenance release. We&amp;#8217;ve acknowledged that the existing architecture has issues when it comes to certain growth paths. To this point, we&amp;#8217;ve also been good in saying &amp;#8220;no&amp;#8221; to those growth paths. But business situations and opportunities have changed.&lt;/p&gt;

&lt;p&gt;One problem with the rewrite is the knowledge that it&amp;#8217;s already been done. &amp;#8220;We already did this three years ago, why can&amp;#8217;t you show me it working in the new system already?&amp;#8221; There senses of worry, fear, excitement all change. This is further exaggerated by the fact that these kind of rewrites are often architectural, perhaps deeply architectural. All of those agile decisions made in earlier versions no longer apply, since many of those decisions may have led to the limitations you&amp;#8217;re trying to overcome. Those decisions were right at the time, and have been right for the past few years. But now you realize that being able to do more promotions, discount options, special offers, are among the things you really want to do with the cart. You also need to handle more delivery options instead of the two you&amp;#8217;ve used for the past two years. You fight and push and think and tango with the cart, just focusing on shipping, with coupons in the back of the mind. Part of you thinks &amp;#8220;I just want to add a shipping column / attribute here and be done with it, and we&amp;#8217;ll expand it later&amp;#8230;. Oh wait&amp;#8230; This IS later&amp;#8230; Oh yeah, we need to support more options&amp;#8230; Oh yeah, this is one of the growth areas we&amp;#8217;re focusing on. Crap!&amp;#8221;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s an interesting struggle now, those two sides in my mind. In practical terms, I just want to add an extra column or attribute and be done. But I know in a week it&amp;#8217;ll already be pushed to its limits. Better to apologize for lack of screens and work this the hell out now. Nothing fancy - keep the interfaces and collaborators simple, and expand on them if needed when more data presents itself.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114911775733683491?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114911775733683491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114911775733683491'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/third-time-slow-time-inventing.html' title='Third Time, Slow Time, Inventing, Revisiting, and Fighting'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114866635048873993</id><published>2006-05-26T11:59:00.000-06:00</published><updated>2006-05-26T11:59:10.560-06:00</updated><title type='text'>Personal File</title><content type='html'>&lt;p&gt;Last night I floated like a ghost past the strip club, under the freeway, over the railroad tracks, past the big electric sign and refrigeration companies and worn out corners until I got to the super-center. I needed milk, inner tubes for my bike, and dog treats. Of course, my cart started filling up with much more than just that. And in the middle of my 11pm shopping excursion I stumbled across the music/video section. As I stared (half-angrily) at the so-called &amp;#8220;top sellers&amp;#8221; in the country department (it&amp;#8217;s where my cart stopped), I remembered coming across a new Johnny Cash collection on the iTunes Music Store.&lt;/p&gt;

&lt;p&gt;So I now have &lt;strong&gt;Personal File&lt;/strong&gt;. It&amp;#8217;s a collection of recordings Johnny made (circa 1973-1980) in his studio. It&amp;#8217;s just Johnny and his guitar: the same kind of intimate, personal, and raw sound that made the first &lt;strong&gt;American Recordings&lt;/strong&gt; album such a standout. Some of these pieces are recognizable, such as &lt;em&gt;When it&amp;#8217;s Springtime in Alaska, It&amp;#8217;s 40 Below&lt;/em&gt; and &lt;em&gt;Jim, I Wore a Tie Today&lt;/em&gt;. Many songs have stories attached to them - why Johnny remembers it, why he wrote it, why he sings it, etc. It was a style seen on some of his commercial albums from that time, although those were accompanied by a larger band and sound.&lt;/p&gt;

&lt;p&gt;The second disc of &lt;em&gt;Personal File&lt;/em&gt; hasn&amp;#8217;t grabbed me much. It&amp;#8217;s fairly religious, and while I respect Johnny Cash&amp;#8217;s religious strength, I have little interest in it. There are some nice songs on that disc though. But the first disc is the good one. It&amp;#8217;s from a good time in Johnny&amp;#8217;s life - settling into his life with June, his drug days behind him. The voice is powerful, most of the songs quite rich. A very enjoyable listen.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114866635048873993?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114866635048873993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114866635048873993'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/personal-file.html' title='Personal File'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114860636579792970</id><published>2006-05-25T19:19:00.000-06:00</published><updated>2006-05-25T19:19:25.856-06:00</updated><title type='text'>Online / Offline / Middle of the Line</title><content type='html'>&lt;p&gt;I&amp;#8217;m still offline at my new home. Curiously, this hasn&amp;#8217;t been a &lt;em&gt;huge&lt;/em&gt; deal for me, so far. I&amp;#8217;m getting home so late (relatively), and then still have to walk the dog (if she stayed home that day), feed her, feed myself, etc. Other factors have been eating up bits of my evenings as well: cleaning out the old place (finally done as of yesterday), getting some finishing-touch little furnishings (one at a time since I don&amp;#8217;t drive), and yet-more organizing and layout.&lt;/p&gt;

&lt;p&gt;The situation with Comcast has just pissed me off enough that I haven&amp;#8217;t wanted to call back to find out what&amp;#8217;s next. Part of this is due to the inherent stress of workdays recently. I don&amp;#8217;t want to add to the pile with long calls and situations where no one really seems to know what&amp;#8217;s going on. But I know I have to, soon. Tomorrow.&lt;/p&gt;

&lt;p&gt;I have not had any major beefs with Comcast (and AT&amp;amp;T before them) up to this point. And the whole situation may not be their fault, but rather the fault of bad information and the odd nature of this particular move. But as someone who has been a good customer for so long, I do feel a little insulted that someone hasn&amp;#8217;t jumped up and said &amp;#8220;hey! you know what, you&amp;#8217;re a valued customer and we want to keep you so I&amp;#8217;ll figure this out personally.&amp;#8221; Not that I expect the average customer service person to care that much, but maybe I could be passed on up to someone who does.&lt;/p&gt;

&lt;p&gt;This is a big thing for me right now. If they don&amp;#8217;t seem to care, why should I? And if I don&amp;#8217;t care, why aren&amp;#8217;t I looking for alternatives? I still don&amp;#8217;t really want to deal with phone companies and DSL, but I know it&amp;#8217;s an option. And as far as television goes: I&amp;#8217;ve long known that I need to cut back. As much as I&amp;#8217;ve loved HBO and its original programming, I haven&amp;#8217;t even noticed that I&amp;#8217;ve missed a couple of weeks of the Sopranos now. I get a handful of channels off my antenna. I&amp;#8217;m starting to think that maybe an option like &lt;a href="http://www.usdtv.com/"&gt;USDTV&lt;/a&gt; could work too. Dish/Satellite is out. I hate those things and don&amp;#8217;t really have anywhere to put the damn dish anyways.&lt;/p&gt;

&lt;p&gt;But it comes down to this: I was told what the builder was told. &amp;#8220;When the first person in wants cable, we just have to connect it to the building. It&amp;#8217;s there and ready to go otherwise.&amp;#8221; But now even the landlord / builder are getting the run-around.&lt;/p&gt;

&lt;p&gt;This service is supposedly &amp;#8220;right there, almost ready to go&amp;#8221;. Why can&amp;#8217;t I just get it turned on already?&lt;/p&gt;

&lt;p&gt;Anyways - thank goodness for Apple&amp;#8217;s iDisk service (as part of their &lt;a href="http://www.mac.com/"&gt;.Mac&lt;/a&gt; offerings). iDisk can be synchronized and worked with off-line. So I can at least keep my iBook up to date with my plans/actions list and a few other key documents, and I can update source code to work from home by bringing the iBook into work and using CVS. This helps with the offline mode - knowing that some information, including work stuff (useful in these busy times) can be brought with me even if there&amp;#8217;s no connection. This is the downside to otherwise wonderful services like &lt;a href="http://www.backpackit.com/"&gt;Backpack&lt;/a&gt;: except for emailing myself a copy of pages, I&amp;#8217;m cut off from any information I may be collecting in a system like that.&lt;/p&gt;

&lt;p&gt;This is something that I&amp;#8217;ve been concerned about ever since Microsoft first started promoting &amp;#8220;internet everywhere&amp;#8221; inside of Windows. I don&amp;#8217;t use Windows, so it didn&amp;#8217;t concern me much (but it&amp;#8217;s been interesting to see how their strategy effectively made the security problem they wrestle with today). But I always wondered: &amp;#8220;what happens if there&amp;#8217;s no internet? if the network&amp;#8217;s down?&amp;#8221;. The Dashboard in &lt;a href="http://www.apple.com/macosx/"&gt;Mac OS X 10.4&lt;/a&gt; is effectively useless on my iMac at home now. Not that I&amp;#8217;d expect anything different: how can it update its backpack widget and all of those weather feeds with nothing to feed it? It&amp;#8217;s just sad though, seeing that computer that is normally so great become so useless without a connection. I can&amp;#8217;t upload photos, can&amp;#8217;t update &lt;a href="http://euc.cx/"&gt;my web site&lt;/a&gt;, can&amp;#8217;t collaborate with musicians, can&amp;#8217;t shop for art supplies, can&amp;#8217;t check the train schedule, can&amp;#8217;t get new documentation, can&amp;#8217;t get new music from the iTunes Music Store, can&amp;#8217;t manage the Netflix queue that I&amp;#8217;m finally going to set up&amp;#8230; All of these things, taken for granted. And now, thanks to a stressful and confusing mess, I don&amp;#8217;t know when I&amp;#8217;ll be able to take them for granted again.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114860636579792970?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114860636579792970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114860636579792970'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/online-offline-middle-of-line.html' title='Online / Offline / Middle of the Line'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114857673366409763</id><published>2006-05-25T11:05:00.000-06:00</published><updated>2006-05-25T11:06:31.380-06:00</updated><title type='text'>Helmet Head</title><content type='html'>
&lt;p&gt;"But I don't have $100 and I can't come by with a truck for two weeks..." No piano for you! &lt;a href="http://www.craigslist.org/about/best/bos/153144227.html"&gt;Life sucks; get a helmet&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/13463691-114857673366409763?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114857673366409763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114857673366409763'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/blog-post_25.html' title='Helmet Head'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114848993120520250</id><published>2006-05-24T10:58:00.000-06:00</published><updated>2006-05-24T10:59:23.790-06:00</updated><title type='text'>Enjoy Forgetting</title><content type='html'>
&lt;blockquote&gt;
  &lt;p&gt;I really enjoy forgetting. When I first come to a place, I notice all the little details. I notice the way the sky looks. The color of white paper. The way people walk. Doorknobs. Everything. Then I get used to the place and I don't notice those things anymore. So only by forgetting can I see the place again as it really is. - David Byrne as Narrator, &lt;a href="http://www.davidbyrne.com/film/true_stories/"&gt;True Stories (1986)&lt;/a&gt;
&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/13463691-114848993120520250?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114848993120520250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114848993120520250'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/blog-post_24.html' title='Enjoy Forgetting'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114842014624684081</id><published>2006-05-23T15:35:00.000-06:00</published><updated>2006-05-23T15:35:46.253-06:00</updated><title type='text'>Post to MarsEdit from QuickSilver, using Markdown</title><content type='html'>&lt;p&gt;This is an AppleScript I cobbled together real quick to post to this weblog quickly from &lt;a href="http://quicksilver.blacktree.com/"&gt;QuickSilver&lt;/a&gt;, using &lt;a href="http://ranchero.com/marsedit/"&gt;MarsEdit&lt;/a&gt; to handle the posting. I don&amp;#8217;t claim to have any real in-depth knowledge of AppleScript, and I doubt this will win any &amp;#8220;prettiest&amp;#8221; or &amp;#8220;best&amp;#8221; code awards. I just thought it might be helpful to others.&lt;/p&gt;


&lt;pre&gt;
    using terms from application "Quicksilver" 
        on process text ThisClipping
            my SendToMars(ThisClipping)
        end process text
    end using terms from

    on SendToMars(IncomingString)
        set mdcommand to "/opt/local/bin/Markdown.pl " 
        set webtext to do shell script "echo " &amp;#38; quoted form of IncomingString &amp;#38; " | " &amp;#38; mdcommand
        tell application "MarsEdit" 
            make new post window
            tell post window 1
                set body to webtext
                send post to weblog
            end tell
        end tell
    end SendToMars
&lt;/pre&gt;

	&lt;p&gt;Any text formatter could be used here &amp;#8211; I went with Markdown for this situation as it seems to be the best fit for the tiny little text window you get with QuickSilver.&lt;/p&gt;


	&lt;p&gt;To install, I put this in &lt;code&gt;Library/Application Support/Quicksilver/Actions&lt;/code&gt; inside my home folder under the name &lt;code&gt;Post to Griddle&lt;/code&gt;. Any text typed can then be posted immediately. Your mileage may vary, depending on your MarsEdit configuration.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114842014624684081?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114842014624684081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114842014624684081'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/post-to-marsedit-from-quicksilver.html' title='Post to MarsEdit from QuickSilver, using Markdown'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114841830307443792</id><published>2006-05-23T15:05:00.000-06:00</published><updated>2006-05-23T15:05:03.120-06:00</updated><title type='text'> </title><content type='html'>&lt;p&gt;This is a test, of sorts, to see how easy it is to write an applescript to send a post to GriddleNoise via &lt;a href="http://ranchero.com/marsedit/"&gt;MarsEdit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's an attempt to see how easy it might be to do some tumblelog style posts using QuickSilver as the entry pad.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114841830307443792?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114841830307443792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114841830307443792'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/blog-post.html' title=' '/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114833607147952252</id><published>2006-05-22T16:14:00.000-06:00</published><updated>2006-05-22T16:14:31.526-06:00</updated><title type='text'>Settling In</title><content type='html'>&lt;p&gt;I moved into my new apartment a week ago. Except for one glaring problem, it&amp;#8217;s really quite nice. The one glaring problem is huge: &lt;strong&gt;no internet, yet.&lt;/strong&gt; I&amp;#8217;ve been a happy user of cable based internet for most of the past six or seven years, from Fredericksburg to Salt Lake. I haven&amp;#8217;t even had a phone line since moving back to &lt;span class="caps"&gt;SLC&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve been happy enough with cable internet, having had very few problems over the past few years. But right now, &lt;span class="caps"&gt;COMCAST&lt;/span&gt; is having troubles recognizing the existence of my new building &amp;#8211; even though the builder remembers working with &lt;span class="caps"&gt;COMCAST&lt;/span&gt; to lay the cable. It&amp;#8217;s there, apparently, waiting for the first tenant to place a subscription order. And hey! That&amp;#8217;s me! I don&amp;#8217;t think it&amp;#8217;s any major fault of &lt;span class="caps"&gt;COMCAST&lt;/span&gt;&amp;#8217;s though&amp;#8230; Not really anybody&amp;#8217;s fault. But I hope it gets resolved soon.&lt;/p&gt;


	&lt;p&gt;The apartment is small, but cozy. And it&amp;#8217;s not even really that small. This is the third in a series of living spaces that have been open plans: the only doors (besides the entrance) in my last three apartments have been for the bathroom, storage areas, and (in the case of the last two) a/c and water heater access. What differentiates the new space is that it features an upstairs loft, letting me separate the living space from the working space while still keeping everything open. It also means that the ceiling in the working space is extremely high. Actually it slopes back as it&amp;#8217;s an arched roof.&lt;/p&gt;


	&lt;p&gt;The building is a converted warehouse. It&amp;#8217;s a newer warehouse than the ones I was previously in, with cinderblock walls. It was one of those high ceiling single-story warehouses with the arched roofs, which is where the room for the upstairs loft comes in. The cross beams up there remain exposed (providing fun places to try to hang / tuck things). The ceiling/roof is punctuated with clear skylights, with one in the loft area that can be cracked open for ventilation. I&amp;#8217;ve enjoyed being able to sit / lie up there while watching clouds go by. The arched roof creates an interesting sense of coziness as it slopes down away from the living space. From my reading space in the corner, the place feels snug &amp;#8211; almost like a cabin. I can then go over to my writing desk and peer into the workspace, enjoying the open nature. But while sitting and writing, it&amp;#8217;s never overwhelming.&lt;/p&gt;


	&lt;p&gt;Another feature across my recent series of apartments has been hard flooring. Hardwood floors in one, painted plywood/particle board (yep) floors in another, and in the new space: &lt;strong&gt;brushed concrete!!!&lt;/strong&gt; Damn that&amp;#8217;s nice. Unlike the last two apartments though, I also have carpet in the loft &amp;#8211; a feature that my dog greatly appreciates (thin-skinned bony greyhounds love soft surfaces).&lt;/p&gt;


	&lt;p&gt;While the kitchen and bath (on the main level) and living space (loft) feature regular lights, the workspace can be illuminated by two pairs of halogen lights. Excellent for painting, drawing, recording, everything! A large modern ceiling fan in this area circulates air and drives down the need to keep the air conditioner on constantly.&lt;/p&gt;


	&lt;p&gt;Perhaps the best feature of all is the neighborhood. I&amp;#8217;m surrounded by metal recyclers, an old concrete plant my dad worked at when I was young (primarily empty now, although its large silos still seem to be in use). Empty warehouses, active warehouses and industry, random pockets of artists, trains, overpasses, underpasses, industrial back-alleys, &lt;a href="http://www.summum.us/pyramid/"&gt;a pyramid&lt;/a&gt;, and more. It feels good to be out just-ahead of the city. My last couple of places were a little closer to the heart &amp;#8211; different sides of the heart, though. The area I moved out of (and where my office remains) has started to feel different over the past few months, and I don&amp;#8217;t like the feeling. It&amp;#8217;s not bad &amp;#8211; in fact, I&amp;#8217;m glad my office is still here. There is a lot of interesting growth happening and on the verge of happening here. And suddenly, it felt boring. It felt too contemporary when I wanted it to feel more creative, which is strange because I lived in the actual artist block of Artspace and had some great (and creative) neighbors. But the edge was gone.&lt;/p&gt;


	&lt;p&gt;I think my last trip to New York woke me up to this feeling. I played a show in the Red Hook neighborhood of Brooklyn and fell in love. I fell into a funk as my plane landed back in Salt Lake. Over the next couple of weeks I daydreamed of a new space to live and work. I hid in old films, images, and articles of SoHo, and scoured Flickr archives for photos from different neighborhoods and cities that captured an elusive feeling that I was wanting back. My lease came up for renewal, which put me on month-to-month until I renewed, and I decided to take a serious look around at some new options. Ideally I wanted a place I could convert on my own, with a big garage door and a layout that&amp;#8217;d let me keep the dog(s) safe on one side while I worked on the other. I don&amp;#8217;t really have the spare time or funds to support such an endeavor at this time. Still, I decided to look around and see what was available that would allow me to separate workspace and living space, or that I could buy. This was when a flyer showed up under my door announcing the lofts that I&amp;#8217;ve now moved into.&lt;/p&gt;


	&lt;p&gt;As I walked down to check them out, I realized that they were in the heart of the industrial area that I loved. In fact, I had been walking through that area a couple of weeks prior and had been kicking myself for not having a camera along with me. The energy of the area was more active, fresh, raw, gritty, real, and beautiful &amp;#8211; to me anyways. And upon seeing these new spaces and their design, I signed almost immediately. A couple of weeks later, I was moved in. It all happened so fast and naturally, just a straight-ahead instinctual thing. Compared to all of the stress I&amp;#8217;ve felt this year, it was nice to do something big that felt just right.&lt;/p&gt;


	&lt;p&gt;Best of all &amp;#8211; the dog &lt;em&gt;loves&lt;/em&gt; it. In fact, she seems even more playful now.&lt;/p&gt;


	&lt;p&gt;All I need now is internet.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114833607147952252?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114833607147952252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114833607147952252'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/settling-in.html' title='Settling In'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114737180783193316</id><published>2006-05-11T12:23:00.000-06:00</published><updated>2006-05-11T12:23:27.880-06:00</updated><title type='text'>Tinderbox, OmniOutliner, and GTD (again)</title><content type='html'>&lt;p&gt;A few months ago I bit the bullet and purchased &lt;a href="http://www.eastgate.com/Tinderbox/"&gt;Tinderbox&lt;/a&gt;, an interesting outlining/mapping/linking application for Mac OS. I primarily purchased it to use Ryan Holcomb&amp;#8217;s template for a Tinderbox based system for the &lt;strong&gt;Getting Things Done&lt;/strong&gt; workflow, but I also dreamt of using it for more.&lt;/p&gt;


	&lt;p&gt;I haven&amp;#8217;t used Tinderbox much in the past couple of months. &lt;a href="http://kinkless.com/"&gt;Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt;&lt;/a&gt; 0.83 came out along with the  &lt;a href="http://www.omnigroup.com/omnioutliner/"&gt;OmniOutliner&lt;/a&gt; 3.6 beta (now in final release), and it solved many of the issues I had with earlier versions of the &lt;span class="caps"&gt;KGTD&lt;/span&gt;/OmniOutliner combination. Prior to OmniOutliner 3.6, there was just a single toolbar customization setting for OmniOutliner. In most Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; Cocoa apps, you can customize the toolbar pretty easily. It&amp;#8217;s just one toolbar &amp;#8211; not the big mess of toolbars that the Office systems have become. Generally, it&amp;#8217;s been a very handy feature.&lt;/p&gt;


	&lt;p&gt;As OmniOutliner grew terrific Applescript support, they allowed you to add your scripts to the toolbar. Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt; is, in fact, a handful of Applescripts that do an implementation of the Getting Things Done method of planning / management. By putting a few new buttons on the toolbar, you essentially got a new specialized application that took advantage of the terrific nature of OmniOutliner (still the easiest and most fluid outliner on Mac &lt;span class="caps"&gt;OS X&lt;/span&gt;, and looks great too). The downside was that if you wanted to work on other outlines, the &lt;span class="caps"&gt;GTD&lt;/span&gt; buttons would still be there even if they had nothing to do with the document you were working on.&lt;/p&gt;


	&lt;p&gt;With OmniOutliner 3.6, you can now have document specific custom toolbars, meaning that my &lt;span class="caps"&gt;KGTD&lt;/span&gt; outline no longer interferes with other outliner documents. A few other concerns were dealt with in the new &lt;span class="caps"&gt;KGTD&lt;/span&gt; release that made it feel much more natural, and I found myself switching back to the OmniOutliner/Kinkless combination as my &amp;#8220;trusted system&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s a big difference in styles between how OmniOutliner / &lt;span class="caps"&gt;KGTD&lt;/span&gt; work and how Tinderbox / GTDRules work.&lt;/p&gt;


	&lt;p&gt;About &lt;strong&gt;OmniOutliner + Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt;&lt;/strong&gt;:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;span class="caps"&gt;KGTD&lt;/span&gt; is an aggressive user of OmniOutliner&amp;#8217;s extensive Applescript support (and in turn, OmniOutliner&amp;#8217;s Applescript support has gotten even stronger).&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;KGTD&lt;/span&gt;&amp;#8217;s main unit of work is a big synchronization script that moves and copies outline elements around. In the Getting Things Done method, you &amp;#8220;plan in projects and work in contexts&amp;#8221;, and often need at least two views of your actions &amp;#8211; the plan list, and the actual &amp;#8220;do this next in this place&amp;#8221; list. Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt; manages both by copying/merging/moving.&lt;/li&gt;
		&lt;li&gt;By using AppleScript so extensively, Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt; works well with tools like &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt;, whose motto is &amp;#8220;act without doing&amp;#8221;. It&amp;#8217;s easy to send an action into your &lt;span class="caps"&gt;KGTD&lt;/span&gt; inbox without ever switching applications or even taking your hands off the keyboard. Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt; has also done a lot of work to integrate with Apple&amp;#8217;s &lt;a href="http://www.apple.com/ical/"&gt;iCal&lt;/a&gt; calendar, which in turn allows one to use various menu bar tools and Dashboard widgets to keep an eye on actions without having to bring OmniOutliner into focus. &lt;strong&gt;The use of applescript brings integration with other common tools&lt;/strong&gt;.&lt;/li&gt;
		&lt;li&gt;However, &lt;span class="caps"&gt;KGTD&lt;/span&gt; requires manual execution of the synchronization command. It&amp;#8217;s possible to end up with ghosts and duplicates since it&amp;#8217;s doing so much copying and moving. It&amp;#8217;s gotten a lot better when it comes to the ghosts and duplicates, but it means that an active action may have two or three copies in the same document, all separate outline rows.&lt;/li&gt;
		&lt;li&gt;OmniOutliner is a single-window application (well, single window per document). But with the new sections and navigation features in OmniOutliner 3, it&amp;#8217;s quite easy to move around and focus on particular elements.&lt;/li&gt;
		&lt;li&gt;As a native and modern Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; application, built by a shop with a long history of Cocoa/OpenStep/NeXTStep development, OmniOutliner also gets to take advantage of many advanced Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; features. Services, text system plug-ins, etc. This includes automatic spell checking, in-place dictionary look-ups, and more (ie &amp;#8211; with &amp;#8220;Equation Service&amp;#8221;http://www.versiontracker.com/dyn/moreinfo/macosx/14090 installed you can easily convert LaTeX source to a rendered &lt;span class="caps"&gt;PDF&lt;/span&gt; and back again, without OmniOutliner ever knowing anything about LaTeX)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;About &lt;strong&gt;Tinderbox + GTDRules&lt;/strong&gt;:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;GTDRules is an aggressive user of Tinderbox&amp;#8217;s system of agents and prototypes.&lt;/li&gt;
		&lt;li&gt;GTDRules main unit of work is a collection of agents that are always running. Agents in Tinderbox are live queries which can also act on the items that they match. In the document view(s), found items are displayed as children of the agent. Most of the agents in GTDRules are &amp;#8216;contexts&amp;#8217; (again &amp;#8211; plan in projects, work in contexts), showing the next actions for the office, for home, for errands, etc, under the agent.&lt;/li&gt;
		&lt;li&gt;Synchronization is always happening, so when an item is marked as complete, it disappears from the agent displaying it immediately.&lt;/li&gt;
		&lt;li&gt;Data is not duplicated &amp;#8211; the agent results are treated as Aliases, which you can also make manually in Tinderbox. Aliases are like their desktop / file system counterparts: a symbolic link. This way, there are no ghosts or duplicates.&lt;/li&gt;
		&lt;li&gt;Tinderbox has a menu, customizable per document, called &amp;#8220;Value&amp;#8221;. You can use the Value menu to quick-stamp values on Tinderbox nodes. Since there are no checkboxes in the outline views, this is how you mark something as complete. But it&amp;#8217;s also a way you can select many actions and set them all to be &amp;#8220;Office&amp;#8221; actions, in one swoop. Or put them on hold in one swoop. Customizing this menu is pretty easy.&lt;/li&gt;
		&lt;li&gt;GTDRules also takes advantage of Tinderbox&amp;#8217;s &amp;#8220;OnAdd&amp;#8221; rule setting, allowing you to set default values for nodes added &amp;#8211; ie, a work project can easily be set to have its children be &amp;#8216;Office&amp;#8217; prototypes so that they show up in the Office context, but projects for an on-site customer could default to &amp;#8216;Remote&amp;#8217; instead.&lt;/li&gt;
		&lt;li&gt;Tinderbox allows many windows to be open for a single document, and remembers their placement and displayed content. This allows one to take a big system like this and section it off into numerous views.&lt;/li&gt;
		&lt;li&gt;Tinderbox, however, is very much a classic style &amp;#8216;Carbon&amp;#8217; application. It still feels like a custom classic Mac application, and does not take advantage of many modern Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; features &amp;#8211; even ones that are available to Carbon, such as Services. This isn&amp;#8217;t a &lt;span class="caps"&gt;HUGE&lt;/span&gt; deal &amp;#8211; at least it&amp;#8217;s native &amp;#8211; but it&amp;#8217;s frustrating to use the Font menu when I have so many many fonts installed that are so easy to work with in Cocoa text areas (using the font browser in &lt;span class="caps"&gt;OS X&lt;/span&gt;).&lt;/li&gt;
		&lt;li&gt;Tinderbox has practically no Applescript support. It&amp;#8217;s an island. Within the system there are a lot of things you can do. But you can&amp;#8217;t easily send yourself notes from Quicksilver, from Mail rules, etc. There&amp;#8217;s no integration with iCal or anything else. Using Tinderbox is almost like using &lt;a href="http://squeak.org/"&gt;Squeak&lt;/a&gt; on Mac &lt;span class="caps"&gt;OS X&lt;/span&gt;. Yeah, your mouse and keyboard and the clipboard all work, but beyond that it&amp;#8217;s a universe unto itself.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Tinderbox&amp;#8217;s isolation was a key figure in driving me back to Kinkless &lt;span class="caps"&gt;GTD&lt;/span&gt; / OmniOutliner. The GTDRules implementation on Tinderbox is a more &amp;#8220;pure&amp;#8221; implementation of the &lt;span class="caps"&gt;GTD&lt;/span&gt; workflow and easier to customize to one&amp;#8217;s preferences (no applescript programming required). But data entry &amp;#8211; especially of the quick &amp;#8220;i need to remember to look at this later&amp;#8221; variety &amp;#8211; is not its strong suit here. There was something about it that started causing me stress when I&amp;#8217;d look at my system. Maybe it was me getting sloppy and not cleaning / planning as well as I should. But something would just feel off.&lt;/p&gt;


	&lt;p&gt;All of that said, Tinderbox has a lot of great features that I&amp;#8217;ve been meaning to explore. The &lt;a href="http://euc.cx/"&gt;euc.cx&lt;/a&gt; universe is ever growing, a great jumble of myth and fact, legend and memory. I&amp;#8217;ve been wanting to start setting down all of the characters, locations, productions, etc, of it all and exploring the relationships. This is Tinderbox&amp;#8217;s strong suit &amp;#8211; links, relationships, visual maps (as well as outlines), prototypes, custom data, all should play in here. I really do need to keep myself still long enough to start learning how to do this. And I want to write again. Like really write, in hypertext, with relationships and cross references. I tried this once with &lt;a href="http://euc.cx/ddec/"&gt;ddec&lt;/a&gt;, a system based on an old implementation of the &lt;a href="http://ftrain.com/"&gt;FTrain&lt;/a&gt; sitekit. But I hated writing in &lt;span class="caps"&gt;XML&lt;/span&gt;. (I just hate &lt;span class="caps"&gt;XML&lt;/span&gt;. I don&amp;#8217;t care about it as a storage format, but I do hate writing in it, configuring in it, etc). This kind of writing is the real concept behind &lt;a href="http://www.eastgate.com/"&gt;Eastgate&lt;/a&gt; as an entity. Whether anything will actually happen is hard to say at this point. But it looks like my writing desk will be in an excellent location in my new space and I hope it&amp;#8217;ll help inspire me.&lt;/p&gt;


	&lt;p&gt;The view from where the desk will most likely be. (It&amp;#8217;s a console table actually, just the right size for an iBook, a small lamp, a pile of notebooks, and the dog&amp;#8217;s leash):&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/jshell/132637114/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/52/132637114_83bd4f843d.jpg" width="500" height="374" alt="Eucci Sunhill, Empty" /&gt;&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/13463691-114737180783193316?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114737180783193316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114737180783193316'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/tinderbox-omnioutliner-and-gtd-again.html' title='Tinderbox, OmniOutliner, and GTD (again)'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114687291064826325</id><published>2006-05-05T17:48:00.000-06:00</published><updated>2006-05-05T17:48:30.690-06:00</updated><title type='text'>Studio Peak (Inspirational Peek)</title><content type='html'>&lt;p&gt;As I&amp;#8217;m getting ready to move to a new loft that will give me a nicer, more dedicated working space, I&amp;#8217;ve found myself doing a lot more painting. I was working on large canvas in front of this stack of metal cube-ish storage things. As I was taking some pictures of the work in progress, I realized I needed to get a shot of what sits up top. Here, in bite sizes, are a lot of representative elements from artists, designers, factories, and companies that are a pretty strong source of inspiration. So, to step away from the usual crankiness and software focus for a bit, I thought I&amp;#8217;d share a bit:&lt;/p&gt;

&lt;div align="center"&gt;&lt;a href="http://www.flickr.com/photos/jshell/140655837/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/44/140655837_c8e0fbdded.jpg" width="500" height="374" alt="Studio Peak (Inspirational Peek)" /&gt;&lt;/a&gt;&lt;/div&gt;


	&lt;p&gt;&lt;strong&gt;SuperSampler, Lubitel, &lt;span class="caps"&gt;LCA&lt;/span&gt;, and Baby Holga (110 Format!) Cameras.&lt;/strong&gt; The 120 Format &amp;#8220;standard&amp;#8221; Holga is on top of my desk and not with the rest of the family. I do love these cameras: they have a lot of personality, with the LC-A being my favorite point&amp;#8217;n&amp;#8217;shoot 35mm camera ever. I don&amp;#8217;t do film as much these days. For a few years my walk home took me past a few places where I could get film developed (including the 110 and 120 formats), often dropping the 35mm off in the morning on the way to work and picking it up on the way home. I haven&amp;#8217;t had that since I moved into my current place, and that&amp;#8217;s taken a big bite out of me rolling over new rolls as often. Plus I do have the digital camera that&amp;#8217;s great for taking endless pictures of &lt;a href="http://www.flickr.com/photos/jshell/sets/1102621/"&gt;the dog&lt;/a&gt;, of paintings, and flash conditions. But it&amp;#8217;s a soulless camera compared to these guys, most of which are completely themed around a terrific (and fun) mantra: &lt;strong&gt;don&amp;#8217;t think, just shoot&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Brushes, Brushes, Brushes&lt;/strong&gt;. Some of these brushes came with me back from Virginia and are still in pretty good shape &amp;#8211; probably because I don&amp;#8217;t paint nearly as much as I used to. But when I got my current place I finally got that container they&amp;#8217;re in, which has made access to my core set much easier than my previous contraptions.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Helmut Lang promotional cards (from one of the last seasons)&lt;/strong&gt;. Helmut Lang was my favorite designer, with a terrific design aesthetic that was applied to everything under the brand. The flagship store in New York, designed by &lt;a href="http://www.gluckmanmayner.com/"&gt;Richard Gluckman&lt;/a&gt;, was a terrific piece of architecture. Completely opposite of most New York stores (crowded, impersonal, or overly flashy), the Helmut Lang space used design to usher you in to a private area with large aisles and easy access to everything, without ever telling you what tricks it was pulling. It was an amazingly comfortable space. There was a &amp;#8220;complete experience&amp;#8221; about Lang that I sorely miss.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Ryoji Ikeda &amp;#8216;Formula&amp;#8217; &lt;span class="caps"&gt;DVD&lt;/span&gt; and Book&lt;/strong&gt;. Another terrific aesthetic minimalist, Ryoji Ikeda&amp;#8217;s installations and a live set are showcased &lt;a href="http://www.ryojiikeda.com/formula/formula/formula+book_43dvd/"&gt;in this excellent volume&lt;/a&gt;. Ikeda is another artist who, like Lang, seems adroit at knowing what to take away, what to shift, and what to tuck into a piece of art (design, clothing, composition).&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;New reissue of Pizzicato Five&amp;#8217;s Romantique 96&lt;/strong&gt;, in front of Merzbow &amp;#8216;Senmaida&amp;#8217; card (making it look like Maki and the Dalmations are on a Merzbow promo here). Two more excellent Japanese artists. Pizzicato Five kept many Jet Age fashions, designs, and ideals alive in their music. Their album packaging was often a step above (with only a couple of the U.S. releases falling short). Credit cards, luggage tags, postcards, stickers, bookmarks were among the things one could find inside a common release. And of course, there were the pictures of Konishi and Maki. Beautiful music, and a favorite artist of mine for years. &lt;strong&gt;Merzbow&lt;/strong&gt; is almost their opposite: harsh noise. Hundreds of releases across an almost equal number of labels and distributors. He carries on almost a pure dadaist spirit. The cover art and packaging quality can vary wildly. The noise is almost always top-notch and he remains one of the kings. The postcard (mostly hidden in this photo) is from &lt;a href="http://www.blossomingnoise.com/senmaida.html"&gt;Senmaida&lt;/a&gt; which featured art by &lt;a href="http://www.valdenham.com/artpaths.html"&gt;Val Denham&lt;/a&gt; that I just had to have for the picture alone.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Stack of book size Hafler Trio and Pizzicato Five releases&lt;/strong&gt;, more albums in excellent packaging. &lt;a href="http://www.brainwashed.com/h3o"&gt;The Hafler Trio&lt;/a&gt; being another terrific inspiration on many many fronts. Among other things, The Hafler Trio has played with sound-as-high-art, putting out releases in very limited numbers and with many extras in the packaging or experience to make it especially worth obtaining.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Brazil!&lt;/strong&gt;. On &lt;span class="caps"&gt;VHS&lt;/span&gt;. Ahhh, Terry Gilliam.&lt;/p&gt;


	&lt;p&gt;&amp;#8220;I draw on anything for inspiration &amp;#8211; a fond memory, a piece of paper, a wall in a train station&amp;#8221; &amp;#8211; Danger Doom/Talib Kwali&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114687291064826325?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114687291064826325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114687291064826325'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/studio-peak-inspirational-peek.html' title='Studio Peak (Inspirational Peek)'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114684871953077908</id><published>2006-05-05T11:05:00.000-06:00</published><updated>2006-05-05T11:05:19.586-06:00</updated><title type='text'>Tools</title><content type='html'>&lt;p&gt;I&amp;#8217;ve never been a fan of &lt;span class="caps"&gt;IDE&lt;/span&gt;&amp;#8217;s. I grew up on Commodore 64 &lt;span class="caps"&gt;BASIC&lt;/span&gt; &amp;#8211; always on, just start typing in code and it works. I used &lt;span class="caps"&gt;IDE&lt;/span&gt;&amp;#8217;s a little bit way back in my high school computer science day, but I remember it as little more than an editor / compiler combination (Lightspeed Pascal on Mac System 6). After that, I did very little programming for a few years except for casual purposes until I started using Python in 1996.&lt;/p&gt;


	&lt;p&gt;Most of my Python programming career has been focused on web development, and subsequently most of my development environments have been on development servers. For a good stretch of time, my editor/environment of choice was XEmacs. A couple of years ago I switched to &lt;span class="caps"&gt;VIM&lt;/span&gt; (lighter weight, didn&amp;#8217;t need to bother setting up X Windows any more, and I could go into a stripped down production server running bare bones VI and not feel completely lost). A couple of months ago I started using &lt;a href="http://macromates.com/"&gt;TextMate&lt;/a&gt; pretty heavily, and started working on my desktops again since Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; is, after all, Unix. Using DarwinPorts I could get the requirements for both Zope 3 and Ruby on Rails going pretty easily. And in this &amp;#8220;just a plain but smart editor please&amp;#8221; camp I remained, using the terminal to start and stop servers, to debug, to watch logs, etc.&lt;/p&gt;


	&lt;p&gt;But the other day I decided to check out &lt;a href="http://www.radrails.org/"&gt;RadRails&lt;/a&gt;, an Eclipse based &lt;span class="caps"&gt;IDE&lt;/span&gt; for Ruby/Rails development.&lt;/p&gt;


	&lt;p&gt;And holy shit, I was impressed.&lt;/p&gt;


	&lt;p&gt;Traditionally &lt;span class="caps"&gt;IDE&lt;/span&gt;&amp;#8217;s have bugged me with their ever proliferating collection of panes and tabs. Too much noise! Too much to set up! Too much fighting to make it work my way! But with a little bit of preference tweaking (to point RadRails at the right Ruby / Rails installations on my desktop), I got RadRails running. I didn&amp;#8217;t use it heavily (I&amp;#8217;m not doing active Rails development, but continue to check it out from a point of envy / curiosity), but I was impressed with what it had: good knowledge of the Rails Generators, the database explorer, consoles, log watchers, etc. All things that I&amp;#8217;m sure &lt;span class="caps"&gt;IDE&lt;/span&gt; users take for granted. I was especially impressed with how easily one could maximize any pane to be full-window size, and then go back to the many-many-many-views, using just a double click.&lt;/p&gt;


	&lt;p&gt;While it still doesn&amp;#8217;t feel 100% native, RadRails/Eclipse actually performed and behaved rather well in Mac &lt;span class="caps"&gt;OS X&lt;/span&gt; &amp;#8211; better than any other Java application I&amp;#8217;ve used. Better by a long shot.&lt;/p&gt;


	&lt;p&gt;Now where&amp;#8217;s something like this for Zope 3? Especially for my bastardized system using SQLAlchemy? :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114684871953077908?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114684871953077908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114684871953077908'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/05/tools.html' title='Tools'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114496455729707506</id><published>2006-04-13T10:29:00.000-06:00</published><updated>2006-04-13T15:42:37.350-06:00</updated><title type='text'>Snakes and Rubies in the Temple of Bondage and Discipline down in the City of Heartbreak and Needles</title><content type='html'>&lt;p&gt;One of the new topics making the rounds is a spate of responses to an old (2-3 years, at least) &lt;a href="http://www.rexx.com/~oinkoink/Ruby_v_Python.html"&gt;post comparing Python and Ruby&lt;/a&gt;. One piece of interest is this bit:&lt;/p&gt;


 &lt;blockquote&gt;
  &lt;p&gt;Larry Wall, the designer of Perl, has the slogan &amp;#8220;There&amp;#8217;s more than one way to do it&amp;#8221;. In contrast, Bertrand Meyer, the designer of Eiffel, says &amp;#8220;A programming language should provide one good way of performing any operation of interest; it should avoid providing two.&amp;#8221; Ruby follows the anarchist approach of Larry Wall, while Python follows the bondage-and- discipline approach of Eiffel.&lt;/p&gt;
 &lt;/blockquote&gt;


 &lt;p&gt;While it&amp;#8217;s stated in the Python &lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;import this&lt;/a&gt; (aka &amp;#8220;The Zen of Python&amp;#8221;): &lt;strong&gt;There should be one &amp;#8211; and preferably only one &amp;#8211; obvious way to do it&lt;/strong&gt;, that&amp;#8217;s seldom the case in actuality. &lt;a href="http://blog.ianbicking.org/re-ruby-and-python-compared.html"&gt;Ian Bicking&amp;#8217;s response&lt;/a&gt; to the post linked above mentions this as well. There are well meaning attempts at consistency &amp;#8211; but do they happen?&lt;/p&gt;


 &lt;p&gt;Python makes some interesting design trades. As many note, it&amp;#8217;s not a so-called &amp;#8220;Pure Object Oriented&amp;#8221; system. You can write Python in a purely procedural style, in a Modula style, in functional style, in pure scripting style, in &amp;#8220;pure OO&amp;#8221; style, or in a mix of all.&lt;/p&gt;


 &lt;p&gt;The comprehensive standard library is a big mix of all of these styles. Some of it stems from certain core modules being thin layers over common C libraries. Some of it stems from different styles of different authors. Some of it stems from age.&lt;/p&gt;


 &lt;p&gt;I&amp;#8217;ve generally been a fan of Python&amp;#8217;s modular approach. Common modules like &lt;strong&gt;os&lt;/strong&gt; and &lt;strong&gt;os.path&lt;/strong&gt; provide a nice &amp;#8211; but thin &amp;#8211; abstraction over operating system specific behaviors, especially in regards to the file system. Python&amp;#8217;s early development, according to legend, happened on Macs (and considering Python&amp;#8217;s age, it should be noted that this was long before &lt;strong&gt;Mac &lt;span class="caps"&gt;OS X&lt;/span&gt;&lt;/strong&gt;). Classic Mac OS, &lt;span class="caps"&gt;DOS&lt;/span&gt;/Windows, and Unix all spell paths differently. In the mid nineties, as Python was starting to really find its audience (including me), its primary rival was perceived to be Perl. Perl&amp;#8217;s history is steeped in Unix style shell scripting. Perl scripts, then, typically had very Unix style paths and elements inside of them, just by default. While there were some good Perl implementations available for classic Mac OS, it was hard to play with other peoples code &amp;#8211; there were just a lot of system expectations built in, especially at the time I started experimenting with the two P languages.&lt;/p&gt;


 &lt;p&gt;Python, on the other hand, had the &amp;#8216;os&amp;#8217; and &amp;#8216;os.path&amp;#8217; modules. These modules contain, among other things, knowledge of how the current OS spells certain file system elements, like &amp;#8216;parent directory&amp;#8217; or path separator. Classic Mac &lt;span class="caps"&gt;HFS&lt;/span&gt; paths were separated by colons, for example, and &amp;#8216;pardir&amp;#8217; was not &amp;#8217;..&amp;#8217; but &amp;#8217;::&amp;#8217;. And, of course, Windows/DOS uses backslashes instead of forward slashes. So while you could write paths the normal way, it was (and still is) considered good design to use the os module&amp;#8217;s tools:&lt;/p&gt;


&lt;pre&gt;
    pydir = os.path.join(os.pardir, 'lib', 'python')
    appdir = os.path.join(pydir, 'example')
&lt;/pre&gt;

 &lt;p&gt;But! The os module&amp;#8217;s elements for working with paths is very procedural. There&amp;#8217;s not really a built in concept of a Path object. That may be changing in Python 2.5 if &lt;a href="http://www.python.org/dev/peps/pep-0355"&gt;&lt;span class="caps"&gt;PEP 355&lt;/span&gt;&lt;/a&gt; really finds its way in. Then the above could be more like:&lt;/p&gt;


&lt;pre&gt;
    pydir = Path(Path.cwd().parent, 'lib', 'python')
    appdir = Path + 'example'
&lt;/pre&gt;

 &lt;p&gt;While that doesn&amp;#8217;t look like much, it&amp;#8217;s when one looks at some of the proposed replacements that one can see the difference:&lt;/p&gt;


&lt;pre&gt;
    CURRENT (using 'os')
    --------------------
    DIR = '/usr/home/guido/bin'
    for f in os.listdir(DIR):
        if f.endswith('.py'):
            path = os.path.join(DIR, f)
            os.chmod(path, 0755)

    NEW (using 'path')
    ------------------
    for f in Path('/usr/home/guido/bin').files("*.py"):
        f.chmod(0755)
&lt;/pre&gt;

 &lt;p&gt;Taking that old &amp;#8211; but useful (and usable) &amp;#8211; procedural code and turning it into a class / objects is just beautiful, and is one of those &amp;#8220;why didn&amp;#8217;t they do that before?&amp;#8221; things. The new Path class also brings a lot of functionality that&amp;#8217;s dispersed in other modules (that people may not even be aware of) together, like &amp;#8216;glob&amp;#8217;, &amp;#8216;fnmatch&amp;#8217;, and &amp;#8216;shutil&amp;#8217;. (It looks like Ruby 1.8 picked up something similar with the new &lt;a href="http://redhanded.hobix.com/bits/howPowerfulPathnameIs.html"&gt;Pathname&lt;/a&gt; class).&lt;/p&gt;


 &lt;p&gt;The point being &amp;#8211; this is an area where there are really quite a few ways of doing things in Python. Is it good? Is it bad? It&amp;#8217;s a nice kind of freedom, I guess, to be able to write in both procedural/modular and OO styles. There&amp;#8217;s definitely no hard &amp;#8220;bondage and discipline&amp;#8221; here.&lt;/p&gt;


 &lt;p&gt;There&amp;#8217;s also no hard &amp;#8220;bondage and discipline&amp;#8221; in Python when it comes to naming. There are some &lt;a href="http://www.python.org/dev/peps/pep-0008"&gt;good practices&lt;/a&gt;, but not everyone follows them (myself included). I have a personal style guide, much of it taken from practices we had at Zope corp (4 spaces indentation, must fit in 80 columns) and styles picked up over recent years (all package/module names lower case, all classes capitalized, never &lt;code&gt;import * &lt;/code&gt; if it can be avoided, etc). And I &lt;strong&gt;wince&lt;/strong&gt; when I see code that differs &amp;#8211; mixed case package/module names being one of the biggest turn-offs to me, personally. &lt;code&gt;import * &lt;/code&gt; has generally been offensive as well. One thing that I&amp;#8217;ve historically liked about Python has been the ability to trace back any name I see in code. &amp;#8220;Path&amp;#8230; ah, it came from &lt;code&gt;from path import Path&lt;/code&gt;!  And implements.. Oh, it came from &lt;code&gt;zope.interface import implements!&lt;/code&gt; and self.bluecheese is obviously an attribute available to the instance!&amp;#8221; &lt;code&gt;import * &lt;/code&gt; tends to get in the way of name chasing. I like to learn code by reading it (since most documentation tends to be flaky), so being able to find where &amp;#8216;mapper&amp;#8217; or &amp;#8216;begin&amp;#8217; or &amp;#8216;desc&amp;#8217; or &amp;#8216;Table&amp;#8217; came from is something I like. And for maintainability reasons, I&amp;#8217;ve liked being able to find and trace names within a function/class/module without having to speculate.&lt;/p&gt;


 &lt;p&gt;But that&amp;#8217;s just my preference. Python&amp;#8217;s namespaces and general rules here have generally worked out for me. But as I&amp;#8217;ve gone on, I&amp;#8217;ve found myself much more critical of other Python code than I should be, which is contributing to this crisis of faith I&amp;#8217;ve been going through. Whereas when I&amp;#8217;m ready Ruby code, I have different expectations and can be a lot more forgiving.&lt;/p&gt;


 &lt;p&gt;But there&amp;#8217;s something significant that I&amp;#8217;ve come to realize about Ruby. It can be argued that Python&amp;#8217;s biggest &amp;#8220;bondage and discipline&amp;#8221; element is its use of significant whitespace (clear structure by indentation is enforced at the language level &amp;#8211; although there are ways around this). Ruby, on the other hand, &lt;strong&gt;enforces significant naming conventions&lt;/strong&gt;. As I&amp;#8217;ve been reading Ruby code (with most of my experience being limited to Rails and code from &lt;a href="http://www.whytheluckystiff.net/"&gt;why the lucky stuff&lt;/a&gt;), I&amp;#8217;ve grown to appreciate this:&lt;/p&gt;


 &lt;ul&gt;
 &lt;li&gt;Constants begin with a capital letter. Classes and modules are constants, and so they are &lt;em&gt;always&lt;/em&gt; capitalized. &lt;code&gt;Pathname.pwd&lt;/code&gt;, &lt;code&gt;ActiveRecord::Base&lt;/code&gt;, and so on.&lt;/li&gt;
  &lt;li&gt;variables are lower case (or at least, start with a lowercase letter). This includes methods.&lt;/li&gt;
 &lt;/ul&gt;


 &lt;p&gt;Understanding those two elements alone (along with learning Ruby&amp;#8217;s symbols for self.attribute access, etc) has made it really easy to start reading and understanding Ruby code. I can understand how Rails can be a system that &amp;#8220;prefers convention over configuration&amp;#8221; &amp;#8211; there seems to be a fair amount of convention enforced in the language and core library as it is.&lt;/p&gt;


 &lt;p&gt;Another thing I find interesting is that object attributes are not exposed directly, but can be exposed easily through methods. With parenthesis being optional on method calls, this makes zero-input methods (ie &amp;#8211; &amp;#8216;reader&amp;#8217; methods) much easier to use and work with. An historical Zope 1 and 2 problem was the case of &amp;#8216;id&amp;#8217;. Some objects would just have their &amp;#8216;id&amp;#8217; (name within their container) set as an attribute. Others would compute it and have a callable method. In &lt;span class="caps"&gt;DTML&lt;/span&gt; and &lt;span class="caps"&gt;TAL&lt;/span&gt;, you could refer to &amp;#8216;id&amp;#8217; and the templating language&amp;#8217;s expression engine would figure out if it needed to be a call or not (and then translate it into &amp;#8216;id()&amp;#8217; if needed). So sometimes, &lt;code&gt;obj.id&lt;/code&gt; would return a string like &amp;#8216;monkey&amp;#8217;. But other times it would return &lt;code&gt;(bound method id of ...)&lt;/code&gt;. Python&amp;#8217;s descriptors (since Python 2.2) make this a little bit better, but in my encounters with Ruby so far, it&amp;#8217;s made code more readable and consistent and predictable. The proposed Path class for Python (mentioned above), for example, has a mix of properties and methods:&lt;/p&gt;


&lt;pre&gt;
    curpath = Path.cwd()
    documents = curpath + 'Documents'
    curpath.parent
    curpath.realpath()
    curpath.mtime()
    curpath.isdir()
    str(curpath)
&lt;/pre&gt;

 &lt;p&gt;Compared now to Ruby&amp;#8217;s Pathname object:&lt;/p&gt;


&lt;pre&gt;
    curpath = Pathname.pwd
    documents = curpath + 'Documents'
    curpath.parent
    curpath.realpath
    curpath.mtime
    curpath.directory?
    curpath.to_s
&lt;/pre&gt;

 &lt;p&gt;The Ruby code just looks cleaner, more consistent &amp;#8211; even though one could put parenthesis on all of these calls. &amp;#8216;Pathname&amp;#8217; is obviously (or highly likely) to be a class. For the Path class proposed in Python &lt;span class="caps"&gt;PEP 355&lt;/span&gt;, one of the open issues in the &lt;span class="caps"&gt;PEP&lt;/span&gt; is this:&lt;/p&gt;


 &lt;blockquote&gt;
  &lt;p&gt;The name obviously has to be either &amp;#8220;path&amp;#8221; or &amp;#8220;Path,&amp;#8221; but where should it
live? In its own module or in os?&lt;/p&gt;
 &lt;/blockquote&gt;


 &lt;p&gt;Let&amp;#8217;s look at that first part again: &lt;strong&gt;The name obviously has to be either &amp;#8216;path&amp;#8217; or &amp;#8216;Path&amp;#8217;&lt;/strong&gt;. Either? Well, a lot of core Python classes and types are lower case &amp;#8211; although many of them weren&amp;#8217;t really types/classes until recently. I&amp;#8217;m talking &amp;#8216;str&amp;#8217;, &amp;#8216;object&amp;#8217;, &amp;#8216;file&amp;#8217; (aka &amp;#8216;open&amp;#8217;), etc. Some of this has to do with the history of the language and how it has grown / changed over the years. But obviously there&amp;#8217;s more than one way to do it &lt;strong&gt;if you can&amp;#8217;t really be sure of the proper way to capitalize it&lt;/strong&gt;.&lt;/p&gt;


 &lt;p&gt;Indentation can be significant when scanning over code (not even reading into details). So can naming and other behaviors. Python programmers may see the &amp;#8216;end&amp;#8217; keywords for Ruby&amp;#8217;s blocks for for loops, if statements, etc, and go &amp;#8220;ha! Python don&amp;#8217;t need that line noise!&amp;#8221;. But Ruby programmers may just as easily look at parenthesis on method calls that take no arguments and go &amp;#8220;Ha! Ruby don&amp;#8217;t need that line noise!&amp;#8221; They may also look at things like &amp;#8216;list.sort()&amp;#8217; and wonder why they don&amp;#8217;t get a sorted copy of the list back (and may also wonder why it took until Python 2.4 for Python to finally grow an in-line &amp;#8216;sorted copy&amp;#8217; function of its own). Ruby&amp;#8217;s use of punctuation helps distinguish between the destructive (changes the object in question) and not destructive (returns a copy of the object in question):&lt;/p&gt;


&lt;pre&gt;
    Python:
    &amp;gt;&amp;gt;&amp;gt; alist = [3,2,7,13,8]
    &amp;gt;&amp;gt;&amp;gt; print alist.sort()
    None
    &amp;gt;&amp;gt;&amp;gt; alist
    [2, 3, 7, 8, 13]
    &amp;gt;&amp;gt;&amp;gt; alist = [3,2,7,13,8]
    &amp;gt;&amp;gt;&amp;gt; print sorted(alist)
    [2, 3, 7, 8, 13]
    &amp;gt;&amp;gt;&amp;gt; alist
    [3, 2, 7, 13, 8]

    Ruby:
    irb&amp;gt; alist = [3,2,7,13,8]
    irb&amp;gt; p alist.sort
    [2, 3, 7, 8, 13]
    irb&amp;gt; alist
    =&amp;gt; [3, 2, 7, 13, 8]
    irb&amp;gt; p alist.sort!
    [2, 3, 7, 8, 13]
    irb&amp;gt; alist
    =&amp;gt; [2, 3, 7, 8, 13]
&lt;/pre&gt;

 &lt;p&gt;Things like list.sort and having len(), sorted(), etc, being separate methods are things you get used to in Python. At the same time, it gives bad guidance for best practices (or just good practices) for writing code. If writing something like a Field object which can be bound to another object &amp;#8211; should &amp;#8216;bind(target)&amp;#8217; return a new copy of the Field bound to the target, or should it bind in place? In Ruby, one might write two methods, &lt;code&gt;bind(target)&lt;/code&gt; and &lt;code&gt;bind!(target)&lt;/code&gt;, with the second one denoting that it changes the Field in place.&lt;/p&gt;


 &lt;p&gt;I don&amp;#8217;t know how consistent other Ruby developers are in following that standard, but it&amp;#8217;s great to have as an option. I also like the question mark used for boolean methods: &lt;code&gt;alist.empty?&lt;/code&gt; &lt;code&gt;alist.include? 7&lt;/code&gt;, and so on. Again &amp;#8211; in my limited experience with Ruby, it&amp;#8217;s been easier to understand a lot of the code I&amp;#8217;ve seen:&lt;/p&gt;


&lt;pre&gt;
    popped = alist.pop if alist.respond_to? :pop
    if popped.nil?
        puts "Bastard didn't pop" 
    end

    if hasattr(alist, 'pop'):
        popped = alist.pop()
    else:
        print "Bastard couldn't pop" 
&lt;/pre&gt;

 &lt;p&gt;The differences are negligible here, mostly a matter of preference. How about testing for emptiness? Not just testing for truth &amp;#8211; but testing to see if a container is empty?&lt;/p&gt;


&lt;pre&gt;
    Ruby:
    if alist.empty?
        puts "It's Empty" 
    end

    Python:
    # truth testing
    if not alist:
        print "It's Empty" 
    # length testing
    if len(alist) == 0:
        print "It's Empty" 

    # Writing a custom 'empty' tester.
    def empty(obj):
        return (len(obj) == 0)

    if empty(alist):
        print "It's Empty" 

    # But 'empty' could also be destructive
    def empty(obj):
        obj[:] = []
        return obj

    if empty(alist):
        print "will always be empty because this version of empty destroys" 
&lt;/pre&gt;

 &lt;p&gt;More than one way to do it. Of course, the truth testing is the most commonly used in Python &amp;#8211; but there are times when &amp;#8216;emptiness&amp;#8217; and &amp;#8216;truthiness&amp;#8217; have different meaning / impact. &lt;code&gt;alist.empty?&lt;/code&gt; reads easy. The punctuation in the name differentiates it from a method like &lt;code&gt;empty&lt;/code&gt; or &lt;code&gt;empty!&lt;/code&gt; which might clear the object out (like &amp;#8216;clear&amp;#8217; does in Ruby arrays). So this useful feature and convention makes it possible to look at an objects list of methods and pick out the queries.&lt;/p&gt;


 &lt;p&gt;So &amp;#8211; am I saying Ruby is better than Python? No. Nor am I saying it the other way around. There are some very different designs here. But the enforced naming conventions and other small touches &amp;#8211; constants versus variables, leading to consistent class and method spellings; punctuation in method names; &amp;#8216;optional&amp;#8217; method call parenthesis causing one not to have to worry about whether they need to use &lt;code&gt;object.id&lt;/code&gt; or &lt;code&gt;object.id()&lt;/code&gt; &amp;#8211; have enabled me to read large framework code like that in Rails or Hobix as easily or more easily than Python, even though Python claims to be written for readability and I&amp;#8217;ve been programming in Python for a decade now and I&amp;#8217;ve still scarcely used Ruby at all. There really seems to be a clean and simple elegance about it that I find myself yearning for.&lt;/p&gt;


 &lt;p&gt;The communities are interesting too. Python can&amp;#8217;t even seem to settle on a good documentation tool. pydoc is way too simple in its &lt;span class="caps"&gt;HTML&lt;/span&gt; mode (but quite nice in the interpreter when you can do help(obj)). &lt;a href="http://epydoc.sf.net/"&gt;epydoc&lt;/a&gt; is quite comprehensive and supports comprehensive markup options, including the ability to document instance variables, method parameters, etc&amp;#8230;, but its output can still be a bit hard to read.. Or at least, to differentiate the wheat from the chaff (I don&amp;#8217;t think it&amp;#8217;s epydoc&amp;#8217;s fault, Python modules and objects may just be exposing too many extra objects that don&amp;#8217;t always need to be documented and those get in the way of finding useful help). The almighty effbot has added &lt;a href="http://effbot.org/zone/pythondoc.htm"&gt;PythonDoc&lt;/a&gt; to the mix as well. And there&amp;#8217;s also &lt;a href="http://pudge.lesscode.org/"&gt;Pudge&lt;/a&gt;. Zope 3 has its own &lt;span class="caps"&gt;API&lt;/span&gt; documentation tool with some specific knowledge of additional Zope 3 elements &amp;#8211; sadly there&amp;#8217;s no publically available online version to use for reference (yet).&lt;/p&gt;


 &lt;p&gt;And with all of these options &amp;#8211; there&amp;#8217;s nothing that quite matches the discoverability and usability of the &lt;a href="http://api.rubyonrails.org/"&gt;Ruby on Rails &lt;span class="caps"&gt;API&lt;/span&gt; Docs&lt;/a&gt;. Again, I&amp;#8217;ve gotten far better answers out of it than on &lt;em&gt;any&lt;/em&gt; of the Python web tools I&amp;#8217;ve evaluated&amp;#8230; Ever. Which is why reading the source and being able to follow names is so important to me in Python. The source is often the best documentation you can easily get to and through. The Python standard library is very well documented. But beyond that, it&amp;#8217;s often a lot of work. Ian Bicking wrote in his post &lt;a href="http://blog.ianbicking.org/orthogonality-is-pretentious.html"&gt;Orthogonality is Pretentious&lt;/a&gt; (a post I generally disagree with &amp;#8211; orthogonality leads to a pleasant predictability, I think, in languages like Smalltalk and also in Ruby) about &lt;span class="caps"&gt;PHP&lt;/span&gt;:&lt;/p&gt;


 &lt;blockquote&gt;
  &lt;p&gt;One example of this design in &lt;span class="caps"&gt;PHP&lt;/span&gt; is the lack of objects in the standard library. Instead it is one very long list of functions. If you want to do something with the standard library there either is a function for doing it, or there is not a function. If you want to see what you can do, you can just scan through the index.&lt;/p&gt;
 &lt;/blockquote&gt;


 &lt;p&gt;And that&amp;#8217;s what I like about Ruby on Rails. In the &lt;span class="caps"&gt;API&lt;/span&gt; Docs, one of the frames lists all of the methods in the system. That alone has been useful for just looking up functionality. One big list of functions (essentially), most of which are available where you need them most. Easy list to turn to and scroll through.&lt;/p&gt;


 &lt;p&gt;Similar functionality is in the &lt;a href="http://pylonshq.com/WebHelpers/module-index.html"&gt;WebHelpers&lt;/a&gt; library for Python &amp;#8211; but there&amp;#8217;s no version of the docs (at this time) that have that nice &amp;#8220;big list of functions&amp;#8221;. It&amp;#8217;s click / try / click / try / click / try. At least it&amp;#8217;s documented! But still, it just takes more time to weed out pertinent information.&lt;/p&gt;


 &lt;p&gt;Jumping to api.rubyonrails.org and scrolling through that bottom list to find &amp;#8216;has_many&amp;#8217; again to find its options is a very quick process. (Just like most Python standard library lookups &amp;#8211; the &lt;a href="http://docs.python.org/lib/lib.html"&gt;library&lt;/a&gt; and &lt;a href="http://docs.python.org/modindex.html"&gt;module indexed&lt;/a&gt; reference for Python is damn handy!)&lt;/p&gt;


 &lt;p&gt;Ugh. Where was I going with all of this? Nowhere really. I still like Python and it&amp;#8217;s still my working programming language. But there are a lot of things about Ruby and what its community has been producing over recent years (beyond just Rails) that are increasingly enticing.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114496455729707506?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114496455729707506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114496455729707506'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/04/snakes-and-rubies-in-temple-of-bondage.html' title='Snakes and Rubies in the Temple of Bondage and Discipline down in the City of Heartbreak and Needles'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114445963618994482</id><published>2006-04-07T19:04:00.000-06:00</published><updated>2006-04-07T19:30:05.810-06:00</updated><title type='text'>Because I Could (SQLAlchemy, Zope 3, Metaclass Fun, Etc)</title><content type='html'>&lt;p&gt;I continue to be (generally) impressed by &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. After a couple of days worth of work, digging around the guts of Zope transactions and thread management along with SQLAlchemy&amp;#8217;s guts of similar nature, I think I have a system in place that will work fine with Zope 3. Zope 3 uses a &lt;em&gt;two phase commit&lt;/em&gt; transaction management system, whereas SQLAlchemy generally supports the basic &amp;#8216;begin / commit / abort&amp;#8217; cycle. However, by taking advantage of SQLAlchemy&amp;#8217;s nesting of transactions, I essentially have the following model in place:&lt;/p&gt;


 &lt;ul&gt;
 &lt;li&gt;Zope transaction begin&amp;#8212;SQLAlchemy &lt;strong&gt;engine begin&lt;/strong&gt; (starts a fresh outer scope and calls &amp;#8216;begin&amp;#8217; on the database connection itself)&lt;/li&gt;
  &lt;li&gt;On Zope commit start (first phase of commit)&amp;#8212;SQLAlchemy &lt;strong&gt;objectstore commit&lt;/strong&gt; (sends changes managed in SQLAlchemy&amp;#8217;s unit of work / object graph over the wire)
 &lt;ul&gt;
 &lt;li&gt;This is of interest because &lt;strong&gt;objectstore commit&lt;/strong&gt; also calls &lt;code&gt;engine.begin()&lt;/code&gt; and &lt;code&gt;engine.commit()&lt;/code&gt;. SQLAlchemy is designed for &amp;#8216;reentrance&amp;#8217;, so that multiple calls to something like &lt;code&gt;engine.begin()&lt;/code&gt; are OK &amp;#8211; as long as they&amp;#8217;re matched by an equal number of finishing calls like &lt;code&gt;engine.commit()&lt;/code&gt;. When the nesting count is back to zero, &lt;code&gt;engine.commit()&lt;/code&gt; saves.&lt;/li&gt;
  &lt;li&gt;In two phase commits, it&amp;#8217;s allowable for an error to happen here. It&amp;#8217;s probably not preferred, but it&amp;#8217;s OK.&lt;/li&gt;
 &lt;/ul&gt;
 &lt;/li&gt;
  &lt;li&gt;On Zope commit finish (final phase of commit)&amp;#8212;SQLAlchemy &lt;strong&gt;engine commit&lt;/strong&gt;. This &amp;#8216;commit&amp;#8217; matches to the &amp;#8216;begin&amp;#8217; at the start of the Zope transaction, and sends the &amp;#8216;COMMIT&amp;#8217; statement to the target database.&lt;/li&gt;
 &lt;/ul&gt;


 &lt;p&gt;Beyond that, I&amp;#8217;m not doing too much work to track changes in either environment (SQLALchemy, &lt;span class="caps"&gt;ZODB&lt;/span&gt;) in this current setup. &lt;span class="caps"&gt;ZODB&lt;/span&gt;&amp;#8217;s persistence manages the loading and unloading of its objects, and SQLAlchemy manages its own too. It&amp;#8217;s not that I&amp;#8217;m trying to mix them &amp;#8211; it&amp;#8217;s just that Zope really really really wants to run with the &lt;span class="caps"&gt;ZODB&lt;/span&gt;, so even if it&amp;#8217;s not used, it&amp;#8217;s probably going to be there.&lt;/p&gt;


 &lt;p&gt;If this system ends up actually doing its job, I&amp;#8217;ll share the code. I&amp;#8217;m trying to write it separate from the application I&amp;#8217;m developing.&lt;/p&gt;


 &lt;p&gt;Also: for kicks, I&amp;#8217;ve toyed with how I might get &lt;a href="http://wiki.rubyonrails.com/rails/pages/ActiveRecord"&gt;ActiveRecord&lt;/a&gt; style sytax (which I like) using Python and SQLAlchemy. This mostly works as it stands right now:&lt;/p&gt;


&lt;pre&gt;
    from ruts.storage.base import Base
    from ruts.storage import act
    import db.tables

    class Venue(Base):
        act.fromTable(db.tables.venues)

        act.hasMany('Event', 'events', order_by='start_date')

    class Presenter(Base):
        act.fromTable(db.tables.presenters)

        act.hasMany('Event', 'events', order_by='start_date')

    class Event(Base):
        act.fromTable(db.tables.events)

        act.hasOne(Presenter)
        act.hasOne(Venue)
&lt;/pre&gt;

&lt;pre&gt;
    &amp;gt;&amp;gt;&amp;gt; v = Venue.get(1)
    &amp;gt;&amp;gt;&amp;gt; v.events
    [&amp;lt;exmple.model.Event object at 0x104a930&amp;gt;]
    &amp;gt;&amp;gt;&amp;gt; v.events[0].venue.title
    'Testy McVenueVille'
    &amp;gt;&amp;gt;&amp;gt; v.events.append(Event(title="Jackson"))    
    &amp;gt;&amp;gt;&amp;gt; v.commit()
    &amp;gt;&amp;gt;&amp;gt; v.events
    [&amp;lt;example.model.Event object at 0x104a930&amp;gt;, &amp;lt;example.model.Event object at 0x2b2c090&amp;gt;]
    &amp;gt;&amp;gt;&amp;gt; e2 = Event.get(2)
    &amp;gt;&amp;gt;&amp;gt; e = Event.get(1)
    &amp;gt;&amp;gt;&amp;gt; from datetime import timedelta
    &amp;gt;&amp;gt;&amp;gt; e2.start_date = e.start_date + timedelta(1)
    &amp;gt;&amp;gt;&amp;gt; e2.end_date = e.end_date + timedelta(1)
    &amp;gt;&amp;gt;&amp;gt; e.end_date
    datetime.datetime(2006, 4, 8, 23, 0)
    &amp;gt;&amp;gt;&amp;gt; e2.end_date
    datetime.datetime(2006, 4, 9, 23, 0)
    &amp;gt;&amp;gt;&amp;gt; v.events[1].end_date
    datetime.datetime(2006, 4, 9, 23, 0)
    &amp;gt;&amp;gt;&amp;gt; v.events[1].title
    'Jackson'
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114445963618994482?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114445963618994482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114445963618994482'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/04/because-i-could-sqlalchemy-zope-3.html' title='Because I Could (SQLAlchemy, Zope 3, Metaclass Fun, Etc)'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114428161729324892</id><published>2006-04-05T17:27:00.000-06:00</published><updated>2006-04-05T18:00:17.306-06:00</updated><title type='text'>SQLAlchemy</title><content type='html'>&lt;p&gt;Among the short list of good (or at least, personally interesting) Python projects under development today stands &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. It&amp;#8217;s a powerful toolkit for working with relational databases in Python, including doing object-relational mapping. It offers a lot more power and flexibility than &lt;a href="http://www.sqlobject.org/"&gt;SQLObject&lt;/a&gt; (Python) and &lt;a href="http://wiki.rubyonrails.com/rails/pages/ActiveRecord"&gt;ActiveRecord&lt;/a&gt; (Ruby), while still staying pretty close to those in relative ease of use (ie &amp;#8211; no &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt; style &lt;span class="caps"&gt;XML&lt;/span&gt; mappings).&lt;/p&gt;


 &lt;p&gt;Especially interesting is that SQLAlchemy is a &lt;span class="caps"&gt;SQL&lt;/span&gt; toolkit first, and O-R mapper second. It has a lot of support for query construction, compilation, native feature support, feature-agnostic support, pre-processing, post-processing, and more, that can also be used in the mapping layer. Already it seems like it&amp;#8217;d be free of the kind of issues that I ran into when &lt;a href="http://griddlenoise.blogspot.com/2006/03/yay-object-database.html"&gt;I tried to deal with a moderately complicated Inheritance / contained object scheme&lt;/a&gt; with Rails and ActiveRecord.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114428161729324892?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114428161729324892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114428161729324892'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/04/sqlalchemy.html' title='SQLAlchemy'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114370677971395772</id><published>2006-03-29T21:38:00.000-07:00</published><updated>2006-03-30T09:10:09.756-07:00</updated><title type='text'>Yay Object Database</title><content type='html'>&lt;p&gt;I&amp;#8217;ll admit &amp;#8211; I&amp;#8217;m &lt;em&gt;very&lt;/em&gt; tempted by &lt;a href="http://www.rubyonrails.com/"&gt;Ruby on Rails&lt;/a&gt;. I like its &amp;#8220;Ruby Everywhere&amp;#8221; philosophy. I like its &amp;#8220;beauty leads to happiness&amp;#8221; philosophy. I like its &amp;#8220;damn straight it&amp;#8217;s opinionated&amp;#8221; attitude. I like how easily it gives you an application starting point out of the box (oh, you don&amp;#8217;t know how I&amp;#8217;ve been struggling with this this week). At least, I like all of this in theory. I haven&amp;#8217;t tried making any real application in it yet. I did a quick version of the Knowledge Base application, just to see some results and see how using Tags felt compared to what I&amp;#8217;ve done in Zope 3, but it's nothing close to complete (or even to matching the Zope 3 implementation).&lt;/p&gt;

 &lt;p&gt;I&amp;#8217;ve been working on another customer&amp;#8217;s application in recent days and have been thinking &amp;#8220;this would be a fun test to develop and compare!&amp;#8221; The thought became more prominent as I&amp;#8217;ve been working on a batch of customer requests &amp;#8211; seemingly simple little things that are turning out to be much harder (in most cases) than I had estimated. If not harder, then just long. Now, some of this struggle is in Javascript and all of the joys of form/widget/etc design. Some of it is just data migration &amp;#8211; extracting objects, etc. Replacing a single text attribute with a single sub-object with multiple fields. Combining a couple of field pairs on an object into two instances of a sub-object. And so on. That&amp;#8217;s where some of the arduous part has come in &amp;#8211; all of the &lt;span class="caps"&gt;ZCML&lt;/span&gt; and Schema required just to get a couple of simple classes registered and secured. And I had to roll a new ObjectWidget base class (I didn&amp;#8217;t like the one that&amp;#8217;s in Zope 3 at this time). With all of that out of the way, however, now I&amp;#8217;m moving on&amp;#8230; Mostly.&lt;/p&gt;

 &lt;p&gt;Anyways, I&amp;#8217;ve started exploring how this application might work in Rails. And it didn&amp;#8217;t take me long to find fresh love for the &lt;acronym title="Zope Object Database"&gt;ZODB&lt;/acronym&gt;.&lt;/p&gt;

 &lt;p&gt;The &lt;a href="http://www.zope.org/Wikis/ZODB/guide/index.html"&gt;ZODB&lt;/a&gt; is a full Python persistence system. It&amp;#8217;s &lt;strong&gt;native&lt;/strong&gt;. A tuple is a tuple, string is a string, a CrewContact object is a CrewContact object, and so on. When developing in Zope 3 in the (general) fashion that I&amp;#8217;ve been developing &amp;#8211; straight Persistent model objects, all of the views, adapters, etc, coming in off disk (looked up and bound by the component architecture, not by Zope 2 techniques like acquisition) &amp;#8211; using the &lt;span class="caps"&gt;ZODB&lt;/span&gt; for a new application is straightforward and quite easy.&lt;/p&gt;

 &lt;p&gt;I think an object-relational mapper is good when developing against an established database. And usually there needs to be some strong mapping for that to work and match database policies against expected object behavior. Rails&amp;#8217; &lt;a href="http://wiki.rubyonrails.com/rails/pages/ActiveRecord"&gt;ActiveRecord&lt;/a&gt; is a really nice system in many respects, and it provides a lot of nice features for fairly natural expressions for establishing relationships, doing validation, etc. But it also seems to expect a fairly rigid structure in place to work. Not that this is necessarily bad. But it begs the question: if you&amp;#8217;re going through such terrific overhead and making certain restrictions (Single Table Inheritance, which I&amp;#8217;ll get to in a minute), why use an &lt;span class="caps"&gt;RDBMS&lt;/span&gt; at all?&lt;/p&gt;

 &lt;p&gt;Well, I know some of the answer to this, and I agree with it in part: the &lt;span class="caps"&gt;DBMS&lt;/span&gt; vendors (including open source ones) are better at the data storage, retrieval, distribution, and connectivity side of things. &amp;#8220;Let the database management system handle that,&amp;#8221; some say. &amp;#8220;Let &lt;span class="caps"&gt;SQL&lt;/span&gt;Object and ActiveRecord make it feel like natural objects with a minimum of fuss.&amp;#8221; OK. That&amp;#8217;s admirable.&lt;/p&gt;

 &lt;p&gt;But I realized today that it&amp;#8217;s been a long time since I&amp;#8217;ve had to think relationally just to store my objects &amp;#8211; objects that have meaningful relations. Specifically, I ran into this problem.&lt;/p&gt;


 &lt;ul&gt;
 &lt;li&gt;I have a class for &lt;strong&gt;Itinerary&lt;/strong&gt; objects. An Itinerary is a container, which can contain many &lt;strong&gt;Legs&lt;/strong&gt;. There are three types of legs, sharing a common base class/interface.
 &lt;ul&gt;
 &lt;li&gt;&lt;strong&gt;ScheduledMeeting&lt;/strong&gt; &amp;#8211; Just a meeting that&amp;#8217;s taking place in this itinerary.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GroundTransportation&lt;/strong&gt; &amp;#8211; A car service, etc. Who&amp;#8217;s providing it, any other notes (where to meet for pickup, etc).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flight&lt;/strong&gt; &amp;#8211; many fields (and in my latest implementation, sub-objects) with information concerning a flight, its crew, its passengers (crew and passengers linked lists to their respective targets), crew contact information, flight details, other notes.&lt;/li&gt;
 &lt;/ul&gt;&lt;/li&gt;
 &lt;/ul&gt;

 &lt;p&gt;I&amp;#8217;ve been wondering how to do this in Rails. In Zope 3, I have a base interface, &lt;strong&gt;IItineraryLeg&lt;/strong&gt; and specify that an IItinerary implementation contains them:&lt;/p&gt;


&lt;pre&gt;
  class IItinerary(IItinerarySchema, IContainer):
      """ 
      Base itinerary information.  ItineraryLegs are associated
      with Itineraries to give trip details.
      """ 
      contains(IItineraryLeg)
&lt;/pre&gt;
 &lt;p&gt;And in the implementation:&lt;/p&gt;


&lt;pre&gt;
    class Itinerary(BTreeContainer):
        implements(IItinerary, IItineraryContained)

        title = DublinCoreProperty('title')

        start_date = None
        end_date = None
        # Use ``Business`` as default, as is also specified in the interface
        trip_type = u"Business" 
        notes = u"" 

        @property
        def legs(self):
            return sorted(self.values(), key=startDate)

    class ItineraryLeg(Persistent, Contained):
        implements(IItineraryLeg, IItineraryLegContained)

        start_date = None
        end_date = None
        notes = u"" 

    class ScheduledMeetingLeg(ItineraryLeg):
        """ 
        'Scheduled Meetings' add nothing to the IItinerayLeg schema, really
        """ 
        implements(IScheduledMeetingLeg)

    class GroundItineraryLeg(ItineraryLeg):
        implements(IGroundItineraryLeg)

        transport_type = u"" 
        service_name = u"" 
&lt;/pre&gt;
 &lt;p&gt;See, these two legs are very simple. In ActiveRecord or any object-relational mapper using &lt;em&gt;Single Table Inheritance&lt;/em&gt;, this would have been easy. But it&amp;#8217;s that Flight leg that gets messy. Very messy. By my understanding of &lt;a href="http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html"&gt;Single Table Inheritance&lt;/a&gt;, the flight leg, ground leg, and scheduled meeting legs data would &lt;em&gt;all&lt;/em&gt; be mashed up in one table. If I were designing tables in an &lt;span class="caps"&gt;RDBMS&lt;/span&gt;, I would never design that way &amp;#8211; and I&amp;#8217;m no genius Relational designer.&lt;/p&gt;

 &lt;p&gt;The point is, there are obviously situations where my expectations of objects &lt;span class="caps"&gt;AND&lt;/span&gt; relational storage, as mapped by &lt;em&gt;ActiveRecord&lt;/em&gt;, don&amp;#8217;t quite mesh up. I&amp;#8217;m not belittling the system &amp;#8211; I just realized that (a) I have no idea how I&amp;#8217;d want to make these tables (especially since I have some equivalent of &lt;code&gt;has_one&lt;/code&gt; to tiny little objects, a transition made this week. Not just to tiny little objects, but a couple of them. Has two?), and (b) after I got them built, I have no idea how to map them into ActiveRecord. I may, however, be distracted things that I may or may not need, like new features &lt;a href="http://wiki.rubyonrails.com/rails/pages/PolymorphicAssociations"&gt;Polymorphic Associations&lt;/a&gt; and &lt;a href="http://wiki.rubyonrails.com/rails/pages/ThroughAssociations"&gt;Through Associations&lt;/a&gt;.&lt;/p&gt;

 &lt;p&gt;I guess, after thinking about it, I would write the three legs as separate tables/objects and write one legs action to combine them (in Rails)?&lt;/p&gt;


&lt;pre&gt;
  def legs
    (ground_itinerary_legs + scheduled_meetings).sort do |a,b| 
      a.start_date &amp;lt;=&amp;gt; b.start_date
    end
  end
&lt;/pre&gt;
 &lt;p&gt;Well, it let me do something like that in the console, but not in my active record class.&lt;/p&gt;

 &lt;p&gt;Anyways, the point is that for many (not all, but many) tasks where a new &amp;#8220;web application&amp;#8221; is being created, a system like the &lt;strong&gt;ZODB&lt;/strong&gt; is great. No translation. No having to bend your brain around &lt;span class="caps"&gt;RDBMS&lt;/span&gt; table creation and styles, and then back to objects, and to what can be done in between. Python data, through and through. The object database doesn&amp;#8217;t work for every situation. But damn, it can be nice.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114370677971395772?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114370677971395772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114370677971395772'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/yay-object-database.html' title='Yay Object Database'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114349652617574459</id><published>2006-03-27T14:55:00.000-07:00</published><updated>2006-03-27T14:55:26.183-07:00</updated><title type='text'>Too Much Effort?</title><content type='html'>&lt;p&gt;I&amp;#8217;ve spent way way way way way too much of the day trying to code in a couple of &lt;em&gt;simple&lt;/em&gt; objects into a Zope 3 application. They&amp;#8217;re ridiculously simple, for the most part, with a couple of specialized business requirements beyond them.&lt;/p&gt;


	&lt;p&gt;Some of the slowdown has come from me back-pedaling on a couple of design decisions earlier in the day. But as I slough through just the basic &lt;a href="http://griddlenoise.blogspot.com/2006/03/zcml-needs-to-do-less.html"&gt;&lt;span class="caps"&gt;ZCML&lt;/span&gt;&lt;/a&gt; to get these stupid little persistent objects registered into Zope (after the amount of work it took just to get here), I feel another headache coming on. And I&amp;#8217;m not even to the actual hard part of the work yet. And this task is still a small part of all that I had hoped to get done today. It&amp;#8217;s something that really should have been done a couple of hours ago, and I bet I have an hours worth of work ahead of me on this one stupid task alone.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114349652617574459?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114349652617574459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114349652617574459'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/too-much-effort.html' title='Too Much Effort?'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114256281655814102</id><published>2006-03-16T19:26:00.000-07:00</published><updated>2006-03-27T15:54:54.753-07:00</updated><title type='text'>No! Fun! Til Brooklyn!</title><content type='html'>&lt;p&gt;
Mar 17, I'll be playing at &lt;a href="http://www.nofunfest.com/2006.html"&gt;No Fun Fest 2006&lt;/a&gt;, in the basement for &lt;a href="http://www.hospitalproductions.com/"&gt;Hospital Productions night&lt;/a&gt;. No Fun Fest runs Mar 17-19 at &lt;a href="http://www.thehookmusic.com/main.html"&gt;The Hook&lt;/a&gt; (18 Commerce Street) in Brooklyn.
&lt;/p&gt;
&lt;p&gt;
Smegma, Ikue Mori, Zbigniew Karkowski, Sickness, and me, the always yodeling &lt;a href="http://euc.cx/aodl/"&gt;aodl&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Show starts around 7:30 each night, and I'm one of the first to go on. Come on down and watch me rock the trumpet tuning mic like you know I do it right.
&lt;/p&gt;
&lt;p&gt;
... &lt;em&gt;&lt;strong&gt;Update, 27 Mar 06:&lt;/strong&gt; I realize now that this didn't get published until way too late. Blogspot was having connection issues when I rapidly tried to post this before I left town, and I forgot about it until today's update. oops.&lt;/em&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114256281655814102?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114256281655814102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114256281655814102'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/no-fun-til-brooklyn.html' title='No! Fun! Til Brooklyn!'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114226730332303338</id><published>2006-03-13T09:20:00.000-07:00</published><updated>2006-03-13T09:28:23.356-07:00</updated><title type='text'>ZCML Needs To Do Less</title><content type='html'>&lt;p&gt;
A few months ago I defended ZCML pretty staunchly. These days, it's becoming feature #1 that makes me NOT want to use Zope.
&lt;/p&gt;
&lt;p&gt;
For the uninitiated, ZCML is an XML configuration language to load up Zope components. I think that having registration separate from implementation, even in another 'language', is a good thing. But ZCML has also taken on heaps of automation capabilities. And those suck. Instead of respecting the Python programmer, it holds your hand and provides a lot of automatic features. Sometimes that's nice. A lot of times, that's wrong. You can't subclass, you can't override, you can't provide slightly different behavior. And don't even think that you can read the code behind the ZCML directives. Most of the code is full of internal handshakes in the configuration loading system. And if all you're trying to do is figure out whether you can provide javascript to a ZCML 'menuItem' directive: good luck trying to figure that one out.
&lt;/p&gt;
&lt;p&gt;
So I stand firmly behind this: &lt;a href="http://www.z3lab.org/sections/blogs/philipp-weitershausen/2005_12_14_zcml-needs-to-do-less"&gt;ZCML Needs To Do Less&lt;/a&gt; (although I don't agree with all of the examples shown).
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114226730332303338?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114226730332303338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114226730332303338'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/zcml-needs-to-do-less.html' title='ZCML Needs To Do Less'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114198194082423100</id><published>2006-03-09T23:33:00.000-07:00</published><updated>2006-03-10T02:18:11.626-07:00</updated><title type='text'>Seaside, Rails, Helpers, Formlib, helping web applications through smart components, tools, and linking</title><content type='html'>&lt;p&gt;A web application framework that truely fascinates me is &lt;a href="http://seaside.st/"&gt;Seaside&lt;/a&gt;. Seaside, written in Smalltalk, has great vision and ideals for web &lt;strong&gt;applications&lt;/strong&gt; by using continuations to suspend and resume code. It breaks free of the typical request/response cycle, and manages state to a fault.&lt;/p&gt;

 &lt;p&gt;This code, from an example store application for Seaside, is the &lt;strong&gt;go&lt;/strong&gt; method of the &lt;strong&gt;WAStoreTask&lt;/strong&gt; object. This method runs the store. Stay with me now, this is important. &lt;strong&gt;This runs the store&lt;/strong&gt;. This is the flow. It&amp;#8217;s native Smalltalk. It&amp;#8217;s not &lt;span class="caps"&gt;XML&lt;/span&gt;, YAML, An Array or list. It doesn&amp;#8217;t get translated into any structure like that. Upon first visit to the application, this code starts executing.&lt;/p&gt;


&lt;pre&gt;
go
    | shipping billing creditCard |
    cart := WAStoreCart new.
    self isolate: [
      [self fillCart. self confirmContentsOfCart] whileFalse
    ].

    self isolate: [
        shipping := self getShippingAddress.
        billing := (self useAsBillingAddress: shipping)
                    ifFalse: [self getBillingAddress]
                    ifTrue: [shipping].
        creditCard := self getPaymentInfo.
        self shipTo: shipping billTo: billing payWith: creditCard
    ].

    self displayConfirmation.
&lt;/pre&gt;
 &lt;p&gt;The &lt;strong&gt;isolate&lt;/strong&gt; method calls wrap a block in a WATransaction, making that transaction run over multiple requests. I&amp;#8217;m not sure if this WATransaction maps to how I&amp;#8217;m used to them as a Zope developer, but I do gather that it cleans extraneous objects up that were racked up in that &amp;#8216;isolate&amp;#8217; call.&lt;/p&gt;

 &lt;p&gt;The use of continuations and a sort of invisible &amp;#8216;session&amp;#8217; management that runs behind it makes for very brief code. Looking at my own Zope 2 e-commerce application, I see many lines spent having to look things back up: getting data out of the Session, getting data out of the Request, getting data out of the Database(s), and so on and so on and so on. With each request/response cycle, especially late into the Checkout process (which depends on all of the accumulated data of the shopping experience), the list of dependencies gets bigger. Guards have to be in place to ensure that the session and account are still active late in the checkout process, and that going to one of the checkout pages with an empty cart is disallowed&amp;#8230; So it&amp;#8217;s interesting to look above and see just a small handful of expressions boil down the whole experience.&lt;/p&gt;

 &lt;p&gt;An aspect of Seaside that is especially interesting is action calling, via hyperlinks or form submission. I also like how it does &lt;span class="caps"&gt;HTML&lt;/span&gt; generation, preferring to use objects/methods instead of templates. This is from a &lt;strong&gt;WAStoreItemView&lt;/strong&gt;. &lt;strong&gt;renderContentOn: html&lt;/strong&gt; is a common method that all the views implement. Unlike the so-called &amp;#8216;MVC&amp;#8217; that is being popularized in Ruby on Rails, Turbogears, etc, this is actually closer to Zope 3&amp;#8217;s views wherein it&amp;#8217;s an object that wraps (decorates) another object.&lt;/p&gt;


&lt;pre&gt;
renderContentOn: html
    html heading: item title.
    html heading: item subtitle level: 3.
    html paragraph: item description.
    html italic: item price printStringAsCents.
    html form: [
        html submitButtonWithAction: [self addToCart] text: 'Add To Cart'.
        html space.
        html submitButtonWithAction: [self answer] text: 'Done'.
    ]
&lt;/pre&gt;
 &lt;p&gt;Still straightforward and readable. Especially interesting are the &lt;strong&gt;submitButtonWithAction&lt;/strong&gt; calls. The first argument is a block that gets executed when that button is clicked. addToCart is straightforward enough:&lt;/p&gt;


&lt;pre&gt;
addToCart
    cart add: item
&lt;/pre&gt;
 &lt;p&gt;The page gets rendered as normal, staying on the &lt;strong&gt;WAStoreItemView&lt;/strong&gt;, but each time you click &amp;#8216;addToCart&amp;#8217; you&amp;#8217;ll watch the cart display component fill up and fill up. &lt;code&gt;[html anchorWithAction: [cart remove: anItem] text: '-']&lt;/code&gt; is in that cart display to, of course, remove the item.&lt;/p&gt;

 &lt;p&gt;Back to the &lt;strong&gt;WAStoreItemView renderContentOn&lt;/strong&gt; buttons, the other interesting one is the button for &lt;em&gt;Done&lt;/em&gt;. It calls &lt;code&gt;self answer&lt;/code&gt;. What&amp;#8217;s it answering? A call! Specifically, this call from &lt;strong&gt;WAStoreFillCart&lt;/strong&gt;. WAStoreFillCart is the component that&amp;#8217;s responsible for browsing, searching, and displaying items. Any link to &lt;code&gt;displayItem: anItem&lt;/code&gt; calls this:&lt;/p&gt;


&lt;pre&gt;
displayItem: anItem
    main call: (WAStoreItemView new item: anItem; cart: cart)
&lt;/pre&gt;
 &lt;p&gt;What calls this display item, and why does it matter? Think of most web applications &amp;#8211; there are more than a few ways to get at the data inside the application. There&amp;#8217;s searching, there&amp;#8217;s browsing by &amp;#8216;tag&amp;#8217;, there are dashboards (big overview pages), there are personal pages, there are direct listings. When you go from one of those listings to something more detailed, how do you go back?&lt;/p&gt;

 &lt;p&gt;In &lt;strong&gt;Seaside&lt;/strong&gt;, &lt;a href="http://seaside.st/Documentation/CallandAnswer/"&gt;call and answer&lt;/a&gt; provide that functionality, among other things. Clicking the &amp;#8216;Done&amp;#8217; button that calls &amp;#8216;self answer&amp;#8217; returns control back up to whatever called it. So if you found the store item on page 3 out of 5 in a batched list, you&amp;#8217;re sent back to page 3 out of 5. If you got there through a list of links from a search result, you&amp;#8217;re taken back to those search results. It feels natural. The developer doesn&amp;#8217;t have to maintain information about the calling page to return back to it.&lt;/p&gt;

 &lt;p&gt;Again, looking at my own big and old Zope 2 based e-commerce application, I have a few &amp;#8216;handlers&amp;#8217; which are thin scripts over the business logic implemented in core components. Many handlers have paths passed in about which page to report errors to, and which page to go to on success. This allows them to be used from multiple pages, within the structure of the good old scripts&amp;#8217;n&amp;#8217;templates system (but the scripts are really thin layers to underlying code that does validation, processing, business logic, etc). Man, wouldn&amp;#8217;t it be nice to have that be more automatic instead of some hidden fields like &amp;#8216;errorto&amp;#8217;, &amp;#8216;returnto&amp;#8217; with paths?&lt;/p&gt;

 &lt;p&gt;All in all, what I&amp;#8217;ve really liked about playing around briefly with Seaside is the feeling of liberation from not only the request/response cycle, but also from the Template model. I&amp;#8217;m suddenly very tired of templates as string insertion languages being the &amp;#8216;view&amp;#8217; (coff!). I don&amp;#8217;t mind using them for the broadest of layouts. But whether it&amp;#8217;s template attribute style languages or string insertion, I&amp;#8217;m just suddenly tired of seeing and maintaining things like this:&lt;/p&gt;


&lt;pre&gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li tal:repeat="item view/listItems"&amp;gt;
      &amp;lt;a tal:attributes="href string:${context/absolute_url}/${item/name}" 
        tal:content="item/description"&amp;gt;Description&amp;lt;/a&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;

  &amp;lt;ul&amp;gt;
    &amp;lt;% for item in view.listItems %&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;a href="./&amp;lt;%= item.name %&amp;gt;"&amp;gt;&amp;lt;%= item.description %&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/ul&amp;gt;
&lt;/pre&gt;
 &lt;p&gt;My problem with them is not so much the language itself, but the casual callous way important bits like URLs and more are constructed. I&amp;#8217;ve generally been a big fan of Zope&amp;#8217;s &lt;span class="caps"&gt;TAL &lt;/span&gt;(Template Attribute Language, used in the first example), but sometimes it&amp;#8217;s too hard to do simple things. Even more frustrating, lately, has been the lack of good helper functions for use in Python expressions in those templates. Zope 2 has &amp;#8220;ZTUtils&amp;#8221; which has a small set of useful utility and objects. But if those are in Zope 3, I haven&amp;#8217;t found them.&lt;/p&gt;

 &lt;p&gt;I&amp;#8217;ve generally been against the &lt;span class="caps"&gt;PHP&lt;/span&gt; style of &amp;#8216;templates&amp;#8217; where it all becomes super muddy (how many &lt;span class="caps"&gt;PHP &lt;/span&gt;&amp;#8216;apps&amp;#8217; do you see with print/echo statements in the code that then have &lt;span class="caps"&gt;HTML&lt;/span&gt; inside of a string?). Most of the Python &lt;span class="caps"&gt;PHP&lt;/span&gt;/ASP/JSP style systems I&amp;#8217;ve seen have been especially bad, primarily because of Python&amp;#8217;s block structure and lack of &amp;#8216;end&amp;#8217; statements or closing braces inside the language, so doing the &amp;#8216;for&amp;#8217; loop like above has varied between different implementations. It&amp;#8217;s just not what Python is built for, at all.&lt;/p&gt;

 &lt;p&gt;My experiences with &lt;strong&gt;Ruby on Rails&lt;/strong&gt; has been better. Ruby has the &amp;#8216;end&amp;#8217; statement. And it really is a nice concise language that doesn&amp;#8217;t look all that bad in Erb templates. But what makes &lt;strong&gt;Ruby on Rails&lt;/strong&gt; especially nice is the large collection of &lt;strong&gt;helpers&lt;/strong&gt;. The helpers are a big collection of functions and objects (much bigger than ZTUtils) that makes it pretty nice to work in the template. So instead of the tag-within-a-tag style shown above to generate the &amp;#8216;href&amp;#8217; part of the link, the common idiom in rails is to use this:&lt;/p&gt;


&lt;pre&gt;
  &amp;lt;%= link_to article.title, :action =&amp;gt; 'show', :id =&amp;gt; article %&amp;gt;
  &amp;lt;%= link_to 'Destroy', { :action =&amp;gt; 'destroy', :id =&amp;gt; article }, :confirm =&amp;gt; 'Are you sure?' %&amp;gt;  
&lt;/pre&gt;
 &lt;p&gt;This brings it closer to one of the things I like about the Seaside experience: you&amp;#8217;re not writing into a string to make a link, you&amp;#8217;re linking to objects and methods directly. Not only that, you&amp;#8217;re using other options (like shown in the second example above) to do things like common Javascript events, or to do tricks to make a regular hyperlink perform an &lt;span class="caps"&gt;HTTP POST&lt;/span&gt; request. Ultimately, they make the development experience feel more like actual application programming. For the record, there&amp;#8217;s a fairly &lt;a href="http://pylonshq.com/RailsHelpers/"&gt;direct Python implementation of many of Rails helpers&lt;/a&gt; available too.&lt;/p&gt;

 &lt;p&gt;Some of the things I&amp;#8217;ve done for my Zope 3 development lately has been to take ideas from these systems. I&amp;#8217;ve started building my own helpers system, implemented as a Zope adapter for the Request. Since the Request has &amp;#8216;skin&amp;#8217; information in it, it&amp;#8217;s possible to extend the helper with specialized functions for a particular skin, knowing that it might have certain javascript libraries or &lt;span class="caps"&gt;DOM&lt;/span&gt; identifiers / &lt;span class="caps"&gt;CSS&lt;/span&gt; stylings available. I also have a simple &lt;span class="caps"&gt;HTML&lt;/span&gt; builder system, inspired by &lt;a href="http://www.kieranholland.com/code/documentation/nevow-stan/"&gt;Nevow&amp;#8217;s Stan&lt;/a&gt;, but without the more advanced features like mutation, macros, or.. well, pretty much anything advanced. Applying a python getitem trick and making an object that generates any kind of Tag object by name, I can spit out pretty much anything.&lt;/p&gt;

 &lt;p&gt;With Zope 3.2 and the introduction of &lt;em&gt;viewlets&lt;/em&gt; and &lt;em&gt;content providers&lt;/em&gt;, I&amp;#8217;ve been focusing on building smaller and smaller view components. I&amp;#8217;ve stopped thinking of pages in the standard macro + content or header + content + footer sense and have gotten back into thinking of a page as a collection of connected yet independent view objects.&lt;/p&gt;


&lt;pre&gt;
  html = api.htmlHelperFor(self)
  ul = T.ul(class_='menu')
  for item in self.listItems():
      ul &amp;lt;&amp;lt; T.li[ html.linkTextTo(item.name, item) ]
  return unicode(ul)

  # Or, for more fun
  html = api.htmlHelperFor(self)
  return unicode(T.ul(class_='menu')[(
      T.li[html.linkTextTo(item.name, html.viewURL(item, 'delete'), confirm='Are you sure?', post=True)]
      for item in self.listItems()
  )])
&lt;/pre&gt;
 &lt;p&gt;Added to that, &lt;strong&gt;zope.formlib&lt;/strong&gt; delivers form components with &amp;#8216;Actions&amp;#8217; bound intelligently to methods. &lt;strong&gt;zope.formlib&lt;/strong&gt; handles dispatching to the proper action instead of just having Zope&amp;#8217;s publisher go to a method / view directly to handle forms:&lt;/p&gt;


&lt;pre&gt;
    @form.action(u"Import Articles", condition=form.haveInputFields,
                 failure='handleFailure')
    def importArticles(self, action, data):
        # This gets called when the 'import articles' button is clicked, and
        # only if validation succeeds. The button only gets rendered if there
        # are input fields - a form can be generated to display data on a field
        # by field basis according to security, which can set up 'view' 
        # situations for unprivileged users - and you wouldn't want to have
        # an input button when there are no input fields, right?
        # 'data' has all of the validated form input, and can be easily
        # applied like this:
        form.applyChanges(self.context, self.form_fields, data)

    def handleFailure(self, action, data, errors):
        # Optionally, individual actions can have other methods associated
        # with them to handle action-specific features for validation,
        # validation failure, and so on.
&lt;/pre&gt;
 &lt;p&gt;Being actual objects, they can be referred to in the view or view&amp;#8217;s template and filtered out if unavailable:&lt;/p&gt;


&lt;pre&gt;
  controls = T.div(class_="controls")
  for action in self.actions:
      if not action.available():
          continue
      controls &amp;lt;&amp;lt; action.render()
      controls &amp;lt;&amp;lt; '&amp;amp;nbsp;&amp;amp;nbsp;'
&lt;/pre&gt;
 &lt;p&gt;I like having tools like this available. It really makes the application feel a lot stronger. &amp;#8216;formlib&amp;#8217; is pretty simple, conceptually, while providing a lot of flexibility and features and strength on the &amp;#8216;web application as actual application&amp;#8217; front. That&amp;#8217;s the nice thing with Seaside and Rails&amp;#8217; controller/view layer and its helpers too: a lot of tools, some simple concepts, a lot of power.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114198194082423100?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114198194082423100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114198194082423100'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/seaside-rails-helpers-formlib-helping.html' title='Seaside, Rails, Helpers, Formlib, helping web applications through smart components, tools, and linking'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114186987271368062</id><published>2006-03-08T19:02:00.000-07:00</published><updated>2006-03-08T19:04:32.730-07:00</updated><title type='text'>Head Go Boom</title><content type='html'>&lt;p&gt;This was the opening line in one of those oil scam spams: &lt;strong&gt;Let me crave your indulgence to introduce myself to you&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;My brain is now stuck in a locked groove.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114186987271368062?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114186987271368062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114186987271368062'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/head-go-boom.html' title='Head Go Boom'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114185021322858407</id><published>2006-03-08T13:28:00.000-07:00</published><updated>2006-03-08T13:37:00.416-07:00</updated><title type='text'>Is this thing back on?</title><content type='html'>&lt;p&gt;
Somehow, &lt;strong&gt;Griddle Noise&lt;/strong&gt; got selected as a spam blog or offensive blog or something along those lines. I'm trying to decide whether I should don the dynamite hat of paranoia or not. It could be fun: add to my crankiness a fear of everyone. "They know I'm right, dammit, and they're trying to shut me up?" "Who?" "THEM!" "Who?" "&lt;a href="http://www.anticon.com/themselves.html"&gt;Them!&lt;/a&gt;"
&lt;/p&gt;
&lt;p&gt;
If it wouldn't be so mind-crushingly depressing (and wasn't so out of budget), I think I could use a vacation. Remember that week I spent in a shot glass in the bay? Me neither.
&lt;/p&gt;
&lt;p&gt;
I actually do have a small chance coming up to get away, but it's not all stress free like I need. It's sortof work. I'll be performing at &lt;a href="http://www.nofunfest.com/2006.html"&gt;No Fun Fest 2006&lt;/a&gt;, March 17th, down in the basement, around 8-ish I think, somewhere in Brooklyn where the trains don't go.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;ls4+2&lt;/strong&gt;. Hearts and springs are stupid things.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13463691-114185021322858407?l=griddlenoise.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114185021322858407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13463691/posts/default/114185021322858407'/><link rel='alternate' type='text/html' href='http://griddlenoise.blogspot.com/2006/03/is-this-thing-back-on.html' title='Is this thing back on?'/><author><name>Jeff Shell</name><uri>http://www.blogger.com/profile/08875953026022510741</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://static.flickr.com/42/79376386_d90c7111a2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-13463691.post-114145673681617668</id><published>2006-03-03T20:07:00.000-07:00</published><updated>2006-03-04T00:22:37.376-07:00</updated><title type='text'>Crisis of Faith: The Messengers Have Been Shot</title><content type='html'>&lt;p&gt;By the way, the &lt;a href="http://griddlenoise.blogspot.com/2006/03/zope-crisis-of-faith-coming-this-march.html"&gt;crisis of faith&lt;/a&gt; mentioned in my last post may be minor. There is a lot about Zope 3 that I like. There&amp;#8217;s a lot about classic Zope that I&amp;#8217;ve liked. But I feel frustrated. That frustration is felt on more than one level too. I&amp;#8217;ll get to the positives soon enough.&lt;/p&gt;


 &lt;p&gt;Again, I&amp;#8217;ll mention that I&amp;#8217;m not necessarily a good person. I haven&amp;#8217;t contributed any actual code for more than a couple of years now. I don&amp;#8217;t even run checkouts from Subversion. I must deliver results to my customers on as much trusted, supported, and released software as possible. I try to keep up on the general discussions on the mailing lists, but can only keep up on a few usually.&lt;/p&gt;


 &lt;p&gt;But I do have a passion for this. I want beauty, I want happiness, I want Python, I want Zope. I want others to want this and have it. But if I&amp;#8217;m having frustrations, what are they going to feel?&lt;/p&gt;


 &lt;h2&gt;Gripe 1, Message message message. There is no message.&lt;/h2&gt;


 &lt;p&gt;Well, if there&amp;#8217;s a message, good luck finding it. Now, a lot of people say &amp;#8220;Python has a lot of web frameworks&amp;#8221;. Well, I wouldn&amp;#8217;t call every Python programmer&amp;#8217;s one-off a real &amp;#8220;framework&amp;#8221;. There are a lot of options. But there are only two others that have a lot of buzz and momentum behind them, are usable today as complete options, and look like they might actually make it to a 1.0 release and beyond. Let&amp;#8217;s look at what they offer (keeping in mind of course that it may change after the time of this writing):&lt;/p&gt;


 &lt;p&gt;&lt;a href="http://www.turbogears.org/"&gt;TurboGears&lt;/a&gt; has a nice site with a narrative text and clear links to what&amp;#8217;s important. You can quickly learn what Turbogears is about, and can quickly see tutorials that deliver something usable and understandable. I think what I like best about the current version of the TurboGears site is that the text is readable. It&amp;#8217;s prose, but full of links. It&amp;#8217;s not just bullet points (we&amp;#8217;ll get to this in a minute).&lt;/p&gt;


 &lt;p&gt;&lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; also has a great site. The main focus is on some great introductory text (again, with links) about where Django came from. Elsewhere on the page, in nicely and subtly separated section, are links and text (with links!) about the essentials of the framework, documentation, showcase sites, and weblog entries about the project itself. The weblog side is small (title, description only). It shows that there is movement and momentum in the project, but it doesn&amp;#8217;t overwhelm the page as the central piece of information. The newspaper mentality of the core Django developers shows through here. Like the front page of any good newspaper or news site (emphasis on the &amp;#8216;good&amp;#8217; part), there are headlines and columns and information that opens up into inner pages, and
