Sunday, January 26, 2014

Konami Code

One of the things that I love about being a developer is you get the chance to hide Easter eggs in apps...and what nerdier Easter egg is there than crediting the team simply by entering the Konami code? So naturally, we added that to ADT's 404 page. Try it. :)

Edit: It has been brought to my attention that a new developer has decided to "optimize" things by ripping out the easter egg. Exactly how much was gained by optimizing a 404 page is unknown at this point, but all I have to say to the developer is boo, you suck! 

Sunday, October 13, 2013

Iterations Rules

As I've mentioned previously, I've been working lately on a side project called Iterations. At the moment, I'm the only back-end developer which means I get to make the rules, something that I don't often get to do. :) And my rules have been formed based on pains that I've experienced first-hand on work-related projects, pains born from mistakes made by both myself and others; pains that I want to avoid this time around.

In general, Iterations is a web app that will allow Agile projects to be tracked...basically to provide functionality that vendors usually charge a pretty penny for, for free, and hosted on your own server pointing to your own database, instead of someone else's.

So what's the technology stack being used? Well, it's a Maven project that uses RESTEasy to allow the front-end to make calls to the back-end, Guice is used for dependency injection, while MyBatis takes care of the database side of things. On the UI side, we're using CoffeeScript and Sass to make things look pretty, which is all being taken care of by the rather talented UI guru Mike Munsie.

Architecturally, there are three main layers to the app; a resource layer which acts as the entry point to the back-end, a service layer where the main logic lies, and a data-access layer that provides all database related functionality. There are other layers that provide things like security and exception handling, but for the main part, it's these three layers that provide the majority of the grunt work. So with that, here are my four simple rules that I apply in order to keep the design as clean as possible:

The resource layer can only talk to the service layer
Each resource is allowed to talk to one or more services only. It seems pretty reasonable that resources cannot talk to DAOs, but let's tighten things up a bit and say that resources cannot talk to other resources either. The reason being that talking to other resources, to me, implies that there is common functionality that should be abstracted out instead.

Resources must not pass HTTP specific information to the services
As requests come in, each resource should extract the information from the HTTP request, and provide that to the services. This way, a service may be reused by some future layer that isn't HTTP based. For example, let's imagine that we're going to start using a scheduler like Quartz to send out emails each night; it would be pretty much hosed if a service that it depends on requires an HttpServletRequest to be passed to it. In order to be reusable, a service must be unaware of who is calling it.

The service layer can only talk to the data-access layer
This is similar to the first rule, and for the same reason; services cannot talk to other services as that implies common functionality that we can abstract out. Services also cannot talk to resources (and if we follow the previous rule, they probably can't anyway). This helps to avoid any entanglement of code, which is a good thing (the avoidance that is, not the entanglement ;).

The data-access layer cannot talk to any other layer
Each DAO is tasked with simply making calls to the database, that's all, so as to keep things simple. A DAO cannot talk to another DAO.

And that's it. Following these four simple rules has so far kept the design pretty simple, as it should be. They've helped prevent the beginnings of spaghetti code from happening, and helped avoid broken windows from appearing in the first place.

I like rules. Especially when they're my rules. :)

Saturday, October 5, 2013

Code Coverage

I've long been a fan of unit tests; they just make sense, and there's really no argument for not having them on production-ready code other than sheer laziness and not giving a crap about quality in general.

Code coverage appears to be a different issue though.

My stance, before I go on, is that I like to get as much code coverage as possible from my unit tests. A full 100% is just not possible these days as I tend to reduce boilerplate code by using Lombok, but I still strive for the most I can get.

Now I've worked with some very talented guys over the years, and one guy in particular is someone who I admire for his sheer level of technical ability. However, he would question my zest for code coverage, asking that just because the code coverage tools showed that a unit test had run through some code, how could you be sure that that piece of  code was actually tested, and not just executed for the sake of code coverage?

And he had a very valid point. And not only that, it was a point that I had difficulty providing any kind of logical answer to that didn't make me come across as sounding like I had OCD or something. Then I started working on a side-project called Iterations, and it was here that I finally found the answer.

With no time constraints on the project, and with no deadlines to hit, I was free to take my time to unit test everything and maintain the highest level of code coverage possible.  And here's what I found:

Increasing code coverage forces more unit tests to be written. Writing more unit tests helps enforce a cleaner design.

As I was working on Iterations, I would find that if unit-testing a piece of code proved to be a pain, then there was something fundamentally wrong with the design of that particular component.  Either a class was becoming too large, or starting to do too much, or inheritance was beginning to make things difficult, or whatever...the key point was that I obviously needed to re-think things, and refactor.

And so I would refactor the design to make the tests much simpler and easier to implement. Lather, rinse, and repeat enough times, and you end up with one heck of a clean design.

So to answer his question, he is absolutely right in that increasing code coverage does not necessarily ensure that the code is really being tested. But the real benefits lie in the overall increase in the quality of the underlying design itself, and that is something that is most definitely something a developer should always strive for.

Thursday, September 26, 2013

Iterations

It's been a while, right?  Obviously I'm not in any danger of becoming some overly-active blogger any time soon. :)

Well, a lot has been going on in my family's life, with a wonderful new addition to the family back in February 2011, and then some rather startling events that kicked off 2013 in a way that I wouldn't wish on anyone; I'll spare the details, but my wife best summed it up (if you'll forgive the language) with "2013 can go fuck itself already".

So in between my last post and now, I've done absolutely zero Android development..King of Suck, I know. But I did get to work on redesigning ADT's site from the ground up with a handful of top-notch developers from Improving Enterprises, I've also learnt a ton of new things, and it was there that I met the highly talented front-end developer Mike Munsie.

As the team follows agile practices, management's initial tool of choice was Version One.  I'm an avid supporter of a blank wall with masking tape-defined swim-lanes, and that's indeed what we've used for the most part, but for tracking purposes management wanted something like Version One. And when that trial license expired, management looked around for a cheaper alternative, eventually landing on Rally.

Now both Version One and Rally, while functional, kinda feel like an anchor when it comes to being an agile developer.  No longer can I just walk up to the board and move my Post-it note task from in-progress to complete, or cross out the hours remaining and write the new hours remaining.  It's just a pain in the ass, and to top it off, both options mean the key details of our agile process is hosted on a third party server. If that third party was to ever go under, bye-bye stories, bye-bye tasks.

So Mike and I got talking while walking to lunch one day.  Why not build our own tool...one that is functional, intuitive, developer-friendly, does everything you need without the need to dig down into various menu options, and above all, is hosted on our own damn server with zero licensing fees. Sounds good, right?

And that's when project Iterations started.

Currently the source code is private while we flesh it out, but the intent is to have a fully functioning war file that you can drop into your own container of choice, point it to your own database of choice, run the scripts to generate the tables, and go on from there. And best of all, it'll be open sourced under the Apache license. Our first goal is to reach a point where we can begin eating our own dog food, and host the Iterations project on one of our own servers so that we can begin placing stories and tasks related to this project. And to help us out once we get there, we've been promised a helping hand from the excellent scrum master Andy Seibel, who will provide valuable feedback on the tool itself, and from Kris Giamello, a highly talented designer who has kindly offered to give give us design feedback.

To say we're stoked to be working on this is an understatement. :)

Monday, November 29, 2010

ADT, Eclipse, and The Mystery of The Frozen Auto-Complete

I like Eclipse...as IDEs go, it's my IDE of choice.  For general day-to-day development, it covers so much straight out of the box, but then along come the wide variety of plugins that are available, and all of a sudden, Eclipse helps make life as a software developer just that little bit sweeter.

And when it comes to Android, the Android Development Toolkit (ADT) plugin is about as nice as they come, from quick and simple project setup, through to easy integration with the Android Debug Bridge, the ADT plugin really does deliver in simplifying Android development.  There has been, however, a slight problem that has left me downright frustrated many times, and that is the terrible slowdown in performance when it comes to auto-complete.

How terrible is terrible?  Well try anything from 5 to 20 seconds or so (on my machine) waiting for the auto-complete box to populate...it doesn't exactly sound like a lot, but it's more than enough to be extremely annoying, it breaks your flow, and it really makes you want to hurl your mouse at the screen as you realize that there's absolutely nothing that you can do about it but wait and seethe.

From what I've read, this is an issue that only affects Eclipse 3.6, and so the interim solution offered was simply to revert back to 3.5.  The only problem with that solution is that I rather like Helios and the increased stability that comes along with it; I really don't want to have to go back to Galileo if I can avoid it.  And I guess others in the same situation agree, because lo-and-behold...a workaround has been found.

How to Have Your Cake And Eat It
As it turns out, the ADT classpath container is looking for source in the standard Android SDK installation directory...except the standard Android SDK doesn't come with the source.  This means that Eclipse attempts to cache entries that are in a directory that doesn't exist.  Everytime.

And so the obvious workaround is to simply download the source, create the directory, and let Eclipse be happy.  To do this, you simply need to do the following:

And that's it...problem solved!  For the guys on this thread where they provided this solution, I offer my utmost thanks.  As do my mouse and monitor. :)

Saturday, November 6, 2010

C2DM: On The Receiving End

My last couple of posts regarding Android's Cloud to Device Messaging framework were purely from the perspective of the server, in that we first had to obtain an authentication token using ClientLogin, and then we actually used the C2DM service to send a message.  But what about the client side?  What's needed from our Android app in order to receive these near-realtime notifications?  Well as it turns out, we simply need to do a couple of things:
  • Register with the C2DM framework to receive messages
  • Pass the registration ID that we get to the server
All in all, that's a pretty small to-do list, don't ya think? :)

Warming Up
Of course, before we can even start to think about using the C2DM framework, we have to do a few things first to make sure our app is fully prepared.  As the ability to use the C2DM framework arrived in the Froyo release, we have to make sure that our application requires version 2.2 or later by specifying it in the manifest:


    
    

    ...

Next, we need to make sure that we have our permissions set up properly. In order to receive notifications, the app must have the following permissions:
  • com.google.android.c2dm.permission.RECEIVE - allows us to register and receive messages.
  • android.permission.INTERNET - we need this so that we can pass the registration key to the third-party server that will be sending us notifications (it needs to know who to send the messages to, right?).
  • <applicationPackage>.permission.C2D_MESSAGE
  • - stops other applications from trying to register as our app in order to steal our messages.
This should be straightforward enough, so let's have a go:


    
    
    

    
    

    
    

    ...

So far, so simple, right?  Good. :)  But, we're not quite out of the woods as far as the permissions go just yet; we still need to make sure that we only receive messages from the C2DM framework, otherwise any other app could send us notifications (which in all likelihood we probably don't want to have happen).  To achieve this, we'll specify a receiver that has the following permissions (each with a category that matches our applicationPackage):
  • com.google.android.c2dm.intent.REGISTRATION
  • com.google.android.c2dm.intent.RECEIVE
So what does this look like?  Well, something like this:


    
    
        
        
            
            
        
        
        
            
            
        
    

    ...

Here, we're specifying a receiver (my.example.app.C2DMReceiver) that will perform the handling of the registration ID and any messages that are sent our way.  Again, all in all relatively straightforward...don't ya just love Android? :)

Registration
Now that we have the permissions sorted, it's time to register our app so that it can receive messages...and here's where it gets super-silly-easy.  All we need to do is create an Intent (com.google.android.c2dm.intent.REGISTER) and pass the email address of the sender (which will be the email address that we set up for the server to use) and our application ID:
public static void register(Context context, String senderEmail) {
    Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
    registrationIntent.putExtra("app",
            PendingIntent.getBroadcast(context, 0, new Intent(), 0));
    registrationIntent.putExtra("sender", senderEmail);
    context.startService(registrationIntent);
}
Wow, pretty easy huh?  (Don't worry, I can sense the nodding) :)  So what happens after we've fired off that Intent?  Well this is where the receiver that we declared in the manifest comes in to play:
public class C2DMReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
            String registrationId = intent.getStringExtra("registration_id");
            String error = intent.getStringExtra("error");
            String removed = intent.getStringExtra("unregistered");
            
            if (error != null) {
                // Perform error processing
                ...
            } else if (removed != null) {
                // Perform any post-unregistration cleanup
                ...
            } else if (registrationId != null) {
                // Send registrationId to third-party server
                ...
            }
        }
    }

}
Our receiver simply checks the Intent to see if it's a com.google.android.c2dm.intent.REGISTRATION Intent, and if it is then it grabs the registration_id and, barring any errors (or if this is a response to our application unregistering itself), it goes ahead and passes the received registration ID to our third-party server.  This now ensures that our app is primed and ready to start receiving messages.

Receiving Messages
Handling any messages that come in is done using the same means that we used for receiving the registration ID.  This means we're going to use C2DMReceiver again...specifically, we're going to be using exactly the same method:
public class C2DMReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        ...
        if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
            // Yay, we've received a message...grab the
            // parameters and do awesome stuff!
            String myParam1 = intent.getStringExtra(SOME_PARAM_1);
            String myParam2 = intent.getStringExtra(SOME_OTHER_PARAM);
            // Perform any processing
            if ("some_condition".equalsIgnoreCase(myParam1)) {"
                doSomethingAwesome(myParam2);
            }
            ...
        }
    }

}
And in a nutshell, that's it...it just about couldn't get any simpler.  Really.  But I'm not quite done with C2DM yet; there are some things that are handy to know when it comes to integration testing...

Testing, Testing, 1-2-3
It's relatively simple to test things out just by using the emulator alone.  As always though, there are some things that we need to make sure of first, and these are:
  • The AVD (Android Virtual Device) must use the package "Google APIs by Google Inc., Android API 8", so make sure you have it installed.  It has to be "Google APIs" and not simply "Android API 8" or it won't work.
  • C2DM requires a valid signed-in Google account in order to establish a connection with the device, which means that the emulator also needs to have a valid Google account that is logged in.  Simply go to Settings > Accounts & Sync > Add Account and provide the account details.
  • If the application server that you will be sending the messages from is running locally, make sure you're not trying to use localhost when sending the registration ID in your app.  Instead, use address 10.0.2.2 to hit the local server instance and save yourself some noodle-scratching. :)
Happy messaging!

Thursday, November 4, 2010

C2DM: Sending Messages

This post follows on from my previous post where we called ClientLogin to obtain an authentication key.  The reason why we needed this key is so that we can do something really cool...send out push notifications to our Android applications.  And similar to that post, the code that is provided here should be just enough to produce a result; a real application will need to implement functionality to handle the different responses that the C2DM service can return, as well as handle things like exponential backoff for when the service is unavailable.

The basics of sending a message are really quite simple; all we need to do is send a well formed HTTPS request to https://android.apis.google.com/c2dm/send and pass along the registration ID of the device that we wish to send a message to, our authentication token, and the payload of the message itself.  So just like we did before when obtaining the authentication token, we start off with the HttpURLConnection object:
HttpURLConnection connection = null;
try {
    URL url = null;
    try {
        url = new URL("https://android.apis.google.com/c2dm/send");
    } catch (MalformedURLException e) {
        // Exception handling
    }
    connection = (HttpURLConnection) url.openConnection();
    connection.setDoOutput(true);
    connection.setUseCaches(false);
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    connection.setRequestProperty("Authorization", "GoogleLogin auth=" + token);
} catch (Exception e) { 
    // Exception handling
}
Once again, I'm using HttpURLConnection as my application is going to be hosted using Google App Engine, and HttpsURLConnection is simply not allowed.  Also, notice how we need to send our authentication token; it needs to be prefixed with the String "GoogleLogin auth=".

Next up, we need to set the parameters that we're going to pass to the C2DM service.  For this, we need to include the registration id that the device received from the C2DM service when the device first registered itself (yes, that means the device will also need to pass that id to us as soon as it gets it).  We also need to specify our message payload in the form of key-value pairs, with the key prefixed with "data.":
StringBuilder sb = new StringBuilder();
addEncodedParameter(sb, "registration_id", deviceRegistrationId);
addEncodedParameter(sb, "collapse_key", "goobr.blogspot.com.someKey");
addEncodedParameter(sb, "data.payload1", "payload1 message data");
addEncodedParameter(sb, "data.payload2", "payload2 message data");
addEncodedParameter(sb, "data.anotherPayload", "even more message data");
String data = sb.toString();
One thing to note is the collapse_key parameter.  This is simply a required key that will be used to collapse our messages so that if the device is switched off, it won't get a ton of messages when it comes online again...in this situation, only the last message will actually be received by the device (although C2DM makes no guarantee on message order, so it might not actually be the last message that was sent).  And just like before, we're using the same addEncodedParameter() method to format our parameters into a String:
public static void addEncodedParameter(StringBuilder sb, String name, String value) {
    if (sb.length() > 0) {
        sb.append("&");
    }
    try {
        sb.append(URLEncoder.encode(name, "UTF-8"));
        sb.append("=");
        sb.append(URLEncoder.encode(value, "UTF-8"));
    } catch (UnsupportedEncodingException e) {
        // Exception handling
    }
}
Finally, we come to the actual sending of the message itself, and processing the response:
try {
    DataOutputStream stream = new DataOutputStream(connection.getOutputStream());
    stream.writeBytes(data);
    stream.flush();
    stream.close();

    switch (connection.getResponseCode()) {
    case 200:
        // Success, but check for errors in the body
        break;
    case 503:
        // Service unavailable
        break;
    case 401:
        // Invalid authentication token
        break;
    }
} catch (IOException e) {
    // Exception handling
}
If the service is unavailable, then we need to check for (and honor) any Retry-After header in the response, and failing that, we need to implement exponential backoff (that is, keep doubling our wait time before trying the request again).  Also, even if we get a 200 response code, that doesn't mean that the message went through.  We still need to check the response body for any of the following:
  • Error=QuotaExceeded
  • Error=DeviceQuotaExceeded
  • Error=InvalidRegistration
  • Error=NotRegistered
  • Error=MessageTooBig
  • Error=MissingCollapseKey
On the first two errors, there's not a lot we can do but wait for a while and try again...it just means that too many messages have already been sent.  For the InvalidRegistration and NotRegistered errors, we need to make sure that we stop sending messages to this registration id as the device has either unregistered itself, uninstalled our Android app (uh-oh!), or simply switched off notifications.  And for the final two errors, well we simply need to look at our code and make sure that:
  • the message is 1024 bytes in size or less and
  • we include a collapse_key in the request
One final thing to note is that the response may include an Update-Client-Auth header from time to time, and all this means is that the authentication token that was used to send the message is about to expire, and so the C2DM framework has generated a new one that we should start using instead.

And that's all there is to it really.  See...told you it was really quite simple! Have fun sending push notifications to your Android apps. :)