<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:gniemeyer</id>
  <title>Gustavo Niemeyer</title>
  <subtitle>Random thoughts</subtitle>
  <author>
    <name>Gustavo Niemeyer</name>
  </author>
  <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/"/>
  <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom"/>
  <updated>2009-10-31T00:21:06Z</updated>
  <lj:journal userid="6599225" username="gniemeyer" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://gniemeyer.livejournal.com/data/atom" title="Gustavo Niemeyer"/>
  <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:22855</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/22855.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=22855"/>
    <title>Google won&amp;#8217;t kill standalone GPS</title>
    <published>2009-10-31T00:17:34Z</published>
    <updated>2009-10-31T00:21:06Z</updated>
    <category term="cloud"/>
    <category term="gps"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;It was already dead.  In some senses, anyway.&lt;/p&gt;
&lt;p&gt;Google &lt;a href="http://googlemobile.blogspot.com/2009/10/announcing-google-maps-navigation-for.html"&gt;announced&lt;/a&gt; a couple of days ago that they&amp;#8217;re advancing into the business of GPS guided navigation, rather than staying with their widely popular offering of mapping and positioning only.  This announcement affected the rest of the industry immediately, and some of the industry leaders in the area have quickly &lt;a href="http://www.wiseandroid.com/NewsItem.aspx?category=News&amp;amp;path=October&amp;amp;itemid=37"&gt;taken a hit&lt;/a&gt; on their share value.&lt;/p&gt;
&lt;p&gt;As usual, Slashdot &lt;a href="http://mobile.slashdot.org/story/09/10/30/1459253/Will-Google-and-Android-Kill-Standalone-GPS?from=rss"&gt;caught up&lt;/a&gt; on the news and asked the question: &lt;i&gt;Will Google and Android kill standalone GPS?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Let me point out that the way the facts were covered by Slashdot was quite misguided.  Google may be giving a hand to change the industry dynamics a bit faster, but both Garmin and TomTom, the companies which reportedly had an impact in their share value, have phone-based offerings of their own, so it&amp;#8217;s not like Google suddenly had an idea for creating a phone-based navigation software which will replace every other offering.  The world is slowly converging towards a multi-purpose device for quite a while, and these multi-purpose devices are putting GPSes in the hands of people that in many cases never considered buying a GPS.&lt;/p&gt;
&lt;p&gt;The real reason why these companies are taking a hit in their shares now is because Google announced it will offer for free something that these companies charge quality money for at the moment, being it in a standalone GPS or not.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:22725</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/22725.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=22725"/>
    <title>Geocaching on the Easter Island</title>
    <published>2009-10-13T23:05:49Z</published>
    <updated>2009-10-14T15:31:36Z</updated>
    <category term="mobile"/>
    <category term="project"/>
    <category term="gps"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;This post is not about what you think it is, unfortunately.  I actually do hope to go to the Easter Island at some point, but this post is about a short story which involves &lt;a href="http://geohash.org"&gt;geohash.org&lt;/a&gt;, &lt;a href="http://geocaching.com"&gt;Groundspeak (from geocaching.com)&lt;/a&gt;, and very very poor minded behavior.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The context&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;So, before anything else, it&amp;#8217;s important to understand what geohash.org is.  As &lt;a href="http://blog.labix.org/2008/02/26/geohashorg-is-public"&gt;announced&lt;/a&gt; when the service was launched (also as a &lt;a href="http://forums.groundspeak.com/GC/index.php?showtopic=186412"&gt;post on Groundspeak&amp;#8217;s own forum&lt;/a&gt;), geohash.org offers short URLs which encode a latitude/longitude pair, so that referencing them in emails, forums, and websites is more convenient, and that&amp;#8217;s pretty much it.&lt;/p&gt;
&lt;p&gt;When people go to geohash.org, they can enter geographic coordinates that they want to encode, and they get back a nice little map with the location, some links to useful services, and most importantly the actual Geohash they can use to link to the location, so as an example they could be redirected to the URL &lt;a href="http://geohash.org/6gkzwgjf3"&gt;http://geohash.org/6gkzwgjf3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course, it&amp;#8217;s pretty boring to be copy &amp;#038; pasting coordinates around, so shortly after the service launched, the support for geocoding addresses &lt;a href="http://blog.labix.org/2008/03/01/enhancements-on-geohashorg"&gt;was also announced&lt;/a&gt;, which means people could type a human oriented address and get back the Geohash page for it.  Phew.. much more practical.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The problem&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;All was going well, until a couple of months ago, when a user reported that the geocoding of addresses wasn&amp;#8217;t working anymore.  After some investigation, it turned out that geohash.org was indeed going over the free daily quota allowed by the geocoding provider used.   But, that didn&amp;#8217;t quite fit with the overall usage reports for the system, so I went on to investigate what was up in the logs.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The cause&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Something was wrong indeed.  The system was getting thousands of queries a day from some application, and not only that, but the queries were entirely unrelated to Geohashes.  The application was purely interested in the geocoding of addresses which the site supported for the benefit of Geohash users.  Alright, that wasn&amp;#8217;t something nice to do, but I took it lightly since the interface implemented could perhaps give the impression that the site was a traditional geocoding system.  So, to fix the situation, the non-Geohash API was removed at this point, and requests for the old API then started to get an error saying something like &lt;i&gt;403 Forbidden: For geocoding without geohashes, please look elsewhere.&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, that wasn&amp;#8217;t the end of the issue.  Last week I went on to see the logs, and the damn application was back, and this time it was using Geohashes, so I became curious about who was doing that.  Could I be mistakingly screwing up some real user of Geohashes?  So, based on the logs, I went on to search for who could possibly be using the system in such a way.  It wasn&amp;#8217;t too long until I found out that, to my surprise, it was &lt;a href="http://www.geocaching.com/iphone/"&gt;Groundspeak&amp;#8217;s iPhone application&lt;/a&gt;.  Groundspeak&amp;#8217;s &lt;i&gt;paid&lt;/i&gt; iPhone application, to be more precise, because the address searching feature is only available for &lt;i&gt;paying&lt;/i&gt; users.&lt;/p&gt;
&lt;p&gt;Looking at the &lt;a href="http://forums.groundspeak.com/GC/index.php?showtopic=228305"&gt;release notes&lt;/a&gt; for the application, there was no doubt.  Version 2.3.1, sent to Apple on September 10th, shortly after the old API was blocked, &lt;i&gt;fixes the Search by Address/Postal Code feature&lt;/i&gt; says the maintainer, and there&amp;#8217;s even a &lt;a href="http://forums.groundspeak.com/GC/index.php?showtopic=230624"&gt;thread discussing the breakage&lt;/a&gt; where the maintainer mentions:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
The geocoding service we&amp;#8217;ve been using just turned their service off. That&amp;#8217;s why things are failing; it was relying on an external service for this feature. We&amp;#8217;re fixing the issue on our end and using a service that shouldn&amp;#8217;t fail as easily. Unfortunately we&amp;#8217;ll have to do an update to the store to get this feature out to the users. This will take some time, but in version 2.4 this will work.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Wait, ok, so let&amp;#8217;s see this again.  First, they were indeed &lt;i&gt;not&lt;/i&gt; using Geohashes at all, and instead using geohash.org purely as a geocoding service.  Then, when the API they used is disabled with hints that the Geohash service is not a pure geocoding service, they workaround this by &lt;i&gt;decoding&lt;/i&gt; the Geohash retrieved and grabbing the coordinates so that they can still use it as a pure geocoding service.  At the same time, they tell their users that they changed to &lt;i&gt;&amp;#8220;a service that shouldn&amp;#8217;t fail as easily&amp;#8221;&lt;/i&gt;.  Under no circumstances they contact someone at geohash.org to see what was going on (shouldn&amp;#8217;t be necessary, really, but assuming immaculate innocence, sending an email would be pretty cool).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Redirecting users to the Easter Island&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;So, yeah, sorry, but I didn&amp;#8217;t see many reasons to sustain the situation.  Not only because it looks like an unfriendly behavior overall, but also because, on their way of using an unrelated free service to sustain their paid application, they were killing the free geocoding feature of geohash.org with thousands of geocoding requests a day, which impacted on the daily quota the service has by itself.&lt;/p&gt;
&lt;p&gt;So, what to do?  I could just disable the service again, or maybe contact the maintainers and ask them to please stop using the service in such a way, after all there are &lt;a href="http://www.google.com/search?q=geocode"&gt;dozens of real geocoding services out there&lt;/a&gt;!  But&amp;#8230; hmmm&amp;#8230; I figured a friendly poke could be nice at this point, before actually bringing up that whole situation.&lt;/p&gt;
&lt;p&gt;And that&amp;#8217;s what happened: rather than blocking their client, the service was modified so that &lt;i&gt;all&lt;/i&gt; of their geocoding requests translated into the geographic coordinates of the &lt;a href="http://geohash.org/3e4jxq9:Easter_Island"&gt;Easter Island&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course, users quickly noticed it and started &lt;a href="http://forums.groundspeak.com/GC/index.php?showtopic=233335"&gt;reporting the problem again&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The answer from Groundspeak&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;After users started complaining loudly, Bryan Roth, which signs as co-founder of Groundspeak, finally contacted me for the first time asking if there was a way to keep the service alive.  Unfortunately, I really can&amp;#8217;t, and provided the whole explanation to Bryan, and even mentioned that I actually use Google as the upstream geocoding provider and that I would be breaking the terms of service doing this, but offered to redirect their requests to their own servers if necessary.&lt;/p&gt;
&lt;p&gt;Their answer to this?  Pretty bad I must say.  I got nothing via email, but they &lt;a href="http://forums.groundspeak.com/GC/index.php?showtopic=233335"&gt;posted this in the forum&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
But seriously, this bug actually has nothing to do with our app and everything to do with the external service we&amp;#8217;ve been using to convert an address into GPS coordinates. For the next app update, we&amp;#8217;re completely dropping that provider since they&amp;#8217;ve now failed us twice. We&amp;#8217;ll be using only Google from that point on, so hopefully their data will be more accurate.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I can barely believe what I read.  They blame the upstream service, as if they were using a first class geocoding provider somewhere rather than sucking resources from a site they felt cool to link their paid application to, take my suggestion of using Google for geocoding, and lie about the fact that the data would be more accurate (it obviously can&amp;#8217;t, since it was already Google that was being used).&lt;/p&gt;
&lt;p&gt;I mentioned something about this in the forum itself, but I was moderated out immediately of course.&lt;/p&gt;
&lt;p&gt;Way to go Groundspeak.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;After some back and forth with Bryan and Josh, the last post got edited away to avoid the misleading details, and Bryan clarified the case in the forum.  Then, we actually settled on my proposal of redirecting the iPhone Geocaching.com application requests to Groundspeak&amp;#8217;s own servers so that users of previous versions of the application wouldn&amp;#8217;t miss the feature while they work on the new release.&lt;/p&gt;
&lt;p&gt;If such communication had taken place way back when the feature was being planned, or when it was &amp;#8220;fixed&amp;#8221; the first time, the whole situation would never have happened.&lt;/p&gt;
&lt;p&gt;No matter what, I&amp;#8217;m glad it ended up being sorted towards a more friendly solution.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:22288</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/22288.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=22288"/>
    <title>Virtual Private Cloud is not the Private Cloud</title>
    <published>2009-08-27T15:12:08Z</published>
    <updated>2009-08-27T15:22:21Z</updated>
    <category term="architecture"/>
    <category term="cloud"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;More than 40 years ago, &lt;a href="http://blog.gardeviance.org/2009/08/cloud-computing-deja-vu.html"&gt;a guy named Douglas Parkhill described the concept of utility computing.&lt;/a&gt;  He described it as containing features such as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Essentially simultaneous use of the system by many remote users.
&lt;li&gt;Concurrent running of different multiple programs.
&lt;li&gt;Availability of at least the same range of facilities and capabilities at the remote stations as the user would expect if he where the sole operator of a private computer.
&lt;li&gt;A system of charging based upon a flat service charge and a variable charge based on usage.
&lt;li&gt;Capacity for indefinite growth, so that as the customer load increases, the system can expanded without limit by various means.
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fast forward 40 years, and we now name pretty much this same concept as &lt;i&gt;Cloud Computing&lt;/i&gt;, and everyone is very excited about the possibilities that exist within this new world.  Different companies are pushing this idea in different ways.  One of the pioneers in that area is of course Amazon, which managed to create a quite good &lt;i&gt;public cloud&lt;/i&gt; offering through their &lt;a href="http://aws.amazon.com"&gt;Amazon Web Services&lt;/a&gt; product.&lt;/p&gt;
&lt;p&gt;This kind of publicly consumable infrastructure is very interesting, because it allows people to do exactly what Douglas Parkhill described 40 years ago, so individuals and organizations can rent computing resources with minimum initial investment, and pay for as much as they need, no more no less.&lt;/p&gt;
&lt;p&gt;This is all good, but one of the details is that not every organization can afford to send data or computations to a public cloud like Amazon&amp;#8217;s AWS.  There are many potential reasons for this, from legal regulations to volume cost.  Out of these issues the term &lt;i&gt;Private Cloud&lt;/i&gt; was coined.   It basically represents exactly the same ideas that Douglas Parkhill described, but rather than using third party infrastructure, some organizations opt to use the same kind of technology, such as the &lt;a href="http://www.eucalyptus.com"&gt;Eucalyptus project&lt;/a&gt; deployed in a private infrastructure, so that the teams within the organization can still benefit from the mentioned features.&lt;/p&gt;
&lt;p&gt;So we have the Public Cloud and the Private Cloud.  Now, what would a &lt;i&gt;Virtual Private Cloud&lt;/i&gt; be?&lt;/p&gt;
&lt;p&gt;Well, it turns out that this is just a &lt;i&gt;marketing term&lt;/i&gt;, purposefully coined to blur the line between a Private and a Public cloud .&lt;/p&gt;
&lt;p&gt;The term was used in &lt;a href="http://aws.amazon.com/about-aws/whats-new/2009/08/26/introducing-amazon-virtual-private-cloud/"&gt;the announcement Amazon has made yesterday&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Amazon VPC enables enterprises to connect their existing infrastructure to a set of isolated AWS compute resources via a Virtual Private Network (VPN) connection, (&amp;#8230;)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;So, what is interesting about this is that this is actually &lt;i&gt;not&lt;/i&gt; a Private Cloud, because the resources on the other side of the VPN are actually &lt;i&gt;public&lt;/i&gt; infrastructure, and as such it doesn&amp;#8217;t solve any of the problems which private clouds were created for solving in the first place.&lt;/p&gt;
&lt;p&gt;Not only that, but it creates the &lt;i&gt;false&lt;/i&gt; impression that organizations would have their own isolated resources.  What isolated resources?  A physical computer?  Storage?  Network?  Of course, isolating these is not economically viable if you are charging 10 cents an hour per computer instance:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Each month, you pay for VPN Connection-hours and the amount of data transferred via the VPN connections. VPCs, subnets, VPN gateways, customer gateways, and data transferred between subnets within the same VPC are free. Charges for other AWS services, including Amazon EC2, are billed separately at published standard rates.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That doesn&amp;#8217;t quite fit together, does it?&lt;/p&gt;
&lt;p&gt;To complete the plot, &lt;a href="http://www.allthingsdistributed.com/2009/08/amazon_virtual_private_cloud.html"&gt;Werner Vogels runs to his blog&lt;/a&gt; and screams out loud &lt;i&gt;&amp;#8220;Private Cloud is not the Cloud&amp;#8221;&lt;/i&gt;, while announcing the &lt;i&gt;Virtual Private Cloud&lt;/i&gt; which is actually a &lt;i&gt;VPN&lt;/i&gt; to his &lt;i&gt;Public Cloud&lt;/i&gt;, with infrastructure shared with the world.&lt;/p&gt;
&lt;p&gt;Sure.  What can I say?  Well, maybe that &lt;i&gt;Virtual Private Cloud is not the Private Cloud&lt;/i&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:22095</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/22095.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=22095"/>
    <title>Accessing RESTful information efficiently</title>
    <published>2009-07-23T23:36:57Z</published>
    <updated>2009-07-23T23:37:31Z</updated>
    <category term="architecture"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Alright, so I appreciate the idea of &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;RESTful Web Services&lt;/a&gt;, but I&amp;#8217;ve got a small dilemma I&amp;#8217;d appreciate some opinions on.&lt;/p&gt;
&lt;p&gt;In the &lt;i&gt;RESTful Web Services&lt;/i&gt; book, by Leonard Richardson and Sam Ruby, there&amp;#8217;s emphasis on making the &lt;i&gt;programmable web&lt;/i&gt; look like the &lt;i&gt;human web&lt;/i&gt;, by following an architecture oriented to having addressable resources rather than oriented to remote procedure calls.  Through the book, the RPC (or REST-RPC, when mixed with some RESTful characteristics), is clearly downplayed.  In some cases, though, it&amp;#8217;s unclear to me what&amp;#8217;s the extent of this advice.  Humans and computers are of course very different in the nature of tasks they perform, and how well they perform them.  To illustrate the point clearly, let me propose a short example.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s imagine the following scenario: we are building a web site with information on a large set of modern books.  In this system, we want to follow RESTful principles strictly: each book is addressable at &lt;i&gt;http://example.com/book/&amp;lt;id&amp;gt;&lt;/i&gt;, and we can get a list of book URIs by accessing &lt;i&gt;http://example.com/book/list?filter=&amp;lt;words&amp;gt;&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Now, we want to allow people to easily become aware of the newest edition of a given book.  To do that, we again follow RESTful characteristics and add a, let&amp;#8217;s say, &lt;i&gt;new-editions&lt;/i&gt; field to the data which composes a book resource.  This field contains a list of URIs of books which are more recent editions of the given book.  So far so good.  Looks like a nice design.&lt;/p&gt;
&lt;p&gt;Now, we want to implement a feature which allows people to access the list of &lt;i&gt;all&lt;/i&gt; recent editions of books in their home library, given that they know the URIs for the books because a client program stored the URIs locally in their machines.  How would we go about implementing this?  We certainly wouldn&amp;#8217;t want to do 200 queries to learn about updates for 200 books which a given person has, since that&amp;#8217;s unnecessarily heavy on the client computer, on the network, and on the server.  It&amp;#8217;s also hard to encode the &lt;i&gt;resource scope&lt;/i&gt; (as defined in the book) in the URI, since the amount of data to define the scope (the 200 books in our case) can be arbitrarily large.  This actually feels like perfectly fit for an RPC: &lt;i&gt;&amp;#8220;Hey, server, here are 200 URIs in my envelope.. let me know what are the updated books and their URIs.&amp;#8221;&lt;/i&gt;  I can imagine some workarounds for this, like saving a temporary list of books with PUT, and then doing the query on that temporary list&amp;#8217;s URI, but this feels like a considerably more complex design just for the sake of purity.&lt;/p&gt;
&lt;p&gt;When I read examples of RESTful interfaces, I usually see examples about how a Google Search API can be RESTful, for instance.  Of course, Google Search is actually &lt;i&gt;meant&lt;/i&gt; to be operated by humans, with a simple search string.  But computers, unlike humans, can thankfully handle a large volume of data for us, and let us know about the interesting details only.  It feels a bit like once the volume of data and the complexity of operations on that data goes up, the ability for someone to do a proper RESTful design goes down, and an RPC-style interface becomes an interesting option again.&lt;/p&gt;
&lt;p&gt;I would be happy to learn about a nice RESTful approach to solve this kind of problem, though.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:21944</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/21944.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=21944"/>
    <title>Screwing up Python compatibility: unicode(), str(), and bytes()</title>
    <published>2009-07-02T15:50:18Z</published>
    <updated>2009-07-02T17:25:27Z</updated>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Backwards and forwards compatibility is an art.  In the very basic and generic form, it consists in organizing the introduction of new concepts while allowing people to maintain existing assets working.  In some cases, the new concepts introduced are disruptive, in the sense that they prevent the original form of the asset to be preserved completely, and then some careful consideration has to be done for creating a migration path which is technically viable, and which at the same time helps people keeping the process in mind.  A great example of what &lt;i&gt;not&lt;/i&gt; to do when introducing such disruptive changes has happened in Python recently.&lt;/p&gt;
&lt;p&gt;Up to Python 2.5, any strings you put within normal quotes (without a leading character marker in front of it) would be considered to be of the type &lt;i&gt;str&lt;/i&gt;, which originally was used for both binary data and textual data, but in modern times it was seen as the type to be used for binary data only.  For textual information, the &lt;i&gt;unicode&lt;/i&gt; type has been introduced in Python 2.0, and it provides easy access to all the goodness of Unicode.  Besides converting to and from &lt;i&gt;str&lt;/i&gt;, it&amp;#8217;s also possible to use Unicode &lt;i&gt;literals&lt;/i&gt; in the code by preceding the quotes with a leading &lt;i&gt;u&lt;/i&gt; character.&lt;/p&gt;
&lt;p&gt;This evolution has happened quite cleanly, but it introduced one problem: these two types were both seen as the main way to input textual data in one point in time, and the language syntax clearly makes it very easy to use either type interchangeably.  Sounds good in theory, but the types are &lt;i&gt;not&lt;/i&gt; interchangeable, and what is worse: in many cases the problem is only seen at runtime when incompatible data passes through the code.  This is what gives form to the interminable &lt;a href="http://www.google.com/search?q=UnicodeDecodeError"&gt;UnicodeDecodeError problem&lt;/a&gt; you may have heard about.  So what can be done about this?  Enter Python 3.0.&lt;/p&gt;
&lt;p&gt;In Python 3.0 an attempt is being made to sanitize this, by promoting the &lt;i&gt;unicode&lt;/i&gt; type to a more prominent position, removing the original &lt;i&gt;str&lt;/i&gt; type, and introducing a similar but incompatible &lt;i&gt;bytes&lt;/i&gt; type which is more clearly oriented towards binary data.&lt;/p&gt;
&lt;p&gt;So far so good.  The motivation is good, the target goal is a good one too.  As usual, the details may complicate things a bit.  Before we go into what was actually done, let&amp;#8217;s look at an ideal scenario for such an incompatible change.&lt;/p&gt;
&lt;p&gt;As mentioned above, when introducing disruptive changes like this, we want a good migration path, and we want to help people keeping the procedure in mind, so that they do the right thing even though they&amp;#8217;re not spending too many brain cycles on it.  Here is a suggested schema of what might have happened to achieve the above goal: in Python 2.6, introduce the &lt;i&gt;bytes&lt;/i&gt; type, with exactly the same semantics of what will be seen in Python 3.0.   During 2.6, encourage people to migrate &lt;i&gt;str&lt;/i&gt; references in their code to either the previously existent &lt;i&gt;unicode&lt;/i&gt; type, when dealing with textual data, or to the new &lt;i&gt;bytes&lt;/i&gt; type, when handling binary data.  When 3.0 comes along, simply kill the old &lt;i&gt;str&lt;/i&gt; types, and we&amp;#8217;re done.  People can easily write code in 2.6 which supports 3.0, and if they see a reference to &lt;i&gt;str&lt;/i&gt; they know something must be done.  No big deal, and apparently quite straightforward.&lt;/p&gt;
&lt;p&gt;Now, let&amp;#8217;s see how to do it in a bad way.&lt;/p&gt;
&lt;p&gt;Python 2.6 introduces the &lt;i&gt;bytes&lt;/i&gt; type, but it&amp;#8217;s not actually a new type.  It&amp;#8217;s simply an alias to the existing &lt;i&gt;str&lt;/i&gt; type.  This means that if you write code to support &lt;i&gt;bytes&lt;/i&gt; in 2.6, you are actually not writing code which is compatible with Python 3.0.  Why on earth would someone introduce an alias on 2.6 which will generate &lt;i&gt;incompatible&lt;/i&gt; code with 3.0 is beyond me.  It must be some kind of anti-migration pattern.  Then, Python 3.0 renames &lt;i&gt;unicode&lt;/i&gt; to &lt;i&gt;str&lt;/i&gt;, and kills the old &lt;i&gt;str&lt;/i&gt;.  So, the result is quite bad: Python 3.0 has both &lt;i&gt;str&lt;/i&gt; and &lt;i&gt;bytes&lt;/i&gt;, and they both mean something else than they did on 2.6, which is the first version which supposedly should help migration, and not a single one of the three types from 2.6 got their names and semantics preserved in 3.0.  In fact, just &lt;i&gt;unicode&lt;/i&gt; exists at all, and it has a different name.&lt;/p&gt;
&lt;p&gt;There you go.  I&amp;#8217;ve heard people learn better from counter-examples.  Here we have a good one to keep in mind and avoid repeating.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:21629</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/21629.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=21629"/>
    <title>My iPhone for an Android!</title>
    <published>2009-07-01T02:50:13Z</published>
    <updated>2009-07-01T02:52:17Z</updated>
    <category term="mobile"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Yes, you&amp;#8217;ve heard it right.  I&amp;#8217;ll exchange a legally unlocked iPhone 3G for a recent Android phone such as the &lt;a href="http://www.phonearena.com/htmls/Samsung-Galaxy-I7500-Preview-review-r_2173.html"&gt;Samsung Galaxy&lt;/a&gt; or the &lt;a href="http://www.engadget.com/2009/06/24/htc-hero-hands-on/"&gt;HTC Hero&lt;/a&gt;, and will pay the difference back! (street price minus 30% of devaluation for the used iPhone 3G).&lt;/p&gt;
&lt;p&gt;I got an iPhone some time ago to learn the concepts introduced in the platform, and get a feeling of how it works out in practice.  I&amp;#8217;m happy I did it, since the hands on experience is worthwhile.  But the experience is done, and even though I have positive things to say about the platform, the &lt;a href="http://toucharcade.com/2009/06/20/full-commodore-64-emulator-rejected-from-app-store/"&gt;omnipotent&lt;/a&gt; &lt;a href="http://apple.slashdot.org/article.pl?sid=09/05/03/029249"&gt;and&lt;/a&gt; &lt;a href="http://news.cnet.com/apple-rejects-nine-inch--nails-iphone-app-update/"&gt;arrogant&lt;/a&gt; &lt;a href="http://arstechnica.com/apple/news/2008/09/apple-rejects-another-app-for-duplicating-functionality.ars"&gt;position&lt;/a&gt; &lt;a href="http://www.eff.org/deeplinks/2009/06/oh-come-apple-reject"&gt;of&lt;/a&gt; &lt;a href="http://www.engadget.com/2009/05/11/apple-rejects-bittorrent-control-app-from-app-store-because-it-m/"&gt;Apple&lt;/a&gt; &lt;a href="http://www.macnn.com/articles/09/05/21/apple.rejects.ebook.reader/"&gt;with&lt;/a&gt; &lt;a href="http://www.macworld.com/article/139316/2009/03/tweetie_rejection.html"&gt;developers&lt;/a&gt; kills any chance of any further involvement I could have with the platform.  I&amp;#8217;m upset enough with it that I don&amp;#8217;t want to see my wife using the device either.&lt;/p&gt;
&lt;p&gt;There are many things in Apple&amp;#8217;s behavior which are a source of arguments, and interminable flamewars, and most of the times I can see both sides of the story.  For instance, when people pay a premium to get the hardware, some feel like it&amp;#8217;s just throwing money away, but if there is good engineering behind it, well.. I understand people may want to pay the premium to get that exclusive product they like.  That said, being so incredibly arrogant in the marketplace, and with &lt;i&gt;developers&lt;/i&gt;, which theoretically should be their most precious partners, since they sustain the platform going, is something I can&amp;#8217;t tolerate.&lt;/p&gt;
&lt;p&gt;I know.. who am I.  Just a random guy that actually gave them some money for one of their products.  But I&amp;#8217;m also a guy that won&amp;#8217;t be buying their upgraded phones, and will be spreading the word to make people realize what a terrible future it will be if Apple ever dominates the marketplace.   Even you&amp;#8217;re not a developer, it&amp;#8217;s a good idea to ponder carefully about this behavior.  It tells a lot about how far they go to defend their own interests, and what kind of &lt;i&gt;lock in&lt;/i&gt; they intend to get you into.&lt;/p&gt;
&lt;p&gt;Finally, compare that to a &lt;a href="http://planetandroid.com/"&gt;nice open source operating system&lt;/a&gt; on which &lt;a href="http://www.openhandsetalliance.com/index.html"&gt;multiple first class vendors are cooperating&lt;/a&gt;.  Sheeshh.. easy choice for me.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:21273</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/21273.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=21273"/>
    <title>Are you ready for the mobile revolution?</title>
    <published>2009-06-24T00:58:45Z</published>
    <updated>2009-06-24T00:58:45Z</updated>
    <category term="mobile"/>
    <category term="gps"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Are you?  I&amp;#8217;m not entirely sure I am, even though I think about this a lot.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re of the tech-savvy kind, you&amp;#8217;re certainly aware of the great capabilities that the &lt;a href="http://planetandroid.com/"&gt;new mobile phone generation&lt;/a&gt; is bringing: Internet connection, a quite decent browser, GPS, camera, etc.  But, really.. did you stop to think about what&amp;#8217;s going on?  This phone generation is still relatively expensive today, but &lt;a href="http://www.engadget.com/2009/05/28/google-at-least-18-android-phones-coming-this-year/"&gt;they&amp;#8217;re here to stay&lt;/a&gt;, and in just a few years, they&amp;#8217;ll be commonplace.&lt;/p&gt;
&lt;p&gt;Now, let&amp;#8217;s forget about ourselves for a moment, and think about what &lt;i&gt;mass adoption&lt;/i&gt; of a quite capable generic computer with full internet connectivity 24h a day being carried with its owner means for the world?  Remember, the &lt;a href="http://www.guardian.co.uk/technology/2008/sep/26/mobilephones.unitednations"&gt;number of mobile phone users in the world&lt;/a&gt; is several times superior to the  &lt;a href="http://www.gizmodo.com.au/2008/06/1_billion_computers_now_in_use_not_necessarily_useful-2/"&gt;number of computers&lt;/a&gt;, and most of the computers are in the so called &lt;i&gt;first world&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;This implies that not only will everyone have access to the world in their pockets, which is already quite amazing by itself, but that a large number of people will have access to the Internet &lt;i&gt;at all&lt;/i&gt; for the first time with their mobiles.  Besides the several social impacts that these changes will bring, there are also many other interesting consequences.  As simple examples,  the &lt;i&gt;most common client&lt;/i&gt; to many web services will be mobile phones, and many people will learn to use a touch screen interface of the mobile to interact with the world before ever having used a desktop computer for that.&lt;/p&gt;
&lt;p&gt;I find that amazing, and this is happening right now, in front of our eyes.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:20996</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/20996.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=20996"/>
    <title>Changing people or changing rules</title>
    <published>2009-05-16T13:02:22Z</published>
    <updated>2009-05-16T13:04:57Z</updated>
    <category term="java"/>
    <category term="c/c++"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In my previous post I made an open statement which I&amp;#8217;d like to clarify a bit further:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;(&amp;#8230;) when the rules don’t work for people, the rules should be changed, not the people.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This leaves a lot of room for personal interpretation of what was actually meant, and TIm Hoffman pointed that out nicely with the following questioning in a comment:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I wonder when the rule is important enough to change the people though. For instance [, if your] development process is oriented to TDD and people don’t write the tests or do the job poorly will you change them then?&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This is indeed a nice scenario to explore the idea.  If it happens at some point that a team claims to be using TDD, but if in practice no developer actually writes tests first, the rules are clearly not working.  If everyone in the team hates doing TDD, enforcing it most probably won&amp;#8217;t show its intended benefits, and that was the heart of my comment.  You can&amp;#8217;t simply keep the rule as is if no one follows it, unless you don&amp;#8217;t really care about the outcome of the rule.&lt;/p&gt;
&lt;p&gt;One interesting point, though, is that when you have a high level of influence over the environment in which people are, it may be possible to tweak the rules &lt;i&gt;or&lt;/i&gt; the processes to adapt to reality, and tweaking the processes may change the way that people feel about the rules as a consequence (arguably, &lt;i&gt;changing people&lt;/i&gt; as a side effect).&lt;/p&gt;
&lt;p&gt;As a more concrete example, if I found myself in the described scenario,  I&amp;#8217;d try to understand why TDD is not working, and would try to discuss with the team to see how we should change the process so that it starts to work for us somehow.  Maybe what would be needed is more discussion to show the value of TDD, and perhaps some pair programming with people that do TDD very well so that the joy of doing it becomes more visible.&lt;/p&gt;
&lt;p&gt;In either case, I wouldn&amp;#8217;t be simply asking people &amp;#8220;&lt;i&gt;Everyone has to do TDD from now on!&lt;/i&gt;&amp;#8220;, I&amp;#8217;d be tweaking the process so that it feels better and more natural to people.  Then, if nothing similar works either, well, let&amp;#8217;s change the rule.  I&amp;#8217;d try to use more conventional unit testing or some other system which people do follow more naturally and that presents similar benefits.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:20793</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/20793.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=20793"/>
    <title>Class member access control: enforcement vs. convention</title>
    <published>2009-05-15T09:26:07Z</published>
    <updated>2009-05-15T09:34:19Z</updated>
    <category term="java"/>
    <category term="c/c++"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;For a long time I&amp;#8217;ve been an advocate of Python&amp;#8217;s notion of controlling access to private and protected members (attributes, methods, etc) with conventions, by simply naming them like &amp;#8220;_name&amp;#8221;, with an initial underline.  Even though Python does support the &amp;#8220;__name&amp;#8221; (with double underscore) for &amp;#8220;private&amp;#8221; members (this actually mangles the name rather than hiding it), you&amp;#8217;ll notice that even this is rarely used in practice, and the largely agreed mantra is that convention should be enough and thus one underscore suffices.  This always resonated quite well with me, since I generally prefer to handle situations by agreement rather than enforcement.  Well, I&amp;#8217;m now changing my opinion.that this works well for this purpose, at least in certain situations.&lt;/p&gt;
&lt;p&gt;This methodology may work quite well in situations where the code scope is within a very controlled environment, with one or more teams which follow strictly a single development guideline, and have the power to refactor the affected code base somewhat easily when the original decisions are too limiting.&lt;/p&gt;
&lt;p&gt;Having worked on a few major projects now, and some of them being libraries which are used by several teams within the same company or outside, I now perceive that people very often take shortcuts over these decisions for getting their job done quickly.  It&amp;#8217;s way easier to simply read the code and get to the private guts of a library than to try to get agreement over the right way to do something, or sending a patch with a suggested change which was carefully architected.&lt;/p&gt;
&lt;p&gt;Many people by now are probably thinking: &amp;#8220;Well, that&amp;#8217;s &lt;i&gt;their&lt;/i&gt; problem, isn&amp;#8217;t it?  If their code base breaks on the next upgrade they&amp;#8217;ll get burden and won&amp;#8217;t be able to upgrade cleanly.&amp;#8221;, and I can honestly understand this feeling, since I shared it.  But, for a number of reasons, I now understand that this isn&amp;#8217;t just &lt;i&gt;their&lt;/i&gt; problem, it&amp;#8217;s very much &lt;i&gt;my&lt;/i&gt; problem too.&lt;/p&gt;
&lt;p&gt;Most importantly, on any serious software, these problems will usually come back to the implementors, and many times the problem will have a much larger magnitude by then than they had at the time a change could have been done &amp;#8220;the right way&amp;#8221; on the implementation, because code dependent on the private bits will have settled.&lt;/p&gt;
&lt;p&gt;Most people are optimist by nature and believe that the implementation won&amp;#8217;t change, but, of course, one of the reasons why private information is made private in the first place is exactly because the implementor believes that having the freedom to change these details in the future is important, and not rarely there&amp;#8217;s already a plan of evolution in place for these private pieces, which may include revamping the implementation entirely for scalability or for other goals.&lt;/p&gt;
&lt;p&gt;In the best case, the careless people will get burden on the upgrade and will ask for support or simply won&amp;#8217;t upgrade silently, and both cases hurt implementors, because providing support for broken software takes time and energy, and amazingly can even hurt the software image. Lack of upgrades also means more ancient versions in the wild to give support for.  Besides these, in the worst case scenario, the careless people have enough influence on the affected project to cause as much burden on it as if the private data was public in the first place.&lt;/p&gt;
&lt;p&gt;As much as I&amp;#8217;m a believer in handling situation by agreement rather than enforcement, I&amp;#8217;m also a believer that when the rules don&amp;#8217;t work for people, the rules should be changed, not the people.  So my positioning now is that the language supported access constraints (public, protected, private), as available in languages like Java and C++, are a better alternative when compared to convention as used today in Python, since they provide an additional layer of encouragement for people to not break the rules carelessly, and that helps in the maintenance and reuse of software that has greater visibility.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:20716</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/20716.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=20716"/>
    <title>Smart Package Manager 1.0</title>
    <published>2008-08-15T00:24:46Z</published>
    <updated>2008-08-15T00:24:46Z</updated>
    <category term="other"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;After 4.5 years in development, &lt;a href="http://lists.labix.org/pipermail/smart-labix.org/2008-August/003703.html"&gt;Smart has been branded as 1.0&lt;/a&gt;. A big Thank You to everyone who contributed along the years.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:20254</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/20254.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=20254"/>
    <title>Wiki + Spreadsheet</title>
    <published>2008-08-12T07:46:18Z</published>
    <updated>2008-08-13T12:56:25Z</updated>
    <category term="project"/>
    <category term="math"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The underlying concept is very simple: spreadsheets are a way to organize text, numbers and formulas into what might be seen as a natively numeric environment: a matrix.  So what would happen if we loosed some of the bolts of the numeric-oriented organization, and tried to reuse the same concepts into a more formatting-oriented environment which is naturally collaborative: a wiki.&lt;/p&gt;
&lt;p&gt;While I do encourage you to answer this with some fantastic new online service (please provide me with an account and the best e-book reader device available once you&amp;#8217;re rich) I had a try at answering this question myself a while ago by writing &lt;a href="http://labix.org/calc"&gt;the Calc macro for Moin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Basically, the Calc macro allows extracting values found in a wiki page into lists (think columns or rows), and applying formulas and further formatting as wanted.&lt;/p&gt;
&lt;p&gt;I believe there&amp;#8217;s a lot of potential on the basic concept, and the prototype, even though functional and useful, surely has a lot to evolve, so I&amp;#8217;ve &lt;a href="https://launchpad.net/moin-calc"&gt;published the project in Launchpad&lt;/a&gt; to make contributions easier. I actually apologize for not publishing it earlier.  There was hope that more features would be implemented before releasing, but now it&amp;#8217;s clear that it won&amp;#8217;t get many improvements from me anytime soon. If you do decide to improve it, please try to prepare patches which are mostly ready for integration, including full testing, since I can&amp;#8217;t dedicate much time for it myself in the foreseeable future.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:20150</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/20150.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=20150"/>
    <title>Write more to write better</title>
    <published>2008-08-04T09:48:25Z</published>
    <updated>2008-08-04T09:52:43Z</updated>
    <category term="other"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In his post &lt;a href="http://www.codinghorror.com/blog/archives/001160.html"&gt;Quantity Always Trumps Quality&lt;/a&gt;, Jeff Atwood made a very interesting reference to an arts-related book:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The ceramics teacher announced on opening day that he was dividing the class into two groups. All those on the left side of the studio, he said, would be graded solely on the quantity of work they produced, all those on the right solely on its quality. His procedure was simple: on the final day of class he would bring in his bathroom scales and weigh the work of the &amp;#8220;quantity&amp;#8221; group: fifty pound of pots rated an &amp;#8220;A&amp;#8221;, forty pounds a &amp;#8220;B&amp;#8221;, and so on. Those being graded on &amp;#8220;quality&amp;#8221;, however, needed to produce only one pot - albeit a perfect one - to get an &amp;#8220;A&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Well, came grading time and a curious fact emerged: the works of highest quality were all produced by the group being graded for quantity. It seems that while the &amp;#8220;quantity&amp;#8221; group was busily churning out piles of work - and learning from their mistakes - the &amp;#8220;quality&amp;#8221; group had sat theorizing about perfection, and in the end had little more to show for their efforts than grandiose theories and a pile of dead clay.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If I tell you that you&amp;#8217;ll get better at doing something if you do it repeatedly you&amp;#8217;ll probably stare at me with a look of obviousness, but even then the correlation made above still feels a bit surprising to a lot of people.  Why is that so?&lt;/p&gt;
&lt;p&gt;I have a guess. In our society we tend to believe that art and innovation is something for the gifted, rather than the product of hard work.  Just think of any great famous painter or musician and you&amp;#8217;ll likely have in your mind the concept of a uniquely gifted genius, rather than someone that worked uniquely hard after a goal.&lt;/p&gt;
&lt;p&gt;Perhaps that&amp;#8217;s why we tend to forget long learned lessons. Some 23 years ago Frederick Brooks already pointed out in &lt;i&gt;The Mythical Man-month&lt;/i&gt; that we should plan to throw away the first version of the software, because it most likely will be a poorly designed prototype that provides insight into the problem for the actual production version.  Even then, it&amp;#8217;s still rare to see the practice &lt;i&gt;intentionally&lt;/i&gt; in use nowadays.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:19868</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/19868.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=19868"/>
    <title>Watch out for list(dict.keys()) in Python 3</title>
    <published>2008-06-27T21:57:20Z</published>
    <updated>2008-06-29T20:04:42Z</updated>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;As everyone is probably aware by now, in Python 3 dict.keys(), dict.values() and dict.items() will all return iterable &lt;em&gt;views&lt;/em&gt; instead of lists.  The standard way &lt;a href="http://www.python.org/dev/peps/pep-3106/"&gt;being suggested&lt;/a&gt; to overcome the difference, when the original behavior was actually intended, is to simply use &lt;code&gt;list(dict.keys())&lt;/code&gt;.  This should be usually fine, but not in all cases.&lt;/p&gt;
&lt;p&gt;One of the reasons why someone might actually &lt;em&gt;opt&lt;/em&gt; to perform a more expensive copying operation is because, with the pre-3.0 semantics, the &lt;code&gt;keys()&lt;/code&gt; method is &lt;em&gt;atomic&lt;/em&gt;, in the sense that the whole operation of converting all dictionary keys to a list is done while the global interpreter lock is held.  Thus, it&amp;#8217;s thread-safe to run &lt;code&gt;dict.keys()&lt;/code&gt; with Python 2.X.&lt;/p&gt;
&lt;p&gt;The suggested replacement in Python 3, &lt;code&gt;list(dict.keys())&lt;/code&gt;, is not.  There&amp;#8217;s a chance that the interpreter will give another thread a chance to run before or during the iteration of the view, and this will cause an exception if the dictionary is modified at the same time.  To fix the problem, either a lock must protect the iteration, or a more expensive operation such as &lt;code&gt;dict.copy().keys()&lt;/code&gt; must be used.&lt;/p&gt;
&lt;p&gt;The 2to3 tool won&amp;#8217;t help you there, unfortunately.  So, keep an eye on it!&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:19485</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/19485.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=19485"/>
    <title>MagLev and distributed VMs</title>
    <published>2008-06-02T01:04:17Z</published>
    <updated>2008-06-02T01:04:17Z</updated>
    <category term="ruby"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Avi Bryant is working on &lt;a href="http://www.avibryant.com/2008/06/maglev-recap.html"&gt;MagLev&lt;/a&gt;, a Ruby interpreter, based on Gemstone&amp;#8217;s Smalltalk VM, with some very amazing features, like transactioned objects distributed across several VMs:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
The integrated VMs, cache, and storage conspire to create an illusion that global state is shared across all instances: no matter how many VMs you add, over however many machines, they all see and work with the same set of Ruby objects.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;My geek side finds this highly exciting, and eager to see it released to see how people will deal with it in practice.&lt;/p&gt;
&lt;p&gt;At the same time, my &lt;i&gt;let&amp;#8217;s-build-stable-and-maintainable-software&lt;/i&gt; side is a bit skeptic.  As Joe Armstrong puts &lt;a href="http://www.infoq.com/presentations/erlang-software-for-a-concurrent-world"&gt;so enthusiastically&lt;/a&gt;, shared state is hard to manage correctly, global transactions reduce scalability, and transparent RPC is seductive, but &lt;a href="http://armstrongonsoftware.blogspot.com/2008/05/road-we-didnt-go-down.html"&gt;dangerous&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m also curious about the speed gains pointed out.  It&amp;#8217;s well known that the Ruby VM isn&amp;#8217;t very fast, which means that there must be opportunities for speedups.  Even then, 100x faster is impressive, and &lt;a href="http://www.sidhe.org/~dan/blog/archives/cat_piethon.html"&gt;history shows&lt;/a&gt; that sometimes the significant improvements are harder when the semantics are precisely the same.  Let&amp;#8217;s hope Avi can manage to &lt;a href="http://headius.blogspot.com/2008/06/maglev.html"&gt;run the Ruby tests successfully&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:19372</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/19372.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=19372"/>
    <title>Improving reading habits</title>
    <published>2008-06-01T20:55:45Z</published>
    <updated>2008-06-01T20:55:45Z</updated>
    <category term="other"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Today, Sunday, on the &lt;a href="http://www.urbandictionary.com/define.php?term=mailman+day"&gt;mailman day&lt;/a&gt;, I decided to change my reading habits.&lt;/p&gt;
&lt;p&gt;You&amp;#8217;d certainly laugh if I told you how many mailing lists, blogs, and IRC channels I try to follow (won&amp;#8217;t include IM networks here as I don&amp;#8217;t really &lt;i&gt;read&lt;/i&gt; them asynchronously).  What I look for is pretty obvious: I want to exchange &lt;i&gt;volume&lt;/i&gt; for &lt;i&gt;quality&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;The first thing I&amp;#8217;m doing is unsubscribing from all high-traffic lists I&amp;#8217;m part of.  The reason is clear: one hundred messages a day can&amp;#8217;t possibly be all interesting.  I&amp;#8217;m not saying there are no interesting posts among these, of course.  But with such a vibrant community of followers, a few smart readers usually bring up the most interesting discussions in more selective formats. I&amp;#8217;ll track these instead.&lt;/p&gt;
&lt;p&gt;For the same reason,  I&amp;#8217;m unsubscribing from most feed aggregators.  &lt;a href="http://en.wikipedia.org/wiki/Planet_aggregator"&gt;Planet&lt;/a&gt; and similars are a great way to subscribe to many feeds quickly, but let&amp;#8217;s face it.. how many posts in &lt;a href="http://www.planetpython.org/"&gt;an aggregator with lots of feeds&lt;/a&gt; are interesting to a single individual?  While getting off from them, I&amp;#8217;m selectively peaking the feeds that interest me and subscribing to each.&lt;/p&gt;
&lt;p&gt;Then, for the not-so-high volume sources, I&amp;#8217;m checking the last 5 posts or so (or days, for IRC channels). Anything  that hasn&amp;#8217;t had information worth tracking will be phased out too.  Interesting topics eventually will find their way to the sources I&amp;#8217;ll still follow.&lt;/p&gt;
&lt;p&gt; I want to read &lt;i&gt;less&lt;/i&gt;, to read &lt;i&gt;more&lt;/i&gt;.  I want to go faster through the queue of pending books, and also follow a wider variety of topics with less pain.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:19184</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/19184.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=19184"/>
    <title>Google using Geohash</title>
    <published>2008-05-21T01:54:15Z</published>
    <updated>2008-05-21T02:02:39Z</updated>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;According to Dave Troy, &lt;a href="http://www.openlocation.org/?p=9"&gt;Google seems to be using&lt;/a&gt; the &lt;a href="http://en.wikipedia.org/Geohash"&gt;Geohash algorithm&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
Google is employing the GeoHash algorithm I’ve been pushing to do spatial searching using BigTable.  Since database schemes like BigTable don’t support traditional GIS extensions/spatial indexes, GeoHash allows for a simple bounding box search using truncated GeoHash substrings.  I will post separately about this shortly, as I am working on some GeoHash tools to expand this functionality.  This is of particular interest to AppEngine developers.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Nice!&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:18583</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/18583.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=18583"/>
    <title>dateutil 1.4 is out</title>
    <published>2008-03-03T03:49:09Z</published>
    <updated>2008-03-03T03:49:09Z</updated>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Friday I&amp;#8217;ve &lt;a href="http://mail.python.org/pipermail/python-announce-list/2008-February/006455.html"&gt;released&lt;/a&gt; version 1.4 of &lt;a href="http://labix.org/python-dateutil"&gt;dateutil&lt;/a&gt;.  There are some interesting fixes there, so please upgrade if you have the chance.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:18392</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/18392.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=18392"/>
    <title>Enhancements on geohash.org</title>
    <published>2008-03-01T21:27:21Z</published>
    <updated>2008-03-01T21:27:21Z</updated>
    <category term="project"/>
    <category term="gps"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Some improvements to &lt;a href="geohash.org"&gt;geohash.org&lt;/a&gt; were made.  Some of them were&lt;br /&gt;
motivated by a conversation with &lt;a href="http://stulzer.net"&gt;Rodrigo Stulzer&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for geocoding addresses (city names, whatever).  E.g. &lt;a href="http://geohash.org/?q=21%20Millbank,%20London"&gt;http://geohash.org/?q=21&amp;nbsp;Millbank,&amp;nbsp;London&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Support for moving the Geohash marker in the embedded map, so that modifying the position visually is easier.&lt;/li&gt;
&lt;li&gt;Support for providing a &amp;#8220;name&amp;#8221; to Geohashes, by appending a colon and the name, in a nice format. E.g. &lt;a href="http://geohash.org/c216ne:Mt_Hood"&gt;http://geohash.org/c216ne:Mt_Hood&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Provided a &lt;a href="http://geohash.org/site/tips.html#gmaps"&gt;bookmark&lt;/a&gt; to get a Geohash while &lt;b&gt;in&lt;/b&gt; Google Maps.&lt;/li&gt;
&lt;li&gt;Provided a &lt;a href="http://geohash.org/site/tips.html#gmaps"&gt;Google Maps Mapplet&lt;/a&gt;.  When enabled, it adds a Geohash marker identifying the Geohash position in Google Maps, and it may be moved around.  Here is a screenshot:&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align: center;"&gt;&lt;img style="border: 1px solid #9999ff" src="http://geohash.org/static/mapplet.png" /&gt;&lt;/div&gt;
&lt;p&gt;Check out the &lt;a href="http://geohash.org/site/tips.html"&gt;Tips &amp;amp; Tricks&lt;/a&gt; page for details on these features.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:18052</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/18052.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=18052"/>
    <title>geohash.org is public!</title>
    <published>2008-02-27T00:11:39Z</published>
    <updated>2008-02-27T00:11:39Z</updated>
    <category term="article"/>
    <category term="project"/>
    <category term="gps"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;After about one year writing this service in my spare time, it&amp;#8217;s finally out.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geohash.org"&gt;geohash.org&lt;/a&gt; offers short URLs which encode a latitude/longitude pair, so that referencing them in emails, forums, and websites is more convenient.&lt;/p&gt;
&lt;p&gt;Geohashes offer properties like arbitrary precision, similar prefixes for nearby positions, and the possibility of gradually removing characters from the end of the code to reduce its size (and gradually lose precision).  I&amp;#8217;ve put the algorithm created in the &lt;b&gt;public domain&lt;/b&gt;.  Some details may be seen in the &lt;a href="http://en.wikipedia.org/wiki/Geohash"&gt;Wikipedia article&lt;/a&gt; about it (hopefully that&amp;#8217;ll help establishing prior art, and prevent Microsoft from &lt;a href="http://www.freepatentsonline.com/20050023524.html"&gt;patenting it&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;To obtain the Geohash, the user provides latitude and longitude coordinates in a single input box (most commonly used formats for latitude and longitude pairs are accepted), and performs the request.&lt;/p&gt;
&lt;p&gt;Besides showing the latitude and longitude corresponding to the given Geohash, users who navigate to a Geohash at geohash.org are also presented with an embedded map, and may download a GPX file, or transfer the waypoint directly to certain GPS receivers. Links are also provided to external sites that may provide further details around the specified location.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:17815</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/17815.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=17815"/>
    <title>Mocker 0.10 and trivial patch-mocking of existing objects</title>
    <published>2007-12-09T23:07:13Z</published>
    <updated>2007-12-10T02:54:20Z</updated>
    <category term="test"/>
    <category term="snippet"/>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://labix.org/mocker"&gt;Mocker&lt;/a&gt; 0.10 is out, with a &lt;a href="https://launchpad.net/mocker/trunk/0.10"&gt;number of improvements&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;While we&amp;#8217;re talking about Mocker, here is another interesting use case, exploring a pretty unique feature it offers.&lt;/p&gt;
&lt;p&gt;Suppose we want to test that a method &lt;i&gt;hello()&lt;/i&gt; on an object will call &lt;i&gt;self.show(&amp;#8221;Hello world!&amp;#8221;)&lt;/i&gt; at some point.  Let&amp;#8217;s say that the code we want to test is this:&lt;/p&gt;
&lt;pre&gt;
 class Greeting(object):

     def show(self, sentence):
         print sentence

     def hello(self):
         self.show("Hello world!")
&lt;/pre&gt;
&lt;p&gt;This is the &lt;i&gt;entire&lt;/i&gt; test method:&lt;/p&gt;
&lt;pre&gt;
def test_hello(self):
    # Define expectation.
    mock = self.mocker.patch(Greeting)
    mock.show("Hello world!")
    self.mocker.replay()

    # Rock on!
    Greeting().hello()
&lt;/pre&gt;
&lt;p&gt;This has helped me in practice a few times already, when testing some involved situations.&lt;/p&gt;
&lt;p&gt;Note that you can also &lt;i&gt;passthrough&lt;/i&gt; the call.  In other words, the call may actually be made on the real method, and mocker will just assert that the call was really made, whatever the effect is.&lt;/p&gt;
&lt;p&gt;One more important point: mocker ensures that the real method &lt;i&gt;exists&lt;/i&gt; in the real object, and has a specification compatible with the call made.  If it doesn&amp;#8217;t, and assertion error is raised in the test with a nice error message.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;UPDATE:&lt;/b&gt; &lt;i&gt;The method for doing this is actually mocker.patch() rather than mocker.mock(), as documented. Apologies.&lt;/i&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:17468</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/17468.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=17468"/>
    <title>Partial stubbing of os.path.isfile() with Mocker</title>
    <published>2007-11-22T23:27:15Z</published>
    <updated>2007-11-22T23:27:15Z</updated>
    <category term="test"/>
    <category term="snippet"/>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;One neat feature which Mocker offers is the ability to very easily implement custom behavior on specific functions or methods.&lt;/p&gt;
&lt;p&gt;Take for instance the case where you want to pretend to some code that a given file exists, but you don&amp;#8217;t want to get on the way of everything else which needs the same function: &lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt;&amp;gt; from mocker import *
&amp;gt;&amp;gt;&amp;gt; mocker = Mocker()
&amp;gt;&amp;gt;&amp;gt; isfile = mocker.replace("os.path.isfile", count=False)
&amp;gt;&amp;gt;&amp;gt; _ = expect(isfile("/non/existent")).result(True)
&amp;gt;&amp;gt;&amp;gt; _ = expect(isfile(ANY)).passthrough()

&amp;gt;&amp;gt;&amp;gt; mocker.replay()

&amp;gt;&amp;gt;&amp;gt; import os
&amp;gt;&amp;gt;&amp;gt; os.path.isfile("/non/existent")
True
&amp;gt;&amp;gt;&amp;gt; os.path.isfile("/etc/passwd")
True
&amp;gt;&amp;gt;&amp;gt; os.path.isfile("/other")
False

&amp;gt;&amp;gt;&amp;gt; mocker.restore()

&amp;gt;&amp;gt;&amp;gt; os.path.isfile("/non/existent")
False
&lt;/pre&gt;
&lt;p&gt;Notice that the &lt;i&gt;count=False&lt;/i&gt; parameter is available in version 0.9.2.  Without it Mocker will act in a more &lt;i&gt;mocking-strict&lt;/i&gt; way and enforce that the given expressions should be executed precisely the given number of times (which defaults to one, and may be modified with the &lt;i&gt;count()&lt;/i&gt; method). &lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:17253</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/17253.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=17253"/>
    <title>More releases: dateutil 1.3 and nicefloat 1.1</title>
    <published>2007-11-19T22:24:33Z</published>
    <updated>2007-11-19T22:24:33Z</updated>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A couple of additional releases tonight: &lt;a href="http://labix.org/python-dateutil"&gt;dateutil 1.3&lt;/a&gt;, and &lt;a href="http://labix.org/python-nicefloat"&gt;nicefloat 1.1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;They&amp;#8217;re both bug fixing releases.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:16992</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/16992.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=16992"/>
    <title>Mocker 0.9</title>
    <published>2007-11-17T21:01:49Z</published>
    <updated>2007-11-17T21:01:49Z</updated>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A few more &lt;a href="http://codebrowse.launchpad.net/~niemeyer/mocker/trunk/annotate/?file_id=news-20071112015353-3p0wa0n8cx1s5crs-1"&gt;improvements&lt;/a&gt; were made to &lt;a href="http://labix.org/mocker"&gt;Mocker&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:16836</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/16836.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=16836"/>
    <title>Storm has always reused connections (connection pooling?)</title>
    <published>2007-11-17T19:57:10Z</published>
    <updated>2007-11-17T19:57:10Z</updated>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I&amp;#8217;ve recently seen some comments here and there about the &lt;i&gt;lack&lt;/i&gt; of connection pooling as an argument for Storm to be faster, and that once this is supported it will be slower, or even as a reason for people not to use Storm at all.&lt;/p&gt;
&lt;p&gt;So, let me kill this argument here, at once.&lt;/p&gt;
&lt;p&gt;We have &lt;b&gt;not&lt;/b&gt; developed Storm only for toy projects that take 10 connections a day.  We have developed Storm for heavy duty web sites like &lt;a href="http://www.canonical.com/projects/landscape"&gt;Landscape&lt;/a&gt; and &lt;a href="https://launchpad.net"&gt;Launchpad&lt;/a&gt;, and we&amp;#8217;re proud to see it being used not only in our systems, but also out there in the wild, like for instance in large scale sites developed by the fantastic guys at &lt;a href="http://www.lovelysystems.com"&gt;Lovely Systems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So how does the &lt;i&gt;connection reuse&lt;/i&gt; work in practice, you ask.  Here is how:&lt;/p&gt;
&lt;p&gt;In Storm, the database is abstracted behind a small, simple, and flexible API, offered in the &lt;i&gt;Store&lt;/i&gt; class.  You use an instance of this class to deal with objects coming from a given database, and this instance will handle several aspects of your interaction with the database, such as committing, rolling back, caching, ensuring that a given row in the database maps to a single instance in memory, control of dirty objects, flushing, and so on.  Pretty much all of these aspects require a correct transactional behavior to work well, and in practice this means we&amp;#8217;ve decided that to maintain the API nice and clean, each Store is internally associated with a single &lt;i&gt;Connection&lt;/i&gt; object. You can have as many stores as you want, connecting to the same database or to different ones, and using the same model class or entirely different code bases.&lt;/p&gt;
&lt;p&gt;So, to summarize the above paragraph, a simple &lt;i&gt;Store&lt;/i&gt; instance is your portal to the database.  You need one of these instances around to add objects to the database (Storm won&amp;#8217;t &lt;i&gt;guess&lt;/i&gt; which Store you want to add things to), and to retrieve objects from it.&lt;/p&gt;
&lt;p&gt;Considering that, if you want to reuse a connection, it&amp;#8217;s very simple: keep your Store instance around.  That&amp;#8217;s even a strange advice, since you&amp;#8217;re &lt;i&gt;already&lt;/i&gt; doing that if you&amp;#8217;re using Storm in the first place.  The code in &lt;i&gt;trunk&lt;/i&gt;, which is about to be released as version 0.12, even handles reconnections for you gracefully, including correct transactional behavior.&lt;/p&gt;
&lt;p&gt;We even offer a tool that deals with more advanced Store management in a very comfortable way for Zope 3.  In the future, we&amp;#8217;re likely to offer the same kind of facility in a more generic API.&lt;/p&gt;
&lt;p&gt;So, connection &lt;i&gt;reuse&lt;/i&gt; is there, and we have &lt;i&gt;always&lt;/i&gt; benefited from it.  Connection &lt;i&gt;pooling&lt;/i&gt;?  No, thanks.  We&amp;#8217;re doing very well without the complexity and overhead.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:gniemeyer:16491</id>
    <link rel="alternate" type="text/html" href="http://gniemeyer.livejournal.com/16491.html"/>
    <link rel="self" type="text/xml" href="http://gniemeyer.livejournal.com/data/atom/?itemid=16491"/>
    <title>Mocker for Python released!</title>
    <published>2007-11-12T02:17:00Z</published>
    <updated>2007-11-12T03:04:17Z</updated>
    <category term="test"/>
    <category term="project"/>
    <category term="python"/>
    <content type="html">&lt;p style="border: 1px solid black; padding: 3px;"&gt;Blog has &lt;a href="http://blog.labix.org"&gt;moved&lt;/a&gt;! Please, &lt;a href="http://blog.labix.org/?p=63"&gt;update your links&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;After being bored for a long time for the lack of a better infrastructure for creating &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;test doubles&lt;/a&gt; in Python, I decided to give it a go.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m actually quite happy with what came out.. it took me about four weekends (was developed as a personal project), and I&amp;#8217;ll dare to say that it&amp;#8217;s the best mocking system for Python at the present time.  Not only that, but it has features that I&amp;#8217;ve not seen in any other mocking/stubing infrastructure, independent of language.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a feature list to catch your attention:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt; Graceful platform for test doubles in Python (mocks, stubs, fakes, and dummies).
&lt;li&gt; Inspiration from real needs, and also from pmock, jmock, pymock, easymock, etc.
&lt;li&gt; Expectation of expressions defined by actually using mock objects.
&lt;li&gt; Expressions may be replayed in any order by default,
&lt;li&gt; Trivial specification of ordering between expressions when wanted.
&lt;li&gt; Nice parameter matching for defining expectations on method calls.
&lt;li&gt; Good error messages when expectations are broken.
&lt;li&gt; Mocking of many kinds of expressions (getting/setting/deleting attributes, calling, iteration, containment, etc)
&lt;li&gt; Graceful handling of nested expressions (e.g. &amp;#8221;person.details.get_phone().get_prefix()&amp;#8221;)
&lt;li&gt; Mock &amp;#8221;proxies&amp;#8221;, which allow passing through to the real object on specified expressions (e.g. useful with &amp;#8221;os.path.isfile()&amp;#8221;).
&lt;li&gt; Mocking via temporary &amp;#8221;patching&amp;#8221; of existent classes and instances.
&lt;li&gt; Trivial mocking of any external module (e.g. &amp;#8221;time.time()&amp;#8221;) via &amp;#8221;proxy replacement&amp;#8221;.
&lt;li&gt; Mock objects may have method calls checked for conformance with real class/instance to prevent API divergence.
&lt;li&gt; Type simulation for using mocks while still performing certain type-checking operations.
&lt;li&gt; Nice (optional) integration with &amp;#8221;unittest.TestCase&amp;#8221;, including additional assertions (e.g. &amp;#8221;assertIs&amp;#8221;, &amp;#8221;assertIn&amp;#8221;, etc).
&lt;li&gt; More &amp;#8230;
&lt;/ul&gt;
&lt;p&gt;Worked?  &lt;a href="http://labix.org/mocker"&gt;Check it out!&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
</feed>
