Tippon won!

I received some happy news just before the new year that my submission to the 2011 Nokia Windows phone developer challenge Tippon have won.

The winner are calculated by download count over the 40 days period. I am super happy about the result, given this is the first public programming competition I have entered.

As a result, I’ve decided to release the source code for Tippon under Apache License 2.0. The source comes with no warranty, but I hope it can be used as a starting point for someone else’s project. I will continue to improve Tippon if I have any new ideas for features.

Download here.

Tagged , ,

Tippon 1.2 released

Tippon, the best tip calculator ever, is now updated to version 1.2.

Along with minor visual enhancements, it is also available in simplified Chinese, traditional Chinese and español.

Tagged , ,

Windows phone 7 vs Android development

I’ve recently had attended a workshop for Windows phone 7 development. It got me started pretty quickly on WP7 development, and I’ve quickly published my first app Tippon, a tip calculator that can take a picture of the bill and keep track of your dining experiences.Afterwards, I reflected on my development experience vs my app development in Android. In a word, developing for Windows phone 7 have been a pleasure.

Visual studio Express + Expression Blend is an awesome combination of tools. My biggest weakest when it comes to application design have always been visual elements, but I was surprised at how effortless it was to create a great looking app on Expression Blend.

Comparing the development experience with Android, Eclipse is quite disappointing. A lot of designs are done manually, and the emulator is unbearably slow. I truly hope Eclipse can soon catch up to the developing experience provided by the Microsoft platform.

Tagged ,

Proxying object for fun and profit

Got a little performance issue, fired up the profiler and tracked 75% of CPU cycle on this block of code.

1
2
3
4
5
public int indexOf(ReportColumn col, UseType use) {
  ReportColumn copyColumn = col.copy();
  copyColumn.setUse(use);
  return columnList.indexOf(copyColumn);
}

The majority of the hold up is in the copy() function which produce a deep clone of the ReportColumn object via reflection. Not only is this very slow, but it also increase the memory needed because of the deep clone process.

My immediate reaction was to use remember the “use” value of the column, make a change to the col object, find the index and change it back. But then I started to worry about the original intent of the function, since I didn’t write it, I just assume whom ever did write it this way must use deep cloning for a reason. Maybe they expect col object to be read by another thread while the search is happening. Hence I just abandoned plan A.

Plan B involved proxying, and went a bit like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public int slowIndexOf(ReportColumn col, final UseType use) {
  ProxyFactory pf = new ProxyFactory();
  pf.setTarget(col);
  pf.addAdvice(new MethodInterceptor() { 
    @Override  public Object invoke(MethodInvocation mi) throws Throwable {  
      if (mi.getMethod().getName().startsWith("getUse")) {
        return use;  
      
      else {
        return mi.proceed();
      }
     }
   });
   ReportColumn copyColumn = (ReportColumn) pf.getProxy();
   return columnList.indexOf(copyColumn);
}

By using the spring’s inbuilt proxying libraries, I constructed a method interceptor to intercept call to getUse and replace the value with the use we want to search for.

However, as the name indicates, it was very slow, slower than I thought it would be, in fact pf.getProxy() was 4 times slower than the deep clone method.

Back to the drawing board, I ended up tracing the code to see if I can find any potential code that might be reading the col object while it is been used, hoping that I can try a locking to prevent that from happening. As it turns out, there is no concurrent access. So I ended up with this.

1
2
3
4
5
6
7
public int indexOf(ReportColumn col, final UseType use) {
  UseType oldUse = col.getUse();
  col.setUse(use);
  int index = columnList.indexOf(col);
  col.setUse(oldUse);
  return index;
}

Lesson here, first instinct/simplest solution is often the best, also question your initial assumptions.

Tagged , ,

Tippon.com has been taken!

I feel like I’m someone important, I feel like I’ve finally made it big.

Shortly after the release of my awesome tip calculator Tippon. I’ve did a bing search 1 week later to see if tippon search word can link me to the app download page.

Although it did find my app download in the search results returned. It also found tippon.com. Curiosity compelled me to click to have a look.

Someone cyber-squatted the domain! They want $5700 to sell it. I know I should probably feel a bit angry about this, or at least a bit foolish for not securing it sooner. But all I feel is flattered, somebody actually noticed my app, and think that it could potentially make enough money to justify the $5700 buy back!

Tagged , ,

Tippon is published

Finally version 1.0 of Tippon is published for the Windows Phone 7 platform.

This first version includes the basic functionality of tip calculation, bill splitting, and allows user to keep track of all their past bills by capturing it with the phone’s camera.

For future version I’ve planned to add social media integration with twitter, Facebook etc. This is my first app on the Windows phone, please support by downloading and leave feedback on your thoughts.

Tagged , ,

Trouble shooting under stress

I thought I knew stress. I am no stranger to production environment hot fixes, day before deadline all night rush, and recently getting a feature in production 30 minutes before a demo.

But it wasn’t until today, at my niece’s 8th birthday party did I truly appreciate what true stress is. Imagine 16 pre-teen girls all around you, screaming at the top of their collective little but efficient lungs, while you are trying to figure out why the cheap made in China knock-off wee-mote (sic) will not sync with your Wii.

The good news is i manage to get the Wii started. However, a little piece of my sanity died today.

Tagged

Strange Generics in Java

So I had an interesting issue in my new project today.

Th cause of the bug is not that strange itself, what essentially happened was that a Hibernate mapping was missing in one of the project’s shared libraries. This caused the query that was suppose to return a collection of the domain objects to instead return a collection of map objects.

So far, totally understandable behavior. But it’s how I found out about this bug that was unusual.

1
2
3
4
5
6
Collection<Domain> objs = daoImpl.getDomains(); // was actually returning a collection of maps
if (objs != null) {
  for (Domain d : objs) {
    //do something with d   
  }
}

This is roughly the code I had that used the share library. I had expected the InvalidCastException to be thrown at line 1. However it was not until line 3 when the for loop was executing before Java detected that something was wrong.

To be sure of this I even stepped the code through the debugger, yep, I can clearly see that it was a Collection of maps, and it is definitely not picked up until the for loop.

It was driving me crazy, I even entertained the thought that maybe java.util.Map secretly inherited my domain object somehow.

Then it suddenly hit me, Java generic type checking is enforced only at compile time. Since Hibernate is creating the domain objects by reflection, the compiler couldn’t possibly have known the class mismatch.

Lesson to remember, beware when pulling in new shared library.

Tagged ,

FTP – A connection to my nightmere

Story time again I guess.

Although this is not a pleasant tale, even remembering some of the details make me squirm in discomfort still.

I remembered it was a Tuesday night, 10 pm, I was wrapping up my photo editing work and getting ready for bed, when a call came to me. It was the support guy from work, he calls to inform me that the prices for some ETFs have not came through. Since there was a new production deployment of the ETL software responsible for sending the prices through the day before, he assumed that the ETL software must be to blame.

Unfortunately the particular colleague that deployed the changes yesterday had turned off her phone, “clever girl” I whispered to myself. Since I was the next person with knowledge on the software, it was up to me to debug the situation.

The first thing I did was to bring up a diff of the code been deployed, I traced through all the configuration changes, everything seem innocent enough. Certainly nothing that will stop the file been picked up from source ftp location to the destination.

Just to be safe, I reversed the changes, most of which are superficial, and redeployed the ETL software, since I had no production access, I IM the support guy to drop the file and try again. The support guy regret to inform me that, the file was again not picked up, completed ignored by the software.

By that point it was close to midnight, and my memory became hazy, but the loop went on something like this, I try something fix the issue, deployed it, support guy tell me it didn’t work. And on and on it went, at one point, even the programming cat that lived next door came over to help debug, he too was stumped. This cycle continued to 3 am.

I was tired and broken by then, my mind was a mess of tangled wires and burnt fuses. But at last, something came to me, something ridiculous in its simplicity.

I asked the support guy, “hey, which FTP are you putting the file in?”

“FTP a of course”

My rage burned with the heat of a thousand suns.

“NO! NO! NO! NEIN! NEIN! NEIN! NEIN! FTP a is the destination FTP, you have to put the file in FTP b, this is an outgoing file not an incoming file!” I might have been more polite had this not been common knowledge and detailed in the support document they made us write.

So another 30 minutes was wasted restoring all the changes back, and redeploy the latest version, and waiting for the support guy to put the file on the correct FTP server, and of course, everything flowed after that.

Lesson to take away from this? If nothing makes sense, question your/their assumptions.

Tagged

House MD debugging

I did a quick search around the interweb. There is no precedence, so i would like to officially coin the pharse House MD debugging.

Official definition: a way to discover the source of the bug by eliminting the impossible and whatever remains, although unlikely, must be the cause. It is also known as the Sherlock Holmes deduction method.

Most of the bugs I have encounted are obvious, with nice stacktrace to help track it down to the line number. Some bugs however, through complexity of configuration or external library obsfucation, hides the source of the bug in a maze of incoherent logics. That’s the perfect time to use HMD!

Just like how House determine the real disease on the show, we can get to root of the cause of the bug by testing all sub component that could possibly cause the problem. Once we discover the offending component, sub divide the areas to test for once more and continue until the bug is found.

So give it a try next time you find a mystey bug, and watch House MD, it’s a great show.

Tagged