<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>mixedCase.nl</title>
    <link href="http://mixedcase.nl/articles/feed.xml" rel="self" />
    <link href="http://mixedcase.nl/articles/" />
    <updated>2013-04-13T20:05:31+00:00</updated>
    <id>http://mixedcase.nl/articles/</id>
    <entry>
        <title type="html"><![CDATA[JobControl is six years old]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2013/04/10/dmmjobcontrol-six-years-old/"/>
        <published>2013-04-10T00:00:00+00:00</published>
        <updated>2013-04-10T19:30:44+00:00</updated>
        <id>http://mixedcase.nl/articles/2013/04/10/dmmjobcontrol-six-years-old/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>I absolutely love open source software. I use all kinds of third party libraries for iOS for example (installed via the open source <a href="http://www.cocoapods.org">CocoaPods</a> project of course), which makes my life as a developer a whole lot easier. And in return I open source <a href="/projects/">some of my work</a> and share it with the community. I&#39;m currently maintaining and/or contributing to more then ten open source projects.</p>
<p>My very first open source project is having a birthday this month: in April 2007 I started <a href="http://typo3.org/extensions/repository/view/dmmjobcontrol">JobControl</a> while working for a web development company in The Netherlands. It&#39;s an extension, written in PHP, for the TYPO3 content management system, and it&#39;s used for showing job openings on a website. We used it a lot in our own projects for our clients and I asked the CEO of the company if I could open source the code so the community could use it and make it better in the process. He said yes, and JobControl became the company&#39;s (and mine) first ever open source project after I wrote extensive documentation for the project.</p>
<p>Open sourcing the code turned out to be a great idea: people submitted translations (the extension was soon available in English, Dutch, German, Danish, Polish and Russian), bug fixes and even completely new features. Many developers used JobControl is their TYPO3 site as well, seeing the number of downloads rise every day was very exiting.</p>
<p>I maintained the extension until June 2009, when I quit the company. In those two years and three months I released <a href="https://github.com/kevinrenskers/dmmjobcontrol/blob/master/CHANGELOG">49 updates</a>, kept the <a href="http://typo3.org/extension-manuals/dmmjobcontrol/current/">documentation</a> up to date and handled developer support. After I left, the company released two more updates in 2010, and that was it. </p>
<p>Meanwhile, I was still getting support requests about JobControl, but I simply referred them to my old employer. It wasn&#39;t my personal extension after all, in fact I didn&#39;t even use PHP or TYPO3 any more since I left the company in June 2009. After some time it became clear that the company abandoned JobControl: nobody received help, new versions of TYPO3 weren&#39;t supported, bugs didn&#39;t get fixed, and I decided to adopt JobControl.</p>
<p>In August of 2012 I got a hold of the code, <a href="https://github.com/kevinrenskers/dmmjobcontrol">put it on GitHub</a> and started on the first update in over two years. Transferring ownership of the extension in TYPO3&#39;s extension repository was a bit harder, but in the end I released the update that fixed compatibility with all recent versions of TYPO3. JobControl was now officially back from the dead! Since then I released twelve more updates, fixing bugs, adding new features and updating the documentation.</p>
<p>As I still don&#39;t use PHP or TYPO3 myself, maintaining JobControl is purely a hobby and most new features will need to come from the community. I&#39;ll keep it bug free, but can&#39;t give free support for example. This has made JobControl, my first ever open source project, also the first one where I earn some money doing paid support and development. If you want my help or want me to create a new feature - very cool, but you&#39;ll need to compensate me for my free time.</p>
<p>The idea of paying for open source development is probably a bit weird for many people, but it seems most businesses are fine with this and it keeps it interesting for me, keeping the extension alive and kicking. Here&#39;s to the next six years!</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Apple&#39;s worst iOS framework: MediaPlayer]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2013/01/29/mediaplayer-apples-worst-framework/"/>
        <published>2013-01-29T00:00:00+00:00</published>
        <updated>2013-03-23T10:56:28+00:00</updated>
        <id>http://mixedcase.nl/articles/2013/01/29/mediaplayer-apples-worst-framework/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>When I started to work on Last.fm&#39;s <a href="http://www.last.fm/hardware/ios">Scrobbler for iOS</a>, I though it would be quite an easy app to create. After all, it&#39;s basically a couple of lists of artists, albums and tracks, and all actual music playback will be done using the MediaPlayer framework. Boy, was I wrong.</p>
<p><em>Note: when talking about MediaPlayer, I am mostly talking about <code>[MPMusicPlayerController iPodMusicPlayer]</code>.</em></p>

<h2 id="toc_0">Problem 1: notifications in the background</h2>
<p>The number one feature of the Scrobbler is of course that it scrobbles, which means sending the tracking you&#39;re playing to your Last.fm profile. This has to be extremely reliable, and should preferably work in realtime, even when the app is in the background. The basics are really simple: the app subscribes to the <code>NowPlayingItemDidChangeNotification</code> notification, and on every track change you get a callback and you can do whatever it is you need to: in our case sending the scrobble to the Last.fm servers. Problem: this only works when the app is running in the foreground. As soon as the screen automatically locks or you open another app, your app won&#39;t get the notifications, and thus you can&#39;t scrobble.</p>

<h2 id="toc_1">Problem 2: music is played back via the native Music app</h2>
<p>We&#39;re using the MediaPlayer framework to play back whatever track you select in the app, and quickly found a problem: the native Music app is actually doing the playback, not some background API that&#39;s invisible to the user. That means that the Music app is visible in the iOS multitasking bar, and its icon will be displayed as the app that&#39;s playing music, not Scrobbler&#39;s icon. It&#39;s a small problem, until we discovered that some people are obsessive about killing apps that they&#39;re not using via the multitasking bar. And when they kill the Music app, of course the music stops, even though in their mind they&#39;re using Scrobbler to play their tracks.</p>

<h2 id="toc_2">Problem 3: AVPlayer can&#39;t play iTunes Match content in the cloud</h2>
<p>So, we had 2 problems to solve: we need notifications in the background, and the client wants to see his icon as the app that&#39;s playing music. My proposed solution was to switch to AVPlayer for music playback. Your app is then the one doing the actual playback so the correct icon will be displayed, plus you&#39;re alive in the background and thus notifications will be received. Meaning, we can scrobble while in the background. Sounds good! So I created <a href="https://github.com/gangverk/GVMusicPlayerController">GVMusicPlayerController</a>, &ldquo;the power of AVPlayer with the simplicity of MPMusicPlayerController&rdquo;, because while AVPlayer will let your app be alive in the background, it doesn&#39;t offer the MediaPlayer features like queries, queues, shuffling, repeat modes and all that good stuff. I was really happy with the result, it did exactly what I needed it to do: with minor changes in my app, I now had solved my 2 problems.</p>
<p>Until I found problem number three: AVPlayer can&#39;t play music in the cloud, so the Scrobbler app would be useless to anyone using iTunes Match. Needless to say, this was unacceptable, and I switched back to the standard MediaPlayer framework. Problems one and two were once again unsolved.</p>
<p>In the end we solved the background problem by playing a silent audio track using AVPlayer, while playing all music using the MediaPlayer framework. It&#39;s a stupid hack, but the only way to stay alive in the background and support iTunes Match as well. This solution brought its own set of problems to solve like battery drain, but let&#39;s get back to MediaPlayer&#39;s problems.</p>

<h2 id="toc_3">Problem 4: broken playbackState</h2>
<p>When you ask the MediaPlayer what its play state is, you would expect an honest answer, right? Apparently Apple doesn&#39;t think this is necessary, and so even though music is clearly playing, sometimes the system will happily tell you that it&#39;s currently paused or stopped. This causes a lot of problems in our interface, as the state of play / pause buttons is dependent on the proper response from the MediaPlayer. Right now, this scenario happens all too often: music is playing, but the play / pause button is set to &ldquo;play&rdquo; instead of &ldquo;pause&rdquo;. Hitting it doesn&#39;t do anything either, because music is already playing.</p>
<p>Our solution is to always call play and then pause when you want to pause. And when you hit play, I first call pause, then play. The button state will often fix itself after that as well. It&#39;s an extremely annoying problem that Apple should really fix, but instead it has only gotten worse with iOS6. All third party music playback apps (that use MediaPlayer) suffer from the same problem, and I don&#39;t even want to think about the amount of time that we&#39;ve wasted on it.</p>

<h2 id="toc_4">Problem 5: you can&#39;t read the queue</h2>
<p>The client had a simple request: the Scrobbler app should show the playback queue in a table, just like the native Music app does. Again one of those things that sound very easy, but no: it&#39;s completely impossible to read the queue from the MediaPlayer. So, right now the Scrobbler app keeps its queue. Every time the user plays a track, no matter if it&#39;s coming from an artist page, album or the &ldquo;all tracks&rdquo; list, we make a copy of the queue before setting it on MediaPlayer. This makes the app sluggish when the user plays a track from the &ldquo;all tracks&rdquo; list, because the queue is <strong>all</strong> his tracks. Saving this list locally takes time. Another fun problem: what to do when the user changes the queue directly in the Music app, for example by playing a different album? Since the queue wasn&#39;t set from the Scrobbler app it&#39;s still displaying the old queue, and since we can&#39;t read the queue from MediaPlayer, there&#39;s no way to tell the user what&#39;s really up next.</p>
<p>Right now we detect when a track is started that&#39;s not part of the current queue, while the app is in the background. This means the queue was changed from outside the Scrobbler app, so then we clear the local queue and message the user, telling him we can&#39;t show his play queue because it was changed from outside the app.</p>

<h2 id="toc_5">Problem 6: you can&#39;t edit the queue</h2>
<p>In the Scrobbler app we have a nifty &ldquo;smart playlists&rdquo; feature, kind of like iTunes Genius, where we create a playlist based on similarities in tracks. Let&#39;s say you&#39;re listening to the &ldquo;slow music&rdquo; smart playlist, and one of the tracks isn&#39;t slow at all. We have this &ldquo;doesn&#39;t belong&rdquo; button, where you can remove this track from the playlist, training the system in the process. Of course, we need to remove this track from your playback queue as well, or it will still come up next. Yeah.. that&#39;s not possible. You can&#39;t edit the queue, you can&#39;t only set a new one. Normally you would then get the current queue, create a local mutable copy, remove the one track and set the queue to your modified copy. But like I said, the queue can&#39;t be read. Luckily, I was already saving a local copy of the queue to deal with problem five.</p>
<p>So, we set the new queue to our current-queue-minus-one version, but the removed track is still played as part of the queue. What gives? Turns out the new queue isn&#39;t actually set until you send the <code>play</code> message to MediaPlayer as well, which results in your currently playing track restarting. Not really what you&#39;d call a smooth experience. So, you have to save the current position of the current track, set the new queue-minus-the-one-track, send the <code>play</code> message and fast forward to the saved position. The user will have a hick up of about a second, but it&#39;s the best we could do.</p>
<p>It&#39;s a lot worse when the user has shuffle enabled though: in that case a completely different random track will start to play, and there&#39;s nothing we can do about that.</p>

<h2 id="toc_6">Problems, problems and more problems</h2>
<p>Not convinced yet that MediaPlayer is Apple&#39;s worst framework?</p>

<ul>
<li>MediaQueries are horribly simple, with no advanced queries possible (&ldquo;all tracks from the 90&#39;s with no rating&rdquo;)</li>
<li>MediaQueries can&#39;t be sorted either, so sorting on number of plays or track rating is but a dream</li>
<li>Tracks are readonly, so you can&#39;t change the rating, lyrics or any other metadata</li>
<li>The shuffle and repeat modes have completely useless &ldquo;default&rdquo; values, where you don&#39;t actually know what they&#39;re set to, so using these values to show the status in your app is not possible</li>
<li>When you set MediaPlayer&#39;s shuffle or repeat modes and go to the native music app, its shuffle and repeat icons have not been updated to reflect the new states</li>
</ul>
<p>All of these problems made sure that this &ldquo;it&#39;s just a music player&rdquo; app took way longer to create then anticipated, while giving a lot more headaches then ever thought possible.</p>
<p>In the end we&#39;ve solved almost all of the problems and Scrobbler for iOS came out really good. I&#39;m immensely proud of it, I just wish that we didn&#39;t have this much problems on the way. Most of the iOS frameworks are very good and good to work with. I have no clue why Apple created such a horrible mess with MediaPlayer. It&#39;s buggy as hell, under powered and over simplified.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[The software I used in 2012]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2013/01/07/software-used-2012/"/>
        <published>2013-01-07T00:00:00+00:00</published>
        <updated>2013-04-11T20:08:52+00:00</updated>
        <id>http://mixedcase.nl/articles/2013/01/07/software-used-2012/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>As a software developer, I use a lot of software and tools to help me in my job. In this post I&#39;d like to list some of my most used software of the last year. Hopefully there are some gems that can help you as well!</p>

<h2 id="toc_0">Xcode</h2>
<p>As an iOS developer, this Objective-C IDE simply has to be listed first. We&#39;ve had some good updates in 2012: Xcode 4 finally got stable and the automatically synthesized properties and &ldquo;modern Objective-C syntax&rdquo; that 4.4 brought were very welcome. Sometimes Xcode is still acting up in <a href="http://www.textfromxcode.com">weird ways</a> but overall I can&#39;t complain much anymore.</p>

<h2 id="toc_1">Dropbox</h2>
<p>Not only do I use it a lot personally (for documents, code, backups and a lot more), some clients share Dropbox folders with me as well. It&#39;s the perfect way to be in sync with the designer, to get new assets, screenshots and wireframes. It&#39;s too bad quite a lot of offices seem to block Dropbox, or I would simply demand from all clients that they&#39;d use it :)</p>

<h2 id="toc_2">1Password</h2>
<p>A long, long time ago I used to use the same password for all my accounts. It was a good password and I guess many people still use one password to rule them all, but holy crap it&#39;s so dangerous. If one site gets hacked and someone gets your password, he has access to your entire online life. So, I started to use a couple of different passwords, but since I had to remember them, they were not what you&#39;d call very strong. In 2009 or so I bought a license to <a href="https://agilebits.com/onepassword">1Password</a> ($50), and since then it&#39;s the first app that gets installed on my computers - together with Dropbox.</p>
<p>1Password keeps a secure database of all your randomly generated (and very very secure) passwords, and protects it with a master password. If you need to login to a website, you can simply press a keyboard shortcut in your web browser, type in your master password, and 1Password logs you in. So now I have an unique password per site, they are very very strong, and I can login everywhere with just one keyboard shortcut. The encrypted database is stored on Dropbox and is synced with 1Password across multiple Macs, my iPhone and iPad.</p>

<h2 id="toc_3">PyCharm</h2>
<p>In 2011 I started to use <a href="http://www.jetbrains.com/pycharm/">PyCharm</a> after a <a href="/articles/2011/04/05/search-perfect-python-ide-django/">long search for the perfect Python IDE</a>. Nowadays I don&#39;t do a lot of Python or Django anymore, but I still love to use PyCharm for HTML, CSS and Javascript. And of course, the few times that I do touch Python code, PyCharm is the first app that I start.</p>

<h2 id="toc_4">Sublime Text 2</h2>
<p>After everybody was raving about Sublime Text 2 in 2011 or so, I also installed it. I don&#39;t like it that much actually, but for quickly editing some text files it&#39;s a good option, when starting PyCharm would simply be overkill. I do love the file overview / scroller on the right.</p>

<h2 id="toc_5">TotalFinder</h2>
<p>I loved TotalFinder, it brought dual panes to Finder and reminded me of good old (and dearly missed) Total Commander for Windows. Some performance problems however have caused me to switch to ForkLift somewhere in the middle of the year.</p>

<h2 id="toc_6">ForkLift</h2>
<p>A dual pane file browser like TotalFinder, but instead of &ldquo;patching&rdquo; Finder, this is a separate app. It bugs me that I now have Finder and ForkLift open (since Finder can&#39;t be closed or removed from the Dock), but as a productivity tool I love it.</p>

<h2 id="toc_7">Skype</h2>
<p>Most of Gangverk&#39;s customers are based in the US, and they all use Skype. It&#39;s also a good option for chatting with my family back in The Netherlands - other then that I hate it with a passion. We&#39;re actually slowly but surely convincing our clients to move to <a href="https://plus.google.com/hangouts">Google+ Hangouts</a> because of much improved video- and audio quality, and functional group-video-chat.</p>

<h2 id="toc_8">ColorSnapper</h2>
<p>A very good global color picker. On the <a href="https://itunes.apple.com/app/colorsnapper/id418176775?l=en&amp;mt=12">App Store for $5</a> and totally worth it.</p>

<h2 id="toc_9">Shrinkage</h2>
<p>Watches a folder and creates non-retina image assets for any @2x file created. Most of our designers only provide retina assets, and this app makes it very easy to quickly create non-retina versions as well. On the <a href="https://itunes.apple.com/app/shrinkage/id505800575?l=en&amp;mt=12">App Store for only $1</a>.</p>

<h2 id="toc_10">Slender</h2>
<p>Another developer tool from the <a href="https://itunes.apple.com/app/slender/id493656257?l=en&amp;mt=12">App Store</a> ($10), this one analyzes your Xcode project and finds any unused image assets. I typically only use it at the end of a project, and can always remove a few images, saving hundreds of kilobytes, sometimes even much more from your app size.</p>

<h2 id="toc_11">SourceTree</h2>
<p>I guess many people will laugh at the idea of using a GUI for Git, but I like it a lot. It makes branching and merging a lot easier. Oh, it also does Mercurial if you&#39;re into that, and is <a href="https://itunes.apple.com/app/sourcetree-git-hg/id411678673?l=en&amp;mt=12">completely free on the App Store</a>.</p>

<h2 id="toc_12">xScope</h2>
<p>A couple of developer tools in one, but I mainly use it for on-screen rulers. It&#39;s not really cheap ($30 on the <a href="https://itunes.apple.com/app/xscope/id447661441?l=en&amp;mt=12">App Store</a>) but I use it multiple times per week and is saving me a ton of time.</p>

<h2 id="toc_13">Acorn</h2>
<p>A very capable image editor for $50 (<a href="https://itunes.apple.com/app/acorn-image-editor-for-humans/id402280036?l=en&amp;mt=12">App Store</a>), I use it for cropping and resizing images. It&#39;s so much quicker to start then Photoshop or even Pixelmator!</p>

<h2 id="toc_14">Photoshop</h2>
<p>Because Acorn doesn&#39;t handle Photoshop files with layer groups, which is exactly what our clients send us, Photoshop is still used at least a couple of times per week.</p>

<h2 id="toc_15">iA writer</h2>
<p>When I write, I do it in Markdown format. All my blog articles, all company documentation, all README&#39;s, everything is in Markdown, and iA writer is the most beautiful app to write in. It&#39;s not always quick to start up, but it&#39;s usually just open during the entire day. There are iOS versions too, and everything works via iCloud. Love it, well worth the <a href="https://itunes.apple.com/app/ia-writer/id439623248?l=en&amp;mt=12">5 bucks</a>.</p>

<h2 id="toc_16">Bartender</h2>
<p>I have a lot of apps that leave an icon in the menu bar. Too many! On my 13&quot; Macbook Pro, sometimes they even get in the way of menu items. Bartender combines them in a separate bar, cleaning up a lot of space: it removes 9 menu bar icons for me, but they are still accessible with one click. It&#39;s about $15 on <a href="http://www.macbartender.com">their website</a>.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[A new (static) website]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2012/12/28/new-static-website/"/>
        <published>2012-12-28T00:00:00+00:00</published>
        <updated>2013-04-13T20:05:31+00:00</updated>
        <id>http://mixedcase.nl/articles/2012/12/28/new-static-website/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>More then a year ago I was <a href="/articles/2011/11/06/playing-around-static-site-generators/">playing around with static site generators</a> because I wanted to simplify my code and ultimately get rid of my server.</p>
<p>My reasons back then were performance, version control and integration with GitHub. I tried a few generators, but never found one that felt right. Most generators expect me to add metadata to my posts, and I simply don&#39;t want to do that. I want my posts to be 100% valid Markdown with no added markup. The title of the article is already in the post (it&#39;s the first line, prefixed with a <code>#</code>), and the date of publication is in the filename. I don&#39;t need categories or tags, so why all this forced metadata crap?</p>
<p>Some generators came close to feeling right, but were written in Ruby. Hacking on them would&#39;ve taken too much effort for me, I really wanted a system written in Python or Node.js.</p>
<p>In the end I found Felix Felicis (aka <a href="https://github.com/lepture/liquidluck">liquidluck</a>), a simple system written in Python. It didn&#39;t support my style of writing articles in Markdown all the way but came very very close. And it was extremely easy to modify, so now it works exactly how I want it to.</p>
<p>This site itself looks almost like it always used to, it only lost the Twitter sidebar (don&#39;t need it), article categories (won&#39;t miss it) and comments (good riddance). I&#39;m really pleased with the result: no more Python and Django and complicated code for something that’s quite a simple website. Articles can be kept in git and the site can be hosted anywhere without costing me a cent.</p>
<p>For anyone interested in static site generators, I&#39;d say have a look at <a href="https://github.com/lepture/liquidluck">liquidluck</a> and the <a href="https://github.com/kevinrenskers/mixedcase.nl">sourcecode</a> of mixedCase.nl.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Looking back at 2012]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2012/12/26/looking-back-2012/"/>
        <published>2012-12-26T00:00:00+00:00</published>
        <updated>2012-12-31T16:43:55+00:00</updated>
        <id>http://mixedcase.nl/articles/2012/12/26/looking-back-2012/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>On January 2 I moved to Iceland with two suitcases and a job contract. My new title: iOS developer at <a href="http://gangverk.is">Gangverk</a>, a small company creating iPhone- and Android apps for CBS in the United States. This was the beginning of an amazing year for me, both personally and professionally.</p>
<p>The biggest adventure was of course the move to Iceland with almost nothing. For the first few days I lived in a small apartment one of Gangverk&#39;s founders had secured for me. It was great to have a place waiting for me when I came to this new country, a good place to start looking for something I could make my own. Within a week I moved to a huge apartment with three roommates and my social life improved dramatically. It was also really helpful to have native guides, pointing out stores and places to eat.</p>

<h2 id="toc_0">Gangverk</h2>
<p>The day after I arrived in Iceland I started on the new job, and my first project was a big one: create the new iPhone app for <a href="http://www.radio.com">Radio.com</a>, a CBS owned website with over 400 streaming radio stations. First though, I had to get back into iOS development, and Paul Hegarty&#39;s <a href="https://itunes.apple.com/nl/course/ipad-iphone-app-development/id495052415?l=en">iTunes U course</a> helped tremendously. For people wanting to get into iOS development I can&#39;t recommend these videos enough. Radio.com for iOS was <a href="https://itunes.apple.com/app/radio-com-for-iphone/id323701765?mt=8">released</a> in March and got very nice reviews.</p>
<p>After that I worked on the new <a href="https://itunes.apple.com/app/metrolyrics/id547825550">MetroLyrics</a> app for iPhone, <a href="https://itunes.apple.com/us/app/tailgate-fan-mobile-companion/id462599724?mt=8">Tailgate Fan</a> and lastly the official <a href="https://itunes.apple.com/app/scrobbler-for-ios/id585235199?ls=1&amp;mt=8">Last.fm Scrobbler for iOS</a>. I am especially proud of the Last.fm Scrobbler, which is an universal app that works on iPhone and iPad. The reviews have been super positive and I can&#39;t wait to add more features in upcoming updates.</p>
<p>Life at Gangverk changed a lot in 2012. When I started, it was just four guys, including me. We had a small boring office and not much else. After a couple of months we moved to a new location: the new office is <a href="https://www.facebook.com/photo.php?fbid=423827087691037&amp;set=pb.388587864548293.-2207520000.1356971916&amp;type=3&amp;theater">light and big and beautiful</a>. We have a soda machine, pool table, foosball table and warm lunches every day in a shared cantina. We lost one of the original four guys, but gained four others. We&#39;re growing, kicking ass in Iceland and abroad and loving it. (Oh, and <a href="https://workforpie.com/companies/gangverk/">we&#39;re hiring</a>.)</p>

<h2 id="toc_1">Open source</h2>
<p>While working on all these projects, I was lucky enough to be able to open source some of my code. My first Objective-C repository was <a href="https://github.com/getsentry/raven-objc">raven-objc</a>, an iOS client for the remote logging service Sentry. It was later adopted by Sentry as the official client, and the repository is now hosted under their GitHub account.</p>
<p>For Gangverk, my first open source project was <a href="https://github.com/gangverk/RemoteConfig">RemoteConfig</a>, making it really easy to load in a remote JSON file with some config values, with locally defined default values. While it&#39;s not very popular on GitHub so far, at Gangverk we&#39;re using it in literally all of our projects.</p>
<p>My most popular open source repository so far is <a href="https://github.com/gangverk/GVUserDefaults">GVUserDefaults</a>, enabling <code>NSUSerDefaults</code> access via properties. Right now it has over 175 &ldquo;stargazers&rdquo; on GitHub, and increasing every day. Other open source projects for Gangverk include <a href="https://github.com/gangverk/LastFm">LastFm</a>, the Last.fm client SDK our Scrobbler app was built on, <a href="https://github.com/gangverk/AdMarvelContainer">AdMarvelContainer</a> and <a href="https://github.com/gangverk/GVMusicPlayerController">GVMusicPlayerController</a>.</p>
<p>I&#39;ve also revived an ancient project of mine: <a href="https://github.com/kevinrenskers/dmmjobcontrol">dmmjobcontrol</a>. It&#39;s a TYPO3 extension for showing jobs on your website. I&#39;ve created it in 2007 while working for a company in The Netherlands. After I left the company, the extension was never updated again, so after 5 years I&#39;ve adopted it under my own name. It was weird to get back to old PHP code, but it felt good to release a much needed update to the community.</p>
<p>This website was <a href="/articles/2012/12/28/new-static-website/">rebuilt as a statically generated site</a>, I&#39;m very happy I dropped all that code and am now server-free, saving me about $215 per year.</p>

<h2 id="toc_2">Other bits and pieces</h2>
<p>I&#39;ve switched browsers <a href="http://mixedcase.nl/articles/2011/12/03/why-there-no-perfect-browser/">yet again</a>, I am now back to using Safari full time on all my devices due to the excellent iCloud features (even though the annoying page refreshes still happen when you two-finger-swipe back a page).</p>
<p>In 2012 I also bought an iPad 3 (and was disappointed when the iPad 4 was announced so soon after) and got an iPhone 5 from work, upgrading from an aging iPhone 4. The larger screen is very welcome, and the improved camera makes a big difference. For me the biggest change is how thin and light it is though. I couldn&#39;t be more happy!</p>
<p>When Mountain Lion was released I tried to upgrade my computer and ended up with a corrupted hard drive, forcing a complete format and reinstall. That wasn&#39;t a lot of fun.</p>
<p>I haven&#39;t touched Python or Django in nine months, and to be honest I don&#39;t really miss it. I do miss the front-end side of creating websites, but I am having so much fun with creating apps that I rarely think about creating sites anymore.</p>
<p>On the personal side of things, I celebrated my 30th birthday in February and missed my friends (and cheap beer) quite terribly. More importantly, I got an Icelandic girlfriend and moved in with her in November. We took a short holiday to The Netherlands together where she met my friends and family. And had cheap beer   of course :) I think I&#39;ve had the most hamburgers and hot-dogs in a year ever, Iceland&#39;s secret obsessions.</p>
<p>I&#39;ve finally started to get my drivers license, and I can&#39;t wait to drive around the country. While Reykjavik is a nice enough city, it&#39;s not particularly beautiful and it&#39;s getting a bit boring. Iceland&#39;s landscape is waiting for me to explore it!</p>
<p>In 2013 I&#39;d like to travel around the country, create my own iOS game and redo my <a href="http://bolhoed.net">personal website</a>. And of course I&#39;m looking forward to another year at Gangverk, I can&#39;t wait to work on all the projects that are lined up. I don&#39;t think it can possibly top 2012, but I&#39;m sure it will be awesome and I&#39;m happy for it to prove me wrong :)</p>
<p>I did fail rather spectacularly at blogging this year, so my resolution for the new year is to improve this. One post per week maybe? At lease one per month!</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[MPVolumeView (Airplay button) on an UIBarButtonItem]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2012/10/12/mpvolumeview-uibarbuttonitem/"/>
        <published>2012-10-12T00:00:00+00:00</published>
        <updated>2012-12-28T10:53:31+00:00</updated>
        <id>http://mixedcase.nl/articles/2012/10/12/mpvolumeview-uibarbuttonitem/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>In an app I&#39;m currently building, the client wants an Airplay button in the navigation bar, with a nice background like so:</p>
<p><img src="https://dl.dropbox.com/u/2310965/toolbar_example.png" alt="toolbar screenshot"/></p>
<p>After trying some things, the solution seems to be to loop over the subviews. It feels a bit hacky, but works perfectly:</p>
<div class="highlight"><pre><span class="n">MPVolumeView</span> <span class="o">*</span><span class="n">airPlayButton</span> <span class="o">=</span> <span class="p">[[</span><span class="n">MPVolumeView</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithFrame:</span><span class="n">CGRectZero</span><span class="p">];</span>
<span class="n">airPlayButton</span><span class="p">.</span><span class="n">showsVolumeSlider</span> <span class="o">=</span> <span class="n">NO</span><span class="p">;</span>
<span class="n">airPlayButton</span><span class="p">.</span><span class="n">showsRouteButton</span> <span class="o">=</span> <span class="n">YES</span><span class="p">;</span>

<span class="k">for</span> <span class="p">(</span><span class="kt">id</span> <span class="n">subView</span> <span class="k">in</span> <span class="n">airPlayButton</span><span class="p">.</span><span class="n">subviews</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">([</span><span class="n">subView</span> <span class="nl">isKindOfClass:</span><span class="p">[</span><span class="n">UIButton</span> <span class="n">class</span><span class="p">]])</span> <span class="p">{</span>
        <span class="n">UIButton</span> <span class="o">*</span><span class="n">button</span> <span class="o">=</span> <span class="p">(</span><span class="n">UIButton</span> <span class="o">*</span><span class="p">)</span><span class="n">subView</span><span class="p">;</span>
        <span class="p">[</span><span class="n">button</span> <span class="nl">setBackgroundImage:</span><span class="p">[</span><span class="n">UIImage</span> <span class="nl">imageNamed:</span><span class="s">@&quot;background&quot;</span><span class="p">]</span> <span class="nl">forState:</span><span class="n">UIControlStateNormal</span><span class="p">];</span>
        <span class="p">[</span><span class="n">button</span> <span class="nl">setFrame:</span><span class="n">CGRectMake</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">45</span><span class="p">,</span> <span class="mi">33</span><span class="p">)];</span>
        <span class="p">[</span><span class="n">button</span> <span class="nl">setImageEdgeInsets:</span><span class="n">UIEdgeInsetsMake</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)];</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="p">[</span><span class="n">airPlayButton</span> <span class="n">sizeToFit</span><span class="p">];</span>

<span class="n">self</span><span class="p">.</span><span class="n">navigationItem</span><span class="p">.</span><span class="n">rightBarButtonItems</span> <span class="o">=</span> <span class="err">@</span><span class="p">[</span>
    <span class="p">[[</span><span class="n">UIBarButtonItem</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithCustomView:</span><span class="n">actionButton</span><span class="p">],</span>
    <span class="p">[[</span><span class="n">UIBarButtonItem</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithCustomView:</span><span class="n">airPlayButton</span><span class="p">],</span>
    <span class="p">[[</span><span class="n">UIBarButtonItem</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithCustomView:</span><span class="n">informationButton</span><span class="p">]</span>
<span class="p">];</span>
</pre></div>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Why is there no perfect browser?]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/12/03/why-there-no-perfect-browser/"/>
        <published>2011-12-03T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/12/03/why-there-no-perfect-browser/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>I&#39;ve used Firefox for a long, long time, back when I still used Windows pc&#39;s, until the summer 2007. Chrome didn&#39;t exist yet, Internet Explorer sucked and Safari was still Mac-only. Since then, I&#39;ve switched browsers many times: from Firefox to Safari, back to Firefox, to Safari, to Chrome, to Safari and back to Chrome again.</p>
<p>Why is there no perfect browser for me? Why am I switching this often, and why am I thinking about switching back to Safari once again?</p>

<h2 id="toc_0">Firefox</h2>
<p>Pros: Firebug. Awesomebar. Fully featured.</p>
<p>Cons: I still need to restart the browser when I install a new extension. It&#39;s pretty slow to start up. They are too quick with their major version upgrades, often breaking existing extensions.</p>
<p>It doesn&#39;t feel good on Lion. I miss the &ldquo;rubber band&rdquo; effect, there&#39;s also no two-finger swiping back and forth. Double-tab with three fingers doesn&#39;t produce the Definition of the selected word (like it does in Safari and Chrome). You can&#39;t zoom with multi-touch gestures.</p>

<h2 id="toc_1">Safari</h2>
<p>Pros: Reader, Reading List (which is synced with iCloud), fast, pretty, new tab &ldquo;top sites&rdquo; page, iPhone-like zooming and panning, good developer tools, awesome download manager, best Lion integration.</p>
<p>Cons: since Lion Safari has become a slow beast, giving me a lot of beachballs. While the sliding back and forth through history with two (or three) fingers is cool, it does refresh the tab, making the experience feel very slow. When I visit one of my open tabs, sometimes it suddenly refreshes itself too. This is unacceptable.</p>
<p>I also don&#39;t like the split url- and search fields in the main toolbar.</p>

<h2 id="toc_2">Chrome</h2>
<p>Pros: Fast, Omnibar, sync bookmarks, extensions and settings with Google, good developer tools.</p>
<p>Cons: It&#39;s pretty bare. I can&#39;t reorder the default toolbar buttons, there&#39;s no RSS functionality, the download manager is very plain. It&#39;s way too hard to turn off Javascript for testing. There&#39;s no built-in Reader (but of course you can get a readability.com account). Panning, zooming and two-finger-swiping isn&#39;t as smooth as in Safari.</p>

<h2 id="toc_3">Opera</h2>
<p>Pros: Fast, Opera Sync</p>
<p>Cons: It has the same problem as Firefox: it doesn&#39;t feel good on Lion. Rubber banding, swiping nor zooming work. I also don&#39;t like the look and feel of the buttons and toolbars.</p>
<p>Just like Safari, it uses separate fields for entering url&#39;s and search queries.</p>

<h2 id="toc_4">Conclusion</h2>
<p>Right now the best browser for me is Chrome, but that&#39;s only since pretty recently, when they added good Lion support. If Safari didn&#39;t do that stupid tab reloading though, I would immediately switch back to it, because it simply feels better, more &ldquo;Mac-like&rdquo; somehow.</p>
<p><strong>Update December 5, 2012</strong><br/>
Since a couple of months I&#39;m back to Safari. The split search/url fields are now combined into one and I use the iCloud features quite a lot since I got me an iPad: syncing my bookmarks and reading lists, and the iCloud tabs from other devices. It still behaves strangely when you go back a page with sudden refreshes and blank pages, but it&#39;s not happening often enough to be very annoying. So for the time being at least, Safari is back to being my main browser.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Looking for a job in the Arctic Circle]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/11/06/looking-for-job-arctic-circle/"/>
        <published>2011-11-06T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/11/06/looking-for-job-arctic-circle/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>For more then ten years I&#39;ve been telling friends and family that I&#39;d like to emigrate to another country. I have long thought that this other country would be Scotland, but about six months ago I&#39;ve changed my mind: I want to move to the Arctic Circle instead. And by that I mean the north of Norway (Tromsø, Bodø, Trondheim), Sweden (Luleå , Kiruna) or Finland (Rovaniemi, Oulu), or Iceland (Reykjavik). Canada would be very nice too, but I hear it&#39;s almost impossible to get permission to live and work there.</p>
<p>I have been looking for jobs in these cities, but found that it&#39;s quite difficult: most companies use local jobboards that I don&#39;t even know exist, and many job postings are in their local language. But still: I have had one job interview in Tromsø and four in Reykjavik, although without much success. One liked me, but my skills had too much overlap with the rest of the team, another decided to suddenly pull all vacancies, one wanted to pay as little as possible (and it wasn&#39;t enough), number four had a horrible office and the one I am most positive about can only hire me if one of their current employees decides to leave.</p>
<p>So, it&#39;s been a couple of months since my big decision and I am still looking for a job. I hope that someone out there has a job for me, or knows someone else who does. I can use all the help I can get!</p>
<p>I am a 29 year old creative webdeveloper who loves both the back end (Python, Django, Node.js) and the front end (HTML5, jQuery, CSS, Less, Coffeescript). Besides programming for the web I&#39;ve also created a couple of iPhone and iPad applications. I like typography, interface- and interaction design and usability. I code to create beautiful things on screen &ndash; any screen.</p>
<p>My ideal company is small, fun, flexible, has an open source mindset, and great people who kick ass and like to drink beer once in a while. Everyone should be able to speak English, bonus points if it&#39;s the primary language at the office.</p>
<p>I have a <a href="http://nl.linkedin.com/in/kevinrenskers">LinkedIn profile</a> and my <a href="http://dl.dropbox.com/u/2310965/KevinRenskers.pdf">CV is posted online</a>.</p>

<h2 id="toc_0">Update (December 3, 2011)</h2>
<p>I&#39;ve found a job as iPhone developer in Reykjavik! I&#39;m starting January 2, 2012. There&#39;s a new blog about my Iceland adventure at <a href="http://movetoarctic.com">MoveToArctic.com</a>.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Playing around with static site generators]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/11/06/playing-around-static-site-generators/"/>
        <published>2011-11-06T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/11/06/playing-around-static-site-generators/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>Even though I&#39;m quite happy with this website and its code, I want to rebuild it using a static site generator: you write your posts and pages with Markdown, write a couple of page html templates, and simply by pushing a new file to Git, your new article is published. </p>
<p>Of course since everything is then based on static html files things like comments need to be Javascript based, which I don&#39;t really like, and searching will need to happened on Google, but the positives are many:</p>

<ul>
<li>Performance. Since it&#39;s all static html, your site will be able to handle millions of visitors without breaking a sweat.</li>
<li>Backups. Since it&#39;s all in a version control system instead of a database-backed CMS, you always have a backup and versioning.</li>
<li>Integration with Github. Static sites can be hosted on Github for free. People can also send you pull requests on articles, for example when they find a typo. Github also lets you directly edit files online.</li>
<li>Easy. I write all my articles in Markdown. It&#39;s more work for me to login in a CMS, create a new article and paste the text, instead of pushing one new file to Git.</li>
</ul>
<p>Also, it&#39;s just a cool new thing to try :)</p>
<p>So, time to find a static site generator. I&#39;ve looked at a couple of them last weekend, and sadly wasn&#39;t very happy with the results so far.</p>

<h2 id="toc_0">Jekyll (Ruby)</h2>
<p>Jekyll is one of the best known generators, as it&#39;s used by Github Pages. This is absolutely its biggest pro: you really only need to push your articles, and Github will generate your site and host it. When you combine this the ability to edit files directly in Github, you now have the ability to edit your posts from everywhere in the world.</p>
<p>While I like Jekyll, it&#39;s too bad it&#39;s way too simple. It doesn&#39;t handle category- or date based archives for example. It&#39;s very hard to combine Markdown text and HTML templates, the templating system is annoying, and it&#39;s not easy to place two pieces of Markdown text into one page. On this website, all pages (homepage, projects and about) have a sidebar with text. I&#39;d like to keep this in Markdown, but Jekyll makes it quite difficult to work with: each page now consists of three different files.</p>
<p>Some other (small) problems: I wish it&#39;s possible to set a default template for your posts, and that it&#39;s possible to turn off the Liquid template system inside my Markdown files.</p>
<p>You can extend Jekyll with plugins, for example to generate category pages, but as Github doesn&#39;t support them, you will lose Jekyll&#39;s biggest feature. So, you might as well use a better generator all together.</p>

<h2 id="toc_1">Octopress (Ruby)</h2>
<p>This is a bit of a weird one: it&#39;s not a generator itself but more like a framework of plugins and a default template for Jekyll. Octopress can generate category pages for you and has some other nice plugins, but most of their featureset is their default template with some Javascript files for Twitter, Github profile, Disqus, etc. Which I won&#39;t use.</p>
<p>Octopress is a very nice project for people who want to use Jekyll and aren&#39;t set on the Github integration. However, as you still have the template limitations, it&#39;s not for me.</p>

<h2 id="toc_2">Hyde (Python)</h2>
<p>I believe Hyde used to simply be a Python port of Jekyll, built on Django. The new version is no longer based on Django but on Jinja2 and includes many of their own ideas.</p>
<p>Because I love Jinja2 templates I was of course very interested in Hyde. As soon as I wanted to get started and looked at the documentation however, my enthusiasm waned: it&#39;s almost non-existent. Still, I installed it and tried it out.</p>
<p>I quickly found a negative so big, that I didn&#39;t need to look at Hyde any more: you can&#39;t write your articles in clean Markdown files: they need to be Jinja2 templates. Of course you can extend another template and just place your post inside <code>{% block content %}</code> and <code>{% markdown %}</code> tags, but for me it feels wrong. I have Googled this problem, and it seems that it&#39;s not possible to write your posts in pure Markdown files and have them first render and then be placed inside a template.</p>

<h2 id="toc_3">Blogofile (Python)</h2>
<p>Unlike Hyde, Blogofile is built on the Mako template language which is not my favorite. Based on this I was hesitant to do much more research, but luckily I did. Once you look past Mako, Blogofile is a remarkably flexible and hackable system. Post are written in pure Markdown, you have Python controllers for things like blog posts and pages, filters and deployment helpers.</p>
<p>I still need to use it in practice to see if it works for me, I&#39;ll update this post as soon as I have.</p>

<h2 id="toc_4">Other generators I want to look at are:</h2>

<h3 id="toc_5">Toto (Ruby)</h3>
<p>From the creator of Less CSS.</p>

<h3 id="toc_6">Chisel (Python)</h3>
<p>Crap documentation, but looks promising. Markdown plus Jinja2.</p>

<h3 id="toc_7">Nanoc (Ruby)</h3>
<p>Embedded Ruby in templates, not so nice. Project and docs look professional.</p>

<h1 id="toc_8">Update (December 3, 2011)</h1>
<p>I&#39;ve tried to recreate mixedCase.nl in Jekyll, but I am not happy with it. Working with categories is too hard, there are no date-based archives, but worst of all: the syntax for blocks of codes has changed, as compared to how all my articles are written (and rendered with Python-Markdown). Jekyll&#39;s code blocks are not &ldquo;official&rdquo; Markdown, and as such don&#39;t play nice with my Markdown editor. I did like many of Jekyll&#39;s other features. It&#39;s easy, it&#39;s fast, and plays very nice with GitHub.</p>
<p>I did create a new blog for my immigration adventure, called <a href="http://movetoarctic.com">MoveToArctic.com</a>. It&#39;s made with Jekyll and hosted on GitHub. As long as you don&#39;t need archives, categories, RSS feeds per category and code highlighting, Jekyll simply kicks ass.</p>
<p>Moving mixedCase.nl to static pages is still a plan, but I&#39;ll need to try one of the other generators for it.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[&quot;How not to license your app&quot;; an open letter to JetBrains]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/09/13/how-not-to-license-your-app/"/>
        <published>2011-09-13T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/09/13/how-not-to-license-your-app/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>I love JetBrains&#39;s <a href="http://http://www.jetbrains.com/pycharm/">PyCharm</a>, a great IDE for Python, and for Django in particular. I would even say it&#39;s the best tool for Django programmers. It&#39;s got great features, good syntax highlighting, excellent support for debugging, and very very good code completetion, even within HTML templates. I think it&#39;s priced fair (although on the expensive side) at 87 euros for individual developers, but sadly their license sucks so much, that it prevents me from buying it.</p>
<p>While you buy a &ldquo;permanent&rdquo; license, it&#39;s only valid for the current major version, with free upgrades to major versions released within the next year. A great new version in 13 months? Sorry, not for you. Well, that&#39;s nothing new, most licenses work like this - but most offer other ways to get the updates at a reasonable price. Not so with JetBrains.</p>
<p>What they propose you do is this: you can buy a &ldquo;subscription renewal&rdquo; every year, for 34 euros per year. In their words: </p>

<blockquote>
<p>To stay current with the new product releases and to continue receiving technical support, you should renew your upgrade subscription annually.</p>
</blockquote>
<p>Well, that&#39;s no so bad, is it? I mean, for every year when there&#39;s no new major version, just don&#39;t upgrade that subscription. Once there is a new major version, just upgrade then! Sadly, no:</p>

<blockquote>
<p>Upgrade subscription renewal is optional. However, if you do not renew your upgrade subscription within 1 year upon expiration of the previous upgrade subscription term, you will not be able to renew your upgrade subscription any more and a new license purchase at the full license price will be needed to use then-current version of PyCharm. Stand-alone upgrades to particular versions of PyCharm are not available.</p>
</blockquote>
<p>Hey, wait a second. So, if I skip one year, I must buy a completely new license, again for 87 euros? Hey, but maybe there&#39;s a bit of hope:</p>

<blockquote>
<p>You can renew your upgrade subscription at the discounted upgrade subscription price during your upgrade subscription term or within 1 year upon its expiration.</p>
</blockquote>
<p>Okay, so I could just wait 11 months and three weeks, and then renew my subscription? That would at least soften the pain, right? Guess again:</p>

<blockquote>
<p>Regardless of the actual upgrade subscription renewal date, your new upgrade subscription term will always start on the date following your previous upgrade subscription expiration date.</p>
</blockquote>
<p>Arg! Why do you hate your paying customers, JetBrains? It&#39;s like you want me to pirate this.</p>
<p>I think one of the most expensive pieces of software I ever bought was <a href="http://www.ultraedit.com/products/ultraedit.html">UltraEdit</a>, way back when I still did PHP development on Windows (yeah, yeah). Their standard license was 57 dollars, with one year of major upgrades. However, they also sold a true permanent license, with free major upgrades for the rest of your life. At only 3 times the cost of one normal license. So while I bought version 9, about 8 years ago, my license is still valid for version 17 today. Hooray!</p>
<p>JetBrains, I love PyCharm, but I refuse to play (and pay) your stupid license game. Either add a true permanent license option, or just let me buy new major versions at a discount, something you specifically mention is not possible now:</p>

<blockquote>
<p>Stand-alone upgrades to particular versions of PyCharm are not available.</p>
</blockquote>
<p>Please, make your licenses as user friendly as your software. I will not pay 34 euros each and every year, only to have to pay 87 euros once again, if I forget to &ldquo;renew&rdquo; within a year. PyCharm is cool, very cool even, but not that cool.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Designing my very own ideal programming language]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/04/24/designing-my-very-own-ideal-programming-language/"/>
        <published>2011-04-24T00:00:00+00:00</published>
        <updated>2012-12-28T11:03:12+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/04/24/designing-my-very-own-ideal-programming-language/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>In 2009 I made the switch to Python, after having worked exclusively with PHP and Javascript for almost a decade. I really like the language, much more then I ever liked PHP. Of course it&#39;s not perfect (see one of my first posts called <a href="http://mixedcase.nl/articles/2009/12/06/things-i-hate-about-python-and-django/">Things I hate about Python and Django</a>), but I never really thought much about the lesser parts of the language.</p>
<p>Until I started to learn other languages as well, that is.</p>
<p>In May of 2010 I learned Objective-C, to create iPhone- and iPad apps. I like the fact that everything is very strict: you always know precisely what types of arguments a methods expects, and what the return value will be. I spend a lot less time looking at source code or documentation; Xcode&#39;s autocompletion will tell me in detail how I should call a function and what I&#39;ll get back. Then again, writing separate header- and implementation files is not on my list of things I like to day all day long.</p>
<p>A few week ago I bought a book on Ruby. Mainly because it looked like a very nice language, but also in great part because of MacRuby and its Cocoa bindings. My suspicion was correct: Ruby is a very nice language. In fact, in many ways it looks much friendlier and more logical then Python. Of course also this language has its quirks, things that would bother me.</p>
<p>I then began to wonder what my ideal language would look like, if I could design my own. One part Ruby, one part Python, sprinkle with the best parts of Objective-C, and finish with the outstanding documentation of PHP. It would probably have the following characteristics:</p>

<ul>
<li>There should be one —and preferably only one— obvious way to do it</li>
<li>Everything is an object</li>
<li>Significant whitespace but with curly braces: easy to see where a function or block ends, but will enforce correct indentation (i.e. will not run when code inside a block is not indented correctly)</li>
<li><a href="http://en.wikipedia.org/wiki/Type_system#Static_typing">Static</a>, <a href="http://en.wikipedia.org/wiki/Strong_typing">Strong</a> and <a href="http://en.wikipedia.org/wiki/Duck_typing">Duck</a> typing</li>
<li>Add methods to existing classes (even internal ones) like in Ruby or Objective-C&#39;s categories.</li>
<li>Unicode everywhere</li>
<li>Function names and variables may end with punctuation codes ? and !. The question marks makes it clear it&#39;s a function that returns a Bool. The exclamation mark indicates the function should be used with care, for example because it modifies a variable in place (instead of returning a modified copy).</li>
<li>Very few global functions, prefer methods on internal classes</li>
<li>Keyword arguments</li>
<li>Visibility: public, protected, private</li>
<li>Blocks like in Ruby or Objective-C</li>
<li>Multiple inheritance</li>
<li>Decorators</li>
<li>Only one way to add comments: the # sign. Multi-line comment syntax like <code>/* */</code> is ugly.</li>
<li>Global variables <a href="http://stackoverflow.com/questions/423379/global-variables-in-python">like in Python</a></li>
<li>Python&#39;s <code>from ... import ...</code> and <code>import ...</code>, giving you great control over namespaces</li>
<li>But not the <code>__init__.py</code> files!</li>
<li>Enforced case convention, no more mixed styles from different programmers working on the same project:

<ul>
<li>CONSTANTS</li>
<li>ClassNames</li>
<li>variable_names</li>
<li>function_names()</li>
</ul></li>
</ul>
<p>Let&#39;s start with some basic hypothetical code examples.</p>

<h2 id="toc_0">Strings</h2>
<div class="highlight"><pre># variable_type variable_name = statement
String greeting = &#39;Hello, world&#39;
String another_string = String.new(&#39;Also a string&#39;)
print greeting # &#39;Hello, world&#39;
greeting.class # String
greeting.length # length is a property, not a function

# Single quoted strings are &quot;raw&quot; strings. Double quoted string can
# contain special escape sequences. Single quoted string are a
# little bit more efficient if you don&#39;t need those sequences.
print &quot;hello\tworld&quot; # &#39;hello   world&#39;
print &#39;hello\tworld&#39; # &#39;hello\tworld&#39;

# String interpolating is not supported, since this often leads to
# unreadable strings. Use string formatting instead:
print &#39;Hello, %s&#39;.format(&#39;World&#39;)
print &#39;Name: %(name)s, age: %(id)d&#39;.format(name=&#39;Kevin&#39;, age=29)
</pre></div>

<h2 id="toc_1">Numbers</h2>
<div class="highlight"><pre>Int one = 1
Float third = 0.3
print one # 1
String one_string = one.to_s()
print one_string # &#39;1&#39;
</pre></div>

<h2 id="toc_2">Lists and ranges</h2>
<div class="highlight"><pre>List my_list = [&#39;a&#39;, 1, another_object]
my_list.length
print my_list[0]

List my_range = [1..3]
# this includes the end number, so the same as [1, 2, 3]

# You can create a list with an infinite length.
# This can be used in place of the while(True) syntax
# seen in other languages (see also Enumeration, below)
List my_infinite range = [0..]

# Since all lists are (yield) generators, this infinite
# list doesn&#39;t use infinite memory.
</pre></div>

<h2 id="toc_3">Hashes</h2>
<div class="highlight"><pre>Hash my_hash = {&#39;food&#39;:&#39;apple&#39;, &#39;color&#39;:&#39;green&#39;, &#39;price&#39;:12}
print my_hash[&#39;food&#39;]

key = &#39;color&#39;
print my_hash[key]
</pre></div>

<h2 id="toc_4">Functions</h2>
<div class="highlight"><pre># (return_type) function_name(arguments) { code }
(Int) make_sum(Int x, Int y) {
    return x + y
}

Int the_sum = make_sum(x=123, y=456)

# Order of arguments doesn&#39;t matter, as long as all
# the required arguments are given.
# Note: Void is the same as Null or None in other languages.
(Void) print_line(String name=&#39;world&#39;, String greeting) {
    print &#39;%s, %s!&#39;.format(greeting, name)
}

print_line(greeting=&#39;Hello&#39;) # print &quot;Hello, world!&quot;

# If a function has no arguments, you can&#39;t leave
# out the parenthesis (like you can in Ruby)
a_function()

# Lastly, if a function doesn&#39;t specifically return
# something, it doesn&#39;t. Unlike Ruby, where the
# last statement is returned.
</pre></div>

<h2 id="toc_5">Decorators</h2>
<div class="highlight"><pre>@login_required()
(String) get_username() {
    return self.user.username
}
</pre></div>

<h2 id="toc_6">Flow control</h2>
<div class="highlight"><pre># Empty string, list, hash and zero are all False.
if variable == True {
    # do stuff
} else {
    # something else
}

# Triple equation marks checks if it&#39;s the same type as well as value
if 1234 === True {
    # this will never be reached since an int is not a boolean
}

variable.switch() {
    case &#39;one&#39; {
        # the value of variable equals &#39;one&#39;
    }

    case &#39;two&#39; {
        # the value of variable equals &#39;two&#39;
    }

    default {
        # the value of variable is neither &#39;one&#39; or &#39;two&#39;
    }
}
</pre></div>

<h2 id="toc_7">Classes</h2>
<div class="highlight"><pre>class MyClass(Superclass) {
    String my_variable

    (MyClass) new(String variable) {
        # This is the default constructor or initializer.
        # If we subclass/override it, we should call the super class:
        self = super.new()

        # Do custom initializing, set instance variables, etc
        self.my_variable = variable

        # new() should always return self
        return self
    }

    (String) to_s() {
        return &#39;&lt;MyClass %s&gt;&#39;.format(self.my_variable)
    }
}

# Extend existing classes by reopening them. After we do this,
# all strings will know how to greet.
class String {
    (Void) protected greet() {
        print &#39;Hello, %s&#39;.format(self)
    }
}

# Overwrite a function in an existing class. Great if you use third
# party software that is perfect except for that one function...
class User {
    (Bool) authenticated?() {
        # The way you want it to work...
    }
}
</pre></div>

<h2 id="toc_8">Symbols</h2>
<div class="highlight"><pre># Symbols are immutable, super lightweight strings. They are created
# with backticks.
Symbol sym = `this is a symbol`

# You can use this when you&#39;re only interested in the value of a string
# and don&#39;t need any of the String methods. A good use is for selectors
# like this:
object.responds_to?(`do_stuff`)

# You only care about the value of the string, you don&#39;t need to trim it,
# make it uppercase, count the letters, etc.
# This also works, but creating an instance of a String and passing
# it around is overkill:
my_list.responds_to?(&#39;do_stuff&#39;)

# Basically, the only thing they know is how is print themselves
print `oh lala`

`oh lala`.upper() # fail! need to convert to a string first
`oh lala`.to_s().upper()

# Since symbols save memory, they are recommended when you&#39;d use a
# string only as identifier:
Hash my_better_hash = {`food`:&#39;apple&#39;, `color`:&#39;green&#39;, `price`:12}
print my_better_hash[`food`]
</pre></div>
<p>Note to self: not really sure about this syntax. Especially in the hash example the mixed use of backticks and single quotes is ugly and confusing. Still better then Ruby&#39;s :symbol syntax though, again especially when combined with hashes.</p>

<h2 id="toc_9">Blocks</h2>
<div class="highlight"><pre># Blocks are anonymous (nameless) functions. Formal syntax:
# (return type) block_name = ^(arguments) { code }

(Int) my_block = ^(Int number) {
    return number * 7
}

print &quot;%d&quot;.format(my_block(3))

# Of course, this was not much different from creating a normal
# function. Comparison:
# (Int) my_function(Int number) {
#   return number * 7
# }

# The real power of blocks is from using them directly as function
# arguments:

my_array.custom_sort(^(Object first_item, Object second_item) {
    return first_item &lt; second_items
})

# A block with no arguments drops the parenthesis: ^{}
3.times(^{print &#39;hooray!&#39;})
</pre></div>

<h2 id="toc_10">Enumeration</h2>
<div class="highlight"><pre># Enumeration is done with blocks.

[1..3].each(^(Int i) {
    print i
}

# Break out of a loop by returning
[0..].each(^(Int i) {
    print i

    if i == 3 {
        return
    }
}
# prints 0, 1, 2 and 3, then exists the loop

my_list.each(^(Object item) {
    print item
}

my_hash.each(^(String k, Object v) {
    print &#39;%(key)s = %(value)s&#39;.format(key=k, value=v)
}
</pre></div>
<p>As you can see, most of the syntax is a blend of Ruby and Python, but with static typing and curly braces. Of course this is not a complete description of a language, but the general feel and syntax should be clear.</p>

<h1 id="toc_11">Why not just use&hellip;</h1>
<p>&hellip;Ruby?</p>

<ul>
<li>I don&#39;t like the <code>do</code> / <code>end</code> block syntax with the vertical bars</li>
<li>Multiple ways to do stuff. I like my language explicit, not implicit.</li>
<li>Whitespace is not significant, correct indentation is not enforced</li>
<li>No multiple inheritance, no decorators</li>
<li><code>@instance_variable</code> and <code>@@class_variable</code>. I think <code>self.instance_variable</code> is much cleaner.</li>
<li><code>$global_variable</code></li>
<li>Parenthesis and return statement are not required but implied. Again: I like explicit much better.</li>
<li>The <code>=&gt;</code> syntax for hashes</li>
</ul>
<p>&hellip;or Python?</p>

<ul>
<li>All those annoying underscores in function names </li>
<li>The <code>__init__.py</code> files. It&#39;s just ugly!</li>
<li>Not everything is an object, too many global functions (i.e. <code>len(list)</code> instead of <code>list.len()</code>)</li>
<li>Ugly syntax bits like the lambda functions and the call to a superclass function: <code>super(MyClass, self).__init__(*args, **kwargs))</code></li>
<li>Dictionaries are unsorted</li>
<li><code>self</code> as the first argument of each and every method</li>
<li>No <code>switch</code> statement</li>
<li>No visibility (public, protected, private)</li>
<li>No easy way to extend existing classes, or overwrite functions in them</li>
<li><code>&#39; &#39;.join(list)</code> instead of <code>list.join(&#39; &#39;)</code> - it&#39;s just backwards!</li>
</ul>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[The search for the perfect Python IDE (for Django)]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/04/05/search-perfect-python-ide-django/"/>
        <published>2011-04-05T00:00:00+00:00</published>
        <updated>2012-12-28T10:58:38+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/04/05/search-perfect-python-ide-django/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>When I first started working with Python in September 2009, I needed a good IDE. I quickly settled for Netbeans and I&#39;ve been using it ever since, even though there are some things that really irritate me. But at least it works, and fits well in my workflow.</p>
<p>Last weekend I did a clean install of Snow Leopard, and while I was busy setting it up again I started to wonder if maybe I needed to look for a better replacement.</p>
<p>My list of must-have features isn&#39;t that long:</p>

<ul>
<li>It needs to run on Mac OS X</li>
<li>Autocompletion for Django code (models/forms)</li>
<li>Be able to set breakpoints and debug my Django project</li>
<li>Virtualenv support</li>
<li>Give warnings and notices for syntax errors, unused imports, unused variables, etc</li>
<li>Besides working with projects, it should also be easy to edit other (separate) files</li>
</ul>
<p>And some nice-to-haves:</p>

<ul>
<li>Subversion and Mercurial need to be supported</li>
<li>Syntax highlighting for Django templates</li>
<li>Build-in sqlite browser</li>
<li>Open source and/or free, although I&#39;d go for a commercial product if it&#39;s better then the rest</li>
</ul>

<h2 id="toc_0">Netbeans with Python plugin</h2>
<p>As I said, I&#39;ve been using <a href="http://netbeans.org/">Netbeans</a> until now. And even though I&#39;d like to find a replacement, there&#39;s a lot to like. It&#39;s free, runs on Mac, has superb version control support and helps me while developing by showing me syntax errors even before I run the script. It helps me keep my code clean by notifying me about unused imports, variables and functions. It mostly stays out of my way, and once started, is pretty snappy.</p>
<p>So, why find a replacement at all? Well, code completion is very limited, barely usable even.</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span> <span class="c"># it won&#39;t autocomplete this!</span>
</pre></div>
<p>It can&#39;t deal with Django templates. To be honest, I don&#39;t really care that much, but the fact that it can&#39;t even recognize HTML5 syntax is getting very annoying. It&#39;s always telling me I have syntax errors even though it&#39;s all perfectly fine.</p>
<p>And last but not least, I&#39;ve never been able to get any form of Django debugging or breakpoints to work. Python scripts, yes, but not a Django project.</p>

<h2 id="toc_1">Komodo</h2>
<p>The first replacement I tried was <a href="http://www.activestate.com/komodo-ide">Komodo IDE 6</a>, a commercial product from ActiveState. At $295 it&#39;s quite expensive, so it has to be a <em>lot</em> better then Netbeans.</p>
<p>Their feature list made me very hopeful: support for debugging, HTML5, Django and all major version control systems was all listed. Add to that a database browser and my whishlist is almost completely fulfilled.</p>
<p>Sadly though, autocompletion doesn&#39;t work properly. I&#39;ve tried the same example as with Netbeans, and it could not figure out what methods were available. My guess is this is because of another big problem: no support for virtualenv, so how could it know what <code>django.db.models</code> is?</p>
<p>Lastly, their advertised Django support seems limited to syntax highlighting of the template language. Based on the lack of virtualenv support alone, I&#39;ve not bothered to test Komodo for more then an hour or so.</p>

<h2 id="toc_2">PyCharm</h2>
<p><a href="http://www.jetbrains.com/pycharm/">PyCharm</a> is a relatively new IDE made by JetBrains. It&#39;s also a commercial product, but at 88 euros (about $125) a lot more affordable. Well, at least the personal license is, as the commercial one for companies is 176 euros, or about $250. However, they also have a free license for open-source projects.</p>
<p>JetBrains markets their IDE as a &ldquo;Powerful Python and Django IDE&rdquo;: the specific mention of Django is promising. Listed features are Code Assistance, Code Analysis, complete Django support, version control, a graphical debugger and a lot more.</p>
<p>I&#39;ve been testing PyCharm for about a week now, and I have to say I really like it, even though it&#39;s kind of buggy right now. Their Django support is very cool: syntax highlighting works, code completion finally works (even for Django&#39;s default template tags and filters), and it also helps you to write better code, faster. For example, it can recognize old function-based generic views and offer to replace them with Django 1.3&#39;s new class-based generic views. Or, when you mention a template that doesn&#39;t exist yet, will offer to create it: very helpful indeed! It also knows what context variables are available in your template, and can auto-complete them too: {{ person. }} will show the possible values.</p>
<p>Their Django support goes further then the features already mentioned: you can run all management command right from the IDE. You can run Django&#39;s runserver command for example. While this is nice and all (after all, doing it in a terminal is just as easy), the ability to set breakpoints and debug the running server is what really sets PyCharm apart for me.</p>
<p>All these features make the life of a Django developer a lot easier. It also works well with virtualenv, where each project has its own Python interpreter and Python path.</p>
<p>Is it all perfect? Sadly, no. It&#39;s a bit buggy - not in the sense that it crashes or locks up, but certain features don&#39;t work as advertised. For example, I mentioned that it can recognize missing templates and auto-complete context variables inside templates. However, this does not work for all render shortcuts inside your views, and does not work well with keyword arguments. So while this code works perfectly with PyCharm:</p>
<div class="highlight"><pre><span class="k">return</span> <span class="n">render_to_response</span><span class="p">(</span><span class="s">&#39;file.html&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;foo&#39;</span><span class="p">:</span><span class="n">bar</span><span class="p">})</span>
</pre></div>
<p>This does not:</p>
<div class="highlight"><pre><span class="k">return</span> <span class="n">direct_to_template</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s">&#39;file.html&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;foo&#39;</span><span class="p">:</span><span class="n">bar</span><span class="p">})</span>
</pre></div>
<p>Luckily they quickly responded to the bug-report, and I am confident that it will be fixed soon. </p>
<p>Another annoying thing is that you can&#39;t have multiple projects in your workspace: they each need their own window, making it hard to work on multiple projects at the same time.</p>
<p>I can&#39;t wait for PyCharm to mature!</p>

<h2 id="toc_3">Wing Python IDE</h2>
<p><a href="http://www.wingware.com/">Wing</a> IDE is a very mature IDE, that focuses on Python since 1999. It promises a graphical debugger, version control, auto completion, and Django support (including breakpoints and debugging).</p>
<p>While it should work on Mac OS X, it needs a separately installed X server like XQuartz. Considering the features of Wing and how mature it is (as opposed to PyCharm), I felt this an acceptable extra step, willing to try it out. Sadly, I never got it working, Wing always crashed right back to the desktop.</p>
<p>I will try to get Wing to work, and if it ever does, will update this post with my findings.</p>

<h2 id="toc_4">Eclipse with PyDev plugin</h2>
<p>Since Aptana Studio 3 is basically the same Eclipse-based IDE but with PyDev already pre-installed, I am not going to test Eclipse with PyDev.</p>

<h2 id="toc_5">Aptana Studio 3</h2>
<p>Aptana offers an open source Eclipse based IDE, which they say supports CSS3, HTML5 and Python (among others). It also mentions debugging, but <a href="http://www.aptana.com/products/studio3">their site</a> is very uninformative on features otherwise. I happened to know that <a href="http://pydev.org/">PyDev</a> is included with Aptana Studio 3, and luckily their site is a lot more helpful.</p>
<p>PyDev specifically lists Django integration, code completion (also with auto import, something done by PyCharm as well), code analysis and a debugger. The features are promising, so even though I kind of hate Eclipse and its weird perspective-based interface, I did download Aptana to look at it with an open mind.</p>
<p>Getting started with a project wasn&#39;t really easy. I always use a specific way of organizing my code: a top folder with the name of the project, with subfolders for the virtualenv stuff (lib, bin, include) which are not committed to version control, and a subfolder called &ldquo;project&rdquo; which contains the actual Django project. So the IDE needs to understand which Python interpreter to use (no problem with Aptana) and which folder is the Django project folder (this was quite a puzzle).</p>
<p>Once I got my project properly set up though, I was pleasantly surprised with Aptana. Code completion does a very nice job, although not quite as nice as PyCharm in some places. For example, when I create a subclass of the ListView generic view, both IDE&#39;s offer to import the correct class, but only PyCharm knows which instance variables (like template_name or model) are available for autocompletion.</p>
<p>Debugging a Django project works very well: set a breakpoint, choose to debug your Django project and Aptana will start the server with the debugger attached. The only problem I could possibly have, is that you have to switch to the debug perspective.</p>
<p>I also like the Problems pane, which shows the output of the code analysis for all Python files inside your project. Most other IDE&#39;s only show the result of the analysis for the currently opened file. Aptana makes it really easy to spot all problems.</p>
<p>In the end, while Aptana feels less buggy then PyCharm, it&#39;s also much less user friendly. Everything is just a bit more complex to set up. Creating a project with existing sources was a bit more complex. And while most IDE&#39;s recognized the .svn folders in my project and let me work with Subversion without having to configure anything, this was not the case with Aptana. I first had to install a plugin to be able to work with Subversion, and sadly trying to search for plugins mostly gave me the dreaded OS X beach-ball. And even when it was finally set up, I didn&#39;t find it easy to work with. I guess command-line based version control is the way to go with Aptana.</p>

<h2 id="toc_6">Conclusion</h2>
<p>If PyCharm was less buggy, there would be no contest to me, even considering its price tag. It&#39;s user friendly, has the best Django support, does a good job debugging projects and makes my life a lot easier. On the other hand there&#39;s Aptana. It&#39;s free, powerful and does a good job with Django project too. It&#39;s complex, but once everything is set up (which needs to be done only once) it&#39;s pretty nice to work with.</p>
<p>Right now I just can&#39;t decide between the two. I&#39;ll keep testing and comparing them both. I have to say though: while I expect that PyCharm will get less buggy very soon, I don&#39;t think Eclipse based products like Aptana will ever get user friendly.</p>
<p><strong>Update August 2012</strong><br/>
I&#39;ve neglected to update the conclusion of this blog post, sorry for that. In the end I decided to go with PyCharm and I couldn&#39;t be happier with it. It quickly got stable and even better, and I have been enjoying it daily since May 2011.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[My wishes for iOS 5]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/02/16/my-wishes-for-ios5/"/>
        <published>2011-02-16T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/02/16/my-wishes-for-ios5/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>In June 2010 Apple finally added multitasking to the iPhone (the iPad had to wait &#39;til November to get iOS version 4) and with this resolved one of my biggest complaints about the operating system. And while I really enjoy iOS on the iPhone and the iPad, I still have wishes, especially after seeing the new HP WebOS.</p>
<p>My wishes for the next version of iOS are listed below in no particular order. Hardware wishes are not included (but in short: LED notification lights on both devices, SD card support and front-facing camera on iPad).</p>

<h2 id="toc_0">Notifications</h2>
<p>Seriously Apple, what the fuck. In 2007 this was already an annoying system, and that was when it was only used for SMS. Now this retarded system is used for push notifications as well, where one is replacing the other and no way of seeming them again after unlocking the screen. This notification system needed to be replaced with something new a long long time ago. All other mobile OS&#39;es have something better. Wake up Apple!</p>

<h2 id="toc_1">iPhone and iPad working together</h2>
<p>Both the iPhone and the iPad have bluetooth. Please let me link the two together so I can send and receive SMS messages on my iPad to give just one small example. Let me send links from one device to the other, and I don&#39;t necessarily mean by tapping one device on the other like HP&#39;s new Pre 3 and TouchPad.</p>

<h2 id="toc_2">Software keyboard</h2>
<p>I never liked how much I have to switch between keyboard layouts, even when I just want to enter some numbers. I have to say, I like what HP&#39;s WebOS is doing. Maybe there is no room for this on the iPhone, but at least steal this idea for the iPad.</p>
<p><img src="http://www.palm.com/us/assets/images/products/pads/touchpad/touchpad-overview-virtual-kbd-lrg.jpg" alt="HP TouchPad keyboard"/></p>

<h2 id="toc_3">No quick settings</h2>
<p>Currently there is no way to quickly and easily disable 3G, WiFi or to change the screen brightness. I have to enter the settings app, where I have to enter a multi-level menu to do this, which is quite annoying.</p>

<h2 id="toc_4">Multitasking user interface</h2>
<p>I am very happy with the fact that Apple finally added multitasking to the iPhone and iPad (especially on the latter). However, this &ldquo;double-click on the homebutton and up slides a small view&rdquo; way of switching between apps is not working for me. You only see the icons of 4 open apps at a time, and have to slide left and right to see other icons. Why not just open a modal popup when I double-click on the homebutton, with enough room to show a 3x4 grid of icons? With the iPod controls always visible?</p>

<h2 id="toc_5">Make the lockscreen usable</h2>
<p>I want to see my calendar without unlocking my iPhone and going to the iCal app. Why can I still not use the lockscreen for anything at all? I understand that for some people privacy might be an issue: being able to see someone else&#39;s calendar on his lockscreen without unlocking the phone. So, simply make this configurable.</p>

<h2 id="toc_6">Custom SMS sounds</h2>
<p>Why the hell is this still not possible? Every time one of my iPhone-wielding friends receives an SMS, everyone else needs to check his iPhone. Why can I sync custom ringtones but not custom SMS tones? What is the logic behind this?</p>

<h2 id="toc_7">Active Weather and Clock icons</h2>
<p>The calendar application shows the current day. I think it would be cool if the weather app would show the current weather and temperature. And why can&#39;t the clock show the current time? Of course this is just nice to have, but I think it would be a nice touch.</p>

<h2 id="toc_8">No easy way to send SMS to multiple contacts</h2>
<p>When I want to send a SMS message to a large group of contacts (usually on the last day of the year just before midnight), I don&#39;t want to click on the plus icon, select a person, select the mobile number and be taken back to the message screen just to repeat these steps for every person. Why can&#39;t I send to a contact-group? Or be able to quickly select multiple contacts?</p>

<h2 id="toc_9">Bring iPhone&#39;s default apps to the iPad</h2>
<p>Why doesn&#39;t the iPad have the clock and weather apps? What&#39;s the logical reason behind this? Also missing: stocks and voice memos, but I personally don&#39;t use those apps. </p>
<p>What are your wishes for the next version of iOS? Let me know in the comments!</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Django-CMS backend usability]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/01/29/django-cms-backend-usability/"/>
        <published>2011-01-29T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/01/29/django-cms-backend-usability/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>Yesterday I wrote <a href="http://mixedcase.nl/articles/2011/01/28/django-cms-vs-feincms-vs-mezzanine/">an article</a> comparing Django-CMS, FeinCMS and Mezzanine. One of the conclusions was that while Django-CMS is the best CMS on paper, I don&#39;t like its backend interface that much. I thought it would be a good idea to properly explain what I don&#39;t like about it, and try to come up with a better interface.</p>

<h2 id="toc_0">The problem</h2>
<p>When you edit a page in the CMS, there is no way to immediately see the content that&#39;s on the page. Have a look at the first screenshot: I can see that there is a &ldquo;content&rdquo; placeholder that contains a text plugin and a picture, and an &ldquo;aside&rdquo; placeholder that contains a text plugin. But what text? Which picture? This is not &ldquo;what you see is what you get&rdquo; levels of easy.</p>
<p>The second problem I have is when you edit a plugin. Have a look at the second screenshot: the current text content is shown both as preview and wysiwyg editor. I don&#39;t see how this is helpful, both (should) show the same content with the same markup and layout. The only place where I found this way of showing the preview together with the form is when editing a picture plugin.</p>
<p><a href="http://dl.dropbox.com/u/2310965/problem-1.png"><img src="http://dl.dropbox.com/u/2310965/problem-1-thumb.jpg" alt="screenshot 1"/></a>
<a href="http://dl.dropbox.com/u/2310965/problem-2.png"><img src="http://dl.dropbox.com/u/2310965/problem-2-thumb.jpg" alt="screenshot 2"/></a></p>

<h2 id="toc_1">A possible solution</h2>
<p>The frontend editing of Django-CMS is very nice. You see the content of the entire page, click on one of the plugins and an editor pops up. Why not replicate this in the admin interface? Show those preview blocks under each other with a link to add a new block to the page. Editing content could be done in a popup just as in the frontend.</p>
<p>With this solution it&#39;s possible to see the layout of the entire page. It also solves the usability problem of multiple save buttons on screen at the same time: currently when you begin to edit a plugin that form gets its own save button, which needs to be clicked before you can then save the page itself.  When you present the form in a modal popup, it is immediately clear that you need to close that popup by saving or canceling. </p>
<p><a href="http://dl.dropbox.com/u/2310965/mockup-1.jpg"><img src="http://dl.dropbox.com/u/2310965/mockup-1-thumb.jpg" alt="screenshot 3"/></a>
<a href="http://dl.dropbox.com/u/2310965/mockup-2.jpg"><img src="http://dl.dropbox.com/u/2310965/mockup-2-thumb.jpg" alt="screenshot 4"/></a></p>
<p>This is a very basic mockup, of course you&#39;d need to be able to see and edit multiple placeholders. I don&#39;t know what would work best: tabs for each placeholder, placeholders underneath each other (kinda like the current interface does), or maybe even next to each other. I think that last option could work very well, at least as long as you don&#39;t have more then two placeholders.</p>
<p>I am very interested in your opinions about the current Django-CMS backend, its usability problems and your solution.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Django-CMS vs. FeinCMS vs. Mezzanine]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/01/28/django-cms-vs-feincms-vs-mezzanine/"/>
        <published>2011-01-28T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/01/28/django-cms-vs-feincms-vs-mezzanine/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>When you need a content management system for Django, there is enough choice. Maybe even too much: the very helpful site <a href="http://djangopackages.com/grids/g/cms/">djangopackages.com</a> lists 13. Some are mature and very feature-complete, while others are barely more then a basic model and a template. The biggest three systems (in terms of downloads, repo forks and -watchers) are <a href="http://www.django-cms.org/">Django-CMS</a>, <a href="http://www.feinheit.ch/labs/feincms-django-cms/">FeinCMS</a> and <a href="http://mezzanine.jupo.org/">Mezzanine</a>. I&#39;ve built sites with both Django-CMS and Mezzanine, looked at FeinCMS and decided to write down a comparison.</p>

<h2 id="toc_0">Django-CMS</h2>
<p>With a very nice and professional looking website, you immediately get the feeling that this is a very mature CMS. The latest version, 2.1, has been in the making for a long time and adds very cool features such as frontend editing and easy integration of third party apps. Version 2.1 final has been released yesterday, so if you never looked at Django-CMS before, now is the perfect time.</p>
<p>Is has some very compelling arguments:</p>

<ul>
<li>Stable and mature, with multiple core developers</li>
<li>Very good documentation for developers</li>
<li>Many extensions available</li>
<li>Extensions are very easy to create</li>
<li>Frontend editing</li>
<li>Very easy to integrate your own apps into the CMS</li>
<li>Extremely easy for developers to work with</li>
<li>Multiple templates, each template can define its own placeholders</li>
<li>Good support for multilingual sites</li>
<li>Moderation workflow and advanced permissions</li>
<li>Revert changes / undelete pages</li>
</ul>
<p>But not all is golden:</p>

<ul>
<li>The plugin system, while nicely extendible, makes the admin interface <a href="http://mixedcase.nl/articles/2011/01/29/django-cms-backend-usability/">pretty sucky</a></li>
<li>Doesn&#39;t work with <a href="http://code.google.com/p/django-grappelli/">Grappelli</a></li>
<li>Doesn&#39;t use the TinyMCE editor by default</li>
</ul>
<p>It&#39;s a very good CMS that&#39;s very easy to work with as a developer. However, I feel that for normal users the CMS could be improved a lot by dropping the current plugin based interface. The idea of multiple plugins per block of content is nice, but the admin interface is not usable enough. Tip for Django-CMS developers reading this: have a look at the TYPO3 backend.</p>
<p>The thing I absolutely like the most about Django-CMS is the way you define one or more placeholders directly in your HTML templates. Then, when you create a new page, you select one of your templates and it scans the source to find the placeholders you&#39;ve defined. No config, no code, very very easy.</p>
<p><em><strong>Update</strong> - just to clarify: I&#39;m not suggesting to drop the plugin system, just its current (backend) admin interface. Maybe when the frontend editing gets even better, it could completely replace it and thus solving the biggest problems I am having with Django-CMS. See also one of my other posts <a href="http://mixedcase.nl/articles/2011/01/29/django-cms-backend-usability/">here</a>.</em></p>

<h2 id="toc_1">FeinCMS</h2>
<p>I&#39;ve never worked with this CMS before, but I did install it for a quick tryout. According to djangopackages.com it&#39;s the second biggest CMS for Django.</p>
<p>Pros:</p>

<ul>
<li>Probably the most flexible CMS</li>
<li>Good documentation</li>
<li>Easy to create you own custom content types</li>
<li>Multilingual</li>
</ul>
<p>Cons:</p>

<ul>
<li>There is no content type that does both rich text and images (and I like TinyMCE and django-filebrowser so much!)</li>
<li>Harder to setup and get started with</li>
<li>Admin interface looks and feels old-fashioned</li>
<li>No reversion </li>
<li>No moderation</li>
</ul>
<p>It&#39;s the most flexible CMS by far, but that does come with a price: it&#39;s also the most complicated CMS of the three (mostly for developers but also for users). It&#39;s a real developers&#39; CMS. As I&#39;ve never actually built a site with FeinCMS I can&#39;t really say much more about it, but I can&#39;t say I am very motivated to try it out with two other excellent content management systems as its competitors.</p>

<h2 id="toc_2">Mezzanine</h2>
<p>For my latest project I used the Mezzanine CMS, because Django-CMS <a href="http://mixedcase.nl/articles/2011/01/17/looking-for-django-cms/">didn&#39;t quite fit right</a>. I&#39;ve worked with Mezzanine for two weeks now.</p>
<p>Pros:</p>

<ul>
<li>Includes Grappelli, TinyMCE and django-filebrowser</li>
<li>Admin interface looks sexy and clean</li>
<li>Frontend editing (although not quite as nicely done as Django-CMS)</li>
<li>Completely integrated blogging engine</li>
<li>Shopping cart module (not used this yet)</li>
<li>Build-in form editor that is actually very usable (as compared to the third party forms extension for Django-CMS)</li>
<li>Admin users can edit some site settings like posts per page, Google Analytics id, etc</li>
<li>Developer docs are basic but good</li>
</ul>
<p>Cons:</p>

<ul>
<li>It&#39;s a young project (not mature, few core developers)</li>
<li>The default templates are pretty bad</li>
<li>Some of the features should not be in the CMS: 960.gs integration and multi-device detection</li>
<li>No reversion</li>
<li>No moderation</li>
<li>Absolutely no support for multilingual sites</li>
<li>The homepage is not part of the CMS</li>
<li>Harder to integrate with third party apps</li>
<li>The url of your blog is hardcoded in settings.py</li>
</ul>
<p>Especially the last three points really bug me. Mezzanine really should look at Django-CMS and steal their apps- and menus integration. The multi-device detection is a nice idea, but I&#39;ll do this with CSS 3 media selectors, thank you very much. I also don&#39;t want to use 960.gs, as I&#39;m using em-based layouts more and more. Things like this should not be in the CMS but in your own app/templates/javascript code. My suggestion is to remove the device detection from the CMS, move it to its own app and release that on Github. Then you could also use it without the rest of Mezzanine.</p>
<p>In the end I did like working with Mezzanine a lot, and after customizing each and every template and removing all of their CSS code, the end-result is very nice too. The biggest plus points when compared to Django-CMS are the integrated blog posts, the very nice admin interface and the consistent use of TinyMCE. I predict that Mezzanine will overtake FeinCMS as the second biggest CMS within a year.</p>

<h2 id="toc_3">Conclusion</h2>
<p>FeinCMS is very flexible and extendible and I can imagine a lot of situations where this is needed. If you don&#39;t need the flexibility though, I would not use FeinCMS because of its admin interface and complexity.</p>
<p>So, which one do I prefer? Django-CMS or Mezzanine? If you need to build a multilingual site or need moderation, the decision is easy, as Mezzanine doesn&#39;t support neither. Otherwise though, it&#39;s difficult. Django-CMS offers the worst admin interface of the two, but has many features and is the easiest of the two to build a site in. On the other hand, Mezzanine feels fresh and has an admin interface which I can show to a client full of confidence.</p>
<p>Maybe that&#39;s why I built my own site with Django-CMS, but for my latest project (which will have multiple writers with probably questionable computer experience) I chose Mezzanine. It&#39;s a head versus heart thing: in my head I know Django-CMS is the better CMS, but Mezzanine just feels better.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Looking for a Django CMS which suits my needs]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2011/01/17/looking-for-django-cms/"/>
        <published>2011-01-17T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2011/01/17/looking-for-django-cms/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>I need to build a content-based website for a client, in Django. Well, that&#39;s easy right? Pick one of the content management systems available, build some templates and css, and ta-da, done. Since I have used <a href="http://www.django-cms.org/">Django-CMS</a> in previous projects, that would make my choice pretty easy too. It&#39;s easy to work with, flexible and pretty user-friendly.</p>
<p>Sadly though, after a day of wrestling with Django-CMS, I am not so sure about this choice. Let me explain why.</p>
<p>The client needs a site with some basic pages (about me, contact information), an articles section, and a home page which shows a mix of latest articles and content that needs to be editable. My first thought was to use Django-CMS in combination with <a href="https://github.com/Fantomas42/django-blog-zinnia">Zinnia</a> for the articles, just as I did for this site and which I still like a lot. However, for this project it just isn&#39;t suitable:</p>

<ul>
<li>There are going to be multiple writers who can all add new articles, but should only be able to edit their own, and;</li>
<li>all new articles need to be approved by an editor before they can be published on the site.</li>
</ul>
<p>Zinnia doesn&#39;t offer this level of moderation, and while I could possibly, eventually, get this to work, there is something nagging me about the combination of Django-CMS and Zinnia: the plugin-based system and the wysiwyg editor. I just don&#39;t like the plugin system used by Django-CMS, where you can add multiple blocks of content to a page. This content can for example be text or a picture. I&#39;d much rather have just one big TinyMCE area with a filebrowser plugin for including pictures right there.</p>
<p>With Zinnia it is possible to use TinyMCE and the filebrowser plugin, great! Since 90% of the site will consist of articles, at least this part is easy to edit for the writers. However&hellip; this functionality depends on the <a href="http://code.google.com/p/django-grappelli/">Grappelli</a> skin for the Django admin interface, which is not compatible with Django-CMS. So I can&#39;t use it.</p>
<p>Not all is lost: Zinnia can also use the plugin system offered by Django-CMS, so at least it&#39;s possible to enter content and pictures. There is a big usability problem with this though: you first need to create a blank article, save it and only then you can add plugins to it. How I am going to sell this to the client?</p>
<p>Right now I am thinking about writing my own articles-app, which does simple moderation and uses TinyMCE and filebrowser. This means I need Grappelli, so I need a stable CMS that plays nice with it and offers at least the following two features:</p>

<ul>
<li>TinyMCE and filebrowser, so the editing is consistent</li>
<li>App integration, for including the articles section in the menu</li>
</ul>
<p><a href="http://www.feinheit.ch/labs/feincms-django-cms/">FeinCMS</a> could be nice, but as far as I can see from the docs, this too doesn&#39;t offer a TinyMCE widget with media/filebrowser integration. <a href="https://github.com/stephenmcd/mezzanine">Mezzanine</a> is pretty cool too, but I can&#39;t use their integrated blog manager, as it doesn&#39;t do moderation.</p>
<p>Any ideas? I know that it would be way easier to just use Plone or TYPO3 or even Wordpress, but the client specifically asked for Django.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[My thoughts after having completed my first Appcelerator projects]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2010/12/02/my-thoughts-after-having-completed-my-first-appcelerator-projects/"/>
        <published>2010-12-02T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2010/12/02/my-thoughts-after-having-completed-my-first-appcelerator-projects/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>A while ago I set out to build my third mobile application. Only this time the client wanted not only an iPhone app, but one for Android too. So that&#39;s why I <a href="http://www.mixedcase.nl/articles/2010/11/09/once-again-i-turn-appcelerator/">turned to Appcelerator</a> once again, after my <a href="http://www.mixedcase.nl/articles/2010/04/21/getting-started-iphone-app-development/">failed first attempt</a>.</p>
<p>In case you don&#39;t know what Appcelerator is and don&#39;t want to read the previous articles, I&#39;l explain it in a few words. Appcelerator is a cross-compiler: you write your app in Javascript using a strict API, and this app is then compiled to both iPhone and Android versions. These apps are truly native apps and use native widgets, tableviews, etc. Sounds pretty good, right?</p>
<p>Well yes. A bit too good actually. While you get a working skeleton app very quickly that does indeed compile to both iPhone and Android, there are quite some disadvantages.</p>

<ul>
<li>You can only use the Appcelerator API to build the interface of your app. If they don&#39;t support feature X, you&#39;re pretty much out of luck. In theory you can build native extensions that can then be used from within your Appcelerator app, but in practice this kind of defeats the purpose and requires you to still know Java and/or Objective-C.</li>
<li>Even though Appcelerator tries very hard to keep up to date, it is always a bit behind in terms of features offered by the native SDK&#39;s.</li>
<li>Debugging is a lot harder if you are used to Xcode&#39;s excellent tools.</li>
<li>Performance on Android is less then stellar. Real native apps perform better, especially when you try to use a tableviews containing images.</li>
<li>I miss Instruments! Of course this is only valid for native iPhone development, but I guess Eclipse for Android development is better for laying out interfaces too. With Appcelerator you have to lay everything out by hand, using absolute pixel-positions.</li>
<li>Making an app that is complicated in terms of interface is very hard in Appcelerator. I&#39;ve never seen the 80/20 rule (the last 20% of work takes 80% of your time) in effect as clear as when developing with Appcelerator. Starting with your project is very nice, very quick. And then everything kind of grinds to a halt while you &ldquo;fight the API&rdquo; to make it do what you want.</li>
<li>Even though you can compile your app to two different platforms with the click of a button, it is never as easy as it sounds. Some widgets are only supported on one platform, so in your code you tend to get quite some <code>if platform == &quot;iPhone&quot;</code> statements. You still have to do a lot of work twice.</li>
<li>And last but not least: normally your iPhone app can be made into an iPad app as well, with only a fairly small amount of work. With Appcelerator this is not possible: as far as I can tell, you need to build it as a separate app.</li>
</ul>
<p>After having completed my first Appcelerator app, I have come to the conclusion that it is nice for pretty simple, low-profile apps. The advantage of building your app once with Javascript simply outweigh the disadvantages. However, as soon as you want to do complicated things, need better performing apps or when quality is very important, I would never use Appcelerator. Let&#39;s say that building an iPhone app would take 100 hours and building the Android version would take another 100 hours. Using Appcelerator to build both apps would instead take 150 hours. That&#39;s a nice 25% reduction, but my feeling is that you would never get the same quality.</p>
<p>In short, if the budget allows for it, building two native apps will result in higher quality apps. That&#39;s why we at <a href="http://www.goldmund-wyldebeast-wunderliebe.com/">Goldmund, Wyldebeast &amp; Wunderliebe</a> are now training two people in building Android apps, and one developer will join me in developing native iPhone apps.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Serving 5000 pages per second with Django]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2010/11/16/serving-5000-pages-second-django/"/>
        <published>2010-11-16T00:00:00+00:00</published>
        <updated>2012-12-28T10:58:02+00:00</updated>
        <id>http://mixedcase.nl/articles/2010/11/16/serving-5000-pages-second-django/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>Okay, this website wasn&#39;t slow and will never need to serve 5000 pages per second, but hey, it&#39;s possible now! Oh right, and it was fun to play around with a nice caching system.</p>
<p>Almost everything on mixedCase.nl needs to come from the database: the list of categories, the menu on top of the site, the articles, the count of the number of comments, how many entries there are per month and category, and so on. So, caching makes a big difference in making the site very quick. When I wanted to play around with caching, I already knew about these options Django provides out of the box:</p>

<ul>
<li>Cache individual views with a decorator</li>
<li>Cache pieces of the rendered templates with the cache templatetag</li>
<li>Use Django&#39;s cache middleware to cache the output of entire pages to memcached</li>
</ul>
<p>Option 1 was not an option, since all views are provided by third-party applications (<a href="https://github.com/divio/django-cms">Django-CMS</a> and one of my all-time favorite apps: <a href="https://github.com/Fantomas42/django-blog-zinnia">Zinnia</a>). Option 2 is better, because all templates are written by myself, so I can do whatever I want. While this is indeed a very nice option if you want to cache &ldquo;expensive&rdquo; bits of your pages, Django still has to do some work. The third option is pretty cool: insert two pieces of middleware in your <code>settings.py</code> and your entire site is cached. However, the webserver still needs to call your Django instance (in my case <a href="http://gunicorn.org/">Gunicorn</a>).</p>
<p>Today I was looking at the documentation of <a href="http://wiki.nginx.org/Main">Nginx</a>, the webserver I use. Listed in the available modules: <a href="http://wiki.nginx.org/HttpMemcachedModule">HttpMemcachedModule</a>. Wow, the webserver can use your memcached cache, so it doesn&#39;t even have to hit the Django server! After looking into this, I quickly saw a problem: Nginx can use the current url as a cache-key, but not much else. And Django&#39;s cache middleware uses a key composed of cookies, sessions, url and md5 hashes. So, the cache as written by Django cannot be read from Nginx. Bummer.</p>
<p>As the saying goes: Google is your friend, and it wasn&#39;t long before I found some posts about this very problem. Some people wrote their own cache middleware, so it&#39;s readable from Nginx. However, invalidating the cache looked difficult in all their solutions: whenever a new comment is made for example, you need to remove the cache for the article, the list of articles on /articles/, all category lists that article is on, and the homepage. Why? Because they all show a count of the comments made on articles. And since all those pages are saved in memcached with an URL as their key, you need to find all those URL&#39;s to remove them from the cache. Ouch.</p>
<p>I then found a very interesting project on Github: <a href="https://github.com/luckythetourist/staticgenerator">StaticGenerator for Django</a>. In short, it&#39;s a piece of middleware that saves the output of the requested page as an HTML file, which can be served from Nginx. And since it&#39;s just a bunch of files on disk, it&#39;s very easy to just remove all of them whenever something on the website has changed (a new page or article has been added, a comment has been made, and so on). I made some modifications on the StaticGenerator, because I only want to cache pages for anonymous users, and want to be able to set a list of excluded URL&#39;s. The <a href="http://bitbucket.org/kevinrenskers/mixedcase/src/tip/project/staticgenerator/">source code is available</a> on my Bitbucket account.</p>
<p>To use the StaticGenerator, add these settings to <code>settings.py</code>:</p>
<div class="highlight"><pre><span class="n">WEB_ROOT</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">),</span> <span class="s">&#39;generated&#39;</span><span class="p">)</span>

<span class="n">STATIC_GENERATOR_ANONYMOUS_ONLY</span> <span class="o">=</span> <span class="bp">True</span>

<span class="n">STATIC_GENERATOR_URLS</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">r&#39;^/$&#39;</span><span class="p">,</span>
    <span class="s">r&#39;^/(articles|projects|about)&#39;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">STATIC_GENERATOR_EXCLUDE_URLS</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">r&#39;\.xml$&#39;</span><span class="p">,</span>
    <span class="s">r&#39;^/articles/search&#39;</span><span class="p">,</span>
    <span class="s">r&#39;^/articles/feed&#39;</span><span class="p">,</span>
    <span class="s">r&#39;^/articles/comments/posted&#39;</span><span class="p">,</span>
<span class="p">)</span>
</pre></div>
<p>You also need to add <code>&#39;staticgenerator.middleware.StaticGeneratorMiddleware&#39;</code> to the end of your <code>MIDDLEWARE_CLASSES</code> list.</p>
<p>Of course, you want to remove the generated pages as soon as something has changed. You can simply add something like this to one of your <code>models.py</code> files:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">django.db.models.signals</span> <span class="kn">import</span> <span class="n">post_save</span>
<span class="kn">from</span> <span class="nn">staticgenerator</span> <span class="kn">import</span> <span class="n">recursive_delete</span>

<span class="k">def</span> <span class="nf">delete_cache</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="n">recursive_delete</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>

<span class="n">post_save</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">delete_cache</span><span class="p">)</span>
</pre></div>
<p>Please note that this is a very simple implementation: every time any of your models is saved, all generated pages are removed. This includes someone simply logging in on the admin site as well, which is of course not something you would want. I&#39;ll update this post with a better way of doing this.</p>
<p>Finally, my (shortened) Ngix config:</p>
<div class="highlight"><pre><span class="k">server</span> <span class="p">{</span>
    <span class="kn">server_name</span> <span class="s">.mixedcase.nl</span><span class="p">;</span>
    <span class="kn">root</span> <span class="s">/path/to/project/generated/</span><span class="p">;</span>

    <span class="kn">access_log</span> <span class="s">/var/log/nginx/mixedcase.nl.access.log</span><span class="p">;</span>

    <span class="kn">location</span> <span class="s">/media/</span>  <span class="p">{</span>
        <span class="kn">alias</span> <span class="s">/path/to/project/media/</span><span class="p">;</span>
        <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span>
        <span class="kn">expires</span> <span class="s">max</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kn">location</span> <span class="s">/adminmedia/</span>  <span class="p">{</span>
        <span class="kn">alias</span> <span class="s">/path/to/project/lib/python2.6/site-packages/django/contrib/admin/media/</span><span class="p">;</span>
        <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span>
        <span class="kn">expires</span> <span class="s">max</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kn">location</span> <span class="s">/</span> <span class="p">{</span>
        <span class="kn">if</span> <span class="s">(-f</span> <span class="nv">$request_filename/index.html</span><span class="s">)</span> <span class="p">{</span>
            <span class="kn">rewrite</span> <span class="s">(.*)</span> <span class="nv">$1/index.html</span> <span class="s">break</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">Host</span> <span class="nv">$http_host</span><span class="p">;</span>
        <span class="kn">proxy_redirect</span> <span class="no">off</span><span class="p">;</span>

        <span class="kn">if</span> <span class="s">(!-f</span> <span class="nv">$request_filename</span><span class="s">)</span> <span class="p">{</span>
            <span class="kn">proxy_pass</span> <span class="s">http://unix:/tmp/gunicorn_mixedcase.sock</span><span class="p">;</span>
            <span class="kn">break</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>As I said in the first sentence: mixedCase.nl can now do 5000 pages per second. I&#39;m impressed!</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Source code of mixedcase.nl now available]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2010/11/13/source-code-mixedcasenl-now-available/"/>
        <published>2010-11-13T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2010/11/13/source-code-mixedcasenl-now-available/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>This website uses quite some Django packages, like Django-CMS and Zinnia. A lot of effort has been put into integrating everything nicely into the design and templates, like comments, sitemaps, archives, Pygments, Markdown, etc.</p>
<p>I understand that for beginning Django developers, building a site like this could take a lot of time and effort, not knowing where to begin. That&#39;s why I&#39;ve decided to open source the entire website. Feel free to have a look around and maybe learn a bit or two.</p>
<p>You can find the source on <a href="https://bitbucket.org/bolhoed/mixedcase">bitbucket.org/kevinrenskers/mixedcase</a>.</p>
]]>
        </content>
    </entry><entry>
        <title type="html"><![CDATA[Once again I turn to Appcelerator]]></title>
        <author><name>kevin</name></author>
        <link href="http://mixedcase.nl/articles/2010/11/09/once-again-i-turn-appcelerator/"/>
        <published>2010-11-09T00:00:00+00:00</published>
        <updated>2012-12-27T03:24:20+00:00</updated>
        <id>http://mixedcase.nl/articles/2010/11/09/once-again-i-turn-appcelerator/</id>
        <content type="html" xml:base="http://mixedcase.nl" xml:lang="en">
            <![CDATA[ <p>After I <a href="http://www.mixedcase.nl/articles/2010/04/21/getting-started-iphone-app-development/">decided</a> to create iPhone apps using just the iPhone SDK and the Objective-C language, I&#39;ve created <a href="http://itunes.apple.com/nl/artist/goldmund-wyldebeast-wunderliebe/id380925906">two iPhone apps</a> that are available in the Dutch App Store. Development for app number three has started today, but no longer will I be using Xcode.</p>
<p>What gives? Well, the client wants an Android app too. Of course I could build the iPhone version with Xcode, the SDK and Objective-C and create the Android version from scratch after that&#39;s finished. But I don&#39;t really know Java and don&#39;t feel like learning yet another mobile SDK. So, back to <a href="http://www.appcelerator.com/">Appcelerator</a> it is! I have to say, so far so good: progress is incredibly fast and the skeleton app I&#39;ve created so far indeed builds for iPhone and Android.</p>
<p>I do wonder if progress will stay this fast. Last time I&#39;ve used Appcelerator, I gave up once I wanted to do more complicated things and support was hard to get. Given that this app is pretty simple though, I have high hopes. If I come across cool tricks or problems, I&#39;ll let you know.</p>
]]>
        </content>
    </entry>
</feed>