Make Your API User Friendly

So, an API is by definition an application interface, meaning it should be usable by applications.  But you know who really has to use them?  People.  Developers.  And if you’re going to write an API, you should make it usable for the interfacing applications, but simple and friendly for the developers.  I don’t think I’m going to hear any argument about this.

I’m writing here to bitch and bitch and bitch about a project that is breaking me.  I expect it will be the last project I do with this company.  This API I have been tasked to consume and integrate with our own system is so difficult to work with and so brittle it is mind-numbing.

When you read their documentation, which is perpetually out of date, and see the data you are working with, the initial conclusion you get is that you literally have to write a UI as defined by their specs.  And that would be the easiest solution, but the dumbest one because then they should just write it themselves and host it for everyone instead of making an API.

The project involves forms.  We fill them out and send them the results.  However, we already have our own forms, so the integration should be as easy as taking our values and translating them to their values.  As part of the integration, they will send us a JSON file with a form definition.  This JSON file contains EVERYTHING needed to construct a UI.  It has the field names, the form control types, the validations, groups (with potentially infinite nesting), rules on groups, required attachments per field, permissions… you get the point here.  It’s not just a simple form definition.

Ok, so I parse out the groups and fields, then add mappings and translation code.  The translation code is off the rails because a “No” in our form must be converted to a “No” in their form.  And a “No” in their form is a GUID.  A GUID nested under the potential response values for a specific question.  So yeah, not just mapping questions, but mapping answers.  On a form with 200+ questions.

Then on top of this, they implement versioning.  So a form can be updated and we’ll get a new definition.  They may (and have done so) rename groups or fields or answers, which just causes the translation code to blow up.  Call me a lame programmer all you want, but I’d like to see someone effectively handle a value they’ve never seen before.  I’ll take the hit for not wrapping everything in an IF to see if the field was removed or renamed.  The timeline demanded does not permit that level of attention.

That’s only part of the troubles.  For each form we complete, we have to make multiple service calls.  Four, actually.  And today, they told me I’m supposed to be making a fifth call, even though things have been working for the 15+ test cases I’ve successfully completed so far.  Ok, that little gripe is not really about a specific API, but more about how the company itself has really created a monster in sum.

So back to the meat of the topic, the simplicity of an API.  So when you want someone to use your API, you want to make it easy.  If you are updating a child record, you shouldn’t have to specify the ID of the parent unless you are allowing that ID to be changed.  You can get everything you need from the ID of the child.  So why in this API must I provide so much data about so many related pieces when all I should have to provide is the ID of the data I am updating??  And another point: the values I’m returning aren’t updatable values anyway.  All that’s happening is the message is being fat and heavy and data is being thrown away.  Or maybe, the data is being saved and my work is saving them the effort of looking it up for themselves.  If that’s the case, then its unvalidated data and subject to exploit.  There is no good answer here.

So lets talk about the responses we have to send to this API.  It’s a JSON body with a dynamically constructed object with properties representing the fields of the form.  And although the field property has a name of UniqueID, it has to be returned in a fully-qualified manner, prepending each containing group’s UniqueID.  So if a group name changes, all fields under it change in the response.  It could have been easier to just send the UniqueID (since it is supposed to be unique, right?).  And the structure of the object, what the fuck.  Why not just have a simple array of key/value pairs.  Instead, you have some mystery object where a property may or may not exist.  It’s the same shit, iterate over properties or iterate over an array.  One can be handled in code with a class and a generic List, the other has to be done through a complex library like Newtonsoft and still results in an object that can’t really be navigated.  I get that JavaScript is taking over the goddamn world, but JS makes everything harder for no real benefit.

That’s as much ranting as I want to do right now.  Although it feels good to get it out, it doesn’t give me any improved perspective of the project or its viability.

TFS 2012 Fails To Create New Team Project

Today, I went to add a new team project to TFS.  I did the usual steps by giving it a name and choosing the template type (not really relevant to me since I’m a solo programmer).  Visual Studio worked for a bit, then failed with the following error in the log file:

Event Description: TF30162: Task "LinkTypes" from Group "WorkItemTracking" failed
Exception Type: Microsoft.TeamFoundation.Client.PcwException
Exception Message: Page not found.

The Internet had plenty of advice to resolve TF30162 errors, but nothing useful for the specific LinkTypes error.  The only suggestion was to reload the project templates.  I was not able to do that because in TFS 2012, those templates are locked and unable to be uploaded and overwritten.

So I attempted a Repair install of TFS 2012.  That had no effect

I then made sure I was on the latest version of TFS, so I installed Update 4.  My scrum project template went from 2.0 to 2.2, but I still got the exact same error.

I then tried to create a new Project Collection and create a team project in that.  Still, no change.

Then I did a repair install on Visual Studio 2015.  This took a very long time and required two restarts.  And after that, no improvement.

So far, I’ve eliminated the TFS binaries, the TFS database, and the VS binaries.  There’s only one element left – IIS.  And that one seems to have potential because of the PageNotFound error.

Poking around the IIS log files, there’s entries in there like this:

2017-01-09 14:27:23 ::1 GET /tfs/_apis/connectionData connectOptions=IncludeServices&lastChangeId=-1&lastChangeId64=-1 8080 MicrosoftAccount\myaccount@domain.com ::1 VSServices/14.98.25331.0+(devenv.exe+,Pro,+SKU:31) – 404 0 0 1719

Looking at IIS log files prior to when my problem happened,  this 404 error has happened before, too.  but there was also other calls to the service like:

2016-03-25 12:43:46 ::1 OPTIONS /tfs/defaultcollection/_apis/ – 8080 MicrosoftAccount\myaccount@domain.com ::1 Team+Foundation+(devenv.exe,+14.0.24712.0,+Pro,+SKU:31)+VSServices/14.0.24712.0+(devenv.exe+,Pro,+SKU:31) – 404 0 0 8

Two suspects come up in Internet searches: Git and IIS plugins.  Disabling some of the plugins in C:\Program Files\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins made no difference.

At this point, I suspect an incompatibility between VS2015 and TFS 2012, so I upgrade my TFS install to 2015.  What else could it be?  A call is being made to a REST service that doesn’t exist, or is different enough that the inbound parameters don’t match up.  This TFS upgrade requires SQLExpress to be upgraded as well.  The rabbit hole keeps going deeper and deeper.

After that entire install and restart, I was finally able to create a new Team Project.  The new default project template is “Agile”, not that I care much.

So, the short solution for my error: Upgrade TFS from 2012 to 2015.  It must’ve become incompatible after a VS update somewhere along the way.