Weathrman 3.1: The Freshmaker

Lots of minor tweaks going into this.

For a long time now, doubletapping has been problematic.  I install a double-tap handler the same way anyone else would, but end up seeing events that belong to the foreground application.  Android has a mechanism for wallpapers to see only two possible gestures out of all of the ones an Android can handle: a tap, and a drop.

I’ve constructed a (very) simple double-tap handler out of the tap events sent via onCommand(), instead of installing a gesture detector, in the hopes of getting rid of these ‘false positives’ that result in the information-about-this-image dialog appearing too often.

I’ve also removed, you might be happy to hear, all analytics tracking.  Its primary use was to send back stack traces and errors back, so that I could track down client problems.  New features in the Android Marketplace for publishers means I should be getting stack traces directly in the publishing console… but I don’t, because they’re not being seen, because I’m sending those stack traces (in a much less efficient form) to Analytics.

So, analytics is gone, which will result in a better experience for all.

I’ll be pushing this onto the market shortly.

Guicing Android: Mobile Antipatterns

Dependency Injection via Guice is great, but it does what you tell it.  Sometimes, we need to do things that are counter to instinctive programming ideals when building agile, testable mobile applications to work around the constrained resources of mobile environments.  Spotting these problems in code reviews isn’t always easy, because most of them cross the boundary layer of a single class.  Their impact is measured on the cost of injecting a new instance, or the cost of constructing the injector itself.

Android has two major (and, generally, obvious) limitations that everyone using Guice should be aware of:  Call stack depth isn’t infinite, and Guice’s implementation is stack-hungry.  Here are some things to avoid if you’re looking to keep your stack footprint low:

  • Long constructor chains
    Foo needs a bar to construct.  Bar needs a Baz.  Baz needs a Bat.  Guice is going to eat a big chunk of call stack to find a constructor, find the parameters to that constructor, locate constructors for the parameters, etc…  Before you know it, you’ve blown your stack and thrown an error.
    Break these up by using field or method injection in place of constructor injection to shrink the stack depth, or using provider methods.  Where they make sense.  The problem with this, of course, is that the resulting fields are non-final, and that makes my eyes bleed to read.
  • Large object graphs
    I’m not suggesting composition is bad.  In fact, composition is almost always better, especially when it comes to anything remotely complex.  But think carefully when you compose, and try to find ways to use the composed instances lazily, by injecting a provider of the instance in place of the instance.
    Think about whether or not the class you have is just plain doing too much orchestration; consider doing a bit of functional decomposition of the problem domain.
  • Costly instance initialization
    The cost of creating an instance can be high, too - and not purely due to constructor chains being long. Consider delaying work outside of the constructor.  Think about whether the instances you’re creating in your constructor should be delayed until the method is called, and use providers of instances to move that cost.
  • Costly class initialization
    Arguably, one of the whole points of using injection is getting away from hand-built singletons and static references to critical objects.  If you’re doing this, you should think long and hard about whether you really want all that construction to live in the classloader, rather than when you needed it.
    If you’re looking to solve the robot legs problem, do it with annotated types.  @Left Leg and @Right Leg are better than private static final Leg LEFT and RIGHT, and push the job of construction down to its use, and out of the classloader window.
    If you’re looking to solve a singleton problem, use a @Singleton.  Avoid it where it makes sense to do so.
    Last, if you’re trying to build complex maps, consider Guava’s MapMaker implementation, which can build maps of complex types by supplying a generator function at the time of lookup, rather than at the time of wrapper class creation.
  • Contexts and Quasi-Singletons
    If you’ve got an object with a strange lifecycle, create that lifecycle - @Request scope is a great example in Servlet-land, and you’ll doubtlessly find others if you look around carefully.  It separates the lifecycle from the code that depends on the data, so that you’re not littering your code with details about what needs to live when and where, or creating messy context objects that might better have been represented by a scope.
  • Singletons and Static Injection
    A well-placed singleton, along with a bit of constructor chaining and lots of tight coupling, can load your whole object graph when your app launches, stopping up your startup.  Think long and hard about what really needs to be a singleton; inject providers instead of instances where possible to reduce the cost of that singleton.
    When using static injection, think about how you’d have written your code to avoid it, and then do that.  When you can’t, use providers of instances in place of instances to decouple where possible.

Guice won’t magically make your application lazily load its required classes and instances.  You can burn memory and stack by building highly dependent object graphs - Guice isn’t afraid to throw a verbose stack trace, as you’ve probably encountered previously; what it does is complex, and while it’s possible to inline all that code, it wouldn’t leave Guice very maintainable.

Constructors should ideally be slim and svelte.  They should ensure they have exactly what they need to be constructed with, and those things which can sensibly be delayed until first use should be.

Ultimately, Guice is doing what you ask it to; if you ask it to build you a tightly coupled object graph, it will do so.  You have the tools to implement lazily-dependent object graphs, should you choose to do so - and in mobile environments, where latency is critical, you should make every effort to do so in critical areas of your codebase.  Record the amount of time it takes to perform critical operations; you can even report that back to centrally through metrics gathering like the Google Analytics client, which will give you a feel for your performance profile on different devices and operating system revisions. 

Make metric-driven decisions.  Don’t prematurely optimize, and when it comes time to do so, make careful decisions about decoupling.  Gather metrics from your deployed applications to help you locate problems and improve quality.

I wish you luck.

Strange restrictions on libraries in Android SDK v8

So the Android team finally get around to adding support for libraries to the ADK’s build process for froyo (2.2, or SDK v8).  Fabulous, you say - so now you can finally extract that chunk of, say, com.ctoforaday.common, rename it to something guicey like com.ctoforaday.guicedroid, and start extracting the reusable bits of guice coding you’ve been building in your application into a place others can use to start freeing themselves from the nightmare of singletons, subclassing, and oversized contexts that someone who much too much liked the word ‘discoverability’ choked on one morning and died from.

So I went and did that (splitting out the project, not choking and dying).  Even got a private github repository hosting it as a separate project, which eventually I’ll get around to open sourcing.

Here’s the gotcha:  Inevitably, someone who writes tests is going to have two implementations of a class, a real one, and for complex stuff, a fake one.

Here’s the limitation: A library can’t depend on a library.  So you either ship your mock/fakes in with your core library, and therefore straight into people’s binaries, enabling the possible mess of ending up with fakes used in production code, or you end up building the mock/fake implementations in each and every test project you create.

I don’t know what it is about testing that mobile developers just don’t seem to get.  It’s as though they assume that their time is worthless, and they’d really like to spend the rest of their lives debugging code.  Executing Android tests never gets easier, never gets faster, and actually writing android tests isn’t becoming a warmer or happier place.  It’s as though they’re just not expending any efforts to improve the testability of the product, or just assume that absolutely everything to be written for Android is either so trivial as to not require testing, or so complex that it’s “too hard” to do anything about.

Bloody frustrating.  Turns a half hour’s extraction into an entire morning of playing with Eclipse wondering why things don’t just work the way you’d imagine they would.

Of Clouds and Silver Linings

I’ve updated the AppEngine app that weathrman uses to perform its searches to a later version of the SDK; hopefully people will either see no change, or see improved response times; I’ll be monitoring the service over the next few days to ensure that all is well, and that error rates stay roughly where they were (or drop).

Fingers crossed.

Weathrman: Any issues?

I’ve heard of two kinds of problems so far; a user reports that on a clear day in London he got a photo of stormtroopers, and another, travelling with roaming off in California, got a crash.

I’ll see if I can investigate and patch next week for the latter crasher. As for the stormtroopers, I fear nothing short of thumbs up/down will do. That will take a (wee) bit longer.

Post if you’ve seen something you think needs fixing.  Personally, I want preferences, and maybe support for wifi-only updating.

Weathrman 3.01: Amsterdamn, I broke the build

Users in non-English locales, particularly those that were in locales that format decimals with commas instead of periods, and periods instead of commas, were sending date information over the air in locale-specific format.

I’ve sent out a new release that should fix this issue; I’ll be watching the logs over the next few hours to ensure that all is well.

Weathrman 3: The Weather Cloud

One of the big problems with Weathrman’s current implementation is that the whole implementation lives in your phone; a worst-case search can trawl through literally tens of thousands of search results, searching for an image relevant to your weather conditions and time of day.

Many of those searches are common to others; city-level searches are the same all over London, for example; local searches are the same for everyone sitting near me.  Much of this can be cached aggressively, massively reducing the amount of time it takes to get good results, and allowing me to do more searches, more often, at less cost and lower latency to end users.

It’s not ready yet - I’m nearly ready, probably another day away or so, and I’ll probably test it out for a week or so.  Come Google I/O, though, I’ll be ready to ship.

It’s notably faster, and pushing the image scaling to the server has resulted in massive improvements in image quality, while turning hundreds of RPC calls to flickr into a single call to the weatherman service.

Open Issues

I’ve seen some strangeness lately, brought on by the fact that we’re no longer making direct use of Flickr’s interestingness to choose which photo to show.

These essentially all boil down to the same issue - search quality.  I need to do more filtering of results to try to wipe out irrelevant or unwanted photos.

My current thoughts go like this:

  • Add “underwear” to the negative keywords list.  I don’t really want to see people in their undies on my phone.
  • Add “indoors” to the negative keywords list.
  • Remove images that weren’t given proper titles by the person who uploaded them.  If you didn’t care enough to name your photo, I don’t care enough to see it.  This includes all-numeric titles, and titles which contain only IMG_XXXX.

There’ll be an update this weekend if all goes well.