Thoughts about software development

Archive for December, 2010

Update 1: There is no native iPad app for Facebook, so maybe the difference is just the iPod Touch?

Wait… an application available on only one flavor of iOS? I thought there was no fragmentation on iOS?

Update 2: Also worth pointing out, perhaps, that while Facebook’s Android app is growing fast, it isn’t catching up to the iPhone app. The Facebook for iPhone app gained about 4.5 million users for the month, going from 53 to 57.5 million users. The Facebook for Android app gained about 4.25 million users, going from 17 to 21 million users.

Another way of looking at it is that the Android app gained 23% while the iPhone app increased only 8.5%. In other words, Android is growing three times as fast as the iPhone.

I don’t think these numbers mean much, to be honest, but isn’t it funny that whenever there are two ways of looking at statistics, Gruber will always pick the one that shows Apple in a more favorable light?

And in a more recent entry, Gruber quotes an entire press release from Amazon saying that the Kindle is their best selling product of all time. His laconic comment:

Short version: Lots of people are buying both Kindles and iPads. (I own both and I’m glad I do.)

Er… no. The short version is that a lot of people are buying Kindles. The PR says absolutely nothing of the iPad.

With these latest posts, Gruber is fast approaching the Fox News level of reporting.

Camera shutter buttons have a two-stop action. Half-press them to lock focus and aperture settings, fully press them to take the picture. There’s a delightful tactile indent at the half-way mark so that your fingers know what’s going on. Let’s borrow this two-stop action for the home button. Press half-way to go to the app’s main screen, all the way to go to the phone’s main screen. If you need to fully escape mash the button. If you just want to head back to the main-screen of the app, tap lightly.

I agree that the need is real, but there is already a superior solution to this problem: long presses.

If you agree that half presses are a good idea, surely long presses are an even better idea, because in a way, it’s similar to leveraging Fitts’s Law, but for buttons.

Fitts’s Law states that the bigger the target is, the easier it is for users to reach it. Mac’s menu bars are very easy to reach because their vertical size is virtually infinite: just move your mouse all the way to the top, it will bump against the screen and it will be positioned on the menu bar.

I’ll argue that the same applies to long presses. Instead of encouraging a design where you only half press the button (very small target area), press the button all the way (infinite target). Then either release right away or keep the button pressed for a short while. The half click works well on cameras because of the way you hold it, but I have a feeling that having similar accuracy on a phone will prove to be more challenging.

Strangely enough, Gruber likes Aza Raskin’s idea, which, in some way, acknowledges that Android’s long presses are not such a bad idea after all (but of course, he would never admit that).

MG Siegler’s posts on Techcrunch are the running joke of the blogosphere, but for some reason, his latest article just prompted me to react.

And that quickly changed to $199 phones subsidized by carriers. In other words, nothing changed.

Google seemed to think they could go around them and sell phones on the web directly to consumers. The carriers didn’t like that idea too much. They pulled their backing of that plan. And Google had to pull the plug.

Google is trying hard to remove power from the carrier in order to give it to customers. Their initial attempt didn’t work as well as we all expected but somehow, you find this to be a reason to rejoice?

I don’t know about you, but if anything, I want Google to keep trying, and trying, and trying. Because that’s how change happens.

Besides, Android did change something: we’re in 2010 and the iPhone is not a monopoly. Now that’s something to celebrate, even though it seems to make you sad for some mystifying reason.

Soon, the vast majority of Android owners will have VCAST apps shoved in their faces

Getting something shoved in your face is never a pleasant thing, but this accusation coming from someone who is such a fan of Apple and Apple’s products is quite humorous. At least on Android, you can buy a different phone if you don’t like what’s coming preloaded on the one you buy. Good luck with that on the iPhone.

And what’s most disturbing about this is Google’s rhetoric. It has morphed from “wait and see” to “we think the carriers will get the message” to “we hope the carriers will get the message”. Newsflash: the carriers are not going to get the message as long as they have any shred of leverage.

Hey, I actually agree with that. And Google is trying to take away that leverage, so why are you so mad at them?

Again, dream world. Google set out with the idea that they could change everything on their terms.

A lot of the technology you and I use and love today exists because at some point, someone dreamed it. And they built it despite the opposition of people like you.

And again, just to be perfectly clear, I’m not saying Google shouldn’t try to change these industries. All of them need to be disrupted — in some cases very badly. I’m just not sure about Google’s execution on any of them.

Well, sure, because you picked all the examples were Google wasn’t very successful while carefully omitting to mention the ones where they did change everything. Android, Gmail, Maps, Earth, just to name a few.

All in all, it feels like the only reason why you dislike Google is because they are challenging your favorite company.

Your motto: “Try to make the world a better place, and if you fail, give up”.

Working on “fundamental” software comes with its own set of challenges, and since a few people have asked me about it, I thought I’d share a few war stories about my experience with working on TestNG.

First of all, what do I call “fundamental” software? It’s a bit hard to define precisely, but it’s basically any jar file that usually ends up at the bottom of your dependency stack. A testing framework seems to belong quite naturally there, but you can extend this to libraries such as the Google Collections, or Guice, or build software (Ant, Maven or Maven plug-ins) and of course, languages themselves (e.g. Groovy).

Exhibit 1: TestNG and Maven

TestNG is built in two forms: via ant (which produces a jar file that is self-contained) and via Maven, which builds a jar file that only contains the TestNG classes. With Maven, If I’m building version N in my pom.xml, I can’t tell my tests to use TestNG version N to run, since this would create a circular dependency, and Maven forbids it.

Instead, I have to create two pom.xml files: one that builds version N-SNAPSHOT (pom.xml but doesn’t run the tests and one that depends on N-SNAPSHOT (which must have been previously installed and deployed) which only runs the tests (pom-tests.xml). The entire build with Maven is therefore a two step process:

mvn clean install -Dgpg.skip=true
mvn -f pom-test.xml test

Note that it’s important to `install` in the first step, otherwise, the second step won’t be able to find the snapshot.

The reason is simple: the TestNG Eclipse plug-in has to use its own version of the testng.jar file, for many reasons. Because of this limitation, the plug-in can’t see modifications of the TestNG code base that I the current instance of Eclipse, since it has already loaded classes from its testng.jar. It’s a bit unfortunate but of course, there are plenty of other ways to work on TestNG without using the plug-in. Most of the time, I just launch a standard Java application. And of course, when I need to work on the Eclipse plug-in itself, I just launch it as an Eclipse application.

I was adding a few features to JCommander some time ago. When I was done, I added a few tests for the new features, ran them with Eclipse, they passed. Then I switched to the shell, ran a quick mvn package to make sure everything was fine before committing when… all the new tests failed.

That was puzzling. Looking closer, it looks like Maven was running the tests against an older version of JCommander, and since the new functionality was obviously not implemented then, they failed with NoSuchMethodException and similar errors.

Now that was quite puzzling, did I find a bug in Maven? Why was it running against a version of the source that’s not the one I’m working on? And where did this version come from? Why that one in particular?

I had to convince Maven to be a bit more verbose than it usually is (it’s actually possible) and I finally solved the mystery.

JCommander obviously uses TestNG to run its tests, and it turns out that TestNG uses JCommander to parse its command line. Of course, the version that TestNG depends on is older than the one I’m working on, so Maven ends up with two versions of JCommander on its classpath, and unfortunately, it puts the dependency’s version first.

Mystery solved.

As it turns out, there is actually a way out of this, which Brett Porter kindly pointed out to me. The solution is to have your Surefire dependency explicitly specify which version of JCommander it wants:

(Update: this still doesn’t quite seem to work, trying to investigate with Brett’s help).

This is just a quick overview of what it’s like to work on fundamental libraries and how this kind of development can differ from working on more regular applications that sit at the top of the software stack.

This blog post shows some interesting data confirming some thoughts that I have harbored about dynamic languages for a while.

In a nutshell, so called “dynamic languages” seem to be more used because they allow you to type less than because they use really dynamic features.

Maybe it’s because static typing is so ingrained into my brain, but when I write something like:

def raise_salary(employee)
...

I really, REALLY, REALLY want to type:

def raise_salary(Employee employee)
...

My fingers are just screaming to add this type information. Same for local variables or return types. It’s in my head, it’s in my code, why can’t I just give this information to the compiler, the tools and to future readers and reviewers of this code? It’s really not that much to type and it buys me so much. Think about it: refactorings that are guaranteed 100% correct.

Implement this interface, let TestNG know about your implementation and whenever TestNG needs to instantiate a test class, it will call the newInstance method of your object factory. This allows for a lot of flexibility, and interestingly, this interface appeared in the TestNG distribution long before Dependency Injection became as popular as it is today.

IObjectFactory has been very useful to TestNG users throughout the years, but the emergence of Dependency Injection has made its existence even more important. More and more TestNG users want to inject their test classes with DI frameworks, and over the past few months, I have noticed a sharp increase in Guice users.

IObjectFactory obviously works great with Guice (and Hani and I documented this extensively in our book) but the increased number of questions on the mailing-list prompted me to wonder if I couldn’t make this easier on Guice users.