<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"><channel><title>Hardcoded Software articles</title><link>http://www.hardcoded.net/articles/</link><description>Pointless babbling of a Python developer</description><lastBuildDate>Fri, 20 Jan 2012 00:00:00 GMT</lastBuildDate><item><title>Going Open Source</title><link>http://www.hardcoded.net/articles/going_open_source.htm</link><description>&lt;p&gt;Free Software and proprietary software are seldom seen as compatible. Free Software proponents are telling us that users should have the &lt;a href="http://www.gnu.org/"&gt;"freedom to run, copy, distribute, study, change and improve the software"&lt;/a&gt;, and proprietary software developers are arguing that it's very hard to earn money from producing Free Software. Both sides have good arguments, but a consensus can never seem to be reached.&lt;/p&gt;
&lt;p&gt;Recently, the author of &lt;a href="http://e-texteditor.com/"&gt;E Text Editor&lt;/a&gt;, Alexander Stigsen, has made a &lt;a href="http://e-texteditor.com/blog/2009/opencompany"&gt;very bold move&lt;/a&gt; by opening the source of his proprietary software. Although I'm not convinced by the Trust Metric system he proposes, I think it is a very interesting move, a move that could potentially, finally, reconcile shareware and open source.
&lt;a href="http://www.hardcoded.net/articles/going_open_source.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/going_open_source.htm</guid><pubDate>Wed, 05 Aug 2009 18:00:00 GMT</pubDate></item><item><title>Using QTreeView with QAbstractItemModel</title><link>http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm</link><description>&lt;p&gt;For someone coming from the Cocoa world, understanding how &lt;code&gt;QTreeView&lt;/code&gt; and &lt;code&gt;QAbstractItemModel&lt;/code&gt; work can be quite hard. While the concept of an item model for a tree view also exists in Cocoa, the way &lt;code&gt;QAbstractItemModel&lt;/code&gt; works is quite different from &lt;code&gt;NSOutlineDatasource&lt;/code&gt;'s.&lt;/p&gt;
&lt;p&gt;The biggest difference between the two models is in the way they refer to cells. In Cocoa, we use an arbitrary identifier supplied by the model through &lt;code&gt;outlineView:child:ofItem:&lt;/code&gt;. Then, this identifier is used in combination with a &lt;code&gt;NSTableColumn&lt;/code&gt; instance for calls like &lt;code&gt;outlineView:objectValueForTableColumn:byItem:&lt;/code&gt; (which is supposed to return what must be displayed for a particular cell). On the Qt side, we use a &lt;code&gt;QModelIndex&lt;/code&gt; instance that is supplied by the &lt;code&gt;index(row, column, parent)&lt;/code&gt; method. The strange thing with &lt;code&gt;QModelIndex&lt;/code&gt; is that it not only holds an identifier, but it also holds a row and a column. Therefore, if &lt;code&gt;index(1, 2, parentId)&lt;/code&gt; is called on the model, what must be returned is a &lt;code&gt;QModelIndex(1, 2, childId)&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;To a Qt newbie, this requirement for the model to return redundant data (row and column) might seem stupid. They might even think that it's downright insane when they discover that subclassing &lt;code&gt;QAbstractItemModel&lt;/code&gt; also requires you to implement a &lt;code&gt;parent(index)&lt;/code&gt; method. After all, the view &lt;em&gt;knew&lt;/em&gt; what was the parent of that index when it asked for it in &lt;code&gt;index(row, column, parent)&lt;/code&gt;! The poor Qt newbie might spend quite some time wondering what the heck was TrollTech thinking when they designed this API.&lt;/p&gt;
&lt;p&gt;It turns out that there's a reason for this strange and complex API: &lt;a href="http://labs.trolltech.com/blogs/2008/10/24/itemviews-the-next-generation/"&gt;TrollTech over-engineered this part of the toolkit&lt;/a&gt;. They wanted to design their item model so that it would be possible for a single model instance to have table views and tree views connected to it &lt;em&gt;at the same time&lt;/em&gt;. While I'm sure that there are cases where this feature is very useful, there's a lot of &lt;code&gt;QTreeView&lt;/code&gt; users out there who have no need for it and are suffering because of this over-engineering.
&lt;a href="http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm</guid><pubDate>Sat, 26 Sep 2009 18:00:00 GMT</pubDate></item><item><title>Cross-Toolkit Software</title><link>http://www.hardcoded.net/articles/cross-toolkit-software.htm</link><description>&lt;p&gt;Developing cross-platform software is easy: use cross-platform libraries, and you're set! When GUIs are involved, however, things get a little trickier. Different platforms tend to have different ways of doing things, GUI-wise. There are libraries that attempt to abstract away these differences to allow developers to build "write once, deploy everywhere" GUI-enabled applications (&lt;a href="http://qt.nokia.com"&gt;Qt&lt;/a&gt;, &lt;a href="http://www.wxwidgets.org"&gt;wxWidgets&lt;/a&gt;, &lt;a href="http://www.gtk.org"&gt;GTK+&lt;/a&gt;, etc.), but they always seem to fall short when it comes to the "nativeness" of the look and feel, especially for Mac OS X. To have a cross-platform GUI-enabled application that looks and feels native on all platforms, one obvious solution is to have a cross-&lt;strong&gt;toolkit&lt;/strong&gt; design.&lt;/p&gt;
&lt;p&gt;By "cross-toolkit", I mean an application that uses more than one toolkit for the different platforms it supports. For example, my own applications use two toolkits: Cocoa (through &lt;a href="http://pyobjc.sourceforge.net/"&gt;PyObjC&lt;/a&gt;) under Mac OS X, and Qt (through &lt;a href="http://www.riverbankcomputing.com/"&gt;PyQt&lt;/a&gt;) under Windows.&lt;/p&gt;
&lt;p&gt;But going cross-toolkit, although it gives your software nativeness, brings its own share of problems. When you create a cross-toolkit software, you have to decide what code belongs to the core, and what code belongs to the toolkit-specific code. If you put too much code in the core, you end up re-writing your own little toolkit wrapper. Then, you realize you abstracted away too much when a platform's specificity forces you to either hack around your core design or rethink that design. If you don't give your core enough responsibilities, you end up with logic duplication among your different toolkit-specific codebases.&lt;/p&gt;
&lt;p&gt;In this article, I'm going to take a look at three softwares: A single-toolkit-cross-platform software (OpenOffice), a cross-toolkit software with logic duplication in it (Transmission), and then my own attempt a creating a great cross-toolkit software (moneyGuru).
&lt;a href="http://www.hardcoded.net/articles/cross-toolkit-software.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/cross-toolkit-software.htm</guid><pubDate>Sun, 20 Dec 2009 18:00:00 GMT</pubDate></item><item><title>How To Customize QTableView's Editing Behavior</title><link>http://www.hardcoded.net/articles/how-to-customize-qtableview-editing-behavior.htm</link><description>&lt;p&gt;&lt;code&gt;QTableView&lt;/code&gt;'s default editing behavior seems to have been designed with spreadsheet-like usage in mind. When your table needs a more "row-based" editing with some columns being read-only, it becomes rather difficult to customize &lt;code&gt;QTableView&lt;/code&gt; to support that. I recently needed to do it for &lt;a href="/moneyguru/"&gt;moneyGuru&lt;/a&gt; and this article explains how I did it.
&lt;a href="http://www.hardcoded.net/articles/how-to-customize-qtableview-editing-behavior.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/how-to-customize-qtableview-editing-behavior.htm</guid><pubDate>Mon, 28 Dec 2009 18:00:00 GMT</pubDate></item><item><title>Building 64-bit PyObjC Applications With Py2app</title><link>http://www.hardcoded.net/articles/building-64-bit-pyobjc-applications-with-py2app.htm</link><description>&lt;p&gt;64-bit is upon us and has been for a while now. With Mac OS X Snow Leopard putting so much emphasis on 64-bit applications, you don't want to be left behind with your py2app built applications, don't you? Well, it turns out you're not entirely out of luck! It requires a bit of tweaking, but building 64-bit Python based applications with py2app is possible.
&lt;a href="http://www.hardcoded.net/articles/building-64-bit-pyobjc-applications-with-py2app.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/building-64-bit-pyobjc-applications-with-py2app.htm</guid><pubDate>Tue, 19 Jan 2010 18:00:00 GMT</pubDate></item><item><title>Embedded PyObjC</title><link>http://www.hardcoded.net/articles/embedded-pyobjc.htm</link><description>&lt;p&gt;When people think of a &lt;a href="http://pyobjc.sourceforge.net/"&gt;PyObjC&lt;/a&gt; application, they usually think of a Python application that uses Objective-C libraries. However, it's also possible to do the opposite: An Objective-C application that embeds Python code through a plugin. Building an application this way has advantages (speed, integration and memory usage) and should be used more often. This article explains why and how to achieve this.
&lt;a href="http://www.hardcoded.net/articles/embedded-pyobjc.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/embedded-pyobjc.htm</guid><pubDate>Mon, 08 Feb 2010 18:00:00 GMT</pubDate></item><item><title>High Level Testing</title><link>http://www.hardcoded.net/articles/high-level-testing.htm</link><description>&lt;p&gt;Too often, developers new to unit testing see them as a liability. They're hard to write, and when you want to deeply refactor your code (for example, when you want to re-organize your classes' respective responsibilities), you have to change your unit tests. This then discourages you to refactor your code, making you &lt;em&gt;less agile&lt;/em&gt;. These developers will probably abandon unit testing and write on their blog that TDD sucks (because it's common knowledge that unit testing is &lt;em&gt;good&lt;/em&gt;, so you can't say that it sucks. It's easier to attack TDD, aka. too many unit tests).&lt;/p&gt;
&lt;p&gt;You know what? They're right. I think we do way too much &lt;a href="http://en.wikipedia.org/wiki/Unit_testing"&gt;unit testing&lt;/a&gt; when we should be doing &lt;a href="http://en.wikipedia.org/wiki/Integration_testing"&gt;integration testing&lt;/a&gt; instead. If you have a class that is all neat and cute and unit tested and that a new requirement in your application requires you to split that class in two (to do it correctly), you either have to change all your tests, or you implement a kludge that allows you to keep your former architecture (don't do that).&lt;/p&gt;
&lt;p&gt;What I've been doing for about 2 years (for &lt;a href="http://hg.hardcoded.net/moneyguru"&gt;moneyGuru's development&lt;/a&gt;, to be precise) is what I call &lt;em&gt;high level testing&lt;/em&gt;, which is like integration testing, but without (or very little) unit testing. It has some downsides, but it's been working great so far and has empowered me with nearly unlimited refactoring potential on the whole project. I'm under the impression that a lot of developers have a narrow view of unit testing, which prevents them from even considering this possibility. I hope, with this article, to broaden their horizon a little bit.
&lt;a href="http://www.hardcoded.net/articles/high-level-testing.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/high-level-testing.htm</guid><pubDate>Wed, 03 Mar 2010 18:00:00 GMT</pubDate></item><item><title>Send Files To Trash On All Platforms</title><link>http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm</link><description>&lt;p&gt;If you've ever needed to send files to trash in your cross-platform application, you've probably noticed the painful void in your toolkit. It's just not there. You can copy, move, delete files, but you can't send them to the trash. There's no easy solution (until now) and you need to implement platform-specific code for Mac OS X, Windows and Linux.&lt;/p&gt;
&lt;p&gt;On Mac OS X, you have to call &lt;code&gt;FSMoveObjectToTrashSync&lt;/code&gt; (or its async friend) from &lt;code&gt;CoreServices&lt;/code&gt;. But then, either you have to make a C extension for it or you have to call it through &lt;a href="http://pyobjc.sourceforge.net"&gt;PyObjC&lt;/a&gt;. If your app is a Qt based app, you might dislike having to add such a big dependency just for a little &lt;code&gt;FSMoveObjectToTrashSync&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;On Windows, a &lt;code&gt;SHFileOperation&lt;/code&gt; (in fact, &lt;code&gt;SHFileOperationW&lt;/code&gt; if you're not stuck in the last unicode-less decade) is needed. Again, if you're not comfortable with C (or you don't want to touch the win32 API with a ten foot pole), you need a dependency on &lt;a href="http://sourceforge.net/projects/pywin32/"&gt;pywin32&lt;/a&gt; (and Tim Golden's &lt;a href="http://timgolden.me.uk/python/winshell.html"&gt;winshell&lt;/a&gt; if you want to make your life even easier).&lt;/p&gt;
&lt;p&gt;On Linux, it's free-for-all (pun intended... in hindsight). There's no unified API to send files to the trash. The convention seems to be that sending stuff in &lt;code&gt;~/.Trash&lt;/code&gt; is good enough, but then there's always the problem of external volumes (you don't want to copy files from external volumes on your main hard disk when you send them to the trash!) and systems with alternate trash conventions (Ubuntu makes further organization of the files inside the &lt;code&gt;.Trash&lt;/code&gt; folder).&lt;/p&gt;
&lt;p&gt;In other words, it's a mess. You thought you could code your cute Qt app once and run it everywhere, but that damn trash thing gets in your way. Well, if you use Python, you're in luck because there's a library for that now! Say hello to &lt;a href="http://hg.hardcoded.net/send2trash"&gt;send2trash&lt;/a&gt;. It's a cross-platform library that sends files to trash using native API calls (without external dependencies).&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;send2trash&lt;/span&gt; &lt;span class="nb"&gt;import&lt;/span&gt; &lt;span class="n"&gt;send2trash&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;send2trash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;some_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm</guid><pubDate>Mon, 03 May 2010 18:00:00 GMT</pubDate></item><item><title>Free as in Speech, Fair as in Trade</title><link>http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade.htm</link><description>&lt;p&gt;Last year, I &lt;a href="going_open_source.htm"&gt;made the source code of my proprietary applications publicly available&lt;/a&gt; in a similar way than what was done for &lt;a href="http://e-texteditor.com/"&gt;e text editor&lt;/a&gt; a couple of months before. The primary goal was to reduce the consequences of the &lt;a href="http://en.wikipedia.org/wiki/Bus_factor"&gt;bus factor&lt;/a&gt; for my customers, while still earning money from developing software. In this primary goal, I was successful (yay!) as my income was not negatively affected by this move. I also had a secondary goal, which was to actually increase the bus factor for my projects by bringing more developers to them. In reaching that goal, I utterly failed. Today, I'm stepping things up a notch by making these applications fully open source (BSD licensed), but with a twist which, I hope, might open a new way for developers working on "generic" (shareware-like) OSS to earn money while doing so.
&lt;a href="http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade.htm</guid><pubDate>Thu, 30 Sep 2010 18:00:00 GMT</pubDate></item><item><title>Getting Started with Python GUI Applications</title><link>http://www.hardcoded.net/articles/getting-started-with-python-gui-applications.htm</link><description>&lt;p&gt;A recurrent question to Python developers is "Which GUI toolkit is the best? How do I get started?". The answer to this question is subjective, so we end up with a pretty long list of toolkits to try. But then, it's only a matter of playing with demos, picking the best toolkit and then creating our application by basing ourselves on demo code, right?&lt;/p&gt;
&lt;p&gt;There are several problems with this approach. First, demo code is usually contained within a demo showcase framework and is hardly an application by itself. The poor newbie often has no idea how to properly structure his application from scratch. Second, comparing toolkits side by side is not so easy to do when demos differ from one toolkit to another.&lt;/p&gt;
&lt;p&gt;Moreover, some GUI application designs are no so easy to start from scratch. I've been talking about &lt;a href="http://www.hardcoded.net/articles/cross-toolkit-software.htm"&gt;cross-toolkit design&lt;/a&gt; as well as &lt;a href="http://www.hardcoded.net/articles/embedded-pyobjc.htm"&gt;embedded PyObjC&lt;/a&gt; lately and these methods are hard to adopt unless you have a simple example in front of you.&lt;/p&gt;
&lt;p&gt;This is why I'm publishing &lt;a href="http://hg.hardcoded.net/guiskel"&gt;guiskel&lt;/a&gt;, a collection of GUI layer skeletons. It's a simple cross-toolkit application that does "Hello [name]!". To create a new application, all you have to do is to copy the project and remove toolkit layers you don't want.&lt;/p&gt;
&lt;p&gt;For now, it supports only two GUI layers (those I use myself), namely PyQt and embedded PyObjC, but I hope others will participate and add additional toolkits.
&lt;a href="http://www.hardcoded.net/articles/getting-started-with-python-gui-applications.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/getting-started-with-python-gui-applications.htm</guid><pubDate>Tue, 23 Nov 2010 18:00:00 GMT</pubDate></item><item><title>New py2app fork: pluginbuilder</title><link>http://www.hardcoded.net/articles/new-py2app-fork-pluginbuilder.htm</link><description>&lt;p&gt;Python 3.2 brought with it a couple of changes that broke &lt;a href="https://bitbucket.org/ronaldoussoren/py2app"&gt;py2app&lt;/a&gt;. It had been a while since I wanted to work on that project, but because the main command is distutils-based, I lacked the motivation to properly learn how its code works. I saw Python 3.2's breakage as a good opportunity to get my feet wet, since as far as I can tell, there's very few of us using the "plugin" feature of py2app, and I'm pretty sure to be alone to, additionally, use Python 3. Nobody was going to fix it except me.&lt;/p&gt;
&lt;p&gt;py2app being a distutils-based command brings needless complexity to the code. Unless you know how distutils commands work, you don't really know what's the main entry point or where options are stored. Because (1) fixing py2app involved code changes that I wasn't sure were backward compatible, (2) I'm one of a very few users of the "plugin" feature, and (3) distutils was increasingly getting on my nerves, I said "screw that, I'm tearing that package apart", and that's what I did. It felt rather good :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What's different?&lt;/strong&gt; Apart from not supporting application building like py2app does and not being based on distutils' command, there's a few things that are different in pluginbuilder.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Invocation is simpler. Instead of having to go through distutils' &lt;code&gt;setup()&lt;/code&gt; to build your plugin, you can call &lt;code&gt;build_plugin()&lt;/code&gt; directly or use the &lt;code&gt;pluginbuilder&lt;/code&gt; command line script.&lt;/li&gt;
&lt;li&gt;The "main" binary file is compiled on your machine rather than being prebuilt. py2app ships with prebuilt binaries for all possible architectures combinations, but it never worked on my machine so I had to rebuild them anyway. A benefit from this is that it simplifies the code in "main.m" because dynamic symbol bindings aren't necessary anymore and &lt;code&gt;Python.h&lt;/code&gt; can be included directly.&lt;/li&gt;
&lt;li&gt;Collected source files aren't zipped. That's actually a drawback, but it was part of the fix for Python 3.2's breakage, which didn't like encodings-related modules to be in a zip file. I'm not sure yet, but I think that feature could come back if I use the newly introduced &lt;code&gt;Py_SetPath&lt;/code&gt; function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Roadmap:&lt;/strong&gt; For the first release of pluginbuilder, I didn't modify a lot of code. I merely, step by step, refactored the thing until I could get rid of distutils' command. The code is not as clean as it should be and I'll probably slowly start to actually change the code. I'm also contemplating the removal of modulegraph's dependency (I think the additional complexity brought by this mechanism is not worth the convenience of not having to manually specify dependencies), but that's something I haven't thought through yet.&lt;/p&gt;
&lt;p&gt;That's all I have to say about this. Here's some links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://bitbucket.org/hsoft/pluginbuilder"&gt;Source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hardcoded.net/docs/pluginbuilder"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pypi.python.org/pypi/pluginbuilder/"&gt;PyPI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/new-py2app-fork-pluginbuilder.htm</guid><pubDate>Mon, 21 Feb 2011 18:00:00 GMT</pubDate></item><item><title>Fairware: It Kinda Works!</title><link>http://www.hardcoded.net/articles/fairware-it-kinda-works.htm</link><description>&lt;p&gt;It's been 6 months since I made Hardcoded Software's apps &lt;a href="http://open.hardcoded.net/about/"&gt;fairware&lt;/a&gt;, and I'm glad to announce today that it kinda works! &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;For the uninitiated, fairware is open source software with expectation of fair contributions from users. The software is BSD licensed, but the developers count their hours and publish them online. Also, all contributions are automatically published (anonymously) and the current amount of unpaid hours is computed in real time. If there are any unpaid hours for the project, a fairware reminder pops up in the application itself on startup, asking for users (only those who haven't contributed yet) for a fair contribution. You can read more about it in the &lt;a href="http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade.htm"&gt;introductory article I wrote 6 months ago&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's right, after a couple of months of tweaking, the last block of 60 hours I've invested in dupeGuru has been paid back at a rate that is very close to the money I was receiving for it when it was closed source, that is roughly 3000$ per month (although there had been exceptional months). It's hard to believe that an open source "shareware type" application could be making nearly as much money as its closed source counterpart, but yup, it's happening!&lt;/p&gt;
&lt;p&gt;One thing I learned with the fairware adventure is that being open source gives a software a &lt;em&gt;lot&lt;/em&gt; of free publicity. In the last 6 months, dupeGuru has been mentioned in a lot more blogs and forums than it was before then (and this kind of publicity, word of mouth, is by far the best one). The average contribution by user is significantly lower than before, but since there's so many more users, the end result, money-wise, is similar. If you consider that I stopped my Google AdWords campaign which was costing me about 300$ per month, fairware is really starting to look nice.&lt;/p&gt;
&lt;p&gt;Of course, measuring the success of fairware by comparing monthly revenue is flawed because when all hours are compensated, the money stops coming in (as I write these lines, there's only a few hours left to pay to the dupeGuru project). What dupeGuru's success proves is not that it can earn as much money as its closed source counterpart, but that for those of us out there who are uncomfortable with the concept of intellectual property (and the thought of sitting on it undeservedly), there's a way out. There &lt;em&gt;is&lt;/em&gt; a large enough pool of fair users out there to compensate work invested in an open source project.&lt;/p&gt;
&lt;p&gt;Another interesting conclusion to draw from this success is the effect of a fairware app on its competitors. Shareware applications having to deal with open source competitors is not new, but what &lt;em&gt;is&lt;/em&gt; new is having to deal with open source competitors for which the author can afford to spend more time than his mere "hobby time" on it. If dupeGuru has many more users now, it means that its closed source competitors have less of them (unless the market for duplicate scanning software widened recently). On the long run, I think that fairware could slowly make closed source software, at least in the field of "little shareware apps", irrelevant.&lt;/p&gt;
&lt;p&gt;So my message to other developers out there: If you're an open source developer, be aware that your users might very well be open to fairly compensating your time if you make it easy to do so. If you're a closed source developer, you might want to consider opening your source, because if one of your competitors does it first, he'll have the first mover advantage and might drive you into irrelevance before you can do anything.&lt;/p&gt;
&lt;p&gt;Can fairware work on anything else than the "one developer little app" type of software? I'm not sure. It also remains to be seen whether you can expect fairness from corporations, that are by their very nature greedy. So it's very possible that the fairware concept doesn't scale. But there's plenty of closed source "one developer little app" out there (for which fairware could work), and I hope fairware is going to shake that world a little bit.&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/fairware-it-kinda-works.htm</guid><pubDate>Tue, 29 Mar 2011 18:00:00 GMT</pubDate></item><item><title>Why I'm Opposed to the Mac App Store</title><link>http://www.hardcoded.net/articles/why-oppose-mac-app-store.htm</link><description>&lt;p&gt;I'm sometimes asked why my apps aren't on the Mac App Store and I thought I should write an article
about this. The pros and cons of the Mac App Store have already been widely discussed, but I think
that the most discussed issues are rather unimportant. Yes, the easy payment system is nice, yes,
the 30% margin is high (despite what Apple wants you to believe), yes, the review system
is a bit opaque (but it seems to have improved lately) and yes, it takes a while for updates to be
published. But all these issues are mundane compared to the real big fat problem: &lt;em&gt;Apple is in the
process of positioning itself as an unavoidable middleman for software.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It's simple: iPhone and iPad apps are in Apple's Walled Garden, right? Despite that, the iPhone and
iPad are still rather popular right? And Apple gets to make a fat 30% of all software sales on the
iOS platform right? I think we can thus conclude that it's clearly in Apple's interest to establish
that kind of walled garden on Mac OS X. You can be sure that when every developer has flocked to
the Mac App Store, Apple will bring Trusted Computing (making the computer run only code that has
been signed by Apple, nothing else) back on the table. When they do, they'll have a monopoly on
software distribution and suddenly, 30% of all software sales will go in Apple's pockets. Even if
they don't do it, a Mac App Store monopoly or near-monopoly would kill alternate distribution
websites such as MacUpdate and greatly reduce visibility for non-MAS apps.&lt;/p&gt;
&lt;p&gt;I find it ironic that iTunes contributes to break the monopoly of record labels for music while
Apple is trying to establish the same kind of monopoly for software. The situation is really similar
to record labels. You're an artist and you want to publish your music, what do you do? You can try
the indie way, but the quickest way to success is through record labels. Then &lt;em&gt;they&lt;/em&gt; decide if
you're worth promoting. In the last few years, the situation of indie music have been getting
better, but it's an uphill battle because the record labels are very well entrenched (they control
MTV, the radio, all that stuff that suggests you that this or that music is good).&lt;/p&gt;
&lt;p&gt;Apple isn't in that situation yet with Mac OS X software but very well could be, and I think it's
in everyone's interest to oppose this upcoming monopoly early. This is why I don't submit my apps to
the Mac App Store.&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/why-oppose-mac-app-store.htm</guid><pubDate>Fri, 14 Oct 2011 18:00:00 GMT</pubDate></item><item><title>Embedding Python in Objective-C: Part 2</title><link>http://www.hardcoded.net/articles/embedding-python-in-objc.htm</link><description>&lt;p&gt;Two years ago, I wrote about how I &lt;a href="http://www.hardcoded.net/articles/embedded-pyobjc.htm"&gt;embedded Python in Objective-C through PyObjC&lt;/a&gt;.
It worked well and everything was fine. The only problem I had with PyObjC was that I felt that
such a massive library (&lt;code&gt;pyobjc-core&lt;/code&gt; has over 5,000 Python SLOC and over 55,000 Objective-C SLOC,
not counting tests) was overkill for what I used of it. The whole library was a black box to me and
that made me a bit uneasy.&lt;/p&gt;
&lt;p&gt;Then, a few weeks ago, I started getting report of weird crashes which seemed related to 64-bit and
the presence on the system of some 3rd party app with specific settings. I could never reproduce the
damn crashes on my computer, but they came around exactly at the same moment as
&lt;a href="http://www.hardcoded.net/dupeguru"&gt;dupeGuru&lt;/a&gt; 3.3.0 which updated PyObjC to fix another 64-bit
related crash, so I could only assume that PyObjC (and/or libffi, which is used by PyObjC) was the
cause. The problem was that I didn't know where to start the bug hunt because of my inability to
work within PyObjC's codebase.&lt;/p&gt;
&lt;p&gt;So, out of curiosity for its feasability and to know if it was going to fix my crashes, I started
working on &lt;a href="http://bitbucket.org/hsoft/objp"&gt;ObjP&lt;/a&gt;. Instead of dynamically dispatching function
call between Python and Objective-C, I would generate source code for static wrappers which would
simply use Python's C API. Early tests were encouraging because it fixed the crashes on my users'
machines, so I continued working on it and a few days ago I completed dupeGuru's conversion from
PyObjC to ObjP and published dupeGuru 3.3.2. So far I haven't heard from crashes, so I guess it
works well.
&lt;a href="http://www.hardcoded.net/articles/embedding-python-in-objc.htm"&gt;More&lt;/a&gt;&lt;/p&gt;</description><guid isPermaLink="true">http://www.hardcoded.net/articles/embedding-python-in-objc.htm</guid><pubDate>Fri, 20 Jan 2012 09:57:28 GMT</pubDate></item></channel></rss>
