Sunday, August 28, 2011

Delayed

Took some time in the morning to evaluate what I had done so far. Considering the main point of this weekend's coding was to create code of such quality I would not ashamed to show it in a job interview, it didn't look that good. Most of the code was hard-to-test database glue, and none of it especially interesting or beautiful.

So I decided to put the implementation on hold. I'll take some time to think again how the persistence should be done. Even in this trivial case, I found that the object-relational mismatch really hurts. I've seen it said that ORM is the Vietnam of computer science, and I'm starting to see where those opinions come from.

Anyway, hopefully I'll get back to this later.

Saturday, August 27, 2011

Progress report

Did the initial failing test, then started implementing. One thing led to another, and six hours later I've got a whole bunch of classes and a semi-complete ContentProvider backed by SQLite database. This didn't go quite like planned. Oh well, not wasted effort anyway. Will have to re-think the interfaces tomorrow to be able to create something testable.

Eclipse tricks: relative paths in linked source folders

One useful trick which I haven't seen properly documented anywhere: You can get relative paths to linked source folders in Eclipse by using the variable PARENT-N-PROJECT_LOC in the path. For example, the link from my test project (parent/TagListTest) to the main project (parent/TagList) in .project file:

<linkedResources>
    <link>
      <name>test-src</name>
      <type>2</type>
      <locationURI>PARENT-1-PROJECT_LOC/TagList/test-src</locationURI>
    </link>
</linkedResources>

EGit troubles

Damn, wasted an hour trying to push changes to GitHub. The relevant commands were grayed out and couldn't figure how to get them enabled. Finally just removed the projects from Eclipse and re-cloned the repository and re-imported the projects. Now everything works.

Mental note: Should add a Git book to reading list.

First Robolectric test running

Decided to try out Robolectric for testing, got everything set up and the first test running pretty quickly. The only problem I had was that the latest 2.0 snapshot didn't seem to work, it crashed with a ClassNotFoundException trying to locate Android.R. Switched to 1.0 RC4 and everything started working.

A screenshot for proof:

Initial design

To get started, I first grabbed a pen and paper and started drafting the minimal initial UI. I decided I need four views:
  1. Home view with buttons to add an item and view a list
  2. Add item view
  3. Tag filter selection view
  4. List view
 From here I could see that the interface the "engine" has provide to the UI has to contain at least the following methods:
  1. Add an item
  2. Remove an item 
  3. Get a list of items for viewing
For previous experience I knew that Android had convenient UI elements that can be backed by the local SQLite data. However, this could potentially couple the data model and UI to each other. I decided I should take a few minutes to study the Android UI APIs and see if I could figure an acceptable compromise.

After some though I identified there is two levels I can try to achieve with decoupling the UI:
  • Not leaking the engine's implementation details to the UI layer (easier)
  • Making the engine code completely Android-independent (harder, especially if I want to use Android-provided UI and DB APIs)
The first idea I had was to split the code to three layers:
  1. Android UI
  2. Android Client
  3. Generic Engine
The client layer provides an Android-specific interface for the UI to use. It hides most of the implementation details, but not the fact that we are using Android APIs. The engine provides a generic Android-independent API for the client layer to use. The Android would probably need inject the concrete Android-specific classes to the engine.

The second interface seems harder to get right, so I decided to start at the Android UI/Client interface first. I could define the the second interface later.

At this point it seems I could go and start writing some tests for the Android Client interface. This requires another short detour to evaluate the Android testing frameworks...

Wednesday, August 24, 2011

...but I'm feeling quite sleepy now

All right, about three hours spent planning and setting up. Time for bed. Trying to find a couple hours tomorrow to set up unit testing tools. Let's see if I can get some TDD going on on Android!

Getting started 3: tools

Setting up the required tools:
  • JDK 6
  • Eclipse 3.7
  • Android SDK r12
  • ADT (Android Development Tools) Eclipse plugin
  • EGit Eclipse plugin
Of these, the EGit plugin was new to me. I've heard many wondrous things about git, but I haven't used it much previously. At work, I've been dealing with CVS, SVN and Perforce. There been talk about switching, but we have always had some actual work to do and the current tools have been "good enough".

To host the VCS data, I set up an account with GitHub. Setting up a GitHub repository, a local project in eclipse, and pushing the project to GitHub took me some time. I really need to catch up with Git. Well, this is a start!

How (not) to get the Android SDK installed

Trying to install the Android SDK on my home machine failed right at the beginning with this error:


But I have the JDK installed! How can this be?

Back in the days before google and stackoverflow this could have blocked me for some time. But nowadays the solution is always just one search away:

http://stackoverflow.com/questions/7050359/cant-install-android-development-toolkit-says-missing-jdk:

"Just in the ADT installer , press back when the installer promite for No JDK Found then press next, the installer will find the JDK"

...and sure enough, pressing back and next gets me this:


Don't know whether I should be more amazed at the technological progress that brings so much information to our fingertips, or the fact that Google has released software with such an embarassing defect :)

Random insightful quote

 Linus Torvalds:
"Nobody should start to undertake a large project. You start with a small _trivial_ project, and you should never expect it to get large. If you do, you'll just overdesign and generally think it is more important than it likely is at that stage. Or worse, you might be scared away by the sheer size of the work you envision. So start small, and think about the details. Don't think about some big picture and fancy design. If it doesn't solve some fairly immediate need, it's almost certainly over-designed. And don't expect people to jump in and help you. That's not how these things work. You need to get something half-way _useful_ first, and then others will say "hey, that _almost_ works for me", and they'll get involved in the project."

Getting started 2: requirement analysis

I'll try to first build the minimal set of features that provide something of value to the end user. Then keep on adding to that, for as long as the time runs out. The minimal thing I could think of:

  • Allow user to add simple text items to a list
  • Persist the values locally
  • Allow user to view the list
  • Allow deleting items (well, this is optional, but very simple)

This should be straightforward. After this, I can proceed with adding more features one by one to make the app actually useful:
  • Allow adding tags when creating new items
  • Allow filtering the list view with tags
  • Allow editing list items (both value and tags)

After these, the app will still be pretty simple, but fulfills the core TagList concept. At this point a small amount of UI polish. Probably needs help from my wife and her artistic eye :)

After these, it's getting to the optional (but still very interesting) features:
  • Advanced list filtering with logical expressions: (TagA && (TagB || !TagC)) and such. Kind of a nerdy feature, but appeals to me.
  • Additional metadata for the list entries, such as GPS position and time (creation/deadline). Might ruin the simplicity of the whole thing, so need to be careful here as well.
  • Sharing of items between users. Needs a backend server. I've been looking at doing something on the Google App Engine, this could be the chance. But this is a pretty big feature, as it needs at least some basic permissions/security. And the syncing protocol. Will need a separate planning session to think of how to make this work, and then split it to smaller pieces. Still a big part of making this actually useful. Think of sharing shopping lists between family members or roommates.

Now that I think of it, the sharing feature would be really nice to show off in the job interview. Would make the application much more interesting and complete. But doesn't seem likely in this timeframe. Should have started earlier!

Getting started 1: how to proceed

As I have some 20 hours to do the initial implementation, I have to be really effective with my time. Additionally, I need to make sure I have something to present next week. To achieve these, I'll break out the standard tools for getting stuff done:
  • small iterations
  • (mostly) familiar tools
In this case the familiar tool is Java, though it might mean I lose some "coolness" points for not using functional languages :) I'll try to recover some of the lost coolness by doing an Android app. Or is it also uncool already? I'm getting so old so quickly...

Anyway, to show I'm a real software professional I'll also make an effort to cover the code with unit tests. This is slightly risky, as unit testing Android apps is sometimes a bit cumbersome. I don't have time for much roadblocks in my 20 hour scheduler.

Next on list: requirement analysis.

Starting a project

As a part of a job interview, I was asked to present some code samples. As I lack any recent "hobby" projects and using code from work is not ideal, I took this as a sign I finally have to implement at least one of my project ideas.

The first and simplest that came to mind was the "taglist". This is really nothing more than a glorified shopping/todo list. The idea is to enable keeping a list, each list item annotated with a set of tags. The application should enable you to add items with any set of tags. You should also be able to filter the items by tags. For example, you might want to check the list of items with tags "todo" and "work". Or just with tag "buy" when you're about to go shopping.

I see this could be a nice, simple and flexible tool for managing my life. Besides, who doesn't like making lists?