Wednesday, June 26, 2013

Changing the JSON object in an API



Interesting discussion with the development team today about a bug that recently surfaced. The JSON object that was being sent back and forth between the client (browser) and the server changed in structure. For a few hours after the deployment a bunch of exceptions showed up in the logs but as users of the site left and rotated out for new users the exceptions became fewer and finally disappeared.

What had happened was that Ajax calls pages on browsers that had been loaded before the deployment were still communicating with the server using the previous JSON structure while the server was expecting the new JSON object. The code to handle the old JSON object had been removed from the server and not knowing how to deserialize the old object the server was throwing and logging (thankfully) exceptions.

The lesson from this is that you should always provide backward compatibility for one version (iteration) of the code base and then remove that backward compatibility.

The best and easiest way to provide backward compatibility is to have a version key/value pair in your JSON object. Increment the version when you change the JSON structure and perform a switch on the server to handle the previous and current versions. This does, however, require that you thought about this ahead of time and your current live object has a version key/value pair in it.

If not, then you can inspect the object for the known change (e.g. new or removed key) and use an if/else to switch which deserializer you're going to use.

The reason that you want to remove the old code after one iteration is because you want to get rid of dead code as soon as it's dead because it becomes a maintenance nightmare. The longer the dead code is in the code base the more worried everyone is about removing it because nobody can remember if it does anything. While the memory of the previous version is still fresh in your head make sure that old code is killed off. Create a work item in the next project that includes the removal of this code.

Incidentally if you have code that you think is dead but can't be certain (e.g. some code uses reflection to call it or it's an entry point to the application like an API endpoint or web service) then I usually put a log statement in there. Then I put a reminder in my calendar, usually a month out, to search the logging database for that string to see if anything has called it and then I remove it.

Tuesday, June 18, 2013

Graffiti Redirect 404

This is an unusual blog post as it's the destination for unredirectable 404 pages for the old Graffiti CMS that used to host this blog.

A couple of blog posts back I wrote that I had migrated this blog from Graffiti CMS to Blogger. I changed the domain of the blog from a non-www version (guyellisrocks.com) to the www version (www.guyellisrocks.com) so that I could host a redirector on the non-www version.

The redirector receives a request for the original URL and then using a bunch of rules and pattern matches attempts to redirect to the new page on Blogger, this blog that you're reading now. However, before it redirects the visitor it checks to see if the blog page exists in this blog. If Blogger returns 404 then it logs this missing lookup and sends the user to this blog post.

At this point, you should type your query again in the search box above and to the left and it will search just this blog for the missing post.

If, in final desperation, you still can't find what you're looking for then feel free to reply to this post and I'll try and help you.

Tuesday, May 28, 2013

Stream ended unexpectedly (got X bytes, expected Y)

I was trying to clone the nopCommerce repository from codeplex (https://hg.codeplex.com/nopcommerce) to my local drive and the first two attempts failed with stream ended unexpectedly (got X bytes, expected Y)



The definition of stupidity is trying the same thing twice and expecting a different result right? In this case I was running it a second time to see if it failed at exactly the same point. If that happened then it was most likely a corrupt source/repo on the server. If the values were different (which they were in this case) then it indicated that it could have something to do with the network.

By checking the "Do not verify host certificate" option in TortoiseHG's close function to I managed to complete the download successfully.


Thursday, May 23, 2013

Migrating from Graffiti CMS to Blogger


I set this blog up in 2008 and have blogged on and off for the last 5 or so years on technology. I selected Graffiti CMS after Rob Howard from Telligent, its creator, gave a talk at our local AZ Groups .Net user group and he gave out a bunch of licenses to a this product which was then going to be sold at $150. It has since become open source.

Graffiti CMS has treated me very well and is a remarkably good product. However, these were the drawbacks that made me decide to move my blog off Graffiti:
  • Very small number of users and one very kind and competent developer maintaining it.
  • I hosted it on my dedicated server. This meant that it was eating up resources that other web apps needed.
  • I had to upgrade it and maintain it and patch it myself and a security vulnerability might impact other applications on the server.
I moved it to Blogger because I already have a blog on Blogger and as such I'm familiar with the tools but I'm sure that other blogging platforms like Wordpress would have had as much as I needed as well.

The migration process went like this:
  • Found some code that someone had written to export the blog into BlogML and tried it out. This failed as Blogger couldn't read it in.
  • Spent a few hours modifying the code to get the export format I wanted but was unsuccessful. Knowing that I don't have much time on my hands to do this type of thing I threw some money at it and asked the Graffiti developer to create an export for me.
  • He kindly did this and here I am, 300 or so migrated posts in Blogger.
The original blog ran off http://guyellisrocks.com/ (no www) and I've migrated it to http://www.guyellisrocks.com/ so that I can redirect to the new url pattern. I've written a web app which is now sitting at the non-www version and when it gets a request it then reaches into the database and pulls out the date for that post and generates the new url. This is then used for redirection to the new (this) site.

What's still to be done?
  • Some of the URLs did not migrate in the predictive fashion I'd expected. I'm logging those and will make changes to the redirection code as I go along.
  • Images have not come across so I'll do that manually as I find time.
  • There are references to the non-www version in the new www version and even though they will redirect correctly they should be fixed as eventually I'd like to get rid of the redirector. I'll do this by checking the referrer header and if it's from the www version I'll log this so that I can find the posts with those links.

Tuesday, May 14, 2013

ShipIt Day at Go Daddy

Shipping
I manage a team of developers in the Presence and Commerce division of Go Daddy. We're responsible for providing small businesses with their Digital Identity. Our two main products are Website Builder and Quick Shopping Cart. Last Friday, May 10, 2013 we had our first ShipIt Day.
ShipIt Days were created by Atlassian. In their words:

Every quarter, we give employees the chance to work on anything that relates to our products, and deliver it during ShipIt Day, our 24-hour hackathon. Been wanting to build that plugin, redesign that interface, or completely rethink that feature that’s been bugging you? You’ve got 24 hours...go!

Our first ShipIt Day pretty much followed the format described by that statement.

We picked a Friday to do it because Fridays are usually less busy than other days because we try and avoid them for deployments. The teams self-organized which included the skill sets of Quality Assurance, Developers, DBAs and Business Analysts. We found a room where everyone could come together and work. Tip: When you do this bring power strips, duct tape and extension cords to make sure everyone has power throughout the day. Also make sure that the wireless is working well and has the bandwidth needed.

During the day we made sure that the team was sugared up on sodas and snacks and brought in lunch and towards the end of the day we brought in some adult beverages when the brain numbing complexity of the coding was done. This allowed everyone to relax and celebrate their work and cruise into the weekend.

We delayed the judging and demos until first thing on Monday morning to allow weekend travelers to get home.

Each team had six minutes on Monday morning to show what they'd created and the Product Managers and other non-participating managers joined in the judging. As score collector I asked the judges to use whatever criteria they through appropriate but to roll it all up into a single score from zero to ten and give that to me. Decimal places were allowed and one of the judges used five criteria and sent me scores to two decimal places.

Based on the generally high scores given out by all the judges, the quality and usefulness of the work done was exceptionally high. I cannot list the features because we will probably ship all of them in one of the two products already mentioned. However, once they're shipped I'll come back here and talk about them some more.

All of the members of the top three teams each received a prize to recognize their innovation. It was a tough call because the scores were close together as all the features were awesome.
Tips for a successful ShipIt Day (not saying we did all of these but in future ShipIt Days we hope to cover them all):
  • Make sure you have power, wireless and a comfortable place for everyone to work.
  • Make sure the team understands what they're doing. (i.e. a feature to enhance the product that they're working on but it doesn't have to come from the backlog.)
  • Let the team know the ShipIt Day date well ahead of time so they can start forming their teams and ideas around what they'll work on and cancel that vacation to Hawaii so they can be there.
  • Make sure they have drinks, snacks, and lunch during the day and of course an adult beverage at the end of the day.
  • Get a budget for prizes, who doesn't like to be recognized?
I'm very lucky to be working with such an awesome team of developers. They are constantly going above-and-beyond in their efforts to make world class products and it's a privilege to be part of this team.

Tuesday, February 19, 2013

Codility Equi Task

Codility is a site that tests coders. Their demo problem task is called Equi. You can read the full description of the problem and solutions in a number of different languages on their blog post about it: Solutions for task Equi

I was somewhat surprise at the complexity of the code required in many languages. Using C#'s LINQ syntax makes it obvious and simple to write:

static int equi(int[] A)
{
    for (int i = 0; i < A.Length; i++)
    {
        if (A.Take(i).Sum() == A.Skip(i + 1).Sum())
        {
            return i;
        }
    }
    return -1;
}

It's also not difficult to modify that function to return all the equilibrium indexes: 

static IEnumerable<int> equi2(int[] A)
{
    for (int i = 0; i < A.Length; i++)
    {
        if (A.Take(i).Sum() == A.Skip(i+1).Sum())
        {
            yield return i;
        }
    }
}

Note that this solution although simple and elegant to write is not performant because the full array get summed in each loop. i.e. the time complexity of this solution is O(n^2). For a time linear solution you would increase and decrease a left and right sum variable as you moved through the index and compare those values.

Sunday, November 18, 2012

Overloading methods in TypeScript

At yesterday's presentation at Desert Code Camp I felt that I gave an inadequate explanation on how you would implement an overloaded method in TypeScript. Hopefully this code snippet will address that:

interface Thing {
    a: number;
    b: string;
    foo(x: string): string;
    foo(n: number): number;
}

function myfunction(myParam: Thing) {
    var stringResult: string = myParam.foo(myParam.b);
    var numberResult: number = myParam.foo(myParam.a);

    console.log(stringResult);
    console.log(numberResult);
}


var myObj = {
    a: 16,
    b: "My String",
    foo: (x: any) => {
        if (x && typeof x === 'string') {
            return x.length.toString();
        } else if (x && typeof x === 'number') {
            return x * x;
        } else {
            if (x) {
                throw { message: "null parameter is unsupported" };
            } else {
                throw { message: "unsupported type: " + typeof x };
            }
        }
    }
}

myfunction(myObj);

Note that in myfunction() you would not be able to call myParam.foo() with any other type of parameter than string or number because the compiler will complain about that. So even though the implementation checks for another type in the final else you cannot pass in another type (e.g. object) because TypeScript won't let you.