Friday, September 25, 2009

Android, Scala, and java.rmi.RemoteException

For fun, I've been experimenting with writing an Android application using scala. Now, being a conscientious developer, I'm following the principles of TDD, at least with the low-level database interface.

This proved a bit hard to do. I won't go into the details of integrating Scala and Android, since Christian Neukirchen did a good job of that with his article Programming for Android with Scala.

After following the advice in that class, you basically have to double it to compile, dex, and trim the test tree as well.

The big issue I had was trying to use ScalaTest with Android testing. As far as I know, no one has tried to do this yet.

First, Android testing is very particular. You can't just run any old class on the phone, instead there is a particular runner called the InstrumentationTestRunner to run tests. So, you need either Android-specific test classes, or JUnit classes. I therefore had to write a converter class:


class ScalaUnitTestRunner extends TestCase {
def testExerciseList() = {
new ExerciseListDaoSpec().execute()
}
}

Simple and needs improvement, but it's the most basic thing that can work. The execute call runs the scalatests in that test class.

The problem was that when running, I would get this error on running:

[exec] android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests:
[exec] Error in testSuiteConstructionFailed:
[exec] java.lang.RuntimeException: Exception during suite construction
[exec] at android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests.testSuiteConstructionFailed(TestSuiteBuilder.java:239)
[exec] at java.lang.reflect.Method.invokeNative(Native Method)
[exec] at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:164)
[exec] at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:151)
[exec] at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:418)
[exec] at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1520)
[exec] Caused by: java.lang.TypeNotPresentException: Type java.rmi.RemoteException not present
[exec] at java.lang.Class.getDeclaredMethods(Native Method)
[exec] at java.lang.ClassCache.getDeclaredPublicMethods(ClassCache.java
[exec] at java.lang.ClassCache.getDeclaredMethods(ClassCache.java:179)
[exec] at java.lang.ClassCache.findAllMethods(ClassCache.java:249)
[exec] at java.lang.ClassCache.getFullListOfMethods(ClassCache.java:223)
[exec] at java.lang.ClassCache.getAllPublicMethods(ClassCache.java:204)
[exec] at java.lang.Class.getMethods(Class.java:1038)
[exec] at android.test.suitebuilder.TestGrouping.getTestMethods(TestGrouping.java:79)

...

The problem was that for some reason every Scala class contains a special method called $tag. If you used javap to investigate, you'd find the class looks like:
~/src/AshExercises $ javap -classpath testbin/classes com.ash.exercisetests.db.ScalaUnitTestRunner
Compiled from "ScalaUnitTestRunner.scala"
public class com.ash.exercisetests.db.ScalaUnitTestRunner extends junit.framework.TestCase implements scala.ScalaObject{
public com.ash.exercisetests.db.ScalaUnitTestRunner();
public void testExerciseList();
public int $tag() throws java.rmi.RemoteException;
}

Because Android's tester is using reflection here to find the test methods, it encounters this method with a class that Android doesn't know about. I tried to define a fake java.rmi.RemoteException, but Android is smart and doesn't let you define core java classes.

So, I had to change my tester to this:

class ScalaUnitTestRunner extends TestCase {
def testExerciseList() = {
new ExerciseListDaoSpec().execute()
}

override def $tag() : Int = {
try {
return super.$tag();
} catch {
case e: Exception => throw new RuntimeException(e);
}
}
}

That fixed that issue.

The next issue it had was that Android was giving me java.lang.VerifyError on running. This turned out to be my fault, but what I had to figure out was that java.lang.VerifyError really meant a ClassCastException. I found this out by looking in the logcat.

E/dalvikvm(  726): Could not find class 'com.ash.exercise.db.ExerciseDatabase', referenced from method com.ash.exercisetests.db.ExerciseListDaoSpec.<init>
W/dalvikvm( 726): VFY: unable to resolve new-instance 13 (Lcom/ash/exercise/db/ExerciseDatabase;) in Lcom/ash/exercisetests/db/ExerciseListDaoSpec;
W/dalvikvm( 726): VFY: rejecting opcode 0x22 at 0x0019
W/dalvikvm( 726): VFY: rejected Lcom/ash/exercisetests/db/ExerciseListDaoSpec;.<init> ()V
W/dalvikvm( 726): Verifier rejected class Lcom/ash/exercisetests/db/ExerciseListDaoSpec;
I/TestRunner( 726): failed: testExerciseList(com.ash.exercisetests.db.ScalaUnit

It turned out I was compiling against the non-test src, but wasn't including the non-test src in my proguard step, so that the classes never wound up in my apk.

I hope these tidbits help someone who is exploring Android, Scala, and unit tests. Good luck, and happy coding!

Monday, June 01, 2009

Distractions

Distractions, or no distractions? For your normal coder, most would prefer no distractions. A distraction at the wrong moment could lose a train of thought, wipe out working memory, and set the programmer back by half an hour of time. Not good. And it is common for programmers to feel overwhelmed with distractions.

However, distractions are useful to the programmer as well. Without distractions, a coder would never get important information. They would never hear a conversation about a problem that they have unique insight into. An interesting fact discussed by two colleagues would go unheard and unremembered. Distractions are unplanned and often
random, but that's often why they are beneficial. The benefits of locality via distractions is dealt with in The Social Life of Information by John Seely Brown and Paul Duguid.

A theoretically distraction-free programmer may get a lot done, but they also deprive others of their insight, and they may miss out on random learning opportunities. This is a problem, because the job of the programmer is not only to design, implement features, or fix bugs, but also to exchange information to help others, and to better themselves. These are the valuable kind of distractions programmers need.

Not only work-related distractions are helpful. Taking a break from work entirely is helpful. Standing up and moving around every once and a while is healthy. Doing fun things with coworkers such as playing foosball promotes camaraderie and teamwork.

We need distractions, although clearly too much is a problem. So, the question is how to process distractions and keep our sanity at the same time.

The first thing to realize is that a distraction creates stress because it causes a prioritization conflict. A developer is supposed to be working on x, but now is distracted and doing task y. Well, there are a few possibilities:

x is more important than the distractor y
A fairly normal case, that comes in a variety of flavors. For example, you are programming very productively when you decide to check your mail. This was a mistake. Now you are out of the mindset of x, and are dealing with some mail y that is not ultimately as important as getting your work done. Or, you are programming and get distracted by an unimportant IM message. Or, you are are programming and the loud conversation next to you is constantly pulling your attention away. For all these things, working in a distraction-free environment for at least part of your time is useful to get rid of part of these distractions, and training your mind not to jump around and want to check mail and surf the web is a way to get rid of the other part. Meditation and just plain practice in focusing is important here.

Even though being distraction free for a while is useful, this shouldn't be an all-day activity, even during rush times. Spend some time and open yourself up to distractions for part of your day. You will learn unexpected things, engage in conversation and relaxation, help people, and get to do all the tiny tasks that accumulate throughout the day.

x is less important than the distractor y
For example, you are working on an important refactoring of your code. All of the sudden, your coworker leans over and tells you that your last changelist broke the build. Obviously, you have to drop what you are doing and fix the problem. You lose context and time, but that's unavoidable. Hopefully, this kind of thing is rare. If it isn't, you may want to check that you have the proper processes in place.

If there are still too many urgent interruptions, then it would help to have one person process all the interrupts of the team. For example, for one week Jane Programmer handles all interrupts for the team, and does not attempt to do non-interrupt-based work at all. This is actually psychology comforting, because she doesn't have to worry about her interrupts slowing her down on her main project. She's already decided that the only work she gets done is what are normally distractions. And if she finds herself distraction-free, she can always do little code cleanups and fixes that she always intended to do but never got around to. She's happy and the rest of the team is more productive by not having to worry about distractions. This should more than offset any productivity loss by Jane Programmer's not working on her project.


Hopefully, by following rules like these we can manage to use the opportunities distractions provide, as well as to minimize their impact.