Organize your data or stop being all over the map

In the last days I was trying to write my first app for [SailfishOS}(https://sailfishos.org/). The data - more or less a few email addresses - should be kept in some simple classes. Storing the data should be very, very basic, not optimal but also very simple. KISS at its best. While pondering about this I wondered how to preserve the data hierarchy. QSettings left the building at this moment. It shall be simple, so why not serialize the data to the disk? On start of the app I could simply read in all in. Or if you dislike a binary format, you could use XML. That's all true until the day you change something in your data model. At this point in time the pain kicks in and things aren't simple anymore. If you don't know what I am talking about right now, just imagine the lines of code you must write to change your data file format. One could say KISS my ass :-)

Database to the rescue?

Really, a database? That should be simple? Well, you're right if you think database server but since it all began with just a few settings, just enjoy the relief that comes with SQLite. Yes, I really said that. What's so über cool about SQLite? If you must upgrade your data model, you can simply run a bunch of SQL commands to do the work. The real dirty work is done by the SQLite software itself.

Change the model?

To track the data in your model and the database some IDs would come in handy, just add them to your existing classes. Wait a moment. How do I synchronize my classes with the database? How can I make use of multithreading to keep the UI fluent? Do I really want to write all this stuff ,like e.g. SQL inserts, updates and queries, on my own[1]? Where is the simple approach gone? Looks more like KIS to me (Keep It Stupid). Not later than now I asked myself if there isn't a out-of-the-box-solution? Problems like this persist in computer science for ages, someone must have built a pattern/library for this. Let's see what Qt got in store.

  • First of all there is QSqlDatabaseand will need it whatever your strategy is. It holds the basic connection to the database and allows an abstraction to the database driver.
  • QSqlQuery executes an SQL query on a QSqlDatabase. Useful but also mean going bare feet.
  • You can load a result set into a QSqlQueryModel, great if you got read-only data. If you really got small amounts of data, you could use QSqlQuery to change the database and then let the view refresh = reload the whole table. Meh!
  • QSqlTableModel brings you an abstracted model that operates on a single database table. The Qt documentation promises that no SQL knowledge is needed to work with that. Sounds not so bad.
  • And finally you can use QSqlRelationalTableModel to present a logical model that consists of several related database tables in the background. Just now I wonder how QSqlRelationalTableModel::insertRowIntoTable will mix with QML on the other side.

Database to the rescue!

The moral of the story? Plan your data storage first, or short: database first! It pays off in the long run. In theory that all sounds very well you say? You're right, this is all theory. Currently I am trying to use this inside a SailfishOS app for the Jolla phone. When it's done, I will send it to Github, that will be proof enough;-)

Update #1 20140118

Ok, this is gonna continue as a rant. If you use Qt with widgets, QSqlTableModel is your friend. Just tell a QTableView to use this as its model and everything is fine and works just out of the box. For whatever reason QML is now the lingua france for creating UIs and everything is so easy they promise. Yes, until you want to access your QSqlTableModel and live your daydream of everthing works out of the box. Nohoo, not in the Qt universe. They are even so bold to invent something like Qt Quick Local Storage. Yes, of course sir, you are right sir. Forget everything about separation of UI and your business logic. Let's soften all boundaries and go back into the stone age of programming and enter the church of the flying Spaghetti Monster.

[1] If you've read The Pragmatic Programmer - From Journeyman to Master* you will certainly refuse to do so. One could write a generator script to produce all that boilerplate code, but I think it should go even more elegant.*