Loving Django Piston

January 10, 2012

A couple of years ago when I was first getting into Python and Django I experimented with building some RESTful services. Maybe it was because of my lack of experience with the platform but I don’t remember it being particularly easy.

Fast-forward a few years and it couldn’t be easier. A simple pip install django-piston then followed the documentation here https://bitbucket.org/jespern/django-piston/wiki/Home and I was on my way.

CSS vs. In Code Styles

March 10, 2009

For this post I thought I’d share with you a recent response I made on the GWT forums regarding the question: “Which is better performance wise; CSS or in code styles?”.

Donald Knuth is credited as once saying “Premature optimization is the root of all evil”. I think the question asked here is well intentioned, however misguided. Whilst performance is important we’re often blinded by it’s supposed benefits as developers and forget more important concepts like separation of concerns. This is the key design principle that should be considered here, not performance. As you’ll also see though there are some nice performance benefits in taking steps to keep things separate.

Setting a style in CSS allows for the presentation aspects of the application to be nicely decoupled from the application code. Using CSS over code however is beneficial for a number of reasons:

1. It reduces the amount of code you have to write.

This cannot be understated enough. In browser land less code == better performance. The vast majority of AJAX/RIA apps performance shortcomings have nothing to do with running code, but rather the time taken to download and parse your JS. So by doing the right thing in keeping your different concerns separate you actually win when it comes to performance.

2. It keeps your code clean and focused on solving the business problem at hand.

When it comes to maintenance (which we all learn at uni is actually 80% of any application’s total cost over its lifetime) there’s nothing worse than trying to pick your way through a veritable minefield of presentation related cruft in an attempt to fix a logical problem. One wrong move, one misunderstood line and BAM, you’ve broken your carefully crafted interface. This is part of the reason why separating your concerns is so valuable, in a way it’s your insurance against complexity. If you can adequately separate things you’re effectively confining the risk to a single discrete, and usually well understood unit of functionality.

3. You can modify the look of your application without touching your code.

From a straight development perspective this is a real time saver. If you’re like me and have to develop large parts of your app in-situ inside an existing web application you don’t have the luxury of using the Hosted Mode browser for the home stretch. If you insist on putting all of your styles inside your code you’re stuck with a total recompile (which for me takes up to a minute) before you can see if your change was successful. Painful.

Further down the track if your client changes their mind and wants something changed, say a particular color or font, it’s really nice if you can make the change without a recompile. With every code change/recompile there’s always the possibility that you will break something that was previously working. Not good when you’re working on something mission critical, or high availability.

4. CSS style are computed natively.

Again this is a performance win. Anything that can be carried out natively by the browser is going to win over interpreted code. Sure some JS VMs like Tracemonkey and Squirrelfish can analyse your code and improve execution speed (and in some cases surpass native performance), however the issue here is that this on the fly optimisation doesn’t come free. This is really only beneficial for repetitive or frequently run pieces of code which may be aggressively optimised. Styles for the most part, bar dynamic ones (e.g. setting width in animations), don’t change often enough for this to be of use.

A common strategy which I use in real life is to apply classes to absolutely everything that could require styling. Then when I start the process of pulling together the look and feel I simply load the page, start analysing the page structure and the class names, then write my CSS. You’d be surprised how much flexibility you have and how quickly it all comes together.

The Support Pattern

January 31, 2009

Today I thought I might write about a little pattern that I like to call the support pattern. It’s probably got some other name, or exists as a composite of one of the original GoF patterns but I always refer to it as the support pattern. The reason I call it the support pattern is because of the Java PropertyChangeSupport class. If you’re not familiar with it, the PropertyChangeSupport class provides a simple means for POJOs to fire an event when a property value changes. Clients can then subscribe to these change events and decide what to do with them. This is particularly useful in MVC type scenarios where changes in the Model need to be propagated to the View. Really when it comes down to it the support pattern is best employed in situations where you want to augment an existing object with some commonly used behavior that doesn’t necessarily fall within what you would consider to be the object’s primary purpose (remember the single responsibility OO design principle).

Anyway last night I found myself needing to add tagging behavior to my Transaction and BudgetItem objects in my personal finance app Freedom. Being that I had to add this behavior in more than one place it was an immediate candidate for some level of encapsulation and/or abstraction. Say hello to the support pattern!

The ITaggable interface

First I created an interface that defines what a taggable object can do.

ITaggable.java

/**
 * Interface for tagging objects.
 *
 * @since 30/01/2009 7:36:24 AM
 * @revision $Revision$ $Date$
 * @author Dave Kuhn
 *
 */
public interface ITaggable {

	/**
	 * Each taggable object that has at least one tag set has a primary tag. The
	 * primary tag is usually the first tag set via {@link #tag(String)} or
	 * {@link #tag(String[])}. Otherwise the primary tag can be set explicitly
	 * via {@link #setPrimaryTag(String)}.
	 *
	 * @return the primary tag
	 */
	String getPrimaryTag();

	/**
	 * Returns all the tags associated with this object.
	 *
	 * @return all tags for this
	 */
	String[] getTags();

	/**
	 * Returns true if this object has the specified tag.
	 *
	 * @param tag the tag to check
	 * @return true if object has tag, otherwise false
	 */
	boolean hasTag(String tag);

	/**
	 * Removes the specified tag from this object. This has no effect if the tag
	 * does not exist on the object.
	 *
	 * @param tag the tag to remove
	 */
	void removeTag(String tag);

	/**
	 * Removes the specified tags from the object. This has no effect if the any
	 * or all of the tags in the array do not exist for this object.
	 *
	 * @param tags the tags to remove
	 */
	void removeTags(String[] tags);

	/**
	 * Sets the primary tag for this object. If the tag does not exist, it is
	 * added to the greater list of tags for this object. If it already exists
	 * then the matching tag is simply set to be the primary tag.
	 *

	 * Where a primary tag has already been set (e.g. via the first call to
	 * {@link #tag(String)}) then setting the primary tag simply relegates the
	 * incumbent tag to being a regular tag, it does not remove it.
	 *
	 * @param tag the tag to set as the primary tag
	 */
	void setPrimaryTag(String tag);

	/**
	 * Tags this object with the specified tag.
	 *
	 * @param tag the tag to apply to this
	 */
	void tag(String tag);

	/**
	 * Tags this object with the specified tags.
	 *
	 * @param tags an array of tags to apply to this
	 */
	void tag(String[] tags);

}

The TagSupport class

The next step was to create a support class that implemented the ITaggable interface. This encapsulates all the necessary knowledge of how to tag an object.

TagSupport.java

/**
 * Utility class that provides tagging support for objects implementing the
 * {@link ITaggable} interface.
 *
 * @since 30/01/2009 6:52:28 PM
 * @version $Revision$ $Date$
 * @author Dave Kuhn
 */
public class TagSupport implements ITaggable {

	private String primaryTag;
	private List tags;

	/**
	 * Constructs a TagSupportProvider initialised with an empty tag list.
	 */
	public TagSupport() {
		tags = new ArrayList();
	}

	/**
	 * Constructs a TagSupportProvider initialised with the tags provided.
	 *
	 * @param tags tags to add
	 */
	public TagSupport(String[] tags) {
		this();
		tag(tags);
	}

	@Override
	public String getPrimaryTag() {
		return primaryTag;
	}

	@Override
	public String[] getTags() {
		return tags.toArray(new String[tags.size()]);
	}

	@Override
	public boolean hasTag(String tag) {
		return tags.contains(tag);
	}

	@Override
	public void removeTag(String tag) {
		// Ignore nulls, empty strings and tags which aren't in list.
		if (tag == null || tag.isEmpty() || !hasTag(tag))
			return;

		tags.remove(tag);

		/* First tag in list becomes primary tag in the event that tag being
		 * removed is the primary tag. If the item being removed is the last
		 * in the list (i.e. there are no tags left) the primary tag is set to
		 * null. */
		if (primaryTag.equals(tag) && tags.size() > 0)
			primaryTag = tags.get(0);
		else
			primaryTag = null;
	}

	@Override
	public void removeTags(String[] tags) {
		for (String tag : tags)
			removeTag(tag);
	}

	@Override
	public void setPrimaryTag(String tag) {
		if (!hasTag(tag))
			tag(tag);

		primaryTag = tag;
	}

	@Override
	public void tag(String tag) {
		// Ignore nulls, empty strings and duplicates.
		if (tag == null || tag.isEmpty() || hasTag(tag))
			return;

		// First tag becomes primary tag by default.
		if (tags.size() == 0)
			setPrimaryTag(tag);

		tags.add(tag);
	}

	@Override
	public void tag(String[] tags) {
		for (String tag : tags)
			tag(tag);
	}

}

Putting it to work

Lastly I added a TagSupport instance to my Transaction and BudgetItem classes, implemented the ITaggable interface, and then delegated to my member TagSupport instance like so:

Transaction.java

/**
 * A stateful transaction implementation.
 *
 * @since 30/01/2009 9:54:00 PM
 * @version $Revision$ $Date$
 * @author Dave Kuhn
 */
public class Transaction implements ITaggable {
	...

	private ITaggable tagSupport = new TagSupport();

	...

	@Override
	public void tag(String tag) {
		tagSupport.tag(tag);
	}

}

That’s all there is to it!

Zombies Ahead

January 25, 2009

Just found an funny article on hacking electronic road signs. I can’t count the amount of times I’ve driven past those things and fantasized about putting something amusing up. 

Hilarious; nice work guys.

Well it’s been nearly a month since I first wrote about project freedom (as in financial) and I thought it might be time give a brief update on where I’m at. Given that we’ve just had Christmas and I’m currently on holidays progress hasn’t been all that dazzling. That said, I’m still pretty happy with what has been done all things considered. So what have I been doing? Well so far I’ve mainly been looking at different approaches to building the application.

The Java Way

Naturally I immediately jumped to looking at a Java based solution – after all it is what I’d call my “home” language. Anyone who’s been around a while and has had the opportunity to program in Java as well as a variety of other programming languages/paradigms would undoubtedly agree that it is a beautiful language. I for one really appreciate the consistency of the syntax, the uncompromising enforcement of the OOP paradigm, and most of all the rich standard library with its accompanying documentation.

Being that I work with this stuff quite a bit my head was filled with all sorts of ideas about how we could achieve our goals using Java as the weapon of choice. The first thing that came to mind was that I could utilize the Eclipse RCP and JFace to get some quick wins getting a basic application framework up and running. This approach has the following distinct advantages:

  1. Eclipse RCP contains an OSGi container built in (Equinox to be exact) which is a very powerful plugin framework in a manner of speaking. Potentially it means that each discrete piece of functionality can be build as a separate plugin (or bundle in OSGi-speak).
  2. SWT/JFace contain a rich component set which would do about 95% of what I require and look/behave just like native components on Mac, Windows and Linux.
  3. RCP comes with a tool that allows to generate an executable and budle a JRE with the application so you can avoid “but my system doesn’t have Java (or version required) installed” type support headaches. It just runs.
  4. It’ll run on Mac, Windows, and Linux with no issues whatsoever.

So why wouldn’t I take that approach?

  1. Personally I’ve found RCP very hard to come to grips with. Documentation is scarce and outdated from what I can determine.
  2. OSGi adds a large amount of overhead in terms of complexity. Now I’m not exactly the smartest guy going round, but I’m not a moron either. I’ve spent hours frigging around with manifests, configurations, interfaces, dodgy docos and classpath hassles getting very little done. It all feels like a tremendous waste of time at this stage.
  3. Need to learn and ORM mapping tool like Hibernate or similar to overcome the OO to Relational mapping mismatch. I’m predominantly a user interface specialist so I usually leave this kinda stuff to someone else. Alternatively I can just battle on through with JDBC (*shudder).

As far as abstractions go Donald Knuth is reputed to have once said:

“There is no complexity problem in programming that cannot be eased by adding a layer of indirection. And there is no performance problem in programming that cannot be eased by removing a layer of indirection.”

Ordinarily I’d agree with this statement. You only have to look as far as something like an ORM to see this principle at work. What could be simpler than just working with your domain objects and letting something else worry about the whole persistence issue? On the contrary though I’m inclined to say that the sheer number of abstractions present in the aforementioned solution actually add to its complexity – not reduce it as promised. As always in Java I seem to be forced to spend a lot of time thinking about the correct way to do something as opposed to just doing it and refactoring later.

So there it is, I’ve spent a whole lot of time without a great deal of success. About the best thing it’s got going for it so far is that I’ve managed to do some modelling of the domain level objects. So where do we go from here?

Back to the Future

Some might consider this a backward step from comfortable walled garden that is Java but I’ve been experimenting a bit lately with C and GTK+. Yes you read right C, not C++, just pure unadulterated structured programming. Why not C++ indeed.

I’ll probably get flamed for saying this, but I just don’t like it. With great power comes great responsibility, and it’s like a wild beast that can take on any form it likes depending on the wild mood swings of your average programmer. Every time I read C++ I get the impression that whoever’s driving the evolution of the language can’t quite decide what they want it to be. If Java is a well manicured, if somewhat anal, golfing green then C++ resembles a hoarders front yard. You know the ones, full of old car bodies and useless junk left over after you take all the useful stuff out. Don’t take my word for it though, ask Linus. That said you can always pick and choose the bits you like and leave out the bits you don’t.

Anyway, so far I’m really impressed. Previously I’d thought that leaving OO behind would just be too painful however I was pleasantly surprised. To demonstrate a few concepts to myself I briefly knocked up this little demo which consists of a simple GTK+ interface sitting atop an SQLite database. As far as I’m concerned this a great “thin line” of technology from top to bottom which could conceivably be employed to write the app.

db_test.c

#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <sqlite3.h>

/* Database file name. */
const gchar *DB_FILENAME = "test.db";

/* A simple SQL query to select all rows from the person table. */
const gchar *DB_QUERY = "SELECT * FROM person;";

/* Index of the name column in the list view */
const gint LIST_COL_NAME = 0;

/* Index of the age column in the list view */
const gint LIST_COL_AGE = 1;

/* The total number of columns in the list view */
const gint LIST_NUM_COLS = 2;

/* Global reference to DB handle. */
static sqlite3 *db;

/* Callback that processes a single row returned from the database. The first
 * parameter is expected to be a pointer to a GtkTreeView. */
static int
process_db_results( gpointer  data,
                    gint      ncols,
                    gchar    *col_values[],
                    gchar    *col_names[] )
{
    GtkTreeView    *view;
    GtkListStore   *store;
    GtkTreeIter     iter;

    /* Get reference to underlying GtkListStore so we can add to it. */
    view = GTK_TREE_VIEW (data);
    store = GTK_LIST_STORE (gtk_tree_view_get_model (view));

    /* Append a row and populate it using the row data provided */
    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter,
            LIST_COL_NAME, col_values[0],
            LIST_COL_AGE, col_values[1],
            -1);

    /* Auto-adjust columns to fit data. */
    gtk_tree_view_columns_autosize (view);

    /* Return a zero to let SQLite know it's okay to continue processing */
    return 0;
}

/* User clicked the "Load List" button. */
static void
button_load_clicked( gpointer data )
{
    gint rc;
    gchar *err_msg = 0;

    /* Populate the list component with data from the DB. */
    rc = sqlite3_exec (db, DB_QUERY, process_db_results, data, &err_msg);
    if (rc != SQLITE_OK)
      {
        fprintf (stderr, "SQL error: %s\n", err_msg);
        sqlite3_free (err_msg);
      }

    return;
}

/* User clicked the "Clear List" button. */
static void
button_clear_clicked( gpointer data )
{
    GtkTreeModel  *model; 

    /* Get reference to underlying GtkTreeModel so we can clear it. */
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (data));

    /* Clear the list using gtk_list_store_clear. This is much faster than
     * calling gtk_list_store_remove once for each row. */
    gtk_list_store_clear( GTK_LIST_STORE (model));

    return;
}

/* This callback quits the program */
static gboolean
delete_event( GtkWidget *widget,
              GdkEvent  *event,
              gpointer   data )
{
    /* Close the database connection. */
    sqlite3_close (db);

    /* Terminate the main program loop. */
    gtk_main_quit ();

    return FALSE;
}

/* Creates a list view component consisting of two columns. The first column
 * is for a persons name, the second for their age. */
static GtkWidget *
create_list_view( void )
{
    GtkCellRenderer        *renderer;
    GtkTreeViewColumn	 *column;
    GtkListStore             *store;
    GtkTreeView             *view;

    view = GTK_TREE_VIEW (gtk_tree_view_new ());

    /* --- Column #1 --- */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
            "text", LIST_COL_NAME,
			NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
    gtk_tree_view_insert_column (view, column, -1);

    /* --- Column #2 --- */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Age", renderer,
            "text", LIST_COL_AGE,
            NULL);
    gtk_tree_view_insert_column (view, column, -1);

    store = gtk_list_store_new (LIST_NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
    gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));

    return GTK_WIDGET (view);
}

/* Initialises the application's database connection. */
static void
init_db( void )
{
    gint rc;

    /* Open the database to initialise the connection object. */
    rc = sqlite3_open (DB_FILENAME, &db);
    if (rc)
      {
        fprintf (stderr, "Can't open database: %s\n", sqlite3_errmsg (db));
        sqlite3_close (db);
        exit(1);
      }
}

/* Initialises the application's user interface. */
static void
init_ui( void )
{
    GtkWidget *window;
    GtkWidget *vbox, *hbox;
    GtkWidget *scrolled_window;
    GtkWidget *list_view;
    GtkWidget *button_load, *button_clear;

    /* Create the main application window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request (GTK_WIDGET (window), 300, 150);
    gtk_window_set_title (GTK_WINDOW (window), "GTK/SQLite DB Example");

    /* Configure app to terminate when closed */
    g_signal_connect (G_OBJECT (window), "delete_event",
			G_CALLBACK (delete_event), NULL);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
    gtk_container_add (GTK_CONTAINER (window), vbox);
    gtk_widget_show (vbox);

    /* Create a scrolled window to pack the CList widget into */
    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
    		GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);

    gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show (scrolled_window);

    /* Create the list view which will display the data. */
    list_view = create_list_view ();

    /* Add the list view widget to the vertical box and show it. */
    gtk_container_add (GTK_CONTAINER (scrolled_window), list_view);
    gtk_widget_show (list_view);

    /* Create a horizontal box to hold our buttons */
    hbox = gtk_hbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
    gtk_widget_show (hbox);

    /* Create the buttons and add them to the window. */
    button_load = gtk_button_new_with_label ("Load List");
    button_clear = gtk_button_new_with_label ("Clear List");

    gtk_box_pack_start (GTK_BOX (hbox), button_load, TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX (hbox), button_clear, TRUE, TRUE, 0);

    /* Connect our callbacks to the three buttons */
    g_signal_connect_swapped (G_OBJECT (button_load), "clicked",
    		G_CALLBACK (button_load_clicked), list_view);
    g_signal_connect_swapped (G_OBJECT (button_clear), "clicked",
            G_CALLBACK (button_clear_clicked), list_view);

    gtk_widget_show (button_load);
    gtk_widget_show (button_clear);

	/* The interface is completely set up so we show the window. */
    gtk_widget_show (window);

    return;
}

int
main( gint   argc,
      gchar *argv[] )
{
    /* Before we even think about doing anything we must initialise GTK */
    gtk_init (&argc, &argv);

    /* Initialise the database connection */
    init_db ();

    /* Initialise the user interface */
    init_ui ();

    /* Now that everything's ready, start the main program loop. */
    gtk_main ();

    return 0;
}

Not bad for 236 lines of code huh? Feel free to use the code in any way you like. You’ll have to create a new database using the sqlite command-line utility first before running it though:

$ sqlite3 temp.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> create table person (name varchar(30), age smallint);
sqlite> insert into person values ("Phillip J. Fry", 33);
sqlite> insert into person values ("Hubert J. Farnsworth", 167);
sqlite> insert into person values ("Zapp Brannigan", 45);
then type CTRL-D to exit

As far as I’m concerned writing this thing in C has a few compelling advantages:

  1. It’s portable. C is arguably the most portable (not to mention widely used) language in the world. If binaries aren’t available for your processor architecture, you can always compile it especially to suit that Z80 you’ve had sitting in your basement – just because you can.
  2. No special libraries or runtimes required here. Just run it baby.
  3. Glib, GTK+ again provide 95% of what I need for the app out of the box. Not to mention that the documentation is awesome and free. They’re cross-platform too!
  4. Working with relational databases is a snack. No OO/RDBMS disparity here, it’s all smooth sailing.
  5. It’s really, really fast. There’s no VM here, just bare-metal machine code.
  6. Like Java, there’s heaps of free libraries and tools out there to take advantage of.

Of course using something as raw as C/GTK+ isn’t without its hangups:

  1. Memory management and pointers frighten the bejesus out of many programmers. I don’t mind them so much, but I do understand that some have a pathological aversion to them.
  2. Cross-compilation isn’t exactly what I’d call straight forward.
  3. If you’ve been spoilt, like I have, working in 4th gen languages with awesome support for strings  NULL terminated character arrays are a rude shock. Don’t get me wrong, it’s not difficult, it’s just one extra thing to keep in mind.
  4. Very little in the way of syntactic sugar.
  5. GTK is still yet to be ported to Mac OSX. This is potentially a dealbreaker.

One thing in particular that I found was very nice was the GTK+ “Object Oriented” style interfaces which allow for a form of inheritance within a standard C program. This is a massive benefit because UI programming can get quite repetitive if you’re unable to extend and modify components simply by subclassing them.

Well that’s about all I’ve got for now. I’d be really interested in hearing what you think on the matter of technology choice, especially if you’re looking to contribute in future.

Project Freedom

December 14, 2008

Over the past few months I’ve been searching high and low for some software that will assist me in managing my personal finances. Ultimately what I want is something that will let me lay out my budget and then proceed to track my expenses against my budget so I can see how I’m doing. This will help me answer some very important questions like:

  1. Is my budget realistic? 
  2. Where am I getting into trouble? 
  3. What are my biggest expenses and can I do anything to reduce them?
  4. How much money have I actually got available (after paying my bills)?
  5. Is there anything on the horizon that I have to put some money aside for?

Knowledge is Power

All of this knowledge is power because it means I can make informed decisions about whether or not to spend depending on my circumstances. Frequently my wife and I have found ourselves saying “No we’d better not, I don’t think we can afford it”, when the reality often is that we can easily afford it. Lucky for us we tend to err on the side of caution and end up with a bit stashed away because of this attitude, however the same principle applies in reverse to those who aren’t so cautious. It all boils down to living within our means which is often quite comfortable – we just don’t know it yet. Most of the time we don’t have to go without, nor do we have to run the risk of getting ourselves into trouble.

We do currently have a system, though it has many moving parts and I’m not really satisfied with the ability to mine more detailed information out of it. What’s more is that I tend to lose a lot of the more fine grained information as it passes through the various stages of being entered into this spreadsheet and that software package. What I’m really after is a solution that is both simple and powerful, without all the accounting-speak. It should have a simple, well designed UI without too much clutter which  belies the underlying power of the application.

Bottom line is that I don’t want have to spend an entire evening every week bringing it up to date, 15-30 mins a week is about all I want to spend on this. I also want to be able to get my vital stats such as cash flow and available funds at a glance. I need something I can look at the start of the day and know exactly where I stand.

Playing the Field

Now being the self-confessed code junkie that I am, my mind immediately jumped to all sorts of fanciful notions of building the damn thing myself. At this point I had to stop and say to myself “Dave, you are not going to build this. There has to be any number of software packages out there that do exactly what you’re looking for and more.”, this was mainly for the benefit of my poor neglected wife however. Deep down I really wanted to write this thing all the same…is there any hope?

Anyway for the record I’ve sampled the following apps so far:

In addition to these I’ve also tried any number of so called budget tracking spreadsheets and access databases.

How Do They Stack Up?

So what did I think? Well, rubbish to be completely honest. I’m sure that all of them fit their niche quite nicely however none of them seem to be able to adequately combine a solid budgeting tool with an expense tracker, let along in an easy to understand, intuitive interface. The ones that came closest in my mind were the online ones,  which leads me to a new dilemma.  I absolutely cannot stand online budgeting tools. In this regard I have to completely agree with Richard Stallman that some things just don’t belong on ‘the cloud’. I don’t really care what the social networking advantages of doing so are (ala Wesabe) I’m just not comfortable in handing over all my financial details to some website (that isn’t a bank an never will be) and hoping that they don’t:

a) Use my information for some nefarious purpose.
b) Accidentally leak my information for others to use for said nefarious purposes.
c) Lose my data when they’re evicted from their hosting provider for not paying their bills.
d) Do any other stupid things that may result in financial loss or general inconvenience on my part. 

That said, being online has the distinct advantage of being available almost anywhere which is a big plus if you’re the kind of person who spends very little time in a fixed location.

Back to Square One

Unfortunately that leaves me back where I started which is I still don’t have an all round tool to help me manage my finances effectively and gives me my vital statistics in a timely fashion. Looks like it’s time to roll up my sleeves and get coding. 

Ideally I want this thing to be a cross-platform desktop app, with a slick user interface and constructed in such a way that we can easily integrate access-anywhere capabilities via the web. You know so you can check before you make that impulse purchase.

Developer Team Assemble!

If you are like me and are frustrated with the current personal money management offerings and you’re interested in contributing then let me know.  If I get enough interest then I think I’ll open source it so I can speed development of the thing up.

First look at Intrepid Ibex

November 1, 2008

In the wee hours of this morning I decided to upgrade from my much loved Hardy Heron installation on my trusty Dell Inspiron 9400 (e1705 for you yanks out there) and give Intrepid Ibex a run. At this point I’d like to digress for a second and state that I’m convinced that the person who designed this laptop probably also is responsible for the design of the sherman tank. This thing is friggen’ huge – it’s claim to portability is roughly the same as that of a spare truck tyre. Sure you probably could drag one around but it really belongs strapped to 20 tons of Detroit muscle to make it easy. Once I had to carry it into work every day for a fortnight. I swear the resultant chiropractic bills coulda bought me a new cheaper, lighter laptop. Anyway enough whinging, gotta leave some room for what’s to come.

Although Intrepid doesn’t boast much in the way of new features, I was excited to hear that the Canonical team had spent a fair amount of time and effort improving the stability of the distro and fixing bugs. Considering I already thought Hardy Heron was getting pretty damn close to M$ Windows killer (I even managed to shun Vista entirely and used it exclusively for a period of about 3 months), I thought surely this latest release was gonna be “the one”.

Given that I already had an existing Ubuntu install with a separate home partition I thought I’d simply overwrite the root partition with the latest incarnation. I was impressed as always with the graphical installer, and the process of performing the upgrade was relatively painless. Feeling rather happy that it had all gone so smoothly I quickly rebooted and logged with baited breath. The system logged in and detected my wireless and ATI graphics card within seconds of logging in. I was really impressed at that point and decided to grab the latest updates off the web. Imagine my disappointment then, when everything came to a screeching halt about 5 min later and about halfway through downloading the latest kernel patch.

Now I’m no stranger to these sort of happenings in Linux, especially when it comes to laptops. The first thing I checked was the temperature of the case by running the back of my hand under the laptop and bingo! The thing was more steamed up than a shower scene with Sharon Stone. Immediately I thought to myself, oh great we’re back to the Edgy days when I’d struggle to keep a lid on the CPU temp of my Inspiron 5150 at 75 degrees Celsius (scary huh). To be honest I was majorly boned about this, I really though they’d sorted out all the ACPI shite in earlier releases. I was just about to give up and revert back to the venerable Heron when I noticed a curious thing. Then hot spot wasn’t anywhere near the CPU!

Turns out my Intel 3945ABG wifi card was trying to turn itself into a mini supernova right from the comfort of my desk. Disabling the wifi card and running using the wired NIC confirmed my suspicions. No lockups, nothing. She was solid as a rock. Turn the wifi card back on and bam! My laptop was cookies (as in baked) within a minute or two. Now that really had me scratching my head. What the hell had they done to the wireless driver stack to hurt my wifi card’s feelings so badly? I mean you shoulda been there, he was really hot under the collar about it all.

Thankfully I stumbled upon a post or two on the Ubuntu forums from people with the same card experiencing similar conflagrations breaking out on their desks spontaneously. The solution was rather straight forward. I simply went to http://linuxwireless.org/en/users/Download and followed their instructions to compile a new driver and presto I had my wireless back.

Now where was I? Oh yeah I was supposed to be feeding you some sycophantic review about how good Intrepid (ergo Linux) is and how much M$ suck. Well I’m not going to – go to ITWire if you want to read one of those.

So what do I think? Well driver issues aside Intrepid’s not bad, I particularly like the new dark theme. Given the aim of this release I think I’m going to withhold judgement till I’ve been living with it for a few weeks and see if it lives up to Canonical’s claims of a more stable and reliable OS.

Follow

Get every new post delivered to your Inbox.