Saturday, September 25, 2010

One day of a programmer

Last Friday I spent most of the time writing an application for Android. In short I was to write an application for Android and Foursquare (a location-based social network), for an assignment of CS3246 - Hypermedia and WWW. I feel obliged to record the experience.



I started with  trying an OAuth library for Java called Scribe to connect to Foursquare API. It was recommended by Foursquare that we use it instead of the Basic Authentication method, which just pushes the username and password to through http. The author offered a sample on how to work with it & Foursquare. The first step would be trying to deploy the sample on my computer. I copied the sample code, added the .jar library file to the project's BuildPath. No compile error. Good. Run. Boomz, I got ClassNotFoundException (or something like that). Admittedly, I didn't use external library (.jar file) before, so I wasn't sure if I did everything correctly. So I went to Google and researched on it. "So the BuildPath and the ClassPath during running time is different. I didn't know that," I thought in relief. However, it turned out that I've done the thing correctly; the library was in ClassPath already! Why did I still get error? I searched and searched again for more similar case. Spent quite some amount of time on searching, yet I couldn't understand why some class definition wasn't found. "I've included the library already!" I kind of screamed in my mind. I would then thought the problem was from the sample source code? So I searched about it on Google, but found little to nothing. After fruitlessly searched for solution, I came back to the project's page on GITHUB, found a link called Getting Started. I missed it before because the content looked mostly the same as the sample file, just broke into steps with instructions. "Ahhh, I need to download another library necessary for it!" (I wished it was Complile Time Error..) Thankfully, it solved the problem. Now I could authenticate and draw some personal information of the user from Foursquare.

However, as I'm developing a phone app, the authentication is supposed to be x_auth, which is a little different. Ehh, I'm not familiar with OAuth, and / or x_auth! I tried to imitate the code from the sample, and tried to find if there is any specific method for x_auth. There was one in the library for Ruby, so I expected similar thing in this Java library. But the library didn't have any documentation! I could guess little to nothing from the functions' signature, especially when all the parameter types were obscure. (Now I think it just doesn't support x_auth, which explains why there is no example using x_auth..).

Thinking that I advance any further with OAuth right then, I decided that I should familiarize myself with the Foursquare Java library first. I turned out to be a greater pain! The whole thing was a big mess. I didn't even know where to start. I guessed the first thing would be creating this Foursquare class. But the constructor takes in some random parameters that I had no clue about. So I dug a little further into these parameters. Ultimately, the parameters' type were String... What value am I supposed to pass in? I tried my luck by passing some value that I thought reasonable, but it wouldn't work. Now I appreciated the need of documentation. I hopelessly spent quite some time playing around with the library, only to gave up later.

I took a break and did a little research on Foursquare API, hope to get some small tutorial or sample application. It crossed my eyes from some article that the Foursquare application for Android itself is an open source application. "Why don't I read its code and see how it uses the library?" I went to its Google Code site, downloaded the application and tried to hack the code. I admit that it is a huge program, with lots of classes and libraries.

First step would be successfully logging in to Foursquare and extracting some information from the site. I proceeded to read its main program imitate the steps needed to do these things. I would go back and forth between the main program and the library, trying to decode what was happening, and what were the meanings of the classes, of parameters and stuff. I must say it was no where near comfortability.  Mostly because of the overwhelming amount of new information needed to process at a time. (Fun Fact: the first thing I noticed was that, Foursquare used Basic Authentication itself. So why did I try so hard to use OAuth? Sad.)

It would be easier if everything was simple and clear, however, sometimes things could be very misleading. Say, there was a version string should be passed into the constructor. I thought (when I tried to play with the library myself) it would be the version of the app, or version of the API, and might have the format of "1.0", or "1". Turned out it was Android package version, or something like that. The worser part is that, it had a very weird structure. I'd be genius if I knew I needed to part something like this: PACKAGE_NAME + ":" + String.valueOf(pi.versionCode);

Now I deeply appreciated the need of documenting the code. Guys, let's comment and document our code nicely, so that the next guy who uses it won't suffer so badly. Or at least he won't swear WT* every 5 minutes.

I kind of gave up with it already. Suddenly I saw a file named FoursquareAPI.zip on my Desktop. Uhm it was the Java API file provided by the teach staff. I thought it was the same as the thing I downloaded from the Foursquare official source, so I never touched it. Thankfully I tried it. To my delight, there was an API introduction file in the zip file. I opened it and found a sweet sort sample program using Foursquare API. Thanks god (& my lecturer), I'm saved. It turned out that the API provided wasn't the same as the Java API provided by Foursquare. However, it was much simpler and easier to use. It could be found here http://code.google.com/p/foursquare4j/. It doesn't always happen that the official thing is the best thing.

I quickly followed the sample program provided and deployed it to my Android application. Within 15 minutes I was able to login, print out the tagged venues around the user's location. I forgot to include the INTERNET permission so it didn't run the first time, but after few minutes I figured out and it worked seamlessly. Finally got something work. Compared to all the frustration & tiredness I faced before, it felt so good. Felt so delighted.

"Let's try to mark these location on the Google map," I continued. I've created a simple app to display and tag location in the map before, so this part is supposed to be easy and quick. I opened that app, copied the code that (I thought) necessary to my app, modified the code a little so that it would display venues extracted from Foursquare. And Ctrl + F11. Boomz. The app crashed. OnClassDefFoundException again! Ok sweet, maybe I haven't included some library? The problem wasn't the same because both of the map code & the piece of code using Foursquare API worked independently. I checked the RunConfiguration, but seemed that Eclipse itself got some problems, which added a little to the frustration I've got. I checked over and over again, but it wouldn't work. Started the debugger, added some breakpoint. It didn't even stopped at the first line of the main program! What I only found was some bizarre exceptions. Android couldn't find the definition of the main class itself. It crashed even before my program started running! What happened? I didn't know. It compiled! At least the class definition should be there!

I started to search for the problems on Google, based on the name of the Exception I found. I went through lots of forums, but still couldn't find anything work. They said check for classname, but apparently mine was correct. They said made sure the AndroidManifest.XML was correct. Good, I found that I hadn't stated that I used the Google map library in the XML; I thought adding it to build path & stuff is enough. However, it didn't solve the problem totally. I would open both the current one and the one from my sample Google Map app, compared line by line. No problem. It was even more frustrated than before. I thought the problem might be from the layout XML for Google map, because there was a warning that the tag "code.google.maps.MapView" is not defined. I hopelessly searched for solution in Google for some more. Still, couldn't find anything helpful. I did a lot of search, with lots of keywords, but none of the solution was applicable to my case. I tried to run the debugger millions time, but nothing happened, it just crashed right at the beginning. Somehow now it managed to reach the first line, but same thing happened afterward. Why : ( I dug deep into the stack track but also found nothing helpful.

Suddenly, in a flash light, I saw the first line of my code was "setContentView.." not "super(...)" (calling the super class to initialize itself). Hmm, I didn't expect it to made the whole thing fail; I didn't even see the foursquare app call super class' constructor. Still, I gave it a try and moved the call to super class' constructor on top. Magically it worked. (Now logically I think it happened (or crashed) like following: setContentView used some class that would supposed to be create by the super class' constructor, but the constructor hasn't called, so obviously setContentView can't find the class and crashed). Anyway, it worked, and the whole thing worked. Now I saw the map, with markers over the venues nearby user's location. Feeling relieved, but drained, I closed Eclipse and called it a day.




To summarize:

- Documentation & comments (of our code) are very important!
- Incremental testing is useful too! Code a little, test a little, then code a little more, test a little more. Restrain the desire to code the whole thing and debug all at one! It will go BOOMZ!
- Debugging is frustrating. It drains energy quickly.
- Google doesn't really helpful for debugging. Sometimes (most of the time) starring at the code, analyzing the errors and trying to figure out what went wrong is more helpful than go straight to Google and search for solution.
- I suddenly realized similar stories happened during CS3216 before: I wasted a lot of time on Google, but turned out I should just sit down, read my code, read the instruction carefully, and I would be able figure out what went wrong faster.
- I guess it is hard to avoid especially when we learn a new, complicated thing. We are clueless and wanted to search for light from people out there. However, it seemed that there were matches & wood just nearby, we should make use of them instead of searching for the light from faraway. After all, the people who wrote the instructions should provide enough information & correct steps to make the things work. We might just missed a small point, or introduced bugs in our own code.
- Still, I am awed by how dependent I am on Google now.

4 comments:

  1. ... anh nghĩ là cả ngày em ngồi viết cái blog này thôi đấy =)) productive quá :P

    ReplyDelete
  2. Too long for me too read. I stared at code the whole week too :'( Got some very weird bugs. And well, need to understand students' code...

    (A bạn Khúc Anh Tuấn kìa, mấy năm cùng ở cái đất nước nhỏ bé này mà mình chưa gặp nhau lần nào =)))

    ReplyDelete
  3. Correct lah.

    More thinking, less coding is the way to go. :-)

    ReplyDelete