Archive for December, 2011
Clojure: Casting to a Java class…or not!
I have a bit of Java code for working out the final destination of a URL assuming that there might be one redirect which looks like this:
private String resolveUrl(String url) { try { HttpURLConnection con = (HttpURLConnection) (new URL(url).openConnection()); con.setInstanceFollowRedirects(false); con.connect(); int responseCode = con.getResponseCode(); if (String.valueOf(responseCode).startsWith("3")) { return con.getHeaderField("Location"); } } catch (IOException e) { return url; } return url; }
I need to cast to HttpURLConnection on the first line so that I can make the call to setInstanceFollowRedirects which isn’t available on URLConnection.
I wanted to write some similar code in Clojure and my first thought was that I needed to work out how to do the cast, which I didn’t know how to do.
I then remembered that Clojure is actually dynamically typed so there isn’t any need – as long as the object has the method that we want to call on it everything will be fine.
In this case we end up with the following code:
(defn resolve-url [url] (let [con (.. (new URL url) openConnection)] (doall (.setInstanceFollowRedirects con false) (.connect con)) (if (.startsWith (str (.getResponseCode con)) "3") (.getHeaderField con "Location") url)))
Which can be simplified to this:
(defn resolve-url [url] (let [con (doto (.. (new URL url) openConnection) (.setInstanceFollowRedirects false) (.connect))] (if (.startsWith (str (.getResponseCode con)) "3") (.getHeaderField con "Location") url)))
Yak Shaving: Tracking the yak stack
While I’ve been learning how to write an android application there’s been plenty of opportunities for me to go off shaving yaks, it’s pretty much Yakville Central.
Typically I’d end up spending hours trying to work out some obscure thing which I didn’t really need to know so I wanted to try and avoid that this time.
I started keeping a track of the ‘yak stack’ which I was currently following and mentally noting exactly where I was up to.
An example of a yak stack I kept while trying to authorise a user of the app with Twitter using OAuth is shown in the photo on the right hand side.
It ended up looking like this:
- Get the home timeline working
- OAuth blowing up
- Not actually capturing redirect back to app
- Launch mode in Android manifest
- Not actually capturing redirect back to app
- OAuth blowing up
Once I realise I’m heading down the stack I’ve been giving myself one pomodoro to try and dig myself one level up.
If I still haven’t managed to solve the problem I might keep going for one more pomodoro or just find another way around the problem.
I’m sure I’ll come across problems where I need to spend more than an hour trying to solve it but for now it’s working ok as a rule of thumb.
It’s definitely fun chasing yaks but I get to the end of the day and haven’t really achieved anything which isn’t fun.
The Language of Risk
A few weeks ago Chris Matts wrote an interesting blog post ‘the language of risk‘ in which he describes an approach he used to explain the processes his team uses to an auditor.
Why did the auditor like what I said?
Because I explained everything we did in terms of risk. When they asked for a “process”, I explained the risk the process was meant to address. I then explained how our different process addressed the risk more effectively.
This seems like a pretty cool idea to me and it got me thinking of the different ‘processes’ we’ve used in teams I’ve worked on and what risks they might be addressing:
- Pair Programming
- Becoming dependent on one person with respect to knowledge of part of the code base.
- Having someone new working on an area of the code that they don’t know well and making a mistake.
- Retrospective
- Making the same mistakes repeatedly/working in a way that (indirectly) wastes money.
- Story Kick Off
- Building the wrong thing
- Solving the business problem in an inefficient way
- Building something which is very difficult to test
- Stand Up
- Someone getting stuck on something which someone else in the group might be able to help with.
- People going down rabbit holes and getting stuck on things that don’t really matter
- Show Case
- Building the wrong thing for too long
- Automated testing
- The application regresses as new functionality is added
- Humans make mistakes when manually going through scenarios
That’s just a first attempt at this, I’m sure others could come up with something better!
In coming up with the list I’ve been working from a process which I’ve seen used and trying to work out what risk that might be addressing.
Chris seems to look at risks/processes the other way around to i.e. we think about what risks we need to address and then work out whether we need a process to address it and if so which one.
Taking that approach would help to explain why some teams don’t necessarily need a lot of process – the risks might be catered for in different ways or maybe they just don’t exist in specific contexts.
For example a lot of risks around communication go away if the product owner and the team are sitting in the same physical location and can easily just turn and talk to each other if they have any questions.
Even with this new way of looking at risks/process I still think it’s useful to keep checking whether or not a process is still necessary because as our team/product changes the risks we face probably do as well.
Learning Android: Sharing with Twitter/the ‘share via’ dialog
One thing I wanted to do in the little application I’m working on was send data to other apps on my phone using the ‘share via’ dialog which I’ve seen used on the Twitter app.
In this case I wanted to send a link and its title to twitter and came across a StackOverflow post which explained how to do so.
To keep it simple I added a button to the view and then shared the data via the on click event on that button:
Button button = createButton(); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Stupid Scanner tricks - http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html"); v.getContext().startActivity(Intent.createChooser(shareIntent, "Share via")); } });
In this case if I choose the Twitter app from the drop down list that appears it will create a new tweet with the value of ‘android.content.Intent.EXTRA_TEXT’ as its body.
If we needed to pass a subject to the other app then we could set that using ‘android.content.Intent.EXTRA_SUBJECT’ but in this case it’s unnecessary.
From what I understand so far only apps which can handle the ‘text/plain’ format will show up in the drop down list but that seems to be pretty much every app on my phone.
This works reasonably well but I wanted to see if it was possible to share directly with the Twitter app rather than having to choose from a selection of apps.
Via a combination of blog posts and StackOverflow questions I came across the following solution for posting directly to the Twitter app:
Button button = createButton(); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Some text"); shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Stupid Scanner tricks - http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html"); final PackageManager pm = v.getContext().getPackageManager(); final List<ResolveInfo> activityList = pm.queryIntentActivities(shareIntent, 0); for (final ResolveInfo app : activityList) { if ("com.twitter.android.PostActivity".equals(app.activityInfo.name)) { final ActivityInfo activity = app.activityInfo; final ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name); shareIntent.addCategory(Intent.CATEGORY_LAUNCHER); shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); shareIntent.setComponent(name); v.getContext().startActivity(shareIntent); break; } } } }):;
It does depend on the Twitter app being installed on the phone to work but since the app is just for me I think it’s ok for the moment.
Reading Code: Know what you’re looking for
In the last week or so before Christmas I got the chance to spend some time pairing with my colleague Alex Harin while trying to understand how an existing application which we were investigating was written.
We knew from watching a demo of the application that the user was able to send some processing off to be done in the background and that they would be emailed once that had happened.
Our starting point was therefore to work backwards from the labels on the UI and finding which code got executed when the user submitted the task.
My initial approach was to find the entry point and then follow the method calls line by line, slowly building my knowledge of how the application actually worked.
Alex used a much quicker approach whereby he thought about how the code would be designed and then looked for the bit of code which proved his belief.
In this case we knew that the application had a 2 tier architecture and that it didn’t use any middleware which meant that it would more than likely be using the database as a queue to store the tasks to be processed.
Another colleague and I were then able to make use of this approach when looking at another piece of code.
It was being used to do pricing and we knew that there were different algorithms depending on which country you were in, which meant that we needed to look for anything country related to answer our questions.
Effectively we’re looking at the code with a hypothesis in hand and then trying to see whether or not what we see proves or disproves that hypotheses.
I need to practice a bit more but it seems to let you navigate code much more quickly and makes you much less likely to dive down a rabbit hole.
Learning Android: WebView character encoding
In my continued attempts to learn how to write an Android application I came across a problem with character encoding when trying to load some text into a WebView.
I was initially trying to write the text to the WebView like this:
WebView webview = new WebView(collection.getContext()); webview.loadData(textWithQuotesIn, "text/html", "UTF-8");
But ended up with the output in the picture on the left hand side. I tried playing around with the encoding and debugged the application all the way through until it hit the WebView but there didn’t seem to be any problem with the text.
I eventually came across a post on StackOverflow where mice suggested using one of the other methods available for writing to a WebView.
I changed my code to read like this:
WebView webview = new WebView(collection.getContext()); webview.loadDataWithBaseURL(url, textWithQuotesIn, "text/html", "UTF-8", url);
And now the single quotes are rendering correctly as can be seen on the image on the right.
I had a quick look at the Android source code to see if there was any obvious reason why one of the methods would work and the other wouldn’t but I couldn’t see anything.
Perhaps I’m doing something wrong with my call to ‘loadData’ and that’s why it’s not rendering the character set correctly. If that’s the case please let me know.
Leiningen: Using goose via a local Maven repository
I’ve been playing around a little bit with goose – a HTML content/article extractor – originally in Java but later in clojure where I needed to work out how to include goose and all its dependencies via Leiningen.
goose isn’t included in a Maven repository so I needed to create a local repository, something which I’ve got stuck on in the past.
Luckily Paul Gross has written a cool blog post explaining how his team got past this problem.
Following the instructions from Paul’s post this is how I got goose playing nicely with clojure:
Inside my clojure project:
/Users/mneedham/github/android/text-extraction $ mkdir maven_repository
I then ran the following command from where I had goose checked out on my machine:
mvn install:install-file -Dfile=target/goose-2.1.6.jar -DartifactId=goose -Dversion=2.1.6 -DgroupId=goose -Dpackaging=jar -DlocalRepositoryPath=/Users/mneedham/github/android/text-extraction/maven_repository -DpomFile=pom.xml
I added the repository and goose dependency to my project.clj file which now looks like this:
(defproject textextraction "0.1.0"
:description "Extract text from urls"
:dependencies [[org.clojure/clojure "1.2.0"],
[org.clojure/clojure-contrib "1.2.0"],
[ring/ring-jetty-adapter "0.3.11"],
[compojure "0.6.4"]
[goose "2.1.6"]]
:dev-dependencies [[swank-clojure "1.2.1"]]
:repositories {"local" ~(str (.toURI (java.io.File. "maven_repository")))}
:main textextraction.main)I then run:
/Users/mneedham/github/android/text-extraction $ lein run
And goose and all its dependencies are included in the ‘lib’ directory.
Learning Android: Deploying application to phone from Mac OS X
I’ve been playing around a little bit today with writing an Android application and while for the majority of the time I’ve been deploying to an emulator I wanted to see what it’d look like on my phone.
The developer guide contains all the instructions on how to do this but unfortunately I’m blessed with the ability to skim over instructions which meant that my phone wasn’t getting picked up by the Android Debug Bridge.
We can check which devices have been detected by running the following command from wherever the SDK is installed:
/Users/mneedham/github/android/android-sdk-macosx/platform-tools/adb devices
This was initially returning no devices and reading Esau Silva’s blog made me realise that I’d failed to follow this instruction:
On the device, go to Settings > Applications > Development and enable USB debugging (on an Android 4.0 device, the setting is located in Settings > Developer options).
I’d assumed it was only necessary if I wanted to debug the application on my phone but it seems like you need to set it to be able to deploy in the first place.
And now my phone gets picked up and can be deployed to, yay!
/Users/mneedham/github/android/android-sdk-macosx/platform-tools/adb devices List of devices attached 3933C40945FA00EC device
If it still doesn’t work then Esau Silva has some other ideas which I haven’t yet needed to try.
The supposed black box
On a reasonable number of the systems that I’ve worked on over the past few years there’s been a ‘black box’ component which the team I’ve been on has needed to integrate with.
I’ve always found it a little strange that you wouldn’t need to/want to know how that part of the system worked or that you could actually believe that it was truly a black box.
If it doesn’t work then you have no way of diagnosing the problem – did you do something wrong, was there something wrong inside the black box or was it something else.
On a project I worked on a few years ago the reason for the black box thinking was that each layer was being developed by people from a different company.
The problem we had was that we were working on the top layer, the one that was visible to the end user and therefore our progress was very visible to the stakeholders who were paying for the product to be built.
We therefore had no choice but to go into the metaphorical black box and try and gather as much information as we could to pass on to the teams working on the other layers so that they would be able to help us better.
I recently watched a talk by Artur Bergman titled ‘Full Stack Awareness‘ where he talks about the necessity of understanding exactly what is happening when our code gets executed rather than thinking of it as magic.
Although Artur is working in a different context to most application developers who maybe don’t need to know the stack as well as he does I think the advice about treating something as magic is useful.
If we think of something as a ‘black box’ then effectively we are saying that it’s somewhat magic.
If the integrated component is being custom written then I think the team who needs to integrate with it should at the very least have someone who knows how it works very well so they can diagnose any problems quickly.
That person then needs to spread their knowledge amongst the rest of the team so that they don’t end up being the bottle neck.
In summary I think the term ‘black box’ is frequently a misnomer and we’ll rarely be able to view said black box in such an opaque way.
The Lean Startup: Book Review
I’d heard about The Lean Startup for a long time before I actually read it, mainly from following the ‘Startup Lessons Learned‘ blog, but I didn’t get the book until a colleague suggested a meetup to discuss how we might apply the ideas on our projects.
My general learning from the book is that we need to take the idea of creating tight feedback loops, which we’ve learnt in the agile/lean worlds, and apply it to product development.
Eric Ries talks about the ideas of the Minimum Viable Product (MVP), which is something that I’ve heard mentioned a lot in the last few projects I’ve worked on so I thought I knew what it meant.
I’d always considered the MVP to effectively be the first release of any product you were building but Ries’ frames it as the minimum product you can release to get feedback on whether your idea is viable or not. For example Dropbox’s MVP was a video demonstrating how it would work when the team had written the code to sync files on all operating systems.
On a lot of the projects that I’ve worked on we start after the point at which the business has decided what their product vision is and we’re responsible for implementing it. They haven’t necessarily then gone on to make a big return from building the product which I always found strange.
The most frequent argument I’ve heard against releasing an ‘incomplete’ product early in the organisations that I’ve worked for is that it could ruin their brand if they took this approach. One suggestion the book makes is to release the product under a spin off subsidiary if we’re worried about that.
The book also discussed the ways that we need to treat early adopters of a product and mainstream customers differently.
For example early adopters won’t mind/may actually prefer to play with an unfinished product if they can help influence its future direction.
By the time we have proved that we have a viable product and are looking to aim it at the mainstream market it will need to be more feature complete and polished in order to please that crowd.
There is a big focus on making data driven decisions such that we gather metrics showing how our product is actually being used by customers rather than just guessing/going on intuition as to what we should be doing next.
Facebook released an interesting video where towards the end they describe the metrics which they have around their application such that they can tell whether a deployment is losing them money and therefore needs to be rolled back.
One particular thing that the book talks about is cohort analysis:
A cohort analysis is a tool that helps measure user engagement over time. It helps UX designers know whether user engagement is actually getting better over time or is only appearing to improve because of growth.
We tend to use metrics to help us see the quality of code and which things we might want to work on there but I think the idea of using it to measure user engagement is really cool and should help us to build a more useful product.
I especially enjoyed the parts of the book where Ries talks about ways that some of the ideas have been applied with startups which are doing well at the moment although I think it’d be fair to say that the lean startup framework has been retrospectively fitted to explain these stories.
I think the danger of thinking that they were following lean startup principles is that it can lead to us not thinking through problems ourselves which I guess is the same problem with any framework/methodology.
I’m intrigued as to whether it will make a difference to the overall success rate of startups or not if they follow the ideas from the book.
I imagine we’ll see some ideas failing much more quickly than they might have otherwise and the suggestion is that when this happens we need to pivot and try and find another approach that will make money. Despite that, there there will come a point when the startup runs out of money without finding a way to monetise their product and it’ll be game over.
Overall the book is quite easy reading and worth a flick through as it has some cool ideas which can help us to spend less time building products which don’t actually get used.