<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkMNQno5eCp7ImA9WhBbFkk.&quot;"><id>tag:blogger.com,1999:blog-8729083</id><updated>2013-05-15T16:08:13.420-04:00</updated><category term="ethics" /><category term="linux" /><category term="livepage" /><category term="mantissa" /><category term="twisted" /><category term="None" /><category term="releases" /><category term="security" /><category term="typing" /><category term="music" /><category term="wacom" /><category term="photos" /><category term="vertex" /><category term="axiom" /><category term="essay" /><category term="tls" /><category term="python" /><category term="divmod" /><category term="drm" /><category term="pyflakes" /><category term="r0ml" /><category term="unicode" /><category term="keyboards" /><category term="evil" /><category term="code" /><category term="flowers" /><category term="fiction" /><category term="lulz" /><title>Deciphering Glyph</title><subtitle type="html">A collection of articles, ideas, and rambling from a guy who wrote some software that one time.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://glyph.twistedmatrix.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>350</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/glyph" /><feedburner:info uri="glyph" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;C0INSH04eip7ImA9WhNVFks.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-1654357426583907472</id><published>2012-12-27T21:23:00.000-05:00</published><updated>2012-12-27T21:26:39.332-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-27T21:26:39.332-05:00</app:edited><title>The Twisted Way</title><content type="html">&lt;div class="separator" style="clear: both; text-align: left;"&gt;
One of the things that confuses me most about Twisted is the fact that so many people seem to be confused by things about Twisted.&lt;/div&gt;
&lt;br /&gt;
Much has been written, some of it by me, &lt;a href="http://twistedmatrix.com/documents/current/web/howto/web-in-60/index.html"&gt;some of it&lt;/a&gt; by &lt;a href="http://www.aosabook.org/en/twisted.html"&gt;other brilliant members&lt;/a&gt; of &lt;a href="http://krondo.com/?page_id=1327"&gt;the community&lt;/a&gt;, attempting to explain Twisted in lots of detail so that you can use it and understand it and control it to do your bidding. &amp;nbsp;But today, I'd like to try something different, and instead of trying to help you figure out how to &lt;i&gt;use&lt;/i&gt; Twisted, I will try to help you understand what Twisted &lt;i&gt;is&lt;/i&gt;. &amp;nbsp;To aid you in meditating upon its essence and to understand how it is a metaphor for software, and, if you are truly enlightened, for all life.&lt;br /&gt;
&lt;br /&gt;
Let us contemplate the Twisted Way.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://farm5.staticflickr.com/4066/4719290483_de089f9c2c.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://farm5.staticflickr.com/4066/4719290483_de089f9c2c.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Image Credit: &lt;a href="http://www.flickr.com/photos/31246066@N04/4719290483/"&gt;Ian Sane&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;In the beginning was the Tao.&lt;/i&gt;&lt;/div&gt;
&lt;div style="font-style: italic; text-align: center;"&gt;
&lt;i&gt;All things issue from it;&amp;nbsp;&lt;/i&gt;&lt;i&gt;all things return to it.&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
- &lt;a href="http://academic.brooklyn.cuny.edu/core9/phalsall/texts/taote-v3.html#52"&gt;Tao Te Ching&lt;/a&gt;&lt;/div&gt;
&lt;div style="font-style: italic; text-align: left;"&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
All information systems are metaphors for the world. &amp;nbsp;All programs are, at least in small part, systems. &amp;nbsp;Therefore, every program contains within it a world of thought. &amp;nbsp;Those thoughts must be developed before they can be shared; therefore, one must have an interesting program before one thinks to do any interesting I/O.&lt;/div&gt;
&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
It is less fashionable these days to speak of "object-oriented modeling" than it &lt;a href="http://www.oopsla.org/"&gt;once was&lt;/a&gt;, but mostly because object-oriented design is now so pervasive that &lt;a href="https://twitter.com/steveklabnik/status/267761760637943810"&gt;no-one&lt;/a&gt; needs convincing any more. &amp;nbsp;Nevertheless, that is what almost all of us do. &amp;nbsp;When an archetypical programmer in this new millennium sets out to create a program, they will typically begin by creating a Class, and then endowing that Class with Behavior; then, by creating an Instance of that Class, and bestowing interesting Data upon that Instance.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;
Such an Instance receives (as input) method calls &lt;i&gt;from&lt;/i&gt; some other object, and produces (as output) method calls &lt;i&gt;on&lt;/i&gt;&amp;nbsp;some other object. &amp;nbsp;It is a system unto itself, simulating some aspect of human endeavor, computing useful results and dispensing them, all in an abstract vacuum.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
But, the programmers who produced this artifact desires it to interact with the world; to produce an effect, and therefore to accept Input and dispense Output.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
It is at this point that the programmer encounters Twisted.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;&lt;i&gt;When you look for it, there is nothing to see.&lt;/i&gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;i&gt;When you listen for it, there is nothing to hear.&lt;/i&gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;i&gt;When you use it, it is inexhaustible.&lt;/i&gt;&lt;/i&gt;&lt;/div&gt;
&lt;i&gt;
&lt;/i&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;
Except that, in fact, nobody ever encounters Twisted this way. &amp;nbsp;If this &lt;i&gt;is&lt;/i&gt;&amp;nbsp;where – and how – you encounter Twisted, then you will likely have great success with it. &amp;nbsp;But everyone tends to encounter Twisted, like one encounters almost every other piece of infrastructure, &lt;i&gt;in medias res.&lt;/i&gt;&amp;nbsp; Method calls are flying around all over the place in some huge inscrutable system and you just have to bang through the tutorial to figure it all out right now, and it looks super weird.&lt;br /&gt;
&lt;br /&gt;
Over the years, so many questions I've answered about Twisted seem to reduce to: "how do I even get this thing&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/7313761/how-do-i-add-two-integers-together-with-twisted"&gt;to do anything&lt;/a&gt;"?&lt;br /&gt;
&lt;br /&gt;
This is Twisted's great mystery: &lt;i&gt;it does nothing&lt;/i&gt;. &amp;nbsp;By itself, it is the world's largest &lt;a href="https://en.wikipedia.org/wiki/NOP"&gt;NOP&lt;/a&gt;. &amp;nbsp;Its job, purely and simply is to connect &lt;i&gt;your object&lt;/i&gt;&amp;nbsp;to the world. &amp;nbsp;You tell Twisted: listen for connections on this port; when one is made, do this. &amp;nbsp;Make this request, and when it has a response, do that. &amp;nbsp;Listen for email over SMTP; when one arrives, do the other.&lt;br /&gt;
&lt;br /&gt;
Without your direction, &lt;span style="font-family: Courier New, Courier, monospace;"&gt;reactor.run&lt;/span&gt; will just ... wait.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
The source of most confusion with Twisted, I believe, is that few objects are designed in this idiom. &amp;nbsp;When we seek to create a program, we feel we must start interacting with it immediately, before it even knows what it is supposed to do. &amp;nbsp;The seductions of blocking I/O are many and varied. &amp;nbsp;Any function which appears to merely compute a result can simply be changed to cheat and get its answer by asking some other system instead, with its callers none the wiser. &amp;nbsp;Even for those of us who know better, these little cheats accumulate and make the program brittle and slow, and force it to be spun out into a thread, or the cold, sparse desert of its own separate process, so it may tediously plod along, waiting for the response to its each and every query.&lt;br /&gt;
&lt;br /&gt;
Thus, desire (for immediate I/O) leads to suffering (of the maintenance programmer).&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;&lt;span style="text-align: -webkit-auto;"&gt;Return is the movement of the Tao.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;&lt;i&gt;&lt;span style="text-align: -webkit-auto;"&gt;Yielding is the way of the Tao.&lt;/span&gt;&lt;/i&gt;&lt;/i&gt;&lt;/div&gt;
&lt;i&gt;
&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
It doesn't need to be that way, though. &amp;nbsp;When you create an object, it &lt;i&gt;is&lt;/i&gt;&amp;nbsp;best to create it as independently as possible; to test it in isolation; to discretely separate its every interaction with the outside world so that they may be carefully controlled, monitored, intercepted and inspected, one iteration at a time.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
All your object needs to do is to define its units of work as atomic, individual functions that it wishes to perform; then, return to its caller and allow it to proceed.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;&lt;span style="text-align: -webkit-auto;"&gt;The Master does his job &lt;/span&gt;&lt;/i&gt;&lt;i&gt;&lt;span style="text-align: -webkit-auto;"&gt;and then stops.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="font-style: italic; text-align: -webkit-auto;"&gt;&lt;i style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;He understands that the universe&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;i&gt;&lt;span style="text-align: -webkit-auto;"&gt;is forever out of control.&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div style="text-align: -webkit-auto;"&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;When you design your objects by contemplating their purpose and making them have a consistent, nicely separated internal model of what they're supposed to represent, Twisted seems less like a straightjacket, contorting your program into some awkward shape. &amp;nbsp;Instead, it becomes a comfortable jacket that your object might slip on to protect itself from the vicissitudes of whatever events may assault it from the network, whether they be the soft staccato of DNS, the confused warbling of SIP or the terrifying roar of IMAP.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div style="text-align: -webkit-auto;"&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;div style="text-align: -webkit-auto;"&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;Better yet, your object can be a model of some problem domain, and will therefore have a dedicated partner; a &lt;i&gt;different&lt;/i&gt;&amp;nbsp;object, a wrapper, whose entire purpose is to translate from a lexicon of network-based events, timers, and Deferred callbacks, into a language that is more directly applicable to your problem domain. &amp;nbsp;After all, each request or response from the network&amp;nbsp;&lt;i&gt;means&lt;/i&gt;&amp;nbsp;something to your application, otherwise it would not have been made; the process of explicitly enumerating all those meanings and recording and documenting them in a module dedicated to that purpose is a very useful exercise.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;When your object has such unity of purpose and clarity of function, then Twisted can help manage its stream of events even if the events are not actually coming from a network; abstractions like deferreds, producers, consumers, cooperators and inline callbacks can be used to manipulate timers, keystrokes, and button clicks just as easily as network traffic.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style="text-align: center;"&gt;&lt;span style="text-align: -webkit-auto;"&gt;
&lt;div style="text-align: -webkit-auto;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: -webkit-auto;"&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;True words aren't eloquent;&amp;nbsp;&lt;/i&gt;&lt;i&gt;eloquent words aren't true.&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;div style="font-style: italic;"&gt;
&lt;i&gt;Wise men don't need to prove their point;&amp;nbsp;&lt;/i&gt;&lt;i&gt;men who need to prove their point aren't wise.&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
So, if you are setting out to learn to use Twisted, approach it in this manner: it is not something that will, itself, give your object's inner thoughts structure, purpose and meaning. &amp;nbsp;It is merely a wrapper; an interstitial layer between your logic and some other system. &amp;nbsp;The methods it calls upon you might be coming from anywhere. &amp;nbsp;And indeed, they should be coming from at least &lt;i&gt;one&lt;/i&gt;&amp;nbsp;other place: your unit tests.&lt;br /&gt;
&lt;br /&gt;
(With apologies to&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/The_Tao_of_Programming"&gt;Geoffrey James&lt;/a&gt;&amp;nbsp;and Laozi.)&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/jbCbnVZi3YE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/1654357426583907472/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=1654357426583907472" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1654357426583907472?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1654357426583907472?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/jbCbnVZi3YE/the-twisted-way.html" title="The Twisted Way" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/12/the-twisted-way.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UDRn05cCp7ImA9WhNTGEU.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-2368621240089315828</id><published>2012-10-22T01:54:00.002-04:00</published><updated>2012-10-22T01:54:37.328-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-22T01:54:37.328-04:00</app:edited><title>A Tired Hobgoblin</title><content type="html">&lt;div&gt;
Alternate (Boring) Title: Why the Twisted coding standard is better than PEP8 (although you still shouldn't care)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
People often ask me why &lt;a href="http://twistedmatrix.com/documents/current/core/development/policy/coding-standard.html"&gt;Twisted's coding standard&lt;/a&gt; – camel case instead of underscores for method names, &lt;a href="http://epydoc.sourceforge.net/epytext.html"&gt;epytext&lt;/a&gt; instead of &lt;a href="http://docutils.sourceforge.net/rst.html"&gt;ReST&lt;/a&gt; for docstrings, underscores for prefixes – is "weird" and doesn't, for example, follow &lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
First off, I should say that the Twisted standard actually follows quite a bit of PEP 8. &amp;nbsp;PEP 8 is a long document with many rules, and the Twisted standard is compatible in large part. &amp;nbsp;For example, pretty much all of the recommendations in &lt;a href="http://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements"&gt;the section on pointless whitespace&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Also, the &lt;i&gt;primary&lt;/i&gt;&amp;nbsp;reason that Twisted differs at all from the standard practice in the Python community is that the "standard practice" was almost all developed &lt;i&gt;after&lt;/i&gt;&amp;nbsp;Twisted had put its practices in place. &amp;nbsp;PEP 8 was created on July 5, 2001; at that point, Twisted had already existed for some time, and had officially checked in its first coding standard just a smidge over one month earlier, on May 2, 2001.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
That's where my usual explanation ends. &amp;nbsp;If you're making a new Python project today, unless it is intended specifically as an extension for Twisted, you should ignore the relative merits of these coding standards and go with PEP 8, because the benefits of consistency generally outweigh any particular benefits of one coding standard or another. &amp;nbsp;Within Twisted, as PEP 8 itself says, "consistency within a project is even more important", so we're not going to change everything around just for broader consistency, but if we were starting again we might.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
But.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
There seems to be a sticking point around the camelCase method names.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
After ten years of fielding complaints about how &lt;i&gt;weird&lt;/i&gt;&amp;nbsp;and &lt;i&gt;gross&lt;/i&gt;&amp;nbsp;and &lt;i&gt;ugly&lt;/i&gt;&amp;nbsp;it is – rather than just how inconsistent it is – to put method names in camel case, I feel that it is time to speak out in defense of the elegance of this particular feature of our coding standard. &amp;nbsp;I believe that this reaction is based on Python programmers' ancestral memory of Java programs, and it is as irrational as people disliking Python's blocks-by-indentation because COBOL made a much more &lt;a href="http://me.veekun.com/blog/2012/09/07/heteroglot-number-15-in-cobol/"&gt;horrible&lt;/a&gt;&amp;nbsp;use of significant whitespace.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For starters, camelCase harkens back to a long and venerable tradition. &amp;nbsp;Did you camelCase haters-because-of-Java ever ask yourselves why Java uses that convention? &amp;nbsp;It's because it's copied from &lt;a href="https://en.wikipedia.org/wiki/Smalltalk"&gt;the very first object-oriented language&lt;/a&gt;. &amp;nbsp;If you like consistency, then Twisted is consistent with 34 years of object-oriented programming history.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Next, camelCase is easier to type. &amp;nbsp;For each word-separator, you have only to press "shift" and the next letter, rather than shift, minus, release shift, next letter. &amp;nbsp;Especially given the inconvenient placement of minus on US keyboards, this has probably saved me enough time that it's added up to &lt;i&gt;at least&lt;/i&gt; six minutes in the last ten years. &amp;nbsp;(Or, a little under one-tenth the time it took to write this article.)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Method names in mixedCase are also more consistent with CapitalizedWord class names. &amp;nbsp;If you have to scan 'xX' as a word boundary in one case, why learn two ways to do it?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Also, we can visually distinguish acronyms in more contexts in method names. &amp;nbsp;Consider the following method names:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;frog_blast_the_vent_core&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;frogBLASTTheVentCore&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
I believe that the identification of the acronym improves readability.&amp;nbsp;&lt;span style="font-family: Courier New, Courier, monospace;"&gt;frog_blast_the_vent_core&lt;/span&gt; is &lt;a href="http://marathongame.wikia.com/wiki/Frog_Blast_the_Vent_Core"&gt;just nonsense&lt;/a&gt;, but &lt;span style="font-family: Courier New, Courier, monospace;"&gt;frogBLASTTheVentCore&lt;/span&gt; makes it clear that you are doing&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/BLAST"&gt;sequence alignment&lt;/a&gt;&amp;nbsp;on frog DNA to try to identify variations in core mammalian respiration functions.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Finally, and this is the one that I think is actually bordering on being important enough to think about, Twisted's coding standard sports one additional feature that actually makes it&amp;nbsp;&lt;i&gt;more expressive&lt;/i&gt;&amp;nbsp;than underscore_separated method names. &amp;nbsp;You see, just because the convention is to separate&amp;nbsp;&lt;i&gt;words&lt;/i&gt;&amp;nbsp;in method names with capitalization, that doesn't mean we broke the underscore key on our keyboards. &amp;nbsp;The underscore is used for something else:&amp;nbsp;dispatch prefixes.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Ironically, since the first letter of a method must be lower case according to our coding standard, this conflicts a little bit with the previous point I made, but it's still a very useful feature.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The portion of a method name before an underscore indicates what type of method it is. &amp;nbsp;So, for example:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;irc_JOIN - the "irc_" prefix on an IRC client or server object indicates that it handles the "JOINED" message in the IRC protocol&lt;/li&gt;
&lt;li&gt;render_GET - the "render_" prefix on an HTTP resource indicates that this method is processing the GET HTTP method.&lt;/li&gt;
&lt;li&gt;remote_loginAnonymous - the "remote_" prefix on a Perspective Broker Referenceable object indicates that this is the implementation of the PB method 'loginAnonymous'&lt;/li&gt;
&lt;li&gt;test_addDSAIdentityNoComment - the "test_" prefix on a trial TestCase indicates that this is a test method that should be run automatically. (Although for historical reasons and PyUnit compatibility the code only actually looks at the "test" part.)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
The final method name there is a good indication of the additional expressiveness of this naming convention. &amp;nbsp;The underscores-only version – test_add_dsa_identity_no_comment – depends on context. &amp;nbsp;Is this an application function that is testing whether we can add a ... dissah? ... identity with no comment? &amp;nbsp;Or a unit test? &amp;nbsp;Whereas the Twisted version is unambiguous: it's a test case for adding a D.S.A. identity with no comment. &amp;nbsp;It would be very odd, if not a violation of the coding standard, to name a method that way outside of a test suite.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Hopefully this will be the last I'll say on the subject. &amp;nbsp;Again, if you're starting a new Python project, you should really just go ahead and use PEP 8, this battle was lost a very long time ago and I didn't even really mind losing it back then. &amp;nbsp;Just please, stop telling me how ugly and bad this style is. &amp;nbsp;It works very nicely for me.&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/ni52K17hyA0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/2368621240089315828/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=2368621240089315828" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/2368621240089315828?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/2368621240089315828?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/ni52K17hyA0/a-tired-hobgoblin.html" title="A Tired Hobgoblin" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>6</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/10/a-tired-hobgoblin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQARXg6eCp7ImA9WhJaFko.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-1299588979762041437</id><published>2012-10-07T17:13:00.000-04:00</published><updated>2012-10-08T02:05:44.610-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-08T02:05:44.610-04:00</app:edited><title>The Lexicology of Personal Development</title><content type="html">These days, everybody talks about geeks. &amp;nbsp;Geek chic, the "&lt;a href="http://leverage.wikia.com/wiki/Alec_Hardison"&gt;age of the geek&lt;/a&gt;"; even &lt;a href="http://www.nytimes.com/2008/05/23/opinion/23brooks.html?_r=2&amp;amp;scp=1&amp;amp;sq=Brooks+AND+Geek+AND+nerd&amp;amp;st=nyt&amp;amp;oref=slogin"&gt;the New York Times op-ed page&lt;/a&gt; has been talking about the rise of "geeks" for years. &amp;nbsp;Bowing to popular usage, even I use the word as it's currently being bandied about. &amp;nbsp;But I think that the real success story is that of nerds.&lt;br /&gt;
&lt;br /&gt;
A pernicious habit I've noticed in the last decade of the growth of geek culture is that it has developed a sort of cargo-cult of meritocracy. &amp;nbsp;Within the self-identified "geek" community, there's a social hierarchy based on all kinds of ridiculous pop-culture fetishism. &amp;nbsp;Who knows the most Monty Python non-sequiteurs? &amp;nbsp;Who knows the most obscure Deep Space Nine trivia? &amp;nbsp;This is hardly a new thing – William Shatner famously complained about it on Saturday Night Live in 1986 – but the Internet has been accelerating the phenomenon tremendously. &amp;nbsp;People who had a difficult time in their teens find each other as adults through some fan-club interest group, and then they make fast friends who had similar social problems. &amp;nbsp;Soon, since that's the shared interest that they know all their friends from, they spend all their time in the totally fruitless pursuit of more junk related to some frivolous obsession. &amp;nbsp;That can be okay, almost healthy even, if the focus of this accumulation is a productive hobby. However, if it's just a pop-culture franchise (Harry Potter, Star Trek, World of Darkness) what was originally a liberating new social landscape can rapidly turn into a suffocating, stale dead-end for personal development.&lt;br /&gt;
&lt;br /&gt;
So I always feel a twinge when I identify myself as a "geek". &amp;nbsp;I usually prefer to say that I am - or at least aspire to be - a nerd.&lt;br /&gt;
&lt;br /&gt;
A &lt;b&gt;nerd&lt;/b&gt;&amp;nbsp;is someone who is socially awkward because they are more thoughtful, introspective, intelligent or knowledgeable than their peers. &amp;nbsp;They notice things that others don't, and it makes interaction difficult. &amp;nbsp;This is especially obvious in younger nerds, where they're a little above their age group's intelligence but not &lt;i&gt;quite&lt;/i&gt;&amp;nbsp;intelligent enough to know when to keep their mouths shut to avoid ostracism. &amp;nbsp;But, even if they have learned to keep a lid on their less-popular observations, it's tough to constantly censor yourself and it makes interaction with your peers less enjoyable.&lt;br /&gt;
&lt;br /&gt;
A &lt;b&gt;geek&lt;/b&gt;&amp;nbsp;is someone who is socially awkward because they are obsessed with topics that the mundanes among us just don't care about that much. They collect things, whether it's knowledge, games, books, toys, or technology. &amp;nbsp;Faced with a popular science fiction movie, a nerd might want to do the math to see whether the special effects are physically plausible, but a geek will just watch it a dozen times to memorize all the lines.&lt;br /&gt;
&lt;br /&gt;
A &lt;b&gt;dork&lt;/b&gt;&amp;nbsp;is just socially awkward because they just aren't all that pleasant to be around. &amp;nbsp;Nerds and geeks have trouble with interacting with others because they're lost in their own little worlds of intellectual curiosity or obsession: dorks are awkward because, let's face it, maybe they're a little stupid, a little mean, and just not that interesting. &amp;nbsp;A dork is unsympathetic.&lt;br /&gt;
&lt;br /&gt;
By way of a little research for this post, I discovered that I'm apparently &lt;a href="http://www.goingthewongway.com/208/difference-between-nerd-geek-and-dork/"&gt;not the only one&lt;/a&gt;&amp;nbsp;who has this impression of the definitions, and even&amp;nbsp;&lt;a href="http://www.paulgraham.com/nerds.html"&gt;Paul Graham seems to agree with me&lt;/a&gt;&amp;nbsp;on word choice. &amp;nbsp;Still: from here on out, these are the &lt;i&gt;correct&lt;/i&gt;&amp;nbsp;definitions of the words, thank you very much.&lt;br /&gt;
&lt;br /&gt;
Maybe you've heard these definitions before, and this is all old news. Also, these are words for the sort of tedious taxonomy of people that fictional teenagers in high-school movies do. &amp;nbsp;It's obviously not karmically healthy to start labeling people "nerd", "dork", &amp;nbsp;and "geek" and then writing them off as such. &amp;nbsp;So, you might ask, why do I bring it up?&lt;br /&gt;
&lt;br /&gt;
Because you, like me, are almost certainly a nerd, a geek, &lt;i&gt;and&lt;/i&gt; a dork. &amp;nbsp;And, as you might have inferred from my definitions above, nerds are better than geeks, and dorks are worse than both.&lt;br /&gt;
&lt;br /&gt;
First, consider your inner nerd. &amp;nbsp;It's &lt;i&gt;good&lt;/i&gt;&amp;nbsp;to be intellectually curious, to stretch your cognitive abilities in new and interesting ways, to learn things about how systems work. &amp;nbsp;Physical systems, social systems, technological systems: it's always good to know more. &amp;nbsp;It's even good to be curious to the point of awkwardness, especially if you're a kid who is concerned about awkwardness; don't worry about it, it'll make you more interesting later. &amp;nbsp;It's good to foster any habits which are a little nerdy.&lt;br /&gt;
&lt;br /&gt;
Second, your inner geek. &amp;nbsp;It's okay to enjoy things, even to obsess about them a little bit, but I think that our culture is really starting to overdo this. &amp;nbsp;Geeks are presented in popular media as equally, almost infinitely, obsessed with Star Wars,&amp;nbsp;calculus,&amp;nbsp;Star Trek, computer security, and terrible food (cheese whiz, sugary soda brands, etc). &amp;nbsp;No real people actually have time for all this stuff. &amp;nbsp;At some point, you have to choose whether you're going to memorize &lt;a href="https://en.wikipedia.org/wiki/Maxwell's_equations"&gt;Maxwell's&lt;/a&gt; or &lt;a href="http://en.memory-alpha.org/wiki/Warp_equation"&gt;Kosinski's&lt;/a&gt; equations.&lt;br /&gt;
&lt;br /&gt;
One way that you can keep your inner geek in check is to always ask yourself the question: am I watching this movie / playing this game / reading this book because I actually enjoy it and I think it's worthwhile, or am I just trying to make myself conform to some image of myself as someone who knows absolutely everything about this one little cultural niche?&lt;br /&gt;
&lt;br /&gt;
There are people who will treat being a fan of something that someone else created as morally equivalent (or, in a sense, even better than) creating something yourself, and those people are not doing you any favors. &amp;nbsp;Do not pay attention to them.&lt;br /&gt;
&lt;br /&gt;
Of course, there's some overlap. &amp;nbsp;People who like playing with systems in real life enjoy the fluffier, more lightweight intellectual challenges of playing with the rules of fictional universes, especially the ones from speculative fiction. &amp;nbsp;When I was a kid, I went to a couple of Star Trek conventions and let me tell you, there were some &lt;i&gt;legit&lt;/i&gt;&amp;nbsp;nerds there; astrophysicists, rocket scientists, and experimental chemists, all excitedly talking about how they were inspired to pursue their careers by fiction of various kinds.&lt;br /&gt;
&lt;br /&gt;
So go ahead, take a break, and geek out. Just don't tell yourself that it's anything other than for fun.&lt;br /&gt;
&lt;br /&gt;
Finally, your inner dork.&lt;br /&gt;
&lt;br /&gt;
As you're enthusiastically cultivating your nerdiness and carefully managing your geekiness, you will be accumulating a little bit of dorkiness as you go: at some point you have to make decisions about whether to do some minor social obligation in order to spend some time on learning a new thing (or re-watching your favorite movie). &amp;nbsp;You have to decide whether to restrain yourself so you can listen to your friend talk about a rough day at their job or to start spouting facts about the progress of the repairs on the large hadron collider.&lt;br /&gt;
&lt;br /&gt;
Sometimes, on balance, it's acceptable to be a little bit inconsiderate in the pursuit of something more important. &amp;nbsp;People worth being friends with will see that and understand. &amp;nbsp;Heck, practically every movie plot these days puts at least one awkward and abrasive nerd in a sympathetic and even heroic position. &amp;nbsp;But be careful: once you decide that social graces are your &lt;i&gt;lowest&lt;/i&gt;&amp;nbsp;priority, it's a hop skip and a jump from being a lovable but absent-minded genius to being a blathering blowhard who just &lt;i&gt;will not shut up&lt;/i&gt;&amp;nbsp;about some tedious Riemannian manifold crap that nobody cares about even we &lt;i&gt;just told them&lt;/i&gt;&amp;nbsp;that somebody&amp;nbsp;&lt;i&gt;died&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The &lt;i&gt;goal&lt;/i&gt;&amp;nbsp;of the nerd or the geek, after all, is not to be awkward; it's easy to forget sometimes that that is an unintentional and unpleasant side effect of the good parts of those attributes. &amp;nbsp;Being a dork is just bad. &amp;nbsp;After all, if you're so smart, why aren't you nice?
&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/F_vk1F_hzEY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/1299588979762041437/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=1299588979762041437" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1299588979762041437?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1299588979762041437?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/F_vk1F_hzEY/the-lexicology-of-personal-development.html" title="The Lexicology of Personal Development" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>12</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/10/the-lexicology-of-personal-development.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UCRXw_fyp7ImA9WhJREUg.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-2344587520417413218</id><published>2012-07-13T00:54:00.001-04:00</published><updated>2012-07-13T00:54:24.247-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-13T00:54:24.247-04:00</app:edited><title>Simple Made Variadic</title><content type="html">Last night I made a &lt;a href="https://twitter.com/glyph/status/223326265464201217"&gt;snarky tweet&lt;/a&gt;&amp;nbsp;about how &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; is doomed. &amp;nbsp;Out of context, it didn't really make a lot of sense, and &lt;a href="https://twitter.com/radian/status/223335487220350976"&gt;Ivan Krstić replied&lt;/a&gt;&amp;nbsp;asking what the heck I was talking about. &amp;nbsp;I tried to fit the following into a tweet but it kinda broke the tweeterizer I was using right in half, and so I had to put it here.&lt;br /&gt;
&lt;br /&gt;
I love a good snark as much as the next person - some might say more - but it really bothers me when people make snide comments denigrating others' free work without at least offering a cogent criticism to go with it, and I don't want to be that guy. &amp;nbsp;So, hopefully before the whole Clojure community finds said tweet and writes me off as an arrogant Python bigot, I would like to explain what I meant in a bit more detail.&lt;br /&gt;
&lt;br /&gt;
Right off the bat I should say that this was a bit tongue-in-cheek. &amp;nbsp;I actually rather like Clojure and I think Rich Hickey has some very compelling ideas about programming in general. &amp;nbsp;I watch his talk "&lt;a href="http://www.infoq.com/presentations/Simple-Made-Easy"&gt;Simple Made Easy&lt;/a&gt;" once every month or two, contemplating its deeper meaning, and I still usually come away with an insight or two.&lt;br /&gt;
&lt;br /&gt;
I should also make it clear that I was linking to the &lt;code&gt;recur&lt;/code&gt;&amp;nbsp;special form specifically, and not just the special forms documentation in general. &amp;nbsp;Obviously having reference docs isn't a bad thing.&lt;br /&gt;
&lt;br /&gt;
Ivan, (or should I say, "@radian"?) you may be right; that documentation you linked to may indeed one day spell Python's doom. &amp;nbsp;If Python does eventually start to suck, it &lt;i&gt;will&lt;/i&gt;&amp;nbsp;be because it collapsed under the weight of its own weird edge cases like the slightly-special behavior of operator dispatch as compared to method dispatch, all the funkiness of descriptors, context managers, decorators, metaclasses, et cetera.&lt;br /&gt;
&lt;br /&gt;
A portion of my point that was serious, though. &amp;nbsp;The documentation for&amp;nbsp;&lt;span style="font-family: monospace;"&gt;recur&lt;/span&gt;&amp;nbsp;does highlight some problems with Clojure that the Python docs can play an interesting counterpoint to.&lt;br /&gt;
&lt;br /&gt;
The presence of the&amp;nbsp;&lt;span style="font-family: monospace;"&gt;recur&lt;/span&gt;&amp;nbsp;form at all is an indication of the unhealthy level of obsession that all LISPs have with recursion. &amp;nbsp;We get it: functions are cool. You can call them. They can call themselves. Every other genre of language manages to use this to a reasonable degree of moderation without adding extra syntactic features to their core just so you can recurse forever without worrying about stack resources. Reading this particular snipped of documentation, I can almost hear Rich Hickey cackling as he wrote it, having just crowned himself God-Emperor of the smug LISP weenies, as he gleefully points out that Scheme has it wrong &lt;i&gt;and&lt;/i&gt;&amp;nbsp;the CL specifications had it wrong with respect to tail call elimination, and that it should be supported by the language but &lt;i&gt;also&lt;/i&gt;&amp;nbsp;be explicit and compiler-verified.&lt;br /&gt;
&lt;br /&gt;
The sad thing is, my hypothetical caricature of Clojure's inventor is actually &lt;b&gt;right&lt;/b&gt;! This is a uniquely clever solution to a particularly thorny conceptual problem with the recursive expression of algorithms. The Scheme folks and the Common Lisp folks &lt;i&gt;did&lt;/i&gt;&amp;nbsp;both kinda get it wrong. &amp;nbsp;But the fact that this has to be so front-and-center in the language is a problem. Most algorithms shouldn't be expressed recursively; it is actually quite tricky to communicate about recursive code, and anyway most systems that really benefit from it have to be mutually, dynamically reentrant anyway and won't be helped by tail call elimination. &amp;nbsp;(My favorite example of this is still the &lt;a href="http://twistedmatrix.com/trac/ticket/411"&gt;unholy shenanigans&lt;/a&gt; that Deferreds have to get up to to make sure you don't have to care about callback chain length or Deferred return nesting depth.)&lt;br /&gt;
&lt;br /&gt;
Also, if you want to be all automatically parallelizable and web scale and "cloud"-y, recursion and iteration are &lt;i&gt;both&lt;/i&gt;&amp;nbsp;the wrong way to do it; they're both just ways of tediously making your way down a list of things one element at a time. &amp;nbsp;What you want to do is to declaratively apply a computation to your data in such a way as to avoid saying anything about the order things have to happen in. &amp;nbsp;To put it more LISPily, (&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;map&lt;/span&gt;) is a better conceptual foundation for the future than (&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;loop&lt;/span&gt;) or (&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;apply&lt;/span&gt;). &amp;nbsp;Of course you can do the &lt;i&gt;naive&lt;/i&gt;&amp;nbsp;implementation of (&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;map&lt;/span&gt;) with (&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;recur&lt;/span&gt;), but smarter implementations need application code to be written some other way.&lt;br /&gt;
&lt;br /&gt;
The language style choices of the manual in this case is also telling. The Python docs that Ivan linked to go into excruciating detail, rephrasing and explaining the same concept in a few different ways, linking to other required concepts in depth so the reader can easily familiarize themselves with any prerequisites, while still essentially explaining a nerdy part of the language that you can ignore while still using it productively. Every Python programmer ignores descriptors while they're learning to write classes and methods, despite that they're using them all the time; this ability to be understood at different levels of complexity is a strength of every good language, and python does particularly well in that regard. Of course one could also make the case that this is just because Python has so many dusty corners hidden behind double-underscores, and a better language would just have less obscure junk in it, not make understanding the obscure junk optional, but I digress.&lt;br /&gt;
&lt;br /&gt;
The description of&amp;nbsp;&lt;span style="font-family: monospace;"&gt;recur&lt;/span&gt;, by contrast, is deeply flawed. &amp;nbsp;It is terse, to a fault. It introduces the concept of "recursion points" without linking to any kind of general reference. &amp;nbsp;It uses abbreviations all over the place ("&lt;span style="font-family: monospace;"&gt;exprs&lt;/span&gt;", "params", "args", "seq") without even using typesetting to illuminate whether they are using a general term or a specific variable name.&lt;br /&gt;
&lt;br /&gt;
But, by far, the worst sin of this document is the use of the words "variadic" and "arity". There is really no excuse for the use of these words, ever. Take it from me, I am exactly the kind of pedantic jerk who will drop "arity" into a conversation about, for example, music theory, just to demonstrate that I can, and as that kind of jerk I can tell you with certainty: I have no excuse.&lt;br /&gt;
&lt;br /&gt;
It should say: "a function that takes a variable number of arguments". Or possibly: "it must take exactly the same number of arguments as the recursion point".&lt;br /&gt;
&lt;br /&gt;
This was particularly disappointing example to me because Clojure strikes me as a particularly... for lack of a better word, "optimistic" lisp, one that looks forward rather than back, one that is more interested in helping people find comprehensible and composeable ways to express programs than in revisiting obscure debates over reader macros or lisp-1/lisp-2 holy wars. &amp;nbsp;But the tone of the documentation for&amp;nbsp;&lt;span style="font-family: monospace;"&gt;recur&lt;/span&gt;&amp;nbsp;aims it straight at the smug lisp weenie crowd.&lt;br /&gt;
&lt;br /&gt;
As I hope is obvious, if not initially, then at least by now, I don't think that Clojure will fail (or succeed) on the merits of one crummy piece of documentation. It's a much younger language than Python, so it may have a ways to go in its documentation practices. It also comes from an illustrious heritage that I can't expect to see &lt;i&gt;none&lt;/i&gt;&amp;nbsp;of in the way that it talks about itself, no matter how unfortunate certain details of that heritage are. &amp;nbsp;Heck, at the parallel point in Python's lifetime, it didn't even have descriptors yet, let alone the documentation for them!&lt;br /&gt;
&lt;br /&gt;
Still, I don't think that this issue is entirely trivial, and I hope that the maintainers for the documentation for Clojure, at least the documentation for the parts of the language you have to see every day, take care to improve its accessibility to the less arcane among us.&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/1kkSUv9lYVs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/2344587520417413218/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=2344587520417413218" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/2344587520417413218?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/2344587520417413218?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/1kkSUv9lYVs/simple-made-variadic.html" title="Simple Made Variadic" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>8</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/07/simple-made-variadic.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAARHc4cSp7ImA9WhVXE0g.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-150013806878248584</id><published>2012-04-13T17:32:00.002-04:00</published><updated>2012-04-13T17:32:25.939-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-13T17:32:25.939-04:00</app:edited><title>We'll Always Have Cambridge</title><content type="html">Half-way through 2012, I will be leaving the east coast.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
There are a great many things I despair of leaving behind; family, friends, &lt;a href="http://meetup.bostonpython.com/"&gt;the most excellent Boston Python Meetup&lt;/a&gt;, participating in the sometimes incendiary, sometimes hilarious&amp;nbsp;Cambridge, Massachusetts / Cambridge, England rap war.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
However, I'm not writing today in order to wax lyrical about the area, or to extoll the virtues of my new home, but hopefully, to prevent a missed opportunity. &amp;nbsp;I know there are at least a few really cool people in Massachusetts who read this blog, and who read my tweets, that I either haven't seen in quite a while or have never actually met in person.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So if grabbing a coffee with me is an interesting idea to you, please drop me a line within the next month. I would love to hear your story about how PHP ruined your summer, or how Twisted changed your life, or how you once pwned a vending machine with nothing but a malformed JPEG.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I'm sure I'll visit the area from time to time, so this isn't quite your &lt;i&gt;last&lt;/i&gt;&amp;nbsp;chance, but it just won't be the &lt;i&gt;same&lt;/i&gt;, you know?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
If I follow you, &lt;a href="http://twitter.com/glyph"&gt;you can DM me on Twitter&lt;/a&gt; of course, but my email address isn't hard to figure out either. &amp;nbsp;If you glance up towards the top of your browser window right now, you're practically looking at it.&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/uCEsYd7lRSs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/150013806878248584/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=150013806878248584" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/150013806878248584?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/150013806878248584?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/uCEsYd7lRSs/well-always-have-cambridge.html" title="We'll Always Have Cambridge" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/04/well-always-have-cambridge.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcNR3w9fSp7ImA9WhRaEEQ.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-7172059099031479788</id><published>2012-02-12T18:41:00.004-05:00</published><updated>2012-02-12T18:41:36.265-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-12T18:41:36.265-05:00</app:edited><title>This Isn't How PyPy Works, But it Might as Well Be</title><content type="html">It seems like a lot of the Python programmers I speak with are deeply confused by PyPy and can't understand how it works. &amp;nbsp;The stereotypical interlocutor will often say things like: A Python VM in Python? &amp;nbsp;That's just crazy! &amp;nbsp;How can that be fast? &amp;nbsp;Isn't Python slower than C? &amp;nbsp;Aren't all compilers written in C? &amp;nbsp;How does it make an executable?&lt;br /&gt;
&lt;br /&gt;
I am not going to describe to you how PyPy actually works. &amp;nbsp;Lucky for you, I'm not smart enough to do that. &amp;nbsp;But I would like to help you all understand how PyPy &lt;i&gt;could&lt;/i&gt;&amp;nbsp;work, and hopefully demystify the whole idea.&lt;br /&gt;
&lt;br /&gt;
The people who &lt;i&gt;are&lt;/i&gt; smart enough to explain how PyPy actually works will do it over at &lt;a href="http://morepypy.blogspot.com/"&gt;the PyPy blog&lt;/a&gt;. &amp;nbsp;At some level it's really quite straightforward, but this impression of straightforwardness is not conveyed well by posts with titles like "&lt;a href="http://morepypy.blogspot.com/2012/02/optimizing-traces-of-flow-graph.html"&gt;Optimizing Traces of the Flow Graph Language&lt;/a&gt;". &amp;nbsp;&lt;i&gt;In addition&lt;/i&gt;&amp;nbsp;to being a Python interpreter in Python, PyPy is a mind-blowingly advanced exploration of the cutting-est cutting-edge compiler and runtime technology, which can make it seem complex. In fact, the fact that it's in Python is what lets it be so cutting-edge.&lt;br /&gt;
&lt;br /&gt;
Most people with a formal computer science background are already familiar with the fairly generic nature of compilers, as well as the concept of a self-hosting compiler. &amp;nbsp;If you do have that background, then that's all PyPy is: a self-hosting compiler. &amp;nbsp;The same way GCC is written in C, PyPy is written in Python. &amp;nbsp;When you strip away the advanced techniques, that's all that's there.&lt;br /&gt;
&lt;br /&gt;
A lot of folks who are confused by PyPy's existence, though, I suspect don't have that background; many working programmers these days don't. &amp;nbsp;Or if they do, they've forgotten it, because the practical implications of the CSS box model are&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug"&gt;so complex&lt;/a&gt; that they squeeze simpler ideas, like turing completeness and the halting problem, out of the average human brain. &amp;nbsp;So here's the easier explanation.&lt;br /&gt;
&lt;br /&gt;
A compiler is a program that turns a string (source code: your program text written in Python, C, Ruby, Java, or whatever) into some kind of executable code (bytecode or runtime interpreter operations or a platform-native executable).&lt;br /&gt;
&lt;br /&gt;
Let's examine that last one, since it seems to be a sticking point for most folks. &amp;nbsp;A platform-native executable is simply a bunch of bytes in a file. There's nothing magic about it. &amp;nbsp;It's not even a particularly complex type of file. &amp;nbsp;It's a packed binary file, not a text file, but so are PNGs and JPEGs, and few programmers find it difficult to believe that such files might be created by Python. &amp;nbsp;The formats are standard and very long-lived and there are tons of tools to work with them. &amp;nbsp;If you're curious, even Wikipedia has a good reference for the formats used by &lt;a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format"&gt;each&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Portable_Executable"&gt;popular&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Mach-O"&gt;platform&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
As to Python being slower than C: once a program has been transformed into executable code, it doesn't matter how slow the process for translating it was: the running program is now just executable instructions for your CPU, so it doesn't matter that Python is slower than C, because it was just the compiler that was in Python, and by the time your program is running, the original Python has effectively vanished and all you're left with is &lt;i&gt;your&lt;/i&gt;&amp;nbsp;program executing.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
(Actually, Python is&amp;nbsp;&lt;a href="http://morepypy.blogspot.com/2011/02/pypy-faster-than-c-on-carefully-crafted.html"&gt;faster than C&lt;/a&gt;&amp;nbsp;anyway, especially at&amp;nbsp;&lt;a href="http://morepypy.blogspot.com/2011/08/pypy-is-faster-than-c-again-string.html"&gt;producing strings&lt;/a&gt;.)&lt;/div&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;
&lt;br /&gt;&lt;/div&gt;
In reality, PyPy takes a hybrid approach, where it is a program which produces a program and then does some stuff to it and creates some C code which it compiles with the compiler of your choice and then creates some code which then creates &lt;i&gt;other&lt;/i&gt;&amp;nbsp;code and then puts it into memory, not a file, and then executes it directly, but all of that is ancillary tricks and techniques to make your code run faster, not a fundamental property of the kind of thing that PyPy &lt;i&gt;is&lt;/i&gt;. &amp;nbsp;Plus, as I said, this article isn't actually about how PyPy works anyway, it's just about how you should pretend it works. &amp;nbsp;So you should ignore this whole paragraph.&lt;br /&gt;
&lt;br /&gt;
For the sake of argument, assume that you know all the ins and outs of binary executable formats for different operating systems, and the machine code for various CPU architectures. &amp;nbsp;The question you should really ask yourself is: if you have to write a program (a compiler) which translates one kind of string (source code) into another kind of string (a compiled program): would you rather write it in C or Python? &amp;nbsp;What if the strings in question were a template document and an HTML page?&lt;br /&gt;
&lt;br /&gt;
It shouldn't be surprising that PyPy is written in Python. &amp;nbsp;For the same reasons that you might use Django templates and not &lt;code&gt;&lt;a href="http://linux.die.net/man/3/snprintf"&gt;snprintf&lt;/a&gt;&lt;/code&gt; for generating your HTML, it's &lt;i&gt;easier&lt;/i&gt;&amp;nbsp;to use Python than C to generate compiled code. &amp;nbsp;This is why PyPy is at the forefront of so many advanced techniques that are too sophisticated to cover in a quick article like this. &amp;nbsp;Since the compiler is written in a higher-level language, it can do more advanced things, since lower-level concerns can be abstracted away, just as they are in your own applications.&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/UjyrD5TPorg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/7172059099031479788/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=7172059099031479788" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7172059099031479788?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7172059099031479788?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/UjyrD5TPorg/this-isnt-how-pypy-works-but-it-might.html" title="This Isn't How PyPy Works, But it Might as Well Be" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>5</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/02/this-isnt-how-pypy-works-but-it-might.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEFSHs6eip7ImA9WhRUEEk.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-1658981130046290535</id><published>2012-01-20T01:23:00.000-05:00</published><updated>2012-01-20T01:23:39.512-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-20T01:23:39.512-05:00</app:edited><title>The Concurrency Spectrum: from Callbacks to Coroutines to Craziness</title><content type="html">&lt;br /&gt;
Concurrent programming idioms are on a spectrum of complexity.&lt;br /&gt;
&lt;br /&gt;
Obviously, writing code that isn't concurrent in any way is the easiest. &amp;nbsp;If you never introduce any concurrent tasks, you never have to debug any problems with things running in an unexpected order. &amp;nbsp;But, in today's connected world, concurrency of some sort is usually a requirement. &amp;nbsp;Each additional point where concurrency can happen introduces a bit of cognitive overhead, another place you need to think about what might happen, so as a codebase adds more of them it becomes more difficult to understand them all, and it becomes more challenging to understand subtle nuances of parallel execution. &lt;br /&gt;
&lt;br /&gt;
So, at the simplest end of the spectrum, you have callback-based concurrency. &amp;nbsp;Every time you have to proceed to the next step of a concurrent operation, you have to create a new function and new scope, and pass it to the operation so that the appropriate function will be called when the operation completes. &amp;nbsp;This is very explicit and reasonably straightforward to debug and test, but it can be tedious and overly verbose, especially in Python where you have to think up a new function name and argument list for every step. &amp;nbsp;The extra lines for the function definition and return statement can be an impediment to quickly understanding the code's intentions, so what facilitates understanding of the concurrency model can inhibit understanding of the code's actual logical purpose, depending on how much concurrent stuff it has to do. &amp;nbsp;Twisted's Deferreds make this a bit easier than raw callback-passing without fundamentally changing the execution dynamic, so they're at this same level.&lt;br /&gt;
&lt;br /&gt;
Then you have explicit concurrency, where every possible switch-point has to be labeled somehow. &amp;nbsp;This is yield-based coroutines, or inlineCallbacks, in Twisted. &amp;nbsp;This is more compact than using callbacks, but also more limiting. &amp;nbsp;For example, you can only resume a generator once, whereas you can run a callback multiple times. &amp;nbsp;However, for a logical flow of sequential concurrent steps, it reads very naturally, and is shorter, as it collapses out the 'def' and 'return' lines, and you have to think of at least two fewer names per step.&lt;br /&gt;
&lt;br /&gt;
However, that very ease can be misleading. &amp;nbsp;You might gloss over a 'result = yield ...' more easily than a 'def whatever(result): return result; something(whatever)'. &amp;nbsp;Nevertheless, if you have 'yield's everywhere you might swap your stack, then when you have a concurrency bug, you can look at any given arbitrary chunk of code and know that you don't need any locks in it, as long as you can't see any yield statements. &amp;nbsp;Where you do see yield statements, you know that you have some code that needs to be inspected.&lt;br /&gt;
&lt;br /&gt;
To continue down that spectrum, a cooperatively multithreading program with implicit context switches makes every line with any function call on it (or any line which might be a function call, like any operator which can be overridden by a special method) a possible, but not likely culprit. &amp;nbsp;Now when you have a concurrency bug you have to audit absolutely every line of code you've got, although you still have a few clues which will help you narrow it down and rule out certain areas of the code. &amp;nbsp;For example, you can guess that it would be pathological for 'x = []; ...; x.append(y)' to context switch. (Although, given arbitrary introspection craziness, it is still &lt;i&gt;possible&lt;/i&gt;, depending on what "..." is.) &amp;nbsp;This is way more lines than you have to consider with yield, although with some discipline it can be kept manageable. &amp;nbsp;However, experience has taught me that "with some discipline" is a code phrase for "almost never, on real-life programming projects".&lt;br /&gt;
&lt;br /&gt;
All the way at the end of the spectrum of course you have preemptive multithreading, where every line of code is a mind-destroying death-trap hiding every possible concurrency peril you could imagine, and anything could happen at any time. &amp;nbsp;When you encounter a concurrency bug you have to give up and just try to drink your sorrows away. &amp;nbsp;Or just change random stuff in your 'settings.py' until it starts working, or something. &amp;nbsp;I never really did get comfortable in that style. &amp;nbsp;With some discipline, you can manage this problem by never manipulating shared state, and only transferring data via safe queueing mechanisms, but... there's that phrase again.&lt;br /&gt;
&lt;br /&gt;
Some programming languages, like Erlang, support efficient preemptive processes with state isolation and built-in super-cheap super-fast queues to transfer immutable values. &amp;nbsp;(Some other languages call these "threads" anyway, even though I would agree with Erlang's classification as "processes".)&amp;nbsp; That's a different programming model entirely though, with its own advantages and challenges, which doesn't land neatly on this spectrum; if I'm talking about left and right here, Erlang and friends are somewhere above or below. &amp;nbsp;I'm just describing Python and its ilk, where threads give you a big pile of shared, mutable state, and you are constantly tempted to splash said state all over your program.&lt;br /&gt;
&lt;br /&gt;
Personally I like Twisted's style best; the thing that you yield is itself an object whose state can be inspected, and you can write callback-based or yield-based code as each specific context merits. &amp;nbsp;My opinion on this has shifted over time, but currently I find that it's best to have a core which is written in the super-explicit callback-based approach with no coroutines at all, and then high-level application logic which wraps that core using yield-based coroutines (@inlineCallbacks, for Twisted fans).&lt;br /&gt;
&lt;br /&gt;
I hope that in a future post, I may explain why, but that would take more words than I've got in me tonight.&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/M1ABaaJrmwY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/1658981130046290535/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=1658981130046290535" title="14 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1658981130046290535?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1658981130046290535?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/M1ABaaJrmwY/concurrency-spectrum-from-callbacks-to.html" title="The Concurrency Spectrum: from Callbacks to Coroutines to Craziness" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>14</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2012/01/concurrency-spectrum-from-callbacks-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMEQHk8eyp7ImA9WhRQGUk.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-3423291996900484779</id><published>2011-12-15T05:20:00.000-05:00</published><updated>2011-12-15T05:20:01.773-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-15T05:20:01.773-05:00</app:edited><title>I'm Sorry It's Come To This</title><content type="html">&lt;div style="text-align: justify;"&gt;
&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;If you want to be a great leader,&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;you must learn to follow the Tao.&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;Stop trying to control.&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;Let go of fixed plans and concepts,&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: center;"&gt;
&lt;i&gt;and the world will govern itself.&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: right;"&gt;
&lt;i&gt;- &lt;a href="http://academic.brooklyn.cuny.edu/core9/phalsall/texts/taote-v3.html"&gt;Tao Te Ching ch. 59,&lt;/a&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style="text-align: right;"&gt;
&lt;i&gt;&lt;a href="http://academic.brooklyn.cuny.edu/core9/phalsall/texts/taote-v3.html"&gt;as translated by S. Mitchell&lt;/a&gt;&lt;/i&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
I usually try not to get too political in my public persona – on blogs, twitter, IRC, mailing lists et cetera – and that's a conscious choice.&lt;br /&gt;
&lt;br /&gt;
I work on open source software. &amp;nbsp;I have for the last ten years. &amp;nbsp;I am lucky enough to have founded a project of my own, but in open source, leaders are more beholden to their followers than vice versa. &amp;nbsp;I depend on people showing up to effectively work for me, for free, on a regular basis. &amp;nbsp;So, I try to avoid politics not because I don't have strong convictions (anyone who knows me personally can tell you that I certainly do) but because I don't want someone to avoid showing up and helping do some good in the world in one area, just because we might disagree in another.&lt;br /&gt;
&lt;br /&gt;
This is a benefit of living in a free and democratic society: we have ways to dispute issues that we have strong feelings about, so we can cooperate on some things without having to agree on everything. &amp;nbsp;It's rarely perfect but we can usually get some good stuff done, with &lt;a href="https://en.wikipedia.org/wiki/Rough_consensus"&gt;rough consensus and running code&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Today though, there's a political issue which I can't ignore. &amp;nbsp;The purpose of &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted&lt;/a&gt; (the open source project which I founded) is to facilitate the transfer of information across the Internet. &amp;nbsp;A new law, &lt;a href="https://en.wikipedia.org/wiki/Stop_Online_Piracy_Act"&gt;SOPA&lt;/a&gt;, is threatening to radically alter the legal infrastructure of the Internet in the United States, granting sweeping new powers to copyright cartels and fundamentally restricting the legal right to transfer any information, and to build tools that transfer it. &amp;nbsp;Twisted is designed to make it easy to implement new protocols, to easily experiment with improvements to systems like the &lt;a href="http://www.plagiarismtoday.com/2011/11/15/dns-sopa-content-blocking-and-more/"&gt;Domain Name System&lt;/a&gt;. &amp;nbsp;SOPA might well make those potential improvements, and with only a little &lt;a href="http://www.svrowle.com/2011/11/when-even-googles-lawyers-are-worried-your-legislation-probably-sucks/"&gt;paranoid&lt;/a&gt; fantasizing, Twisted itself, illegal.&lt;br /&gt;
&lt;br /&gt;
It's my view that this law is a blatantly &lt;a href="http://www.net-coalition.com/wp-content/uploads/2011/08/tribe-legis-memo-on-SOPA-12-6-11-1.pdf"&gt;unconstitutional&lt;/a&gt;&amp;nbsp;restriction on free speech. &amp;nbsp;It will &lt;a href="http://boingboing.net/2011/12/14/kill-sopa-save-americas-int.html?amp"&gt;kill job creation&lt;/a&gt;, at a time when our nation can scarce afford another blow to its economy. &amp;nbsp;It will create the infrastructure to suppress political dissent, &lt;a href="http://advocacy.globalvoicesonline.org/2011/12/03/for-chinese-netizens-sopa-is-another-great-firewall/"&gt;similar to the infrastructure in China and Syria&lt;/a&gt;, at a time when our &lt;a href="http://rootstrikers.org/"&gt;corrupt&lt;/a&gt; political system needs dissent more than ever. &amp;nbsp;It is the wrong thing at the wrong time.&lt;br /&gt;
&lt;br /&gt;
This bill is being discussed in the house&amp;nbsp;&lt;i&gt;today&lt;/i&gt;. &amp;nbsp;If you're in the US, call your representative &lt;a href="http://americancensorship.org/modal/call-form.html"&gt;right now&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
(As always, I don't speak for anyone but myself; no one else has reviewed or endorsed these remarks.)&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/OQAKL9kOYMI" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/3423291996900484779?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/3423291996900484779?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/OQAKL9kOYMI/im-sorry-its-come-to-this.html" title="I'm Sorry It's Come To This" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><feedburner:origLink>http://glyph.twistedmatrix.com/2011/12/im-sorry-its-come-to-this.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AMR3kzcCp7ImA9WhRTFEg.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-4493860799690752323</id><published>2011-11-04T21:16:00.000-04:00</published><updated>2011-11-04T21:16:26.788-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-04T21:16:26.788-04:00</app:edited><title>Blocking vs. Running</title><content type="html">I've heard tell of some confusion lately around what the term "non-blocking" means. &amp;nbsp;This isn't the first time I've tried to explain it, and it certainly won't be the last, but blogging is easier than the job &lt;a href="http://en.wikipedia.org/wiki/Sisyphus"&gt;Sisyphus&lt;/a&gt;&amp;nbsp;got, so I can't complain.&lt;br /&gt;
&lt;br /&gt;
A thread is &lt;a href="http://j.mp/nuSjZk"&gt;blocking&lt;/a&gt;&amp;nbsp;when it is performing an &lt;em&gt;input or output operation&lt;/em&gt;&amp;nbsp;that may take an &lt;em&gt;unknown amount of time&lt;/em&gt;. &amp;nbsp;Crucially, a blocking thread is &lt;em&gt;doing no useful work&lt;/em&gt;. &amp;nbsp;It is stuck, consuming resources - in particular, its &lt;a href="http://stackoverflow.com/questions/2340093/how-is-stack-size-of-process-on-linux-related-to-pthread-fork-and-exec"&gt;thread stack&lt;/a&gt;, and its&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Process_table"&gt;process table&lt;/a&gt; entry. &amp;nbsp;It is sucking up resources and getting nothing done. &amp;nbsp;These are resources that one can most definitely &lt;a href="http://en.wikipedia.org/wiki/Fork_bomb"&gt;run out of&lt;/a&gt;, and are in fact &lt;a href="http://pubs.opengroup.org/onlinepubs/007904975/functions/getrlimit.html"&gt;artificially limited&lt;/a&gt; on most operating systems, because if one has too many of them, the system &lt;a href="http://oreilly.com/catalog/linuxkernel/chapter/ch10.html"&gt;bogs down&lt;/a&gt; and becomes unusable.&lt;br /&gt;
&lt;br /&gt;
A thread may also be "stuck" doing some computationally intensive work; performing a complex computation, and sucking up CPU cycles. &amp;nbsp;There is a very important distinction here, though. &amp;nbsp;If that thread is burning up CPU, it is &lt;em&gt;getting work done&lt;/em&gt;. &amp;nbsp;It is computing. &amp;nbsp;This is why we have computers: to compute things.&lt;br /&gt;
&lt;br /&gt;
It is of course possible for a program to have a bug where a program goes into an infinite loop, or otherwise performs work on the CPU without actually getting anything useful &lt;em&gt;to the user&lt;/em&gt;&amp;nbsp;done, but if that's happening then the program is just buggy, or inefficient. &amp;nbsp;But such a program is not &lt;em&gt;blocking&lt;/em&gt;: it might be "thrashing" or "stuck" or "broken", but "blocking" means something more specific: that the program is sitting around, doing nothing, while it is &lt;i&gt;waiting for some other thing&lt;/i&gt; to get work done, and not doing any of its own.&lt;br /&gt;
&lt;br /&gt;
A program written in an event-driven style may be busy as long as it needs to be, but that does not mean it is &lt;i&gt;blocking&lt;/i&gt;. &amp;nbsp;Hence, &lt;i&gt;event-driven&lt;/i&gt; and &lt;i&gt;non-blocking&lt;/i&gt;&amp;nbsp;are synonyms.&lt;br /&gt;
&lt;br /&gt;
Furthermore, &lt;i&gt;non-blocking&lt;/i&gt; doesn't necessarily mean &lt;i&gt;single-process&lt;/i&gt;. &amp;nbsp;&lt;a href="http://twistedmatrix.com/"&gt;Twisted&lt;/a&gt;&amp;nbsp;is non-blocking, for example, but it has a sophisticated facility for &lt;a href="http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IReactorProcess.spawnProcess.html"&gt;starting, controlling and stopping other processes&lt;/a&gt;. &amp;nbsp;Information about changes to those processes is represented as plain old events, making it reasonably easy to fold the results of computation in another process back into the main one.&lt;br /&gt;
&lt;br /&gt;
If you need to perform a lengthy&amp;nbsp;&lt;a href="http://teddziuba.com/2011/10/node-js-is-cancer.html"&gt;computation&lt;/a&gt;&amp;nbsp;in an event-driven program, that does &lt;a href="http://corbinsimpson.com/entry/posion-was-the-cure"&gt;not&lt;/a&gt; mean you need to stop the world in order to do it. &amp;nbsp;It doesn't mean that you need to give up on the relatively simple execution model of an event loop for a mess of threads, either. &amp;nbsp;Just ask another process to do the work, and handle the result of that work as just another event.&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/0vDUkrm6JHE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/4493860799690752323/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=4493860799690752323" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/4493860799690752323?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/4493860799690752323?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/0vDUkrm6JHE/blocking-vs-running.html" title="Blocking vs. Running" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>9</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2011/11/blocking-vs-running.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUHQn85eCp7ImA9WhdVGE4.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-4828541273833625392</id><published>2011-09-10T02:05:00.003-04:00</published><updated>2011-09-23T23:00:33.120-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T23:00:33.120-04:00</app:edited><title>2L2T: DjangoCon Feedback</title><content type="html">I've been having a great time over here at &lt;a href="http://djangocon.us/"&gt;DjangoCon&lt;/a&gt;, but now that I've had an opportunity to relax and process some feedback from my talk, I have noticed a couple of themes to that feedback. &amp;nbsp;This isn't really a full article, just a response, but it's too long to tweet. &amp;nbsp;If you're curious about the talk, I believe it will be showing up on blip.tv under &lt;a href="http://blip.tv/djangocon"&gt;http://blip.tv/djangocon&lt;/a&gt; somewhere next week. &amp;nbsp;(I'll try to remember to update this post when it's available.)&lt;br /&gt;
For the most part, the talk was exceedingly well-received and I want to thank the Django community both for the opportunity to speak and for the overwhelmingly positively response. &amp;nbsp;Thanks for making an outsider to your community feel welcome and appreciated.&lt;br /&gt;
There have been a couple misconceptions though, and perhaps I didn't express myself clearly on a few points.&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;I realize that there are times – plenty of times, even – when using some component that's in a different language from your main application is the right choice. &amp;nbsp;I wasn't trying to say "all Python all the time no matter what, no exceptions". &amp;nbsp;I just want you all to consider that &lt;em&gt;there is a cost&lt;/em&gt;&amp;nbsp;to using a component that's in a different language, and you should be aware of that cost. &amp;nbsp;It's not as simple as a tick-a-box feature comparison of the features and drawbacks of multiple products. &amp;nbsp;If I came out as sounding really extreme on this, it just was to provoke a response.&lt;/li&gt;
&lt;li&gt;You can have an architecture which is driven by Python and organized by Python without actually having all the implementation &lt;em&gt;be&lt;/em&gt;&amp;nbsp;in Python. &amp;nbsp;For example, an inordinate number of people asked me about memcache. &amp;nbsp;If you want using something like that, sure, use memcache, there's not a lot that it being in Python would buy you. &amp;nbsp;Some might say that the whole point of memcache is that it &lt;em&gt;isn't&lt;/em&gt;&amp;nbsp;very deeply configurable and doesn't have much in the way of behavior. &amp;nbsp;Plus, it's an internal component, not an externally visible service, so even my usual flimsy "no buffer overflows" argument doesn't really hold up; it's more like a library than a server.&amp;nbsp; You can incorporate memcache into a Python-in-the-driver's-seat architecture by spawning memcache from your Python process&amp;nbsp;instead of making memcache a configuration dependency. &amp;nbsp;That way,&amp;nbsp;you don't need a separate configuration file and a separately managed service or a chef script that boots memcache for you before your application. &amp;nbsp;This applies equally well to any other, similar services: write their config files from your Python code, and start them automatically.&lt;/li&gt;
&lt;/ol&gt;Finally, thanks to everyone who really thought about what I said, took the time to respond, and prompted me to write this.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt;&amp;nbsp;The &lt;a href="http://blip.tv/djangocon/keynote-glyph-lefkowitz-5573264"&gt;video of my talk is now available&lt;/a&gt; on blip.tv.&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/f-WP6I1K9cI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/4828541273833625392/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=4828541273833625392" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/4828541273833625392?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/4828541273833625392?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/f-WP6I1K9cI/2l2t-djangocon-feedback.html" title="2L2T: DjangoCon Feedback" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2011/09/2l2t-djangocon-feedback.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04HSHk5fyp7ImA9WhdUGEQ.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-8020811463903910585</id><published>2011-06-19T22:43:00.002-04:00</published><updated>2011-10-06T06:12:19.727-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-06T06:12:19.727-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="r0ml" /><title>ἁγιολογία for r0ml</title><content type="html">I have the rare distinction of being a &lt;a href="http://c2.com/cgi/wiki?SecondGenerationProgrammer"&gt;second-generation software developer&lt;/a&gt;. &amp;nbsp;Most recently, &lt;a href="http://thechangelog.com/post/5160421440/episode-0-5-8-twisted-with-glyph-lefkowitz"&gt;I mentioned this in an interview&lt;/a&gt;&amp;nbsp;when asked who my programming heroes are. &amp;nbsp;It might sound kind of corny, but I'm serious when I say that my father is my programming hero.&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;a href="http://www.flickr.com/photos/x180/202613524/" title="Robert &amp;quot;r0ml&amp;quot; Lefkowitz by duncandavidson, on Flickr"&gt;&lt;img alt="Robert &amp;quot;r0ml&amp;quot; Lefkowitz" height="332" src="http://farm1.static.flickr.com/62/202613524_9c0153f7da.jpg" width="500" /&gt;&lt;/a&gt;&lt;/div&gt;My dad had a cool hacker alias in the&amp;nbsp;&lt;em&gt;&lt;a href="http://dadsaretheoriginalhipster.tumblr.com/"&gt;seventies&lt;/a&gt;&lt;/em&gt;. &amp;nbsp;He's been known as "r0ml" around the web since &lt;em&gt;before there was a web.&amp;nbsp;&lt;/em&gt;If you are in a particularly typographically hip part of the internet, it might even be "RØML". &amp;nbsp;How many of your parents have a nom de plume with a digit, or a non-ASCII character in it? &amp;nbsp;Or, for that matter, any kind of hacker pseudonym?&lt;br /&gt;
I had the good fortune to work with one of r0ml's colleagues, Amir Bakhtiar. &amp;nbsp;Amir paid me one of the highest compliments I've ever received: he said that the code for systems I've worked on is similar to r0ml's in its style and exposition. &amp;nbsp;My dad taught me how to program in x86 assembler, and in that process, I learned a lot about the way he thought about solving problems and building systems. &amp;nbsp;I regard thinking that well, or even comparably well, as a real achievement.&lt;br /&gt;
That's not to say that I would do everything exactly the way that he does. &amp;nbsp;For example, he writes a lot of networking code in Java. &amp;nbsp;He doesn't use Twisted, for the most part. &amp;nbsp;If you know me and you know my dad, you know that we disagree on plenty of stuff.&lt;br /&gt;
Unlike the stereotypical,&amp;nbsp;often-satirized filial argument, these discussions are something I look forward to. &amp;nbsp;Disagreeing with my dad is still one of the most intellectually challenging activities I've ever engaged in. &amp;nbsp;Whenever I have a conversation with him about a topic where he has a different view, I come away enlightened – if not necessarily convinced.&lt;br /&gt;
Conversations among my friends occasionally turn to the topic of our respective upbringings, as they do in any close group. &amp;nbsp;One of the recurring themes of my childhood is that, while my siblings and I were sometimes told to be quiet, we were never told to be quiet because our opinions weren't valuable. &amp;nbsp;Sometimes we were told in unequivocal terms that we were&amp;nbsp;&lt;em&gt;wrong&lt;/em&gt;, of course. &amp;nbsp;However, my dad always encouraged us to present our thoughts. &amp;nbsp;Then, he wouldn't pull any punches in relentlessly refuting our arguments, using a combination of facts, estimates, calculations, and rhetorical flourishes. &amp;nbsp;I learned more about influencing people and thinking clearly around the dinner table than in my entire formal education.&lt;br /&gt;
r0ml always questions glib answers, challenges the official version of events, distrusts things that are "intuitively obvious" or "common sense". &amp;nbsp;The skepticism I've developed as a result of his consistent example has rarely led me astray. &amp;nbsp;Glib answers, official versions, and common sense are frequently, if not always, wrong. &amp;nbsp;He taught me to search for the non-intuitive answer, the surprising inflection point in the data.&lt;br /&gt;
In a roundabout way, he also taught my siblings and I how to perform some delightful rhetorical flourishes of our own, but also not to trust them. &amp;nbsp;Pretty phrases can be deployed equally effectively in the service of illustration or deception. &amp;nbsp;Although I can appreciate that parents often come to a point where they've &lt;a href="http://en.wikipedia.org/wiki/Go_the_Fuck_to_Sleep"&gt;had enough&lt;/a&gt; and a little deception can be a useful thing.&lt;br /&gt;
One cannot be a practiced rhetorician without a heaping helping of eclectic life experience; r0ml has that too. &amp;nbsp;He's a fencer. &amp;nbsp;And a&amp;nbsp;&lt;a href="http://www.natuba.com/photo/Zfgs2j/"&gt;juggler&lt;/a&gt;. &amp;nbsp;He still has the highest score on &lt;a href="http://en.wikipedia.org/wiki/Space_Harrier"&gt;Space Harrier&lt;/a&gt; of anyone I've ever met. &amp;nbsp;(I can remember a crowd gathering in an arcade to see him start level 18.) &amp;nbsp;He's an avid scholar of medieval thought and custom. &amp;nbsp;For that matter, he's an avid scholar of a couple dozen other things, but listing them all would take a whole day.&lt;br /&gt;
He has the common occupational affliction of being a science fiction fan. &amp;nbsp;However, fandom was never an identity for him. Again, by consistent example, he taught me to focus on my own creativity, and do something cool, never to just passively consume others' ideas. &amp;nbsp;He treats entertainment as an inspiration, rather than an escape. &amp;nbsp;For instance, one of the earliest memories I have about my father talking about software is&amp;nbsp;a reference to the movie "Terminator". &amp;nbsp;(Please keep in mind that this memory is ~20 years old at this point, so it might not be terribly accurate.) &amp;nbsp;I remember him saying something like "All software should be relentless. &amp;nbsp;If you remove its legs, it should use its arms. &amp;nbsp;Whatever errors it encounters, it should deal with them, and keep going if it can."&lt;br /&gt;
Nevertheless, seeing&amp;nbsp;"Tron: Legacy" with my dad, the hacker, in IMAX 3D, 20 years after we saw the original together... I didn't need to take a life lesson from that to think it was pretty rad[1].&lt;br /&gt;
Unlike many quiet geniuses who labor in obscurity, dispensing wisdom only to a fortunate few, r0ml is a somewhat notorious public speaker. &amp;nbsp;You&amp;nbsp;can &lt;a href="http://www.oscon.com/oscon2011/public/schedule/speaker/6635"&gt;see him this year at OSCON&lt;/a&gt;. &amp;nbsp;If you hunt around the web, you can find some video examples of his previous talks, &lt;a href="http://www.viddler.com/explore/GreggPollack/videos/2/840/Robert%20'r0ml'%20Lefkowitz"&gt;like this great 30-second interview&lt;/a&gt;[2]&amp;nbsp;about the nature of open source process, from a talk he gave in 2008 (&lt;a href="http://itc.conversationsnetwork.org/shows/detail3995.html"&gt;audio of the full talk here&lt;/a&gt;).&lt;br /&gt;
([1]: Although, jeez, what was the point of that whole open-source subplot at the beginning? &amp;nbsp;It seemed like a great idea, but then it went absolutely nowhere!)&lt;br /&gt;
([2]: Speaking of not doing things exactly the way he does - where&amp;nbsp;he uses a metaphor to "single-threading" and "multi-threading", I would have said "blocking" and "event-driven" - but more on that in a future post.)&lt;br /&gt;
Happy Father's Day, r0ml.&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/caozdw4MAy8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/8020811463903910585/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=8020811463903910585" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/8020811463903910585?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/8020811463903910585?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/caozdw4MAy8/blog-post.html" title="ἁγιολογία for r0ml" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm1.static.flickr.com/62/202613524_9c0153f7da_t.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2011/06/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4NSHc-eip7ImA9WhZSF08.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-891913984768859236</id><published>2011-04-02T01:09:00.000-04:00</published><updated>2011-04-02T01:09:59.952-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-02T01:09:59.952-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="lulz" /><category scheme="http://www.blogger.com/atom/ns#" term="tls" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><category scheme="http://www.blogger.com/atom/ns#" term="vertex" /><title>Calling all Ascetic Buddhist Rock Musicians</title><content type="html">&lt;h3&gt;The Presentation&lt;/h3&gt;The inimitable &lt;a href="http://www.zooko.com/"&gt;Zooko&lt;/a&gt; recently &lt;a href="http://twitter.com/#!/zooko/status/52583456814809088"&gt;made me aware&lt;/a&gt; of &lt;a href="https://docs.google.com/present/view?id=df9sn445_206ff3kn9gs&amp;amp;pli=1"&gt;an excellent presentation about HTTPS: "It's Time to Fix HTTPS"&lt;/a&gt;, by &lt;a href="http://noncombatant.org/"&gt;Chris Palmer&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The presentation is both hilarious and illuminating; I highly recommend you view it right away. &amp;nbsp;It's not saying anything that I haven't been thinking for a &lt;a href="http://bazaar.launchpad.net/~divmod-dev/divmod.org/trunk/files/head:/Vertex/"&gt;very long time&lt;/a&gt;. &amp;nbsp;Except the thing about how IE can silently add certificates to your root CA store, that was definitely new, and a little depressing. &amp;nbsp;But this is a somewhat esoteric topic and it needs to be made more popular for the everyday user. &amp;nbsp;Sexy, even.&lt;br /&gt;
&lt;h3&gt;A Brief Review&lt;/h3&gt;(But seriously, &lt;a href="https://docs.google.com/present/view?id=df9sn445_206ff3kn9gs&amp;amp;pli=1"&gt;go read the slides&lt;/a&gt;, they're more entertaining.)&lt;br /&gt;
&lt;br /&gt;
Internet security is based on trust. &amp;nbsp;The math behind modern cryptography doesn't ensure anything beyond that you're talking to someone that holds a particular special secret ("private key"). &amp;nbsp;You can verify that the party you're talking to has the same key as the one you talked to last time, and that a particular private key corresponds to a particular &lt;em&gt;public&lt;/em&gt; key, but that's about it. &amp;nbsp;The public key can be published for everyone to see without risking any of the secrets being sent, but you still need some way to determine whether the public key actually belongs to the person you want to talk to. &amp;nbsp;So, in order to have a secure system, you have to layer some rules on top of that which give you some way to know whether that private key corresponds to an identity that you care about and trust.&lt;br /&gt;
&lt;br /&gt;
The current system goes something like this: each web browser vendor decides, more or less at random, on a group of entities we will all trust completely. &amp;nbsp;By virtue of the trust of the software, they become the authorities who can decide whose public keys are valid. &amp;nbsp;Actually, a public key isn't quite enough: you need a key plus some metadata about the person sending it: we call this a "certificate". &amp;nbsp;So these entities are termed "certificate authorities". &amp;nbsp;The browser vendors tend to decide on the same group, because there's a lot of social pressure to maintain a list that makes sense (and also, anybody who gets accepted by one browser but denied by another can't really sell certificates: the whole point of this exercise is to sell things that make the little lock icon come up, so you know your web shopping cart is "secure").&lt;br /&gt;
&lt;br /&gt;
The problem with this system is that almost all of these "completely trustworthy" entities are enormous companies or, &lt;a href="http://www.freedom-to-tinker.com/blog/felten/mozilla-debates-whether-trust-chinese-ca"&gt;possibly even foreign governments&lt;/a&gt;, which have diverse motivations and huge amounts of legitimate business to conduct, making it very hard to spot a small amount of malfeasance. &amp;nbsp;(Although there is &lt;em&gt;some&lt;/em&gt; good news: people do notice, and they &lt;a href="https://blog.torproject.org/blog/detecting-certificate-authority-compromises-and-web-browser-collusion"&gt;freak the hell out&lt;/a&gt; when they do; so at least there's some policing of the current system.) &amp;nbsp;One compromised certificate authority (and there are &lt;a href="http://www.mozilla.org/projects/security/certs/included/"&gt;lots and lots&lt;/a&gt; to try and compromise) means a complete "game over" for everybody who uses a web browser and trusts the little lock icon.&lt;br /&gt;
&lt;br /&gt;
Basically there's no such thing as "completely trustworthy". &amp;nbsp;There's only: do I trust &lt;em&gt;you&lt;/em&gt;.&lt;br /&gt;
&lt;h3&gt;The Next Step&lt;/h3&gt;The solution that Mr. Palmer proposes is extremely similar to the one which I thought I originally devised in about 2004, but probably was floating around in the security zeitgeist even before that. &amp;nbsp;It's a combination of 3 general principles:&lt;br /&gt;
&lt;h3&gt;Trust On First Use&lt;/h3&gt;Basically, the first time I see you, on the internet, it's unlikely that you're trying to trick me. &amp;nbsp;So you can give me any old public key, and I'll accept that it's you.&lt;br /&gt;
&lt;br /&gt;
Mr. Palmer gives this one a catchy pseudoym, "TOFU", which I quite like (and I guess is pretty widely known at this point).&lt;br /&gt;
&lt;h3&gt;Persistence Of Pseudonym&lt;/h3&gt;The important point is that then I &lt;em&gt;remember&lt;/em&gt; that it's you, forever, so it's very hard to attack our communications after that point.&lt;br /&gt;
&lt;br /&gt;
I'll come up with a name for you (let's say "Bob Smith" or "The Most Secure Bank In The World Dot Com"), and my software will make sure that it sticks to that public key. &amp;nbsp;You can potentially tell me that your key has changed, but you'd better be prepared to present your old key, otherwise I have to get re-introduced to you, and now I'm suspicious that something may have been fishy. &amp;nbsp;Especially if some other thing shows up and say "Hi, it's Bob Smith" (with the correct, old public key) - "Hey, who's this guy?"&lt;br /&gt;
&lt;br /&gt;
This is referred to as "POP". &amp;nbsp;Also pretty catchy.&lt;br /&gt;
&lt;h3&gt;Mesh Overlay Network Keysigning&lt;/h3&gt;The third concept Mr. Palmer refers to as a "trustiness metric" which includes "perspectives", and says "You can't fool all of the people all of the time". &amp;nbsp;He includes some other stuff in his trustiness metric here, but I'm going to extrapolate from that sentence:&lt;br /&gt;
&lt;br /&gt;
It's really, really easy to &lt;a href="http://codebutler.com/firesheep"&gt;sit down in a café and intercept some of my network traffic&lt;/a&gt;. &amp;nbsp;It takes about 2 minutes to collect a dozen passwords this way, on today's mostly-not-encrypted internet. &amp;nbsp;So it would be very&amp;nbsp;&amp;nbsp;easy for someone to break this system if all you had was a little re-introduction warning; users might not understand it and just click anyway, and then it's just as broken (if not worse) than the current model; at least in the current model, normal users don't usually get those warnings, and they're "safe" if they're looking for the lock, but in this new model, users would get them for all new secure introductions. &amp;nbsp;So we need something better.&lt;br /&gt;
It's not so easy to sit down in a café and intercept network traffic from me and also intercept traffic from my friend, on a different network, doing a different thing. &amp;nbsp;You have to know where my friend is. &amp;nbsp;You have to be able to intercept our pre-arranged secure communication (I already remember all my friends keys when I first see them, you'll recall). &amp;nbsp;If you're a casual attacker who just wants to sniff a couple of credit card numbers at the local starbucks, you probably don't have the resources to do that, even for a single individual.&lt;br /&gt;
&lt;br /&gt;
It is definitely not easy to figure out where every single one of my currently-online friends - let's say Facebook friends, because you can&amp;nbsp;&lt;a href="https://www.facebook.com/blog.php?post=486790652130"&gt;maybe they finally care about security now&lt;/a&gt;&amp;nbsp;- is online from, and also attack their networks simultaneously, to provide exactly the same bogus first-introduction certificate to Super Secure Bank Dot Com. &amp;nbsp;This is a level of sophistication and coordination that not even most governments can muster.&lt;br /&gt;
&lt;br /&gt;
So if we had a reasonably available &lt;a href="http://en.wikipedia.org/wiki/Mesh_networking"&gt;mesh&lt;/a&gt;&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Overlay_network"&gt;overlay network&lt;/a&gt;, where I can tell my friends, and my friends can tell their friends (etc forever) about first-introduction key correspondence with DNS names, and legitimate changes to keys where the site operator has had a security problem, then we could address many of these issues much more robustly than we can today. &amp;nbsp;It might not be perfect, but it would silently work often enough that it would be much better than today's default of "bah, I don't know why you're getting the browser warning; just use HTTP".&lt;br /&gt;
&lt;h3&gt;Badump Ching&lt;/h3&gt;If you've been paying attention I think you can see where I am going with this.&lt;br /&gt;
&lt;br /&gt;
We (those of us in the open source hipster security noosphere) need to popularize this concept, because it's not that hard to implement, people keep re-inventing it everywhere, it's mostly just about getting some browser vendor to think it's a good idea.&lt;br /&gt;
&lt;br /&gt;
The acronym is TOFU POP MONK, so clearly we need a vegetarian monk - buddhist seems most likely - who sings pop songs about how great tofu is. &amp;nbsp;We need it to go viral on the you tubes, and any other tubes that are appropriate.&lt;br /&gt;
&lt;br /&gt;
(Graphic design nerds, and&amp;nbsp;&lt;a href="http://www.zefrank.com/theshow/"&gt;sports racers&lt;/a&gt;&amp;nbsp;of all stripes, start your engines. &amp;nbsp;I challenge you. &amp;nbsp;Show me some &lt;i&gt;awesome&lt;/i&gt;&amp;nbsp;macroable meme images starring the Tofu-Pop Monk. &amp;nbsp;I will post any particularly compelling ones here.)&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/94ZaGpKGaEQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/891913984768859236/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=891913984768859236" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/891913984768859236?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/891913984768859236?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/94ZaGpKGaEQ/calling-all-ascetic-buddhist-rock.html" title="Calling all Ascetic Buddhist Rock Musicians" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2011/04/calling-all-ascetic-buddhist-rock.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMBQ38-eyp7ImA9Wx9SFEs.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-7691015725038541184</id><published>2010-12-04T06:00:00.000-05:00</published><updated>2010-12-04T06:00:52.153-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-04T06:00:52.153-05:00</app:edited><title>Resolving diverged Bazaar branches on the go with 'dead heads'.</title><content type="html">If you're like me, occasionally you grab the latest version of a bzr branch onto your laptop before you're going somewhere without network access. But, as you're about to leave, you glance over at your laptop screen, and you see the dreaded:&lt;br /&gt;
&lt;pre&gt;bzr: ERROR: These branches have diverged. Use the missing command to see how.
Use the merge command to reconcile them.&lt;/pre&gt;but you don't have time to do a merge, and wait for the (reliably agonizingly slow) network round trip to negotiate with the server about what the latest revision is - the train's about to leave, or you're late for your flight, or the cafe is closing and you need to shut your laptop right now. &amp;nbsp;Sadness! &amp;nbsp;You continue to work on a diverged branch and merge later. &amp;nbsp;Which is a shame, because mechanically dealing with merge conflicts or just making sure the tests still pass after what looks like a trivial merge is &lt;em&gt;exactly&lt;/em&gt;&amp;nbsp;the sort of thing which is convenient to do when you're stuck waiting at a network-access-free bus stop.&lt;br /&gt;
As it turns out, Bazaar has actually already done all the hard work necessary for you to just go ahead and do that merge when you get to your potentially non-networked destination. &amp;nbsp;The diverged revisions have already been pulled into your branch and are just sitting there, waiting to be merged, but you can't see them. &amp;nbsp;The 'bzrtools' plugin provides the 'heads' command, which you can use to reveal the previously invisible revision. &amp;nbsp;You can then just 'merge .' instead of merging from your usual pull location, as long as you specify the appropriate revision.&lt;br /&gt;
To demonstrate, here's a transcript of a sample session which simulates this common problem:&lt;br /&gt;
First, set up a branch:&lt;br /&gt;
&lt;pre&gt;you@computer:~$ mkdir tmp
you@computer:~$ cd tmp
you@computer:~/tmp$ mkdir a
you@computer:~/tmp$ cd a
you@computer:~/tmp/a$ bzr init
Created a standalone tree (format: 2a)
you@computer:~/tmp/a$ touch initial.txt
you@computer:~/tmp/a$ bzr add
adding initial.txt
you@computer:~/tmp/a$ bzr ci -m "inital revision"
Committing to: /Domicile/glyph/tmp/a/
added initial.txt
Committed revision 1.&lt;/pre&gt;We'll call 'a' the 'server' branch.  Next, let's make a branch that represents the 'on the go' branch, your local working copy:&lt;br /&gt;
&lt;pre&gt;you@computer:~/tmp/a$ cd ..
you@computer:~/tmp$ bzr get a b
Branched 1 revision(s).&lt;/pre&gt;Now, it's time to diverge.  Let's give each branch its own revision.&lt;br /&gt;
&lt;pre&gt;you@computer:~/tmp$ cd a
you@computer:~/tmp/a$ touch a.txt
you@computer:~/tmp/a$ bzr add
badding a.txt
zyou@computer:~/tmp/a$ bzr ci -m 'revision from a'
Committing to: /Domicile/glyph/tmp/a/
added a.txt
Committed revision 2.
you@computer:~/tmp/a$ cd ../b/
you@computer:~/tmp/b$ touch b.txt
you@computer:~/tmp/b$ bzr add
adding b.txt
you@computer:~/tmp/b$ bzr ci -m 'revision from b'
Committing to: /Domicile/glyph/tmp/b/
added b.txt
Committed revision 2.&lt;/pre&gt;Now, it's time to get on that sad, wifi-free train.  Let's make sure we're up to date with 'a' first...&lt;br /&gt;
&lt;pre&gt;you@computer:~/tmp/b$ bzr pull ../a
bzr: ERROR: These branches have diverged. Use the missing command to see how.
Use the merge command to reconcile them.
[Error: 3]&lt;/pre&gt;Oh no!  But, here comes 'bzr heads' to the rescue:&lt;br /&gt;
&lt;pre&gt;you@computer:~/tmp/b$ bzr heads --dead
HEAD: revision-id: &amp;lt;strong&amp;gt;you@computer-123456&amp;lt;/strong&amp;gt; (dead)
committer: You &amp;lt;you@computer&amp;gt;
branch nick: a
timestamp: now-ish
message:
revision from a&lt;/pre&gt;Now you know what the revision ID of the already-pulled-but-not-visible revision is - the tip of 'a', in other words.  Now you just need to ask 'b' to merge it:&lt;br /&gt;
&lt;pre&gt;you@computer:~/tmp/b$ bzr merge . -r &amp;lt;strong&amp;gt;you@computer-123456&amp;lt;/strong&amp;gt;
+N  a.txt
All changes applied successfully.
you@computer:~/tmp/b$ bzr ci -m 'merge from a'
Committing to: /Domicile/glyph/tmp/b/
added a.txt
Committed revision 3.&lt;/pre&gt;Done!  And, as you can see when you get back to your cozy 10gigE fiber connection at home, or whatever you happen to have, you see that the revision you've merged lines up neatly with 'a':&lt;br /&gt;
&lt;pre&gt;you@computer:~/tmp/b$ bzr pull ../a
No revisions to pull.
you@computer:~/tmp/b$&lt;/pre&gt;Et voila.  I hope this saves somebody some time when dealing with failed pulls.&lt;br /&gt;
For those of you who may be curious about the use-case, if you don't have it: I rarely encounter this with actual codebases I work on, as I tend to have a local trunk mirror, and features are neatly segregated into branches.  It comes up more frequently in my personal configuration-files repository, where I make little changes to my desktop, little changes to my laptop, and then want to get out the door quickly with the latest merged copy.  I was so happy when #bzr on freenode (thanks, spiv!) solved this problem for me that I just had to share.&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/5zRwKkdKjsA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/7691015725038541184/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=7691015725038541184" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7691015725038541184?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7691015725038541184?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/5zRwKkdKjsA/resolving-diverged-bazaar-branches-on.html" title="Resolving diverged Bazaar branches on the go with &amp;#39;dead heads&amp;#39;." /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2010/12/resolving-diverged-bazaar-branches-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMBRXo7fSp7ImA9WxBRGE4.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-7383323720467782084</id><published>2010-01-06T23:10:00.001-05:00</published><updated>2010-01-06T23:10:54.405-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-06T23:10:54.405-05:00</app:edited><title>Some Common Onomatological Errors</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;The open-source event-driven networking engine that I work on is called "&lt;a href='http://en.wikipedia.org/wiki/Twisted_%28software%29'&gt;Twisted&lt;/a&gt;".  If you're uncomfortable using something that sounds like an adjective in a place where a noun should go, the following noun phrases are equivalent:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;the Twisted project&lt;/li&gt;&lt;li&gt;the Twisted engine&lt;/li&gt;&lt;li&gt;the Twisted networking engine&lt;br/&gt;&lt;/li&gt;&lt;li&gt;the Twisted framework&lt;/li&gt;&lt;/ol&gt;The unofficial group (of which I am a member) which works on that software is known as "Twisted Matrix Laboratories", sometimes shortened to "Twisted Matrix Labs" or "TMLabs".&lt;br/&gt;&lt;br/&gt;I can understand that there is some confusion around this stuff, since these words often appear in close proximity, but to my knowledge there is nothing called "Python Twisted", "Twisted Python", or "Twisted Matrix".  There's "python-twisted", which is the &lt;a href='http://www.debian.org/distrib/packages'&gt;package&lt;/a&gt; name that some operating systems use to package Twisted.  There is also "twisted.python", which is a python  &lt;a href='http://docs.python.org/tutorial/modules.html#packages'&gt;package&lt;/a&gt; within Twisted itself.  Finally there is "twisted-python@twistedmatrix.com", which is the mailing list for discussing Twisted stuff in the Python programming language.  (This discussion list is so named to distinguish it from the possibility of not-quite-&lt;a href='http://bazaar.launchpad.net/%7Eglyph/%2Bjunk/amphacks/annotate/head%3A/java/src/com/twistedmatrix/internet/Reactor.java'&gt;hypothetical&lt;/a&gt; discussion of Twisted implemented in &lt;a href='http://mochikit.com/doc/html/MochiKit/Async.html'&gt;other languages&lt;/a&gt;, although no other implementations are currently actively maintained.)&lt;br/&gt;&lt;br/&gt;I just thought you'd all like to know that.  That is all.  (For now, anyway.)&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=1638b72c-fd68-85ab-b77a-33039a8a0942' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/l29ayJeOirY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/7383323720467782084/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=7383323720467782084" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7383323720467782084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7383323720467782084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/l29ayJeOirY/some-common-onomatological-errors.html" title="Some Common Onomatological Errors" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>4</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2010/01/some-common-onomatological-errors.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QGR3g5eSp7ImA9WxNVE0o.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-6411330827513725269</id><published>2009-10-24T04:02:00.000-04:00</published><updated>2009-10-24T04:02:06.621-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-24T04:02:06.621-04:00</app:edited><title>Learn Twisted</title><content type="html">&lt;a href="http://jcalderone.livejournal.com/51697.html"&gt;Jean-Paul Calderone continues&lt;/a&gt; his excellent "&lt;a href="http://jcalderone.livejournal.com/50562.html"&gt;Twisted Web In 60 Seconds&lt;/a&gt;" tutorial series. &amp;nbsp;If you haven't checked it out yet, you should!&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/L2iEhCwp5gE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/6411330827513725269/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=6411330827513725269" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/6411330827513725269?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/6411330827513725269?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/L2iEhCwp5gE/learn-twisted.html" title="Learn Twisted" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/10/learn-twisted.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cHSX04eyp7ImA9WxNVE0g.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-8212287773632886857</id><published>2009-10-24T00:37:00.000-04:00</published><updated>2009-10-24T00:37:18.333-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-24T00:37:18.333-04:00</app:edited><title>Do you want WiFi to work at your conference?</title><content type="html">&lt;a href="http://www.blogger.com/"&gt;&lt;/a&gt;&lt;span id="goog_1256358333276"&gt;&lt;/span&gt;&lt;span id="goog_1256358333277"&gt;&lt;/span&gt;I've been pretty busy for the last couple of weeks, so I've just had an opportunity to catch up with blog posts that have been piling up. &amp;nbsp;In particular I noticed this one:&amp;nbsp;&lt;a href="http://www.joelonsoftware.com/items/2009/10/08.html"&gt;The “WiFi At Conferences” Problem&lt;/a&gt;, by Joel Spolsky.&lt;br /&gt;
&lt;br /&gt;
Joel has a lot of what look like good recommendations. &amp;nbsp;However, I can provide a much-abridged list.&lt;br /&gt;
&lt;br /&gt;
Some years, WiFi access at &lt;a href="http://us.pycon.org/"&gt;PyCon US&lt;/a&gt; has been provided by the venue, or by a contractor whose name I mercifully do not know. &amp;nbsp;Those years, it has not worked. &amp;nbsp;Some years, it has been provided, or at least managed, by &lt;a href="http://tummy.com/"&gt;tummy.com&lt;/a&gt;. &amp;nbsp;Those years, it has worked. &amp;nbsp;They are probably much more critical of their own efforts than I am, as you can see in &lt;a href="http://www.tummy.com/Community/Articles/pycon2008-network/"&gt;this thorough write-up that they did of PyCon's 2008 WiFi situation&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
My two-step plan for you if you want your conference to have working WiFi access at your conference is:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;e-mail somebody at &lt;a href="http://tummy.com/"&gt;tummy.com&lt;/a&gt;, telling them that you want a working wireless network, and&lt;/li&gt;
&lt;li&gt;give them whatever they ask for.&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;If you do these things, then when people open their laptops at your conference, their networks will work.&lt;br /&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/J_REV3A6rHo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/8212287773632886857/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=8212287773632886857" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/8212287773632886857?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/8212287773632886857?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/J_REV3A6rHo/do-you-want-wifi-to-work-at-your.html" title="Do you want WiFi to work at your conference?" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/10/do-you-want-wifi-to-work-at-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQCRXg7fSp7ImA9WxNXFkg.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-65940598180596469</id><published>2009-10-04T07:38:00.001-04:00</published><updated>2009-10-04T07:39:24.605-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-04T07:39:24.605-04:00</app:edited><title>Hobgoblin History</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I like &lt;a href='http://jon.es/terry.html'&gt;Terry Jones&lt;/a&gt;; I think &lt;a href='http://fluidinfo.com/fluiddb'&gt;FluidDB&lt;/a&gt; has a lot of potential.  But, sometimes when he's talking about it, he gets a little carried away and forgets that the rest of us don't live in his future yet.  In his latest missive on the official &lt;a href='http://blogs.fluidinfo.com/fluidDB/'&gt;FluidDB blog&lt;/a&gt;, "&lt;a href='http://blogs.fluidinfo.com/fluidDB/2009/10/04/digital-hobgoblins/'&gt;Digital Hobgoblins&lt;/a&gt;", he describes some of the problems that FluidDB sets out to solve.&lt;br/&gt;&lt;br/&gt;The problem is, I already have solutions for all of these problems, and I don't quite understand why they don't (or shouldn't) work for me.  (Since he organizes the post in terms of problems that existing systems have, I'm going to take the liberty of re-labeling these in terms of the problems that he seems to be describing rather than the lead text he used.  Please post a comment if you think my labeling is wrong.)&lt;br/&gt;&lt;br/&gt;In existing systems, Terry says:&lt;br/&gt;&lt;br/&gt;"&lt;b&gt;Things must be named, and have one name&lt;/b&gt;."  Specifically, Terry calls out file systems.  Except... file systems have lots of ways of introducing multiple names for the same thing.  Symbolic links.  Hard links, if you really want to allow for ambiguity.  If you want to track that ambiguity, Windows "shortcuts" and MacOS "aliases" can do that.  Overlay mounts, loopback mounts and chroot execution allow for semi-arbitrary renaming.  Lots of other systems support this, too.  Database systems have a specific provision for multiple names: the many-to-one relation.  Any programming language with pass-by-reference data structures allows for some level of multiple-naming.  In fact, there's a whole discipline for allowing things to have lots of different names: indexing.  Anywhere you have a full-text index or an object where multiple attributes are indexed in some kind of database, you've got objects with more than one name.&lt;br/&gt;&lt;br/&gt;"&lt;b&gt;You have to be consistent and unambiguous.&lt;/b&gt;"  As I mentioned on the first point, there are lots of ways to be slightly ambiguous at a human level.  You can refer to the same thing by different names, or, with mutable binding, you can refer to the different things with the same name.  In some circumstances, you must be precise, but that's because fundamentally, algorithmic thinking requries a certain level of precision, not because of any specific problem with computers.  In fact, there is a word for inconsistency and ambiguity in programming languages: &lt;i&gt;polymorphism&lt;/i&gt;.  Any time you invoke an interface rather than a concrete implementation (which is to say any time you do &lt;i&gt;anything&lt;/i&gt; in a dynamic language like Python) you are being ambiguous and potentially inconsistent in your program's behavior.&lt;br/&gt;&lt;br/&gt;"&lt;b&gt;You only get one way to organize stuff.&lt;/b&gt;"  This is a pretty weak point, though, given that Terry himself immediately turns around and notices that tagging and other multiply-indexed database systems are becoming popular.  So he gives us two examples of exceptions, but no examples of the rule.  I'm not sure what I could add to that.&lt;br/&gt;&lt;br/&gt;"&lt;b&gt;Programmers are obsessed with "meaning".&lt;/b&gt;&lt;i&gt;"&lt;/i&gt;  On this one, I'm going to agree, except I don't think it's a problem.  In the computational world, we are obsessed with the meaning of data, because if you get the meaning of the inputs wrong, then the meaning of the outputs is wrong too.  For example: if you have a number that represents the total liabilities that your company has accumulated, it's pretty important that you don't ever treat that as your total profit.  At a deeper level, if you have a sequence of bits that represents a floating-point number, it's important to know about its intended meaning, and not treat it as a string of characters, unless what you really want is a string.  "@H=N" is not as useful a concept as "3.1287417411804199" if you are trying to add it to something.  For what it's worth, I have my own, similar take on how we should treat &lt;a href='http://divmod.org/trac/wiki/DivmodImaginary'&gt;computational objects that have multiple meanings: Imaginary&lt;/a&gt;. Even systems like Imaginary and FluidDB depend on a very rigid definition of some simpler concepts, like numbers consistently being numbers and words consistently being words.  In my view, even if we treat the book itself as multifaceted, it's important to know what the data representing the "readable object" part of a book is really "about", and make sure it stays distinct from the data representing the "paperweight" part of the book.  To be fair, FluidDB appears to do this itself — and this terminology is my least-favorite part of FluidDB — by having single-purpose, permission-controlled "objects" just like every other system, but calling them "tags", and re-using the word "objects" to refer instead to what others might call a "UUID" or "central index".  In Imaginary, the system is similar; although the centrality of the FluidDB "object" (in Imaginary's case, the "Thing") is less stark; using FluidDB's terminology, in Imaginary, a "tag" can have a "tag" of its own; in fact, there's nothing but tags ("Items") anywhere.&lt;br/&gt;&lt;br/&gt;"&lt;b&gt;Metadata is separated from the data it describes.&lt;/b&gt;"  This may be true in some systems, but the web is probably the system with the most data in it anywhere, and in that system, metadata is always available as part of the request and the response.  You can put in any headers you want in the response, and there are lots of pieces of metadata (like content-type) which are almost always found along with the data.  In my opinion, the problem is more that we don't have enough of the previous problem.  Web developers haven't been obsessed enough with meaning: there aren't enough useful conventions around the HTTP request/response metadata, and so it's hard to bundle more metadata in with your response and have it faithfully propagated elsewhere.  We don't know what arbitrary headers might mean, because we don't have any way of expressing a schema for them.&lt;br/&gt;&lt;br/&gt;Terry says he's going to write more about these problems, and the solutions that FluidDB provides for them.  I'm looking forward to it.  As part of that, I'd really like to see a clear description of how these problems affect me, or someone I know, either as a programmer or as a user.  What do I, or should I, really want to do with some application right now that these five problems are preventing me from doing?&lt;br/&gt;&lt;br/&gt;The reason I felt compelled to write about this is that history — and particularly the history of websites like &lt;a href='http://freshmeat.net/'&gt;freshmeat&lt;/a&gt; and &lt;a href='http://sourceforge.net/'&gt;sourceforge&lt;/a&gt; — is littered with the corpses of projects which promised to fundamentally change the way we represent data.  A common problem with these projects is that they have expansive denunciations of current techniques to represent data, or manage persistence, and claim to provide an advance so significant that they will displace all current applications.  What most of the people working on these projects don't realize is that the current techniques for representing data have a history, and there are good reasons for their limitations.  Granted, not all of those reasons are currently relevant, and many are examples of &lt;a href='http://en.wikipedia.org/wiki/Path_dependence'&gt;path dependence&lt;/a&gt;, but it's still important to understand the reasons in order to escape the problems.&lt;br/&gt;&lt;br/&gt;In FluidDB's case, I think that the problem isn't so much that Terry doesn't have the historical perspective, but that he assumes that we all do.  And that we can all make the cognitive leap to see why FluidDB is necessary.  But if I can't do it, I have to assume there are at least a few other programmers who aren't getting the message either.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=a78923de-f4de-8142-9f66-56e430b02b2f' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/0fWQ1bmDieM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/65940598180596469/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=65940598180596469" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/65940598180596469?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/65940598180596469?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/0fWQ1bmDieM/hobgoblin-history.html" title="Hobgoblin History" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/10/hobgoblin-history.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEMRno-fCp7ImA9WxNQGE8.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-9123080297324275352</id><published>2009-09-24T16:21:00.003-04:00</published><updated>2009-09-24T16:21:27.454-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-24T16:21:27.454-04:00</app:edited><title>Diesel: A Case Study In That Thing I Just Said</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Thanks to jamwt for the &lt;a href='http://shoptalkapp.com/blog/2009/9/23/announcing-diesel'&gt;shout-out on the announcement of Diesel&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Since the reaction to &lt;a href='http://glyph.twistedmatrix.com/2009/09/what-i-wish-tornado-were.html'&gt;my reaction to tornado&lt;/a&gt; was so good (or at least so ... &lt;a href='http://news.ycombinator.com/item?id=818840'&gt;energetic&lt;/a&gt;), I figure I should comment on Diesel as well.  Spoiler alert: my reaction is ... largely similar, but since jamwt has been &lt;a href='http://www.jamwt.com/pgasync/'&gt;kind of nice&lt;/a&gt; to Twisted in the past, and didn't actually say anything mean this time, I'm somewhat reluctant to have that reaction.  Nevertheless, I swore a solemn oath to tell it like it is, keep it real, and soforth.  So I must.&lt;br/&gt;&lt;br/&gt;Once again, I'm happy that event-driven programming is getting some love.  This time, I'm pleased that nobody is saying anything especially snarky or FUD-ish about Twisted.  I do feel like it's a little weird not to mention Twisted, or include some comparisons to &lt;a href='http://divmod.org/trac/wiki/DivmodNevow'&gt;Nevow&lt;/a&gt; or &lt;a href='http://orbited.org/'&gt;Orbited&lt;/a&gt;, both of which provide different, comprehensive approaches to COMET with Twisted.&lt;br/&gt;&lt;br/&gt;(Worth noting: Orbited also originally started out using its own event-driven I/O layer, but switched to Twisted later, &lt;a href='http://orbited.org/blog/2007/04/twisted-orbited-crazy-delicious/'&gt;because Twisted is "crazy delicious"&lt;/a&gt;.)&lt;br/&gt;&lt;br/&gt;Diesel has many more interesting ideas at the level of async I/O than Tornado did.  I think the generator-based approach for implementing protocols is interesting and deserves some more exploration.  I'm not sold on it for every use-case, and I think the implementation might have some flaws, but it definitely has some advantages.&lt;br/&gt;&lt;br/&gt;I'd give jamwt a hard time for not reporting issues and communicating with Twisted more before re-writing the core, but for three issues:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;jamwt's been around in the Twisted community for a while.  He's written a bunch of fairly deep Twisted code and he clearly knows what the framework is capable of.&lt;/li&gt;&lt;li&gt;I've spoken with him on a number of occasions, and for all I know I might have discussed this with him.  I don't remember it, but it would be pretty embarrassing to write a big rant about how nobody talks to us only to have him paste some chat log where he explained why he was writing Diesel six months ago, and I said "oh, okay" ;-).&lt;/li&gt;&lt;li&gt;Nobody is calling Twisted names or making vague, unsubstantiated accusations.  You're not &lt;i&gt;obligated&lt;/i&gt; to examine Twisted, nor Nevow, nor Orbited, I just feel that you owe us some explanation if you publicly say that you tried it and found it wanting.  The tone on the Diesel announcement, in its one brief mention of Twisted, is "we tried it, but we kinda wanted to do our own thing".  So, good for them, they did their own thing, I hope they had fun.&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;Now, personally, I'd like to leave it at that, but there is a certain inevitable comparison that I think is going to take place.  Diesel has a nicer web page than Twisted.  They have entwittered ... twitified ... uh ... tweetened ... the project, and we haven't; we just have an old-fashioned "&lt;a href='http://labs.twistedmatrix.com/'&gt;blog&lt;/a&gt;".  Diesel is smaller than Twisted, so it's easier to explain, and so the people approaching it will have a better idea of its scope.  This might give the immediate impression that it is a simpler, better, more "modern" replacement for Twisted's I/O layer, and this is not the case.  So I still feel it's important that I set the record straight.&lt;br/&gt;&lt;br/&gt;Before I launch into my critique, I should say that I don't want to harsh on Diesel too bad. It's a neat little hack and you should go play with it.  And I feel bad pointing out problems with it, since as I mentioned above, nobody's dumping on Twisted.  So, Diesel fans, please take this in the spirit of a frank code-review, not a complaint about your behavior.&lt;br/&gt;&lt;br/&gt;The interesting generator-munging bits could be easily adapted to run on top of Twisted's loop, which, arguably, they should have been in the first place; and the toy "hub" that they've written might be good enough for some simple applications where reliability under load is not a serious concern.  In fact, &lt;a href='http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.html#inlineCallbacks'&gt;inlineCallbacks&lt;/a&gt; might provide a good deal of what is needed to support Diesel's programming style.  Alternately, Diesel might provide some hints as to how things like inlineCallbacks could be made more efficient.&lt;br/&gt;&lt;br/&gt;That said, Diesel's I/O loop sucks.&lt;br/&gt;&lt;br/&gt;It's disappointing to see the same mistakes getting made over and over again.  First and foremost: no tests.  Come on, Python community!  You can do better!  &lt;i&gt;Write your damn tests first!&lt;/i&gt;&lt;br/&gt;&lt;br/&gt;The #1 benefit that a brand-new I/O loop project &lt;i&gt;could&lt;/i&gt; have over Twisted is that Twisted was written in the bad old days before everybody knew that TDD was the right way to write programs, so we don't have 100% test coverage.  But, we strive to get closer every day, while every new project decides that they don't need no stinking quality control.&lt;br/&gt;&lt;br/&gt;Predictably, as it has no tests, Diesel's I/O layer is full of dead code, inaccurate  documentation, and unhandled errors.  Consider this gem, which I found about 30 seconds into reading the code: &lt;a href='http://bitbucket.org/boomplex/diesel/src/82dac40bdba2/diesel/hub.py#cl-161'&gt;KqueueEventHub&lt;/a&gt; is documented to be "an epoll-based event hub", and its initializer defines an inner function which is never used.  I'm not going to belabor the point by enumerating all the typo bugs I found, but you may find the output of 'pyflakes diesel' interesting.&lt;br/&gt;&lt;br/&gt;Instead of Tornado's inaccurate handling of EINTR, Diesel has &lt;i&gt;no&lt;/i&gt; handling of EINTR, as far as I can tell.  It also doesn't handle EPERM, ENOBUFS, EMFILE, or even EAGAIN on accept().  To be fair, it has a catch-all exception handler all the way at the top of the stack, so none of these will cause instant crashes, but they will cause surprising behavior in odd situations (and possibly infinite traceback-spewing loops).&lt;br/&gt;&lt;br/&gt;More surprisingly - I had to re-read the code about five times to make sure - it doesn't appear that sockets are ever set to be non-blocking, and EAGAIN is not handled from accept(), recv(), or send().  And yes, this &lt;i&gt;can&lt;/i&gt; happen even if your multiplexor says your socket is ready for reading and/or writing.  The conditions are somewhat obscure, but nevertheless they do happen.  So, occasionally, Diesel will hiccup and block until some slow network client manages to send or receive some traffic.  In other words: Diesel is not really async.  It just fakes it convincingly, most of the time.&lt;br/&gt;&lt;br/&gt;Once again, there's no way to asynchronously spawn a process, and no way to asynchronously connect a TCP client.  Sure, &lt;a href='http://bitbucket.org/boomplex/diesel/src/7661232a4178/diesel/client.py#cl-47'&gt;this looks like an asynchronous connect call&lt;/a&gt;, but it's misleading: it blocks on resolving the hostname, and it potentially blocks on the initial SYN/ACK/SYN+ACK exchange.  There's no asynchronous SSL support.  And no, that is &lt;a href='http://twistedmatrix.com/trac/browser/trunk/twisted/internet/tcp.py?rev=26296#L104'&gt;not&lt;/a&gt; &lt;a href='http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/tls.py?rev=26919'&gt;trivial&lt;/a&gt;.  Not to mention handling all the crazy errors that spew out of the Windows TCP stack.  And since the loop is implemented to be incompatible with Twisted, it's not obviously trivial to compatibly plug it in and get those features.&lt;br/&gt;&lt;br/&gt;Again, I don't want to dump on Diesel here; for what it is, i.e. an experiment in how to idiomatically structure asynchronous applications, it's all right.  For that matter Twisted has its fair share of bugs too, which would be pretty easy to lay out in a similar post; you wouldn't even need to do the research yourself, just go look at our bug tracker.&lt;br/&gt;&lt;br/&gt;But both Diesel and Tornado make the mistake of attempting to replace the years of trial-and-error, years of testing discipline, and years of portability and feature work that Twisted has accumulated with a few oversimplified, untested hacks.&lt;br/&gt;&lt;br/&gt;What they &lt;i&gt;could&lt;/i&gt; have done is contributed any extensions that they needed to Twisted's loop, or modifications to Twisted's packaging that would allow them to get a smaller sliver of Twisted's core to bootstrap, if that's what they needed.&lt;br/&gt;&lt;br/&gt;My goal in pointing out all these flaws is not to illustrate any particular point about Diesel, but to reinforce the point I implicitly made in my Tornado post, which is that &lt;i&gt;if you try to write a new mainloop &lt;b&gt;(especially without tests)&lt;/b&gt;&lt;/i&gt; you &lt;b&gt;&lt;i&gt;will&lt;/i&gt;&lt;/b&gt; screw it up.  You will most likely screw it up in ways which will only surface later, under mysterious circumstances, when your servers are under load and you are under the gun for a deadline.&lt;br/&gt;&lt;br/&gt;Or if I happen to get wind of it and write a blog post about it, of course.  Then you get to cheat a little.&lt;br/&gt;&lt;br/&gt;It's not an indictment of Diesel that it screwed this up; everyone screws it up.  &lt;i&gt;I&lt;/i&gt; would probably screw it up, if I didn't have Twisted sitting in front of me as a direct reference.  POSIX by itself is unreasonably subtle and difficult, but POSIX, plus the subtle variations in different platforms which implement it, plus the Windows APIs which are almost-but-not-quite-exactly-nothing-like the POSIX APIs, presents an inhuman challenge.&lt;br/&gt;&lt;br/&gt;Hopefully Diesel will grow some tests.  Hopefully it will fix, or better yet shed, its somewhat unfortunate I/O hub.  I am hopeful that someone will &lt;a href='http://dustin.github.com/2009/09/12/tornado.html'&gt;follow Dustin's excellent lead&lt;/a&gt; (perhaps Dustin himself!) and port Diesel's API and generator system over to Twisted's I/O architecture and eliminate all these silly bugs.  Of course, it someone did that, you could use Dustin's tornado port with Diesel.&lt;br/&gt;&lt;br/&gt;With the silly bugs from the I/O loop out of the way, the Diesel team can write tests for the more interesting pieces, and fix the bugs which aren't entirely silly :-).&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=a7f26cb5-58d0-8e07-af80-38e548349e97' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/3ChKIhJ5_r8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/9123080297324275352/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=9123080297324275352" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/9123080297324275352?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/9123080297324275352?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/3ChKIhJ5_r8/diesel-case-study-in-that-thing-i-just_24.html" title="Diesel: A Case Study In That Thing I Just Said" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>8</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/diesel-case-study-in-that-thing-i-just_24.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMNR3c5fyp7ImA9WxNQGE0.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-7190388803250341952</id><published>2009-09-24T10:38:00.000-04:00</published><updated>2009-09-24T10:44:56.927-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-24T10:44:56.927-04:00</app:edited><title>Making Twisted Specific</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;blockquote&gt;"pffft. twisted isn't specific."&lt;br/&gt;          — &lt;a href='http://twistedmatrix.com/trac/browser/trunk/doc/fun/Twisted.Quotes?rev=24576#L1067'&gt;W. Allen Short&lt;/a&gt;&lt;/blockquote&gt;The original goal of the Twisted project, as I have been frequently reminded of late, is to create a general, inter-operable mainloop that isn't specific to any particular protocol.  The main loop wasn't a goal in itself, as the point of making it general was to provide an opportunity for all protocols could have serious, production-quality implementations that any Twisted application could have access to.  Twisted itself ships with many different protocol implemenations in furtherance of this goal, in an attempt to get critical mass.&lt;br/&gt;&lt;br/&gt;This generality is a great strength.  It means that we've attracted a small crowd of generalists.  We have an excellent development process, ever-increasing quality of both code and documentation, and a wide variety of different protocol implementations and libraries for doing common networking and inter-process communication tasks.  We have recently been lucky to attract a &lt;a href='https://launchpad.net/%7Ejesstess'&gt;few&lt;/a&gt; &lt;a href='https://launchpad.net/%7Elvh'&gt;more&lt;/a&gt; &lt;a href='https://launchpad.net/%7Eesteve'&gt;excellent&lt;/a&gt; developers to help with this.&lt;br/&gt;&lt;br/&gt;The one thing we haven't been so lucky about is attracting specifists.  Although we still need more people to make Twisted awesome as a library, our community is getting better and better at doing that.  What we need even more than that is individuals with a very specific, focused interest on just one thing that Twisted does.  Czars, if you will, to push the development of Twisted as a suite of interoperating &lt;i&gt;applications&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;Twisted already has within it the seeds of excellent replacements for Apache httpd, OpenSSH, BIND, hybrid ircd, Sendmail, imapd, pop3d, and a few other servers, not to mention clients like Pidgin and the OpenSSH command-line client.  In order to sprout and take root, those seeds each need a dedicated advocate, someone who cares deeply about the experience of a user or administrator who just wants Twisted to perform one particular function and doesn't want to write their own application code to make it do that.&lt;br/&gt;&lt;br/&gt;Projects like the ones above - OpenSSH and BIND, for example - have an advantage in becoming useful: they have dedicated people who care deeply about satisfying a particular use-case, and are singularly focused on that case.  Since they only have the one problem to worry about, they can give it a much more direct treatment.&lt;br/&gt;&lt;br/&gt;However, given the team of infrastructure programmers already working on Twisted, such a focused individual would have an incredible force multiplier.  Consider &lt;a href='http://www.usenix.org/events/usenix03/tech/freenix03/full_papers/lefkowitz/lefkowitz_html/index.html#SECTION00081000000000000000'&gt;the statistics on Conch from our 2003 USENIX paper on Twisted&lt;/a&gt;: going just by line count, Conch was 4x easier to write than even J2SSH, which was itself substantially smaller than OpenSSH.  It was 10x easier to write than OpenSSH.  So, with the support of Twisted as infrastructure, one Twisted application programmer can do the work of ten merely mortal ones ;-).&lt;br/&gt;&lt;br/&gt;It might seem to those of you looking to write a chat client, DNS server, or whatever open-source giant that you want to do battle with, that Twisted is just a library, and you want to write an application.  But we really &lt;i&gt;want&lt;/i&gt; twisted to be a comprehensive suite of applications, we're just stretched too thin already to make it realize that potential.&lt;br/&gt;&lt;br/&gt;So please rest assured that we would love to have your help with turning Twisted itself into a worthy competitor for these open-source giants - or, for that matter, if you want to build your own competitor as a layer on top of Twisted (for whatever reason: you love .ini files and we don't, you want a more freewheeling development process, or you want a different shade of green on your web pages) we'd still love to help you out and support that effort by fixing whatever issues you have with Twisted's core or protocols.  There's even a super-project on Launchpad for &lt;a href='https://launchpad.net/tx'&gt;Twisted-but-not-part-of-Twisted projects&lt;/a&gt;.  I invite all you application developers out there to join that group and help us with world domination.&lt;br/&gt;&lt;br/&gt;(If all that stuff about being ten times more effective as a programmer wasn't enough for you, how about this?  On the Twisted Matrix Labs map of the post-revolutionary world, I'm pretty sure the Emancipated Territory of New Jersey is still missing an archduke and several viscounts.  I can't make any promises, but if you get in on the ground floor of this thing there's still a chance you could be a ruling member of the Twisted over-government!)&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=9c276b59-014a-8114-9436-a9ea196596cf' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/y8mDIBLMF4I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/7190388803250341952/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=7190388803250341952" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7190388803250341952?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/7190388803250341952?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/y8mDIBLMF4I/making-twisted-specific.html" title="Making Twisted Specific" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>9</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/making-twisted-specific.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ACRH4yeCp7ImA9WxNRF0o.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-5573830108638052774</id><published>2009-09-12T13:18:00.001-04:00</published><updated>2009-09-12T14:22:45.090-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-12T14:22:45.090-04:00</app:edited><title>The Hole At The End Of The Pipe</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Matt Campbell, a long-time fan of my ramblings, pointed out &lt;a href='http://ejohn.org/blog/javascript-language-abstractions/'&gt;a post from John Resig&lt;/a&gt; that reads almost like a response to &lt;a href='http://glyph.twistedmatrix.com/2009/09/web-untangled.html'&gt;my ideas about the browser as a deployment target&lt;/a&gt;, despite the fact that it was written several years ago.&lt;br/&gt;&lt;br/&gt;While Mr. Resig isn't adamantly against "language abstractions" - he notes many of their benefits - his counterpoint is summed up in this paragraph:&lt;br/&gt;&lt;br/&gt;	&lt;blockquote&gt;&lt;p&gt;In the case of these language abstractions you are gaining none of the benefit of learning the JavaScript language. When a leak in the abstraction occurs (and it will occur - just as it's bound to occur in any abstraction) what resources do you have, as a developer, to correct the problem? If you've learned nothing about JavaScript then you stand no chance in trying to repair, or work around, the issue.&lt;/p&gt;&lt;/blockquote&gt;&lt;br/&gt;This is becoming a popular fallacy in programming language circles; treating Joel Spolsky's "&lt;a href='http://www.joelonsoftware.com/articles/LeakyAbstractions.html'&gt;Law of Leaky Abstractions&lt;/a&gt;" as if it were an actual law.&lt;br/&gt;&lt;br/&gt;Let's examine the metaphor of the "leak".  In plumbing, a leak is a hole in a pipe where water gets out.  Joel has noticed that every pipe has a hole in it, and therefore all pipes are leaky.&lt;br/&gt;&lt;br/&gt;But that's not quite accurate.  There's another hole in pipes where water gets out: it's called the "faucet", and without that part, the rest of the pipe is pretty useless.  To say that a pipe whose faucet is turned on is "leaky" is somewhat misleading, just as it's misleading to say that an abstraction that propagates errors in its lower levels is misleading.  Joel's entire original essay is based on a subtle (and, I suspect, intentional) misunderstanding of TCP: the error conditions that result from failures in the lower level, unreliable packet delivery mechanism are not &lt;i&gt;leaks&lt;/i&gt; in the abstraction, they are very carefully specified and thoroughly documented.  They are &lt;i&gt;part&lt;/i&gt; of the abstraction.  The abstraction of TCP does not try to pretend that connections are never broken, it just provides a unified idea of a "broken connection" that is clearly specified so you don't need to understand the five million ways that packet delivery can go wrong.&lt;br/&gt;&lt;br/&gt;Put more simply: there are abstractions which do not leak.  The example that Joel provides is one of them: TCP is a comprehensive abstraction.&lt;br/&gt;&lt;br/&gt;Then there are abstractions which really &lt;i&gt;do&lt;/i&gt; leak.  Every object-relational mapper that provides a facility where you need to directly execute SQL, for example, is leaking the SQL through the abstraction.  Every web templating framework where you can directly generate strings is leaky: the browser speaks DOM, and if you're generating strings, then bytes are leaking through the abstraction.&lt;br/&gt;&lt;br/&gt;But "language abstractions" — or as those of us who are not hip to the new web lingo call them, "compilers" — are generally accepted to be the kind of thing that work well enough that you can trust them.  I don't know the specifics of the current crop of javascript-targeting compilers.  Maybe GWT and Pyjamas have issues that would require some knowledge of JavaScript to use them correctly.  A well-written compiler, one that really lived up to the promise of treating the browser as a deployment target, wouldn't have those kinds of issues though.  Let's turn the wayback machine to 1969 and cast Mr. Resig's argument against the contemporary contender for moving up the abstraction stack:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;  &lt;p&gt;In the case of UNIX, you are gaining none of the benefit of learning the PDP-11 instruction set. When a bug in the C compiler occurs (and it will occur - just as it's bound to occur in any compiler) what resources do you have, as a developer, to correct the problem? If you've learned nothing about PDP-11 assembler then you stand no chance in trying to repair, or work around, the issue.&lt;/p&gt; &lt;/blockquote&gt; &lt;br/&gt;So, for those of you who work on UNIX-like operating systems using that fancy "C" machine-code abstraction: how much PDP-11 assembler have you written recently?&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=4ed5b893-409c-8593-a040-96e473523850' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/yiPSIk7rHSo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/5573830108638052774/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=5573830108638052774" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/5573830108638052774?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/5573830108638052774?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/yiPSIk7rHSo/hole-at-end-of-pipe.html" title="The Hole At The End Of The Pipe" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>8</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/hole-at-end-of-pipe.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ECQXo5eyp7ImA9WxNRF0s.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-1711877362725880272</id><published>2009-09-12T11:34:00.001-04:00</published><updated>2009-09-12T11:34:20.423-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-12T11:34:20.423-04:00</app:edited><title>Tornado + Twisted</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Many kudos to Dustin Sallings, &lt;a href='http://dustin.github.com/2009/09/12/tornado.html'&gt;who has &lt;i&gt;already&lt;/i&gt; created a branch of Tornado which uses Twisted for both networking and HTTP parsing&lt;/a&gt;, in probably less time than it took me to write my previous post about how somebody should do that.  Awesome!&lt;br/&gt;&lt;br/&gt;(The method it uses is currently a little weird, where you create a "Site" object, but it looks like it would be pretty simple to use a Resource instead if you were so inclined.)&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=4623d07e-87c7-89e3-943c-1a7a3c258a9d' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/vqUSFRAyXD4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/1711877362725880272/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=1711877362725880272" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1711877362725880272?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1711877362725880272?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/vqUSFRAyXD4/tornado-twisted.html" title="Tornado + Twisted" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/tornado-twisted.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUGR3k5cSp7ImA9WxNRF04.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-2901853552149046084</id><published>2009-09-12T01:42:00.001-04:00</published><updated>2009-09-12T01:43:46.729-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-12T01:43:46.729-04:00</app:edited><title>What I Wish Tornado Were</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;FriendFeed has released &lt;a href='http://www.tornadoweb.org/'&gt;its web server, Tornado&lt;/a&gt;.  It seems like everyone's blogging about it, and it's obviously &lt;a href='http://knowyourmeme.com/photos/235'&gt;relevant&lt;/a&gt; to my interests, so I feel like I should say something.&lt;br/&gt;&lt;br/&gt;Let me start with the good stuff.  First of all, I think it's great that we have yet another asynchronous contender in the Python world.  Every time something like this comes out, it means that Twisted has to fight that much less hard to get over the huge hump of event-driven programming being too hard, or too weird, or whatever.  It's good to have an endorsement of the general message "if you need a web server to handle COMET requests, it needs to be asynchronous to perform acceptably" from such a high-profile company as Facebook.&lt;br/&gt;&lt;br/&gt;Unfortunately I think the larger picture here is a failure of communication in the open source community.  In the course of developing Tornado, there are several things that FriendFeed could have done to move the Twisted community forward, at no cost to themselves.  I don't want to rag on FriendFeed, or Bret Taylor, or Facebook here; they're not the first to re-write something without communicating.  In fact I recently had almost this exact same discussion with &lt;a href='https://garage.maemo.org/pipermail/brisa-develop/2009-August/thread.html'&gt;another project&lt;/a&gt; that did the same thing.  Since Tornado is such a high-profile example, though, I want to draw attention to the problem so that there's some hope that maybe the next project won't forget to communicate first.&lt;br/&gt;&lt;br/&gt;My main point here is that if you're about to undergo a re-write of a major project because it didn't meet some requirements that you had, &lt;i&gt;please&lt;/i&gt; tell the project that you are rewriting what you are doing.  In the best case scenario, someone involved with that project will say, "Oh, you've misunderstood the documentation, actually it does do that".  In the worst case, you go ahead with your rewrite anyway, but there is some hope that you might be able to cooperate in the future, as the project gradually evolves to meet your requirements.  Somewhere in the middle, you might be able to contribute a few small fixes rather than re-implementing the whole thing and maintaining it yourself.&lt;br/&gt;&lt;br/&gt;This is especially important if you are later going to make claims about that project not living up to your vaguely-described requirements, and thereby damage its reputation.  Bret Taylor &lt;a href='http://bret.appspot.com/entry/tornado-web-server'&gt;claims in his blog&lt;/a&gt;:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;We ended up writing our own web server and framework after looking at existing servers and tools like &lt;a href='http://twistedmatrix.com/'&gt;Twisted&lt;/a&gt; because none matched both our performance requirements and our ease-of-use requirements.&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;First and foremost, it would have been great to hear from Bret when he started off using Twisted about any performance problems or ease-of-use problems.  I'm guessing that Twisted itself had only ease-of-use problems, and other "tools like Twisted" were the ones with performance problems, since later, &lt;a href='http://bret.appspot.com/entry/tornado-web-server#comment-16389114'&gt;in a comment on the same post, he says&lt;/a&gt;:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;I can't imagine there is much of a performance difference [between Twisted Web and Tornado].  The bottom is not that complex in my opinion.&lt;br/&gt;&lt;/blockquote&gt;&lt;br/&gt;It would also be great if he had explicitly &lt;i&gt;said&lt;/i&gt; that Twisted didn't have performance problems rather than making me guess, because I'm sure that is what lots of developers will take away from this.  When you have the bully pulpit, off-the-cuff comments like this can do serious damage to smaller projects.&lt;br/&gt;&lt;br/&gt;More to the point, what is the problem with "ease of use", exactly?  The fact that he found Deferred tedious, in particular, seems very strange to me, given that it is so &lt;i&gt;un-&lt;/i&gt;tedious that it has become a de-facto standard &lt;a href='http://www.mochikit.com/doc/html/MochiKit/Async.html'&gt;even in the JavaScript community&lt;/a&gt;.  We had no opportunity to help him or anyone else out, because as far as I can tell from searching our archives, we never heard from him or from anyone else at FriendFeed when they were trying out Twisted at first.  Even as he's saying that Twisted is hard to use and (maybe?) performs poorly, he isn't pointing to any particular example of what about it is hard to use, or what performs poorly.  There's still nothing we can do to address this criticism.  And there's still not much we can do to make sure that future potential Twisted users won't have this problem.&lt;br/&gt;&lt;br/&gt;&lt;a href='http://bret.appspot.com/entry/tornado-web-server#comment-16314810'&gt;Later, in yet another comment&lt;/a&gt;, Bret points out the root problem:&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;&lt;div id='dsq-comment-body-16314810' class='dsq-comment-body'&gt;&lt;div id='dsq-comment-message-16314810' class='dsq-comment-message'&gt;... the HTTP/web support in Twisted is very chaotic (see &lt;a href='http://twistedmatrix.com/trac/wiki/WebDevelopmentWithTwisted' rel='nofollow'&gt;http://twistedmatrix.com/trac/wiki/WebDevelopme...&lt;/a&gt; - even they acknowledge this)...&lt;br/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br/&gt;This is true.  However, as I frequently like to note, Twisted is starved for resources.  Reconciling the chaos described on the page about web development with Twisted is an ongoing process.  For a tiny fraction of the effort invested in Tornado, FriendFeed could have worked with us to resolve many of the issues creating that chaos.&lt;br/&gt;&lt;br/&gt;This is the main thing I want to reinforce here.  If half a dozen occasional contributors with a real focused interest in web development showed up to help us on Twisted, we'd have an awesome, polished web story within a few months.  If even &lt;i&gt;one&lt;/i&gt; person really took responsibility for twisted.web, things would pick up.  But if everyone who wants an asynchronous webserver either uses twisted.web (because it's great!) without talking to us or decides not to use it (because it doesn't meet their unstated requirements) without talking to us, it's going to continue to improve at the same sluggish pace.&lt;br/&gt;&lt;br/&gt;Even at the current rate, by the time we have an excellent HTTP story, I somehow doubt that Tornado will have a good &lt;a href='http://twistedmatrix.com/trac/wiki/TwistedConch'&gt;SSHv2 protocol&lt;/a&gt; story ;-).&lt;br/&gt;&lt;br/&gt;In his comment, Bret also takes a couple of pot-shots at Twisted that I think are unnecessary, and I'd like to address those too.&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;In general, it seems like Twisted is full of demo-quality stuff, but most of the protocols have tons of bugs.&lt;/blockquote&gt;&lt;br/&gt;We're not talking about "most" of the protocols here, Tornado is only concerned with HTTP.  And the HTTP implementation(s) in Twisted do not have "tons of bugs".  They are production quality, used on lots of different websites, and have lots of automated tests.  While much of the code in twisted.web doesn't have &lt;i&gt;complete&lt;/i&gt; test coverage, since it's old enough to predate our testing requirements, I note that &lt;a href='http://github.com/facebook/tornado/tree/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado'&gt;Tornado appears to have &lt;i&gt;zero&lt;/i&gt; test coverage&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;There's a kernel of truth here — &lt;i&gt;some&lt;/i&gt; of the older, less frequently used protocols have a few problems — but in most cases the "bugs" are really just a lack of functionality.  Twisted overall has very few protocol-related bugs, and again, our test policy makes sure that we have get new bugs very rarely.&lt;br/&gt;&lt;br/&gt;&lt;blockquote&gt;Given all those factors, it didn't seem to provide a lot of value. Our core I/O loop is actually pretty small and simple, and I think resulted in fewer bugs than would have come up if we had used Twisted.&lt;/blockquote&gt;&lt;br/&gt;I must respectfully disagree.  Again, I don't want to rag on FriendFeed here, but here are several features that Tornado would have, and bugs that it wouldn't have, if it used Twisted for the event loop and none of the HTTP stuff:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;&lt;a href='http://twistedmatrix.com/trac/browser/trunk/twisted/internet/pollreactor.py#L153'&gt;EINTR&lt;/a&gt; wouldn't &lt;a href='http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/ioloop.py#L175'&gt;cause your application to exit&lt;/a&gt; if run in a non-US-english locale.&lt;/li&gt;&lt;li&gt;You don't have the opportunity to &lt;a href='http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/ioloop.py#L56'&gt;forget to set a socket to be non-blocking&lt;/a&gt; and thereby make your entire application stop.&lt;/li&gt;&lt;li&gt;It would be possible to run your application on Windows.&lt;/li&gt;&lt;li&gt;&lt;a href='http://twistedmatrix.com/trac/browser/trunk/twisted/internet/tcp.py#L903'&gt;Firewalled connections&lt;/a&gt; and &lt;a href='http://twistedmatrix.com/trac/browser/trunk/twisted/internet/tcp.py#L910'&gt;running out of file descriptors&lt;/a&gt; wouldn't &lt;a href='http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/httpserver.py#L95'&gt;cause your server to spew errors forever&lt;/a&gt; (at least, it won't &lt;a href='http://twistedmatrix.com/trac/ticket/662'&gt;any more&lt;/a&gt;).&lt;br/&gt;&lt;/li&gt;&lt;li&gt;You could write &lt;a href='http://twistedmatrix.com/trac/browser/trunk/twisted/internet/tcp.py#L648'&gt;a TCP client&lt;/a&gt; that didn't &lt;a href='http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/iostream.py#L40'&gt;block for an arbitrary amount of time in connect()&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Finally, of course, you could use all of Twisted's other protocols, client and server: IMAP, POP, SMTP, IRC, AIM, etc.  You could also use external protocol implementations like &lt;a href='https://issues.apache.org/jira/browse/THRIFT-148'&gt;Thift&lt;/a&gt;.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;You could spawn asynchronous subprocesses.&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;and this is a very short list, based on a cursory reading of the source code, not actually running tornado and not a particularly deep audit.  Some of these bugs might not be as serious as I think, and there might be plenty of other bugs.  But I can't really be sure what works for sure, since again: there are no automated tests.&lt;br/&gt;&lt;br/&gt;This list is a great example of why projects like Tornado really &lt;i&gt;should&lt;/i&gt; use Twisted.  Tornado implements some innovative web-framework stuff, but absolutely nothing interesting that I can see at the level of async I/O.  Using Twisted would have allowed them to focus exclusively on cool web things and left the never-ending stream of incremental surprising platform-specific, only-happens-in-weird-situations bugfixes to a single, common source.&lt;br/&gt;&lt;h3&gt;What To Do Now&lt;/h3&gt;I hope that someone at FriendFeed will be a little heavier on detail and a little lighter on FUD in some future conversation about Twisted.  However, I'm sure they're going to have their hands full maintaining their own code, so I don't have high expectations in this area.  I'm sure Bret wasn't intentionally slamming Twisted, either; it wasn't like he wrote a big &lt;a href='http://laurentszyster.be/blog/tcp-stack-flaking-out/'&gt;screed&lt;/a&gt; about it, he just dropped in a few unsubstantiated comments into a much larger post about Tornado. So I just want to be clear: I don't have sore feelings, I don't need anybody to apologize to me or to Twisted.&lt;br/&gt;&lt;br/&gt;If any of you out there are fans of both Tornado and of Twisted, it would be great if you could contribute a patch to Tornado which would allow it to at least optionally use Twisted as an I/O back-end.  It would be great, of course, if lots of people interested in web stuff would help us out with our web situation, but supporting the Twisted event loop would be good regardless. It would mean that when people wanted to speak multiple protocols, they wouldn't need to re-write or kludge in their existing Tornado application, so it would increase the chances that we could get some help with our SSH, FTP, IRC, or XMPP code instead.  It would also open up a much wider multi-protocol landscape to users of Tornado, even if Tornado's default mode of operation still used ioloop.py.&lt;br/&gt;&lt;br/&gt;Even better would be to hook up something that made a Tornado IResource implementation, so that Tornado applications and twisted.web and Nevow applications could all be seamlessly integrated into one server.&lt;br/&gt;&lt;br/&gt;The whole point of Twisted is to have a common I/O layer that lots of different libraries can use, share, and build on, so that we can solidify the common and highly complex abstraction required of a comprehensive, cross-platform, event-driven I/O layer.  In order to realize that vision, we need help not just with the code; we need more Twisted ambassadors to go out into the community and help us integrate these disparate applications, help us find out where real users are finding the documentation inadequate or the organization confusing.&lt;br/&gt;&lt;br/&gt;Tornado could be an excellent opportunity for those ambassadors to go out and introduce others to the wonders of Twisted, because its endorsement from FriendFeed guarantees it an audience of a tens of thousands of developers, at least for its first few months of life.  If you've shied away from contributing to Twisted itself because of our aggressive testing and documentation requirements, well, Tornado apparently doesn't have any, so it would be a great place for you to start :).&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=71828765-8022-8031-8eb1-7b32ca9f114f' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/vkqqYNTfU1s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/2901853552149046084/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=2901853552149046084" title="23 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/2901853552149046084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/2901853552149046084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/vkqqYNTfU1s/what-i-wish-tornado-were.html" title="What I Wish Tornado Were" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>23</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/what-i-wish-tornado-were.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8ARHc6fSp7ImA9WxNRF08.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-8931984238054923891</id><published>2009-09-11T23:07:00.001-04:00</published><updated>2009-09-11T23:07:25.915-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-11T23:07:25.915-04:00</app:edited><title>The Web, Untangled</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;In &lt;a href='http://glyph.twistedmatrix.com/2009/09/oh-atangled-web-we-weave-from.html'&gt;my previous post&lt;/a&gt;, I outlined some reasons that web development is worse than other kinds of development (specifically: traditional client-server development).  I left off there saying that I had some prescriptions for the web's ailments, though, and now I'll describe those.  Given that we're stuck with web development for the forseeable future, how can we make it a tolerable experience?&lt;br/&gt;&lt;br/&gt;First, let me tell you what the answer isn't.  It isn't a continuation of the traditional "web framework" strategy.  These have been important tools in dredging the conceptual mire of the web for useful patterns, and at this point in history they have a long life ahead of them.  I'm not predicting the death of Django or Rails any time soon.  Django and Rails are the stucco of the web.  An important architectural innovation, to be sure: they let you cover over the materials underneath, allowing you to build structures that are appealing without fundamentally changing the necessarily ugly underpinnings.  But you can't build a skyscraper out of stucco.&lt;br/&gt;&lt;br/&gt;As Jacob covered in great detail in his talk, innovations in the "framework" space generally involve building more and more abstractions, creating more and more new concepts to simplify the underlying concepts.  Eventually you run out of brain-space for new concepts, though, and you have to start over.&lt;br/&gt;&lt;br/&gt;I started here by saying that we're stuck with the web.  If we can understand &lt;i&gt;why&lt;/i&gt; we're stuck with the web, we can make it a pleasant place to be.  Of course everybody has their own ideas about what makes the web great, but it's important to remember that none of that is what makes the web &lt;i&gt;necessary&lt;/i&gt;.&lt;br/&gt;&lt;br/&gt;What makes the web necessary is very simple: a web browser is a turing complete execution environment, and everyone has one.  It's also got a feature-complete (if highly idiosyncratic) widget set, so you can display text, images, buttons, scrollbars, and menus, and compose your own widgets (sort of).  Most importantly, it executes code without prompting the user, which means the barrier to adoption of new applications is at zero.  Not to mention that, thanks to the huge ecosystem of existing applications, the user is probably already running a web browser.&lt;br/&gt;&lt;br/&gt;I feel it's important to emphasize this point.  When developing an application, &lt;b&gt;delivery is king&lt;/b&gt;.  It doesn't matter how great your application is if no users ever run it, and given how incredibly cheap in terms of user effort it is to run an application in a web browser, your application has to be really, really awesome to get them to do more work than clicking on a link.  I can't find the article, but I believe &lt;a href='http://www.threerings.net/'&gt;Three Rings&lt;/a&gt; once did an interview where they explained that some huge percentage of users (if I remember correctly, something like 90%) will leave immediately if you make them click on a "download" link to play the game, but they'll stick around if you can manage to keep it in the browser without making them download a plugin.&lt;br/&gt;&lt;br/&gt;Improvements to &lt;a href='http://www.ecma-international.org/news/PressReleases/PR_Ecma_finalises_major_revision_of_ECMAScript.htm'&gt;ECMAScript&lt;/a&gt; and &lt;a href='http://www.whatwg.org/specs/web-apps/current-work/'&gt;HTML&lt;/a&gt; sound fun, but if, tomorrow morning, somebody figured out how to &lt;a href='http://code.google.com/p/nativeclient/'&gt;securely execute x86 machine code&lt;/a&gt; on web browsers, &lt;i&gt;and distribute that capability to every browser on the internet&lt;/i&gt;, developers would start using that almost immediately.  HTML-based applications would slowly die out, as their UIs would be comparatively slow, clunky, and limited.&lt;br/&gt;&lt;br/&gt;Tools like the &lt;a href='http://code.google.com/webtoolkit/'&gt;Google Web Toolkit&lt;/a&gt; (and &lt;a href='http://pyjd.sourceforge.net/'&gt;Pyjamas&lt;/a&gt;, its Python clone), recognized this fact early on.  They treat the browser as what the browser should be: a dumb run-time.  A deployment target, not a development environment.  Seen in this light, it's possible to create layers for integration and inter-op &lt;i&gt;above&lt;/i&gt; the complexity soup of DOM and JavaScript: despite the fact that the browser itself has no "linker" to speak of, and no direct support for library code, with GWT you get Java's library mechanism.&lt;br/&gt;&lt;br/&gt;Although it's not particularly well-maintained, &lt;a href='http://codespeak.net/pypy/dist/pypy/doc/'&gt;PyPy&lt;/a&gt; also has a JavaScript back-end, which allows you to run a restricted subset of Python ("RPython") in a web browser; I hope that in the future this will be expanded to give us a more realistic, full-featured Python VM in the browser than Pyjamas' fairly simplistic translation currently does.  In opposition to the "worrying trend" that Jacob noted, with individual applications needing to write new, custom run-times, they leverage an existing language ecosystem rather than inventing something new.&lt;br/&gt;&lt;br/&gt;Using tools like these, you can write code &lt;i&gt;in the same language client-side and server-side&lt;/i&gt;.  This simplifies testing.  You can at least get basic test coverage in one pass, in one runtime, even if some of that code will actually run in a different runtime later.  It simplifies implementation and maintenance, too.  You can write functions and then decide to run them somewhere else based on deployment, security, or performance concerns &lt;i&gt;without&lt;/i&gt; necessarily rewriting them from scratch.&lt;br/&gt;&lt;br/&gt;If toolkits like these gained more traction, it would go a long way towards interop, too.  It would be a lot easier to have an FFI between Python-in-the-browser and Java-in-the-browser than to try to wrangle every possible JavaScript hack in the book.  Similarly on the server side: once a few frameworks can standardize on rich client-server communication channels, it will be easier to have a high-level abstraction over those than over the mess of XmlHttpRequest and its various work-alikes.&lt;br/&gt;&lt;br/&gt;There's still an important component missing, though.  Web applications almost always have 3 tiers.  I've already discussed what should happen on the first tier, the browser.  And, as GWT, NaCl and Pyjamas indicate, there are folks already hard at work on that.  The middle tier is basically already okay; server-side frameworks allow you to work with "business logic" in a fairly sane manner.  What about the database tier?&lt;br/&gt;&lt;br/&gt;The most common complaint about the database tier is security.  Since half the time your middle tier needs to be generating strings of SQL to send to the database, there are a plethora of situations where an accidental side-channel is created, allowing users to directly access the database.&lt;br/&gt;&lt;br/&gt;This is a much more tractable problem than the front-end problem.  For one thing, a really well-written framework, one which &lt;a href='http://glyf.livejournal.com/49935.html'&gt;doesn't encourage you to execute SQL directly&lt;/a&gt;, can comprehensively deal with the security issue.  Similarly, &lt;a href='https://storm.canonical.com/'&gt;a good ORM &lt;/a&gt;will allow you complete access to the useful features of your database without forcing you to write code in two different programming languages.&lt;br/&gt;&lt;br/&gt;Still, there's a huge amount of wasted effort on the database side of things.  Pretty much every major database system has a sophisticated permission system that nobody really uses.  If you want to write stored procedures, triggers, or constraints in a language like Python, it is at worst impossible and at best completely non-standard and very confusing.  Finally, if you want to test anything... you're not &lt;a href='http://sqlunit.sourceforge.net/'&gt;entirely&lt;/a&gt; on your own, but it's going to be quite a bit harder than testing your middle-tier code.&lt;br/&gt;&lt;br/&gt;One part of the solution to this problem comes, oddly enough, from Microsoft: LINQ, the &lt;a href='http://en.wikipedia.org/wiki/Language_Integrated_Query'&gt;Langauge Integrated Query&lt;/a&gt; component, provides a standard syntax and runtime model for queries executed in multiple different languages.  More than providing a nice wrapper over database queries, it allows you to use &lt;i&gt;the same&lt;/i&gt; query over in-memory objects with no "database engine" to speak of.  So you can write and test your LINQ code in such a way that you don't need to talk to a database.  When you hook it up to a database, your application code doesn't even really need to know.&lt;br/&gt;&lt;br/&gt;The other part of the solution comes from &lt;a href='http://sqlite.org/'&gt;SQLite&lt;/a&gt;.  Right now, managing the deployment of and connection to a database is a hugely complex problem.  You have to install the software, write some config files, initialize your database, grant permissions to your application user, somehow get credentials from the database to the application, connect from the application to the database, and verify that the database's schema is the same as what the application expects.  And that's before you can even &lt;i&gt;do&lt;/i&gt; anything!  Once you're up and running, you need to manage upgrades, schedule downtime for updating the database software (independently of upgrading the application software).  Note that the database can't be a complete solution for the application's persistence needs, either, because in order to tell the application where it needs to find the rest of its data, you need, at the very least, a hostname, username, and password for the database server.&lt;br/&gt;&lt;br/&gt;All of this makes testing more difficult - with all those manual steps, how can you really know if your production configuration is the same as your test configuration?  It also makes development more difficult: if automatically spinning up a new database instance is hard, then you end up with a slightly-nonstandard manual database setup for each developer.  With SQLite, you can just say "database, please!" from your &lt;i&gt;application code&lt;/i&gt;, specifying all the interesting configuration right there.&lt;br/&gt;&lt;br/&gt;Finally, SQLite allows you to very easily write stored procedures and triggers in your "native" language.  You also don't need to quite as much, because your application can much more easily completely control access to its database, but if you want to work in the relational model it's fairly simple.  The stored procedures are just in memory, and are called like regular functions, not in an obscure embedded database environment.&lt;br/&gt;&lt;br/&gt;In other words, for modern web applications, a database engine is really just a &lt;i&gt;library&lt;/i&gt;.  The easier it is to treat it like one, the easier it is to deploy and manage your application.&lt;br/&gt;&lt;br/&gt;In the framework of the future, I believe you'll be able to write UI code in Python, model code in Python, and data-manipulation code in Python.  When you need to round a number to two digits, you'll just round it off, and it'll come out right.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=2e048ace-bee4-8839-8100-0a1c4e26a00d' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/RBQ_zoT5jZw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/8931984238054923891/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=8931984238054923891" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/8931984238054923891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/8931984238054923891?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/RBQ_zoT5jZw/web-untangled.html" title="The Web, Untangled" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/web-untangled.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04MQXczeip7ImA9WxNRFUo.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-688326045273799626</id><published>2009-09-10T06:53:00.001-04:00</published><updated>2009-09-10T06:53:00.982-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-10T06:53:00.982-04:00</app:edited><title>Oh &lt;what&gt; a.tangled {web, we} WEAVE FROM</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;The always entertaining Jacob Kaplan-Moss recently posted a missive, "&lt;a href='http://jacobian.org/writing/snakes-on-the-web/'&gt;Snakes on the Web&lt;/a&gt;", which, if you haven't already read it, is a highly edifying trip through a variety of Python web technologies and history.  He begins with a simple statement — "Web development sucks." — and goes on to ask a number of interesting questions about that.&lt;br/&gt;&lt;br/&gt;What sucks about web development?  How will we fix it?  How has python fixed it, and how will python fix it in the future?  While I can't say I agree with every answer, I found myself nodding quite a bit, and he has something useful to say on just about every point.&lt;br/&gt;&lt;br/&gt;I noticed one very important question he leaves out of the mix, though, which seems more fundamental than the others: &lt;i&gt;why&lt;/i&gt; does web development suck?  In particular, why do so many people who are familiar with multiple styles of development feel like developing for the web is particularly painful by comparison, while so much of software development moves to the web?  And, why does web development in Python suck, despite the fact that otherwise, Python mostly rocks?&lt;br/&gt;&lt;br/&gt;Programming for the web lacks an important component, one that Fred Brooks identified as crucial for all software as early as 1975: &lt;a href='http://en.wikipedia.org/wiki/The_Mythical_Man-Month#Conceptual_Integrity'&gt;&lt;i&gt;conceptual integrity&lt;/i&gt;&lt;/a&gt;.  Put more simply, it is difficult to make sense of "web" programs.  They're difficult to read, difficult to write and difficult to modify, because none of the pieces fits together in a way which can be understood using a simple conceptual model.&lt;br/&gt;&lt;br/&gt;Rather than approach this head on, from the perspective of a working web programmer, let's start earlier than that.  Let's say someone approached you with a simple programming task: write an accounting system that includes point-of-sale software to run a small business.  Now, considering some imagined requirements for such a system, how many languages would you recommend that it be written in?&lt;br/&gt;&lt;br/&gt;Most working programmers would usually say "one" without a second thought.  A too-clever-by-half &lt;a href='http://washort.twistedmatrix.com/'&gt;language nerd&lt;/a&gt; might instead answer "two, a general-purpose programming language for most things and a domain specific language to describe accounting rules and promotions for the business".  Why this number?  Simply put, there's no reason to use more, and introducing additional languages means mastering additional skills and becoming familiar with additional quirks, all of which add to initial development time and maintenance overhead.  Modern programming languages are powerful enough to perform lots of different types of tasks, and are portable across both different computer architectures and different operating systems, so other concerns rarely intrude.&lt;br/&gt;&lt;br/&gt;But, in the practical, working programmer's world, what's the web's answer to this question?  Six.  You have to learn six languages to work on the web:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;HTML.  This isn't really a programming language, but in web development you do end up reading and writing quite a lot of it.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;CSS.  In order to apply visual styles to your HTML so that it actually looks nice in a browser, you need to understand a different language (with a different conceptual model for how documents are laid out than the HTML itself).&lt;br/&gt;&lt;/li&gt;&lt;li&gt;JavaScript.  In today's competitive AJAX-y world, you need to be able to react instantly in the browser, writing a real client application.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;SQL, so that you can store your data in a database.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Your "middle-tier" language: in my case and Jacob's, that would be Python.  This is where people tend to spend the bulk of their programming time, but not all of it.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;A templating language; in Jacob's case, the Django template language.&lt;/li&gt;&lt;/ol&gt;If you're unlucky, you might need to learn XML, more than one back-end language, a deployment language (UNIX shell scripting or Windows's "batch" language), and ActionScript.  You'll probably need to learn a smattering of some awful web-server configuration language though, like the not-quite-XML-not-quite-HTML used to configure Apache.&lt;br/&gt;&lt;br/&gt;Of course, Jacob lists a pile of related technologies too, and rightly points out that it's a lot to keep in your head.  But he is talking about a problem of needing extensive technical knowledge, something which all programmers working in a particular technology ecosystem learn sooner or later.  I'm talking about a different, more fundamental problem: in addition to the surface problem of being complex and often broken, these technologies are fundamentally &lt;i&gt;conceptually incompatible&lt;/i&gt;, which leads to a whole host of other problems.  Furthermore, the only component which is really &lt;i&gt;complete&lt;/i&gt; is the "middle-tier" language, although bespoke web-only languages like PHP and Arc manage to screw that up too.&lt;br/&gt;&lt;br/&gt;Here are a few simple example problems that are made depressingly complex by the impedence mismatch between two of these components, but which are incredibly easy using a different paradigm.&lt;br/&gt;&lt;br/&gt;How do you place two boxes with text in them side-by-side?  Using a GUI toolkit, like my favorite PyGTK, it often goes something like this:&lt;br/&gt;&lt;blockquote&gt;left = Label("some text")&lt;br/&gt;right = Label("some other text")&lt;br/&gt;box = HBox()&lt;br/&gt;box.add(left)&lt;br/&gt;box.add(right)&lt;br/&gt;&lt;/blockquote&gt;The conceptual model here is simple: the HBox() is a container, the "left" and "right" things are widgets, which are in that container.  You can add them, remove them, swap them, or handle events on them easily.  You can discover how these things are done by reading the API references for the appropriate classes of object.  However, there's no right answer to this question on the web.  You can use a &amp;lt;table&amp;gt; tag, and then some &amp;lt;tr&amp;gt;s and &amp;lt;td&amp;gt;s to make a single-row table with two cells, but that has a variety of limitations; plus, it's considered somehow gauche by most web designers to use tables for layout these days.  Or, you could cook up a collection of CSS classes.  So there's the first impedence mismatch: do you do layout in HTML, or CSS?  Of course most design gurus would like to tell you that "always and only CSS" is the right answer here, but more practically-minded web developers who actually write code will often prefer HTML, partially because it's simpler but partially because CSS's featureset is incomplete and there are some things you can still only do with HTML, or only do portably with HTML.&lt;br/&gt;&lt;br/&gt;Plus, how do you discover how these layouts work?  There are a variety of reference materials, but no canonical guide that says "this is exactly what a &amp;lt;table&amp;gt; tag should do, and how it should look".  There are different forms of documentation for both.&lt;br/&gt;&lt;br/&gt;If you have a variable number of elements, you quickly run into another problem.  Should this be the responsibility of the HTML, the CSS, or some code (in the templating layer) that emits some HTML or some CSS?  Should the code in the templating layer be written as an invocation of your middle-tier language, or should the template language itself have some code in it?  Reasonable people of good conscience disagee with each other in every possible way over every one of these details.&lt;br/&gt;&lt;br/&gt;This is all part of a very complex problem though.  For all of these crazy hoops you have to jump through, HTML and CSS &lt;i&gt;do&lt;/i&gt; provide a layout model that allows you to do some very pretty and very flexible things with layout, especially if you have large amounts of text.  Perhaps not as good as even the most basic pre-press layout engine, but still better than the built-in stuff that most GUI toolkits allow you.  So there is an argument that this complexity is a trade-off, where you get functionality in exchange for the confusion.  So let's look at a much simpler problem.&lt;br/&gt;&lt;br/&gt;Let's say that, in our hypothetical accounting application, you have a list of items in a retail transaction, and you want to process the list and produce a sum.  Where is the right place to do that?  It turns out you have to write the code to do that three times.&lt;br/&gt;&lt;br/&gt;First, you have to write it in JavaScript.  After all, the numbers are all already in the client / browser, and you want to update the page instantaneously, not wait for some potentially heavily-loaded server to get back to you each time the user presses a keystroke.  And why not?  You've got plenty of processing power available on the client.&lt;br/&gt;&lt;br/&gt;Then you have to write it in Python.  That's where the real brain of the application lives, after all, and if you're going to do something like send a job to a receipt printer or email a customer or sales representative some information in response to a sale, the number has to be located in the middle tier.&lt;br/&gt;&lt;br/&gt;Finally you have to do it in SQL.  Since this is a traditional web application, your Python code is going to be spread out among multiple servers, and the database is the ultimate arbiter of recorded truth.  So you need to have transactions around the appropriate points and execute any interesting aggregate functions (such as SUM()) in the database tier.&lt;br/&gt;&lt;br/&gt;So, you've got three times as much work to do in your fancy new web application as you would in a simple record-based application with a GUI.  A worthy price to pay to run in the brave new world of tomorrow rather than on some crusty old client/server system, right?&lt;br/&gt;&lt;br/&gt;Well, as it turns out, the problem is somewhat deeper than that.  It turns out that JavaScript, Python, and SQL actually have slightly different numerical models (in fact Python implements at least 4 itself: fixed-point decimal, floating-point decimal, IEEE 754 floating-point binary, and integer math; you should really only use decimal for money, but this isn't availble in JavaScript and its availability in SQL is spotty).  After applying some discounts, your register might read $19.74 but your receipt will read $19.75; and the reports sent to the accounting department will read $19.74898989898989.&lt;br/&gt;&lt;br/&gt;Even if you know a lot about math on computers, the limitations of each of these runtimes, and you happen to get all of that &lt;i&gt;just right&lt;/i&gt;, you still have another problem to contend with: what happens when somebody else needs to &lt;i&gt;change&lt;/i&gt; the logic in question?  How do you test that the Python, the JavaScript, and the SQL are all still in sync?  It's possible, but you have to go above and beyond the usual discipline of test-driven development, because you need to have integration tests that verify that different, almost unrelated code, in different languages, in different environments is all executing properly in lock-step.  Just getting the code from SQL and JavaScript to run in your Python test suite at all is a major challenge; in a language like PHP it's borderline impossible.&lt;br/&gt;&lt;br/&gt;This is all even worse when it comes to security, because every part of the application exposes an attack surface, and because you can't use the same language or the same libraries to do any of the work, they all expose a &lt;i&gt;different&lt;/i&gt; attack surface.&lt;br/&gt;&lt;br/&gt;In his talk, Jacob notes that "frameworks suck at inter-op", but the problem is &lt;i&gt;much&lt;/i&gt; deeper than that.  As I've shown here, a single page from a single application written using a single framework, which has only one task to do, &lt;i&gt;can't even inter-operate with itself cleanly&lt;/i&gt;, at least not at the level that Jacob wants — or that I want.  He says, "gateways aren't APIs", and he's right: the correct way to inter-operate is through well-defined APIs.  APIs can be discovered through a single, consistent process.  Their implementations can be debugged using a single set of development tools.&lt;br/&gt;&lt;br/&gt;CSS isn't an API.  HTML isn't an API.  Strings containing a hodgepodge of SQL and data aren't an API either.&lt;br/&gt;&lt;br/&gt;It's not all doom and gloom, but my ideas for a future solution to this problem will have to wait for another post.&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=a1688120-d69c-8585-9875-4b9ab4812b86' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/_pHJxyjWZX0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/688326045273799626/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=688326045273799626" title="23 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/688326045273799626?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/688326045273799626?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/_pHJxyjWZX0/oh-atangled-web-we-weave-from.html" title="Oh &amp;lt;what&amp;gt; a.tangled {web, we} WEAVE FROM" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>23</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/oh-atangled-web-we-weave-from.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYASHo6cSp7ImA9WxNRE0s.&quot;"><id>tag:blogger.com,1999:blog-8729083.post-1419935141198728255</id><published>2009-09-07T19:29:00.001-04:00</published><updated>2009-09-07T19:29:09.419-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-07T19:29:09.419-04:00</app:edited><title>Threat 2: Attacks via E-Mail</title><content type="html">&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;div align='left'&gt;Continuing &lt;a href='http://glyph.twistedmatrix.com/2009/06/my-threat-model.html'&gt;my series on simple threat models for internet users&lt;/a&gt;, I'll now address the second threat I mentioned: threats via e-mail.&lt;br/&gt;&lt;br/&gt;There are two kinds of e-mail attacks: direct attacks, and trojan horses.  First let's talk about direct attacks.&lt;br/&gt;&lt;br/&gt;The basic idea behind a direct e-mail attack is that the program you use to &lt;i&gt;read&lt;/i&gt; your e-mail might have flaws in it, which a specially-crafted message will exploit.  That message will have a program in it, and a mistake by the programmers who wrote your e-mail client will cause that program to be executed.&lt;br/&gt;&lt;br/&gt;Unlike attacks from the outside, which you can very simply protect against by denying outside attackers access to your computer entirely, there is no fool-proof method to protect against this kind of threat.  E-mail formats are highly complex, and messages can contain multiple parts, including images, etc.  The code that decodes images is &lt;a href='http://www.ubuntu.com/usn/USN-730-1'&gt;notoriously&lt;/a&gt; &lt;a href='http://www.ubuntu.com/usn/USN-472-1'&gt;prone&lt;/a&gt; to &lt;a href='http://www.microsoft.com/technet/security/bulletin/ms06-001.mspx'&gt;security problems&lt;/a&gt;.  Even e-mail programs which don't process images are &lt;a href='http://www.vuxml.org/freebsd/67c05283-5d62-11d8-80e3-0020ed76ef5a.html'&gt;occasionally prone to security problems&lt;/a&gt; dealing with the structure of certain messages.&lt;br/&gt;&lt;br/&gt;Chances are that you are going to want to read e-mail somewhere, and you probably want to be able to see images and download attachments; shutting off e-mail completely isn't really an option.  The more general advice I gave &lt;a href='http://glyph.twistedmatrix.com/2009/07/threat-1-attacks-from-outside.html'&gt;against the first threat&lt;/a&gt; still applies, though: keep all your software up to date, including your e-mail client.  People who make e-mail software take these kinds of threats very seriously and release updates very quickly when problems are discovered.&lt;br/&gt;&lt;br/&gt;One way you can mitigate this risk, and reduce the amount of work required to keep up to date (and therefore the opportunity for you to forget to do so) is to use a web-based e-mail client like GMail.  If you use GMail, the potentially vulnerable program running on &lt;i&gt;your&lt;/i&gt; computer is just your web browser, and you already need to keep your browser up to date for other reasons.  The code which deals with the structure of messages is all run on the server, and constantly kept up to date by the fine folks at Google.  Similarly, they take steps to protect your browser; stripping out harmful attachments and filtering spam for you so that potentially dangerous messages never reach you.&lt;br/&gt;&lt;br/&gt;The much more common form of e-mail attack is easier to defend against, but is attacking something more potentially vulnerable than your e-mail software: it's attacking &lt;i&gt;you&lt;/i&gt;.  A trojan horse is a program which doesn't do anything tricky to get itself run automatically, but instead elicits your cooperation in making it run.  Whether you run a web-based email client or the oldest, buggiest version of Microsoft Outlook, you are equally vulnerable to these kinds of attacks.&lt;br/&gt;&lt;br/&gt;The key to defending yourself against a trojan horse is to &lt;i&gt;understand what you are double-clicking on&lt;/i&gt;.  Look inside that trojan horse before you open it; there may be a bunch of armed greeks inside.  Before you open any document or run any program that was attached to an e-mail, very carefully read the message that it came from.  Ask yourself a few questions:&lt;br/&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Were you expecting this message?&lt;/b&gt;&lt;br/&gt;If you weren't expecting the message, you should double-check to make sure.  In the best case, use some mechanism other than e-mail to check.  Give the sender a phone call.  Ask if they actually sent you the message in question.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Is the message really from who it says it's from?&lt;br/&gt;&lt;/b&gt;It's &lt;i&gt;very&lt;/i&gt; easy to fake e-mail addresses, so if you are used to receiving messages from Bob Dobbs and you see "From: Bob Dobbs &amp;lt;bobdobbs@example.com&amp;gt;", you shouldn't necessarily believe it.  Does the text of the message read like Bob wrote it?  Does Bob usually send you these kinds of attachments?  Is the "To" line correct?  Does he use your real name?  A lot of spam which includes viruses is very generic, but it is increasingly cleverly disguised as coming from people in your addressbook.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Is an attachment trying to disguise itself?&lt;br/&gt;&lt;/b&gt;Sometimes, even messages you are expecting, from people that you know, will contain evil attachments.  If Bob's computer is infected with a virus, he may well have actually legitimately written you the message but a trojan horse packed itself along for the ride.  In this case, you need to see if the attachment is trying to look like something different than it is.  Does the file's name have multiple extensions?  For example, "business-plan.doc" is a Word document, but "business-plan.doc.exe" is an executable program, with its name changed to &lt;i&gt;pretend&lt;/i&gt; to be a Word document to fool you.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Is anything trying to warn you?&lt;br/&gt;&lt;/b&gt;Most browsers and operating systems these days will double-check with you before opening executables which you've downloaded.  If a box pops up saying "&lt;b&gt;Are you sure you want to do that?&lt;/b&gt;", don't just click past it immediately; read it completely and try to understand what it's telling you.  &lt;i&gt;Even if you don't understand a word&lt;/i&gt;, pausing for a moment to reflect on whether the warning is serious or not will often help you realize that something might be amiss.&lt;br/&gt;&lt;/li&gt;&lt;/ol&gt;If you're careful and look for details which seem out of place, you don't need to be an expert to spot e-mails that look wrong.  The most basic task here is to &lt;b&gt;recognize genuine human communication&lt;/b&gt;, and not to scan for any particular technical trick.  That's not all, of course; as I mentioned, there are ways that programs can hijack legitimate communications, but these are much more sophisticated, and much rarer than the much more common type of message, which is one that simply says "hey buddy, click this" and expects you to click on it without thinking.  If you can recognize those you will be safe 99% of the time.&lt;br/&gt;&lt;br/&gt;In using the Internet, this is a generally useful skill, and particularly important when it comes to security.  It will be particularly useful when I discuss threat #4, phishing attacks.&lt;br/&gt;&lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=ce5f889d-804e-8d88-affb-309b3d87a258' alt='' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/glyph/~4/ZI76IW2CDMI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://glyph.twistedmatrix.com/feeds/1419935141198728255/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=8729083&amp;postID=1419935141198728255" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1419935141198728255?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8729083/posts/default/1419935141198728255?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/glyph/~3/ZI76IW2CDMI/threat-2-attacks-via-e-mail.html" title="Threat 2: Attacks via E-Mail" /><author><name>glyph</name><uri>http://www.blogger.com/profile/07021175796928101086</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_X8hqcsy8KQM/SKTs7BlXY3I/AAAAAAAAACE/733q5QW12Sg/S220/hard-edged-iconograph-blogger.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://glyph.twistedmatrix.com/2009/09/threat-2-attacks-via-e-mail.html</feedburner:origLink></entry></feed>
