The Stochastic Game

Ramblings of General Geekery

Simple workaround for the iPad’s smart cover’s design flaws

I recently got an iPad (more on this later), and with it I got the much hyped smart cover.

IMG_4353.jpg

I loved the simplicity of it, and how quickly you can take it off and put it back on again… However, I quickly realized that I probably had more dust on the screen while using that thing than if I didn’t have any cover at all. Among the problems I had the infamous “dust lines” – those three lines you get on the screen at exactly the same spot as the cover’s folds.

The problem was pretty obvious: the natural way to fold the cover, and the way Apple advertises it, is as follows:

IMG_4357.jpg

But this results in the following situation:

IMG_4354.jpg

The iPad rests on the folded cover as expected, but the outer faces of that triangular stand are the faces that go against the screen when the cover is closed! They would therefore pick up dust and other particle directly from the table and all around, and put them back onto your screen as soon as you walk away… I don’t know where Steve Jobs used to go with his iPad, but my house is not always spotless clean, and neither are any restaurant tables or office desks that I want to put my iPad on.

An easy workaround for this problem is to fold the cover the other way:

IMG_4355.jpg

This way, the faces that go against the screen are actually inside the triangular stand, where they’re very unlikely to pick up any dust. This way of folding is a lot less intuitive, but once you get the hang of it, you can actually close and open it as fast as before. I haven’t had much dust on my screen ever since I started using this technique.

There’s just one big caveat to this workaround: it doesn’t work with the “stand up” mode.

IMG_4358.jpg

If you look closely at the picture above, you’ll notice what’s wrong: gravity alone can unfold the cover and make your iPad fall down on the table. In my case, the magnetic strength of the cover is barely enough to counteract the iPad’s weight and make it stand on its own, but the slightest touch can make it crumble down like a house of a couple of very expensive cards. However, I don’t care because I’ve never felt the need to use that position so far.


Article drafts in PieCrust

A common feature of a blog engine is to let the user work on an article for a while before actually publishing it. Thanks to pagination filtering, it’s pretty easy to do in PieCrust.

All you have to do is add the following to your blog’s home page’s configuration header:

posts_filters:
    not:
        has_tags: draft

This will skip any post that has the draft tag.

You will probably need to add some similar filtering to other pages such as the _tag or _category pages.

Edit: as Keilaron mentioned in the comment, you can’t modify the filters on a tag or category listing page, because their filters are preset to, well, filtering posts with a specific tag or category. This means that, unfortunately, you should not actually tag/categorize your drafts.

Edit 2: as of PieCrust 1.0, it’s possible to use a posts_filters on the _tag or _category pages, so it’s all good!


Fresh PieCrust available

I just pushed version 0.1.2 of PieCrust, the lovely static website generator that powers this blog, and most of my other websites.

Pie, anyone?

Yep, the version was bumped from 0.0.4 to 0.1.2. The main reason is that I very heavily refactored the code to make it a lot more readable and maintanable. This also means a whole new batch of bugs are lurking in the dark!

The main change for users is that there’s no _chef directory anymore. It’s all a lot cleaner, with everything living in _piecrust. Just be sure to delete your old directories before getting the new ones, so you don’t have old junk lying around. This also means that you need to (slightly) change your bootstraping code for running PieCrust. If you didn’t customize anything, you can just grab the new index.php from the sample website and overwrite your own. If not, you may want to check out the updated documentation on PieCrust bootstraping.

Among the new features, you’ll find:

If you want to see what’s planned in the future, there’s also a brand new public
Trello project board
.

Finally, check out the slightly redesigned and reorganized PieCrust website!


PHP is fucked up

You may be shocked by what I’m about to say but here it is: PHP is fucked up.

Well, duh

Oh, no. Wait. No you’re not shocked. You already knew it.

Today’s topic: namespaces.

PHP’s namespace implementation is fucked up. There’s really no way to say it nicely, and you will realize it 5 minutes after starting to use them, when most of your code breaks and you need to litter the beginning of your files with use statements and you really wonder what you gained in the process. It really comes down to the impossibility to import a whole namespace, and PHP’s inability to look into parent namespaces when a class is not found in the current one. Sure, I understand the first feature is actually very tricky in a dynamic language, and the second one may have been rejected because of performance reasons, but with that many downsides you have to wonder why namespaces were implemented at all. Pornel gives a good list of all those downsides in his article on PHP namespaces.

Sure, namespaces let us get rid of the PEAR naming conventions, and they work nicely with spl_autoload_register, but they also gave me my biggest WTF moment in recent history.

Consider the following code:

namespace Foo;

class BarException extends Exception
{
}

class Bar
{
	public function trySomethingSafe()
	{
		try
		{
			throw new BarException("Catch this!");
		}
		catch (Exception $e)
		{
			echo "Caught exception: ".$e->getMessage();
		}
	}
}

It defines a new exception type (FooException), and a class (Bar) that does something safe by wrapping the code of the function inside a try/catch statement.

Now run this from another file:

require_once 'foobar.php';

$b = new FooBar();
try
{
    $b->trySomethingSafe();
}
catch (Exception $e)
{
    echo "This should never show up, right?";
}

Well, guess what you get in your output window? Yep:

This should never show up, right?

It’s like the first try/catch block is not catching the exception! Surely it can’t be a bug in the PHP runtime, right?

Well, of course not. It’s the user’s fault. And that’s because PHP’s namespaces suck ass.

Look at the catch statement in trySomethingSafe: it’s meant to catch all types of exceptions by specifying the top parent Exception type, but this is actually not it. See, that code is inside namespace Foo, and I didn’t specify either a use Exception at the top of the file, nor did I use Exception’s full name, Exception. Yes, that leading backslash is really super important in this case, because it makes all the difference between what you meant (the standard Exception type) and what PHP understands (a completely imaginary FooException type).

To fix the problem, replace the catch clause in trySomethingSafe with this:

catch (Exception $e)

You will then get the expected result:

Caught exception: Catch this!

The tricky thing here is that PHP doesn’t seem to care that FooException doesn’t exist. It happily runs the script, gets the exception, which is of type FooBarException, figures out that the class name does not equal to FooException, and bubbles the exception up the call stack. It doesn’t stop to check that the exception type we want to catch actually exists.

So, yeah. You need to be careful with PHP namespaces, especially when you add them to a previously un-namespaced project.


From Archos to Amazon

As you probably already know, Amazon’s tablet, the Kindle Fire, was announced a few days ago. Priced at a pretty amazing $199, its purpose is more focused than your general usage tablet like the iPad or the Xoom: it’s specifically designed for consuming content like books, music and video (preferably through Amazon’s own services, of course). Although it will probably be possible to install some other apps (through Amazon’s AppStore) to do some email and chatting and gaming and what have you, it will probably be more limited than on those bigger tablets, and will likely be only advertised as the last bullet point on the list of specs, if at all.

Now you know what else was priced around $200 and was useful mostly for consuming content like books, music and video? Yep. The Archos 70 I got last year for $249 (I got it on a discount, it was normally at $279).

Oh sure, Archos may not have been advertising their product like that. They may have advertised it along the lines of:

The most awesome Android tablet ever! Do everything you want! Web browsing! Videos and music! Email!! Games!!! Video chat!!!! This is so awesome we’re running out of exclamation marks!!!!!

Being a long time Archos user, I’m used to their bullshit and I know how to read through it. It usually translates to:

It’s rubbish at everything, especially anything web-related, but it can read any fucking video format in the universe, doesn’t come with any bullshit iTunes-like sync program, and is so much cheaper than the competition.

And as I stated last time, that was just perfect: I only wanted a good portable media player, and maybe a nicer way to read my Instapaper clips. But, of course, everytime somebody saw my small cheap looking tablet, there was a good chance the discussion would go like this:

  • “What’s that?”
  • “My Archos 70. Android tablet. I use it mainly as a portable media player, though.”
  • “Why didn’t you get an iPad?”
  • “Too big. Not enough codec support. Too expensive.”
  • “Yeah but you can do so much more with it!”
  • “Don’t care.”
  • “Come on! Apple is so awesome! The iPad is so shiny!”
  • “Yeah, whatever.”

Well it looks like Amazon found a lot of people like me out there because the Kindle Fire’s product story is exactly what I was looking for a year ago. Well… apart for that one small detail about data freedom, because I’m not sure exactly how easy it will be to get your own content onto the device, without necessarily going through Amazon (especially since most of their content is not even available outside of the U.S. anyway).

At least I’m very happy to see someone try to move the market into a slightly new direction instead of spitting out confusing all-purpose Android tablets like everyone else.


MongoDB for Lucene and ASP.NET

My latest home project (yet to be announced) is using MongoDB for storage, which led me to write a couple of libraries you may be interested in if you use that kind of database. Keep reading for the details.

MongoDB directory for Lucene

MongoDB.Lucene is what you would expected given the name: a MongoDB backend for Lucene indexes.

It’s a simple port of the standard FSDirectory using Mongo’s GridFS storage. I’m sure there’s a lot of room for improvement (performance, storage efficiency, lock reliability), but it’s working well enough for small applications.

It’s available as a NuGet package.

MongoDB providers for ASP.NET

MongoDB.Web is a set of providers for ASP.NET:

  • Membership provider
  • Role provider
  • Profile provider (not fully-featured yet)

It also contains a TraceListener that stores log events in a MongoDB collection.

This one’s got a funny story behind it. I wrote it quickly to get going with the rest of my project, and came back to it later thinking I could clean it up and publish it on the NuGet Gallery… but I got a package ID already exists error because of this similar package also called MongoDB.Web. I guess I should have checked first…

Why did I keep my own version then? Well:

  • My providers use a bit less storage in the database.
  • Provider initialization (like getting the right connection string) has more options (useful when you want to run on AppHarbor for instance, where they have pretty limited configuration customization).

The other version is however fully-featured, and probably better tested.


The extension method trick

If you’ve been writing C# code lately you should be pretty familiar with extension methods: it’s a nice compiler feature added to C# 3.0 which lets you “attach” methods to an existing type.

So for instance, if you define the following extension method:

    static class ConsoleExtensions
    {
        public static void WriteReversed(this TextWriter writer, string message)
        {
            writer.WriteLine(new string(message.Reverse().ToArray()));
        }
    }

You can write:

    Console.Out.WriteReversed("hello world!");

You effectively “extended” the TextWriter type with a new WriteReversed method in which you get a pseudo-this reference. Before extension methods, these types of methods would have been in a ConsoleHelper class of some kind – a lot less discoverable for the clients of your library.

Now, the (not so-)peculiar thing about it is that the pseudo-this variable can be null. Indeed, since this whole feature is only syntactic sugar, as they say, it’s just a more elegant way to write the following, which is a plain old function call:

    ConsoleExtensions.WriteReversed(Console.Out, "hello world!");

But it means it would look like you’re calling a method on a null object without getting slapped in the face with the infamous NullReferenceException.

You just need to add some simple parameter validation code to your extension method:

    static class ConsoleExtensions
    {
        public static void WriteReversed(this TextWriter writer, string message)
        {
            if (writer != null)
                writer.WriteLine(new string(message.Reverse().ToArray()));
        }
    }
    TextWriter writer = null;             // woah, are you crazy!?
    writer.WriteReversed("hello world!"); // woah, this is crazy!!

This trick can be pretty useful if you have an API that aims to be as minimalist as possible for the user and null is a valid case for one of the objects exposed publicly. You can already handle this with various well known techniques like wrapping or the NullObject pattern, but the extension method is a nice new alternative that’s enough in some cases and requires a minimum of code.

I’ve seen that trick used only once so far, in the excellent MvcMiniProfiler:

    using (MiniProfiler.Current.Step("Getting the answer to the ultimate question"))
    {
        var result = DeepThought.Compute();
        ViewBag.UltimateAnswer = result;
    }

Here, it’s totally OK if you disabled profiling in your web application, which means MiniProfiler.Current would return null. That’s because the Step() method is an extension method that checks for a null value provided as “this”, and doesn’t do much in that case.

Sure, they could have abstracted the profiler behind an IProfiler interface and have the MiniProfiler.Current return a NullProfiler when profiling is disabled, or something like that, but that would have been a lot more code than just using an extension method.


Formatting mongo output

If you’re working with MongoDB’s mongo command line tool and you often see yourself reading through this:

> db.contactInfos.find({"source":ObjectId("4e39da93058cfe28a039b546")})

{ "_id" : ObjectId("4e6e9a9f058cfe01dc1bcded"), "source" :ObjectId("4e39da93
058cfe28a039b546"), "sourceId" : "754731", "sourceUserName" : "loudej", "ful
lName" : "Louis DeJardin", "description" : "A software guy on the ASP.NET te
am and author of Spark", "avatarUrl" : "http://a2.twimg.com/profile_images/1
161371928/DSC01367_normal.jpg", "websiteUrl" : "http://louis.dejardin.org",
"location" : "Kenmore, WA", "friendCount" : 97, "followerCount" : 1428 }
{ "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf3"), "source" : ObjectId("4e39da9
3058cfe28a039b546"), "sourceId" : "16925866", "sourceUserName" : "sebastienr
os", "fullName" : "Sébastien Ros", "description" : "", "avatarUrl" : "http:/
/a1.twimg.com/profile_images/1074060902/f71ee9e786d8340a5eb08dd6154c2095_1__
normal.jpeg", "websiteUrl" : "http://about.me/sebastienros", "location" : "S
eattle", "friendCount" : 18, "followerCount" : 142 }
{ "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf4"), "source" : ObjectId("4e39da9
3058cfe28a039b546"), "sourceId" : "768197", "sourceUserName" : "haacked", "f
ullName" : "Phil Haack", "description" : "This bio is not true.", "avatarUrl
" : "http://a2.twimg.com/profile_images/1315393964/image_normal.jpg", "websi
teUrl" : "http://haacked.com/", "location" : "Bellevue", "friendCount" : 225
, "followerCount" : 15947 }

…then you may want to add toArray() at the end of your line:

> db.contactInfos.find({"source":ObjectId("4e39da93058cfe28a039b546")}).toArray()

[
    {
        "_id" : ObjectId("4e6e9a9f058cfe01dc1bcded"),
        "source" : ObjectId("4e39da93058cfe28a039b546"),
        "sourceId" : "754731",
        "sourceUserName" : "loudej",
        "fullName" : "Louis DeJardin",
        "description" : "A software guy on the ASP.NET team and author of Spark",
        "avatarUrl" : "http://a2.twimg.com/profile_images/1161371928/DSC01367_normal.jpg",
        "websiteUrl" : "http://louis.dejardin.org",
        "location" : "Kenmore, WA",
        "friendCount" : 97,
        "followerCount" : 1428
    },

    {
        "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf3"),
        "source" : ObjectId("4e39da93058cfe28a039b546"),
        "sourceId" : "16925866",
        "sourceUserName" : "sebastienros",
        "fullName" : "Sébastien Ros",
        "description" : "",
        "avatarUrl" : "http://a1.twimg.com/profile_images/1074060902/f71ee9e786d8340a5eb08dd6154c2095_1__normal.jpeg",
        "websiteUrl" : "http://about.me/sebastienros",
        "location" : "Seattle",
        "friendCount" : 18,
        "followerCount" : 142
    },
    {
        "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf4"),
        "source" : ObjectId("4e39da93058cfe28a039b546"),
        "sourceId" : "768197",
        "sourceUserName" : "haacked",
        "fullName" : "Phil Haack",
        "description" : "This bio is not true.",
        "avatarUrl" : "http://a2.twimg.com/profile_images/1315393964/image_normal.jpg",
        "websiteUrl" : "http://haacked.com/",
        "location" : "Bellevue",
        "friendCount" : 225,
        "followerCount" : 15947
    }
]

Much more readable, isn’t it? The only problem is that mongo will, by default, return only the first 20 hits of a query (it will write “has more” at the bottom to indicate that, well, there’s more). The toArray() method, however, will get everything and print it out. This could mean printing a lot of stuff, so you may want to stick a limit(20) in between if you’re not sure:

> db.contactInfos.find({"source":ObjectId("4e39da93058cfe28a039b546")}).limit(20).toArray()

New PieCrust features

After several release candidates1 , I finally updated PieCrust to version 0.0.4.

Pie

There are quite a few nice new things in it:

  • pattern-based ability to skip files from baking
  • pagination filtering
  • multi-tag pages
  • multi-blog support
  • various bug fixes and optimizations

More details after the break.

“Skip patterns” for the baker

As part of the ongoing PieCrust cookbook, I blogged about previewing a baked site in IIS or Apache. Back then I mentioned how just one piece was missing to make it simpler: the ability to specify a pattern for files to exclude from baking. Well, I did just that.

Now, in your site configuration, you can specify an array of skip_patterns in the baker category. See the documentation for more info.

Pagination filtering

If you have a page that displays a list of posts, you can now do some custom filtering for those posts. In that page’s configuration header, add a section called posts_filters like such:

posts_filters:
    has_tags: piecrust
    has_tags: cookbook

This will only list blog posts that have both the “piecrust” and “cookbook” tags. This is useful for example if you only want to display important annoucements on your homepage, and have a separate “news” page with all the posts.

For more info, check out the documentation on pagination.

Multi-tag pages

Edit: in PieCrust 1.0RC and above, the multi-tags syntax changed!

PieCrust can generate tag pages, like for example the page listing all my posts related to PieCrust. However, if you want to generate a page that shows all the posts related to the PieCrust cookbook, you would have to specify two tags ("piecrust" and “cookbook”)… that is, assuming you really didn’t want to create specific “piecrust-cookbook” tag.

This is now possible by separating tags with a / like so: cookbook/piecrust. Try it!

If you’re using Twig, the default template engine, or Dwoo, one of the optional ones, it means you can use the pctagurl like so:

{{ pctagurl('cookbook/piecrust') }}

The only limitation is when you bake your site: only tag combinations that you insert with the Twig or Dwoo pctagurl functions will be baked. Since you should always insert links with the pc* functions, it should be all right, but you may want to link to a tag combination from outside your website. If that’s the case, you can specify custom tag combinations to be baked. Check the documentation for more details.

Multi-blog support

PieCrust now also supports multiple blogs in the same website. I debated with myself for quite a long time before adding this feature. On one hand, it felt a bit too complicated for a system that’s supposed to feel simple and natural, but on the other hand, well, I needed it. And after much pondering, I figured out a way to make it rather simple to the user. I think. Maybe. Hopefully.

Anyway, if you have a single-blog site, you don’t have to change anything (yay!). If you want more than one blog… go check out the documentation on multi-blog sites!

Other changes

Other changes include a more clever cache validation mechanism, some new debugging features, and many bug fixes.


  1. a.k.a: Ludovic doesn’t test his shit enough before applying a version tag. ↩︎


Using Mercurial to publish a PieCrust website

These days, all the cool hipster kids want to deploy stuff by pushing a Git or Mercurial repository up to their server.

And that’s pretty cool indeed, because you basically update your website by doing something like:

hg push myserver

So here’s how you can do it with PieCrust (although 90% of this article has nothing to do with PieCrust):

  1. Installing Git/Mercurial/whatever on your server
  2. Setting up your SSH keys
  3. Pushing your repository
  4. Defining hooks/triggers

Keep reading for the meaty details…

I’m going to use Dreamhost as the hosting provider in this pseudo-tutorial, but most of the information would be valid for another provider.

Installing the DSCM on your server

As far as I can tell, Git is installed on most servers at Dreamhost, so that’s already taken care of.

For Mercurial, they seem to have a super old version so you may want to install a more recent one yourself. It’s actually pretty easy since the steps are described on their community wiki. In my case, it boiled down to:

  1. mkdir -p ~/srcs
  2. cd ~/srcs
  3. wget http://mercurial.selenic.com/release/mercurial-1.7.5.tar.gz
  4. tar xvzf mercurial-1.7.5.tar.gz
  5. cd mercurial-1.7.5
  6. make local
  7. make install-home-bin

And then adding the new paths to my ~/.bash_profile and ~/.bashrc:

export PYTHONPATH=~/lib/python
export PATH=~/bin:$PATH

Setting up your SSH keys

If you’re using BitBucket or GitHub, you probably already have some SSH keys lying around somewhere. If not, then, well, create an account at either one (depending on whether you use Mercurial or Git). Not only are those websites super useful, but they can also help you (somewhat) with setting up an SSH access:

The Git help pages are way better than the Mercurial ones, so even if you don’t like Git you may want to check them out if you’re lost.

If your SSH access works with Git/Mercurial, then enable password-less login on your Dreamhost account (you basically just need to copy/paste your public key into an ~/.ssh/authorized_keys file… this should work on any other Unix-based host). This will make things super smooth in the future.

Pushing your repository to Dreamhost

Create a directory in your Dreamhost home to store your repository. For example, with Mercurial:

  1. mkdir -p ~/hg/myproject
  2. cd ~/hg/myproject
  3. hg init .

Now back on your local machine, in your local repository, edit the .hg/hgrc file with:

[paths]
dreamhost = ssh://yourlogin@yourdomain.ext/hg/myproject

If you type hg push dreamhost, it should all work! If not… well… go back to the beginning and start again.

Things would look very similar with Git, and you should be able to do it yourself since you’re already a Git user!

Setting up hooks/triggers

Now’s the time to do actual work. The idea is to run a custom script on your server when you push updates to the repository you have up there.

For example, on the Dreamhost server and using Mercurial, you can edit the ~/hg/myproject/.hg/hgrc file and add:

[hooks]
changegroup = ~/scripts/bake_site.sh

Now you only need to write the actual script bake_site.sh! You probably want something that does:

  1. Export the repository into a temporary folder.
  2. Bake your site in that temporary folder.
  3. If all went well, copy the baked site into your home.
  4. Clean up.

This would look something like:

#!/bin/sh

set -e

HG_REPO_DIR=~/hg/myproject
ARCHIVE_DIR=~/tmp/hg_archival
PUBLIC_DIR=~/yourdomain.com

# Archive (export) the repo.
echo "Archiving repository to ${ARCHIVE_DIR}"
if [ -d ${ARCHIVE_DIR} ]; then
    rm -fr ${ARCHIVE_DIR}
fi
mkdir -p ${ARCHIVE_DIR}
hg archive -r tip ${ARCHIVE_DIR}

# Bake your website
mkdir -p ${ARCHIVE_DIR}/baked
${ARCHIVE_DIR}/_piecrust/chef bake -r http://yourdomain.com/ -o ${ARCHIVE_DIR}/baked ${ARCHIVE_DIR}/mywebsite

# Move baked website into the public directory.
echo "Copying website to ${PUBLIC_DIR}"
cp -R ${ARCHIVE_DIR}/baked/* ${PUBLIC_DIR}

# Clean up.
echo "Cleaning up"
rm -fr ${ARCHIVE_DIR}

But don’t use that script!

Obviously it won’t work for you unless you change a lot of directory names, tweak the options for chef, etc. But it should be a good starting point.

  • I recommend you test your script by first running it manually while logged in via SSH, and after changing the PUBLIC_DIR to some temporary directory. You’ll probably get it wrong a couple times at first, especially if you’re quite rusty with Bash syntax like me.
  • When it’s working as expected, do a repository push and check that the script is baking everything correctly in the temporary directory.
  • If that’s all good, then you can revert PUBLIC_DIR back to its intended path.

Now you can enjoy your new coolness: hg push dreamhost!