Thinking outside the box

A hopefully enlightening story.

I had the need to get the latitude and longitude for UK postcodes. Knowing that another developer had recently done a lot of work doing similar things using the Google Maps API, I had a look at the code she had written. Following the Google guidelines, she had ended up adding wads of C# classes, defining the various data types that the API returns, as well as a lot of helper methods to parse the data. I had that horrible sinking feeling you get when you can see a small design requirement blow up out of all proportion.

Whilst contemplating the problem, I had an epiphany (as in a sudden, intuitive perception of or insight into the reality or essential meaning of something, usually initiated by some simple, homely, or commonplace occurrence or experience to quote dictionary.reference.com as opposed to the festival!), and realised that I could solve the problem in a much simpler way, albeit with some initial effort. I thought the technique might be useful to others, but more significantly, thought that the idea of thinking outside of the box may be of interest.

This latter point became even more significant with my second epiphany (see previous overly long and irrelevant bracket).

Epiphany 1

The main problem with the approach advocated by Google is the sheer volume of code required to accomplish a relatively simple task. Google Maps API returns Json, and all you need to do is parse that. Even if you’re not familiar with the syntax, a quick look at a sample result makes it quite clear. The voluminous code Google offered mainly consisted of parsing methods and classes to hold the data.

I had been working with a lot of Javascript (a horrible language, but essential for web sites that do anything other than sit there looking pretty). One of the main things I really dislike about Javascript is that it is dynamic. Those of us who program in C# are used to strongly-typed objects, where the compiler warns you as soon as you mis-type the name of an object’s property, method or event. You avoid an enormous amount of bugs, because the incorrect code won’t compile.

Javascript isn’t like that. It’s dynamic, meaning that you can do pretty much what you like, and the run-time environment will try and make sense of it. For example, the following is perfectly valid Javascript, but probably not what you wanted to do…

var jim = {
  Age: 3,
  Name: "Jim"
}
jim.age = 4;

For those of you fortunate enough not to be familiar with Javascript, the first four lines declare an object (using the aforementioned Json syntax) named jim that has two properties, Age and Name. The last line attempts to change Jim’s age, but due to a sleepy coder’s typo has the property with a lowercase “a” instead of an uppercase one. In C# this would give a compiler error. In Javascript it creates a new property altogether. Lovely! I could write a book about what I don’t like about Javascript, but I’ll restrain myself and leave it at that one example. See the Afterward (right at the bottom of this overly long page) for a slightly irreverent comment on that subject.

When C#4 came out (with Visual Studio 2010), it included support for dynamic objects. At the time, I thought it was about the most pointless addition to the language they could have made. OK, so maybe not the most pointless, but pretty useless all the same. After all, why make a strongly-typed language look like Javascript? Can’t be any use for that can there? Turns out I was wrong, although it took about seven years for me to find a use.

If you could load the Json into a dynamic object, then you could navigate your way down the graph, and pick out the properties you wanted. The compiler wouldn’t need to know whether or not the properties existed or not, avoiding the need for all of those extraneous classes, and so you wouldn’t need huge amounts of code to parse the Json into those classes. As long as it worked at run-time, you’d be fine.

So, after that ridiculously long introduction, here is the code that replaces about ten million lines of Google-powered C#…

public Tuple<double, double> GetLatLongFromPostcode(string postcode) {
  WebClient client = new WebClient();
  string url = "http://maps.google.com/maps/api/geocode/json?address="
               + postcode.Replace(" ", "+") + "+uk";
  dynamic loc = JsonConvert.DeserializeObject(client.DownloadString(url));
  double lat = (double)loc.results[0].geometry.location.lat;
  double lng = (double)loc.results[0].geometry.location.lng;
  return new Tuple<double double>(lat, lng);
}

If you want to try this at home, you’ll need to add the Newtonsoft.Json Nuget package to your project. Don’t let that put you off by the way, Microsoft trust this package enough to include it as standard when you create an MVC project.

As you can see, I was able to enter the path down the hierarchy without any complaints from the compiler, as loc is a dynamic object.

The downside to this is that it took a bit of fiddling around to work out the exact path, but it was still a lot quicker than adding all of those extra classes and methods. By the way, if you want to do this yourself, I strongly recommend you do it in LinqPad, not Visual Studio, as it’s much quicker to run, so you get through the make-a-change, try-it-out, oh-no,it-didn’t-work, make-another-change cycle with a lot less frustration.

The moral: So, a bit of sideways thinking saved me a significant amount of time and effort. I can’t claim to be enough of a genius to do this all the time, but it’s worth remembering that when faced with a problem, it’s always a good idea to step back and take a look at the bigger picture. Maybe there is another way of approaching the problem. Rubber ducks or teddy bears (for those of us who never grew up) are a huge benefit for this by the way!

Epiphany 2

A few days later, I was watching a video about F# type providers. One of my (many) weaknesses is that I love shiny new things.

In truth, F# isn’t actually very new, the first version came out about the same time as .NET 1.0, but it’s new to many people, and it’s very shiny! Anyway, I was watching this video, where the presenter showed how you can pull information from Wikipedia about the changes of appearance in Dr Who over the years with remarkably little F# code. For those interested, here is the code…

#r @"packages\FSharp.Data.2.3.3\lib\net40\FSharp.Data.dll"
open FSharp.Data
 
type DoctorWhoData = HtmlProvider<"https://en.wikipedia.org/wiki/Doctor_Who">
let data = DoctorWhoData.GetSample().Tables.``Changes of appearance``.Rows

Line 1 is only needed as I was doing this in an F# script file, which isn’t built as part of a project, so I needed to tell it where to find the DLL I opened (think C#’s using statement) on line 2. Line 3 creates a data type based on the Wikipedia page, and line 4 extracts the data. Basically two lines of real code! Compare that to how much you would need to write in C# to achieve the same, and you might be able to understand why I was interested. More specifically, when doing this in Visual Studio, you get Intellisense. No examining the source code of the Wikipedia page, no guesswork, just simply picking the options…

See how the provider worked out what the tables represent for you? You don’t even need to look at the page in a browser to do this, much less wade through HTML!

At some point during the video (when I had calmed down at the thought of being able to extract Dr Who data and call it coding), it occurred to me that the JsonProvider that comes in the same package would enable me to extract my postcode data in a similar manner.

It turned out to be every bit as easy as I thought. With the aid of Intellisense, I had my latitude and longitude in no time…

type GoogleData =
  JsonProvider<"http://maps.google.com/maps/api/geocode/json?address=SW1W+0DT+uk">
 
let lat = GoogleData.GetSample().Results.[0].Geometry.Location.Lat
let lng = GoogleData.GetSample().Results.[0].Geometry.Location.Lng

(BTW, the postcode there is for Buckingham Palace, useful in case you want to visit the Queen)

Given the similarity between the two lines, I’m sure there must be a cleaner way of doing this, but it was quick enough for me.

Now, much as I would love to use F# in my day-to-day coding, I imagine I would have our CTO biting my ankles fairly quickly. However, by writing the code in F#, I was able to get the right path through the hierarchy in seconds, and could then convert the code to C#. The only real differences are that the F# Json provider capitalises the properties, so I needed to change Results to results and so on, and the small syntax difference that F# uses dot notation for array indexing, so I needed to change .[0] to just [0] and I could then copy the code directly into my C# project.

Again, stepping back and thinking about the problem from a different angle (admittedly with the help of a well-timed video) gave me a very quick and painless solution to a problem, albeit after I had already solved the problem!

Afterword – A slightly irreverent but mostly accurate comment on Javascript

Nothing to do with the above, but slightly amusing. I may have given the impression that I’m not a fan of Javascript. I have support for my opinion. I have a book titled Javascript: The Definitive Guide, which has 1096 pages. I also have a book titled JavaScript: The Good Parts, which has 172 pages. Based on the page count of these two books, one can deduce that Javascript is more than 84% bad! More truth in that than many people would like to admit.

Be First to Comment

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.