Posts tagged with usability
Several years ago I worked on a payroll package developing a core engine that required an API to let third parties write calculations, validations and security gates that would execute as part of it’s regular operation.
We were a small team and I had many conversations with another developer tasked with building a payroll using the API I would provide. Some methods here, classes there, the odd helper function and I had an API and then we had a mini payroll running.
Then he showed me the code he had written and that smug grin dropped off my face. It was awful.
Perhaps this other developer wasn’t as great as I’d thought? Looking at the code though made me realize he had done the best anyone could with a terrible API. I’d exposed parts of this core payroll engine with hooks when it needed a decision. Its job was to run the payroll – a very complex task that involved storage, translation, time periods, users and companies. That complexity and context had leaked out.
Unfortunately it’s not a unique story – many API’s are terrible to use. They’re concerned with their own terminology, limitations and quirks because they are exposed sections of an underlying system developed by those responsible for the underlying system.
If you want others to have a good experience with your product you have to put yourself in their shoes. Whether it’s a UI or an API makes no difference.
You are not the user
That’s the real difference between writing the classes that form your regular implementation and those that make up your public API.
We had time to fix our payroll API. Instead of refining and polishing here and there we took the 20 or so snippets developed for the mini payroll and pruned, cleaned and polished until they looked beautiful. They scanned well and made sense to payroll developers unfamiliar with our package. When a third developer familiar with payrolls but unfamiliar with out package developed the necessary code for a fully-functional jurisdiction in record time with minimal assistance we knew we had hit our goal.
Sure implementing that new API was hard work. Instead of simple methods sticking out of the engine we had a facade over our engine but it was justified. They were two different systems for two different types of user with distinct ideas about what the system was and how it was going to be used.
Many years later I found myself on a small team of 3 people tasked with putting a brand new API on top of Entity Framework for configuring models with code the .NET world would come to know as Code First. I was determined to use my experience and avoid another complex API surface littered with terminology and leaky abstractions. Parts of EF already suffered from that problem.
So for the first few weeks of that project we didn’t write any of the code that would in fact become Code First.
Instead we decided who our user was – in this case a C# developer who likes writing code, knows LINQ and some database concepts but doesn’t know Entity Framework as people who did were already using Model First or Database First.
Then we wrote tiny sample apps and tried to find simpler and simpler ways to describe them in code. We’d often start on a whiteboard with a scenario and write the complete mapping. We’d then try and find conventions that would remove the need for most of it and then try to write succinct code to configure the rest. As the newest guy to the team I’d fight to keep EF terms away from the main API surface in order to reduce that barrier to entry and help drive adoption.
Finally we’d hit the computer and develop stub classes and methods to make samples compile and let us try the IntelliSense. This isn’t always necessary but if you want to develop a fluent API or provide lots of type-safety such as Code First’s relationship mapping it’s highly recommended.
We’d then revisit the samples later and see if they could be read as easily as they were written and figure out what problems people were likely to run into and whether we could solve them without too much noise. Sometimes this meant having more than one way to do things such as chaining the fluent methods or allowing a bunch of properties to be set (solved with an extension method class providing the fluent API) and how users could manage larger models (solved by sub-classing EntityConfiguration
We finally ended up with succinct code like this with IntelliSense guiding you along the way and preventing you from even being able to specify invalid combinations. The HasMany prompts the properties on Customer and it won’t show you WithRequired unless it is valid. In the case of Required to Required it will ensure that the WithRequired specified which end is principle and dependent. In short it guides you through the process and results in highly readable code.
Entity<Customer>().HasMany(c => c.Orders).WithRequired(o => o.Customer).WillCascadeOnDelete();
This process took a little longer but given the amount of use the API will get that time will be saved by users countless times over.
Code First went down incredibly well with both the target audience and existing EF users and inspired the simpler DbContext interface that became the recommended way of accessing EF.
I think it’s one of the nicer APIs to come out of Microsoft and .NET.
PS. Martin Fowler has some great guidance in his book Domain Specific Languages.
Some people just love shipping applications with the stupidest possible default settings.
Internet Explorer 7.0 seems to be just one such application.
If turning on the automatic phishing filter is recommended why does it default to off?
Why does IE7 feel the need to ignore your Windows setting for ClearType and implement it’s own?
If it’s the case that they want more people to use ClearType then how about turn on the setting in Windows?
Finally, my favorite – language which just screams that your language and preference is obviously inferior and you made a mistake.
You should switch to United States at ONCE!
Perhaps they might be able to change it for whilst IE7 is now released and wild at least this configuration page is up on msn.com so they could change it there…
Last night I booked some flights with your web site and must say I’m rather disappointed with the experience. We needed to book two return flights with one going out on a different day but both returning on the same flight, and ideally next to each other.
It is a little disappointing that to book two different flights that you have to book each one separately despite obviously being possible on the phone or with non-airline sites such as Amazon. To avoid booking one and finding the other not available and being left with useless tickets we decided to book each using a different computer so that we could try and make sure it went through at the same time.
Our first issue was that once you have chosen your flights there is no indication of the dates again until the payment has been processed. Other sites seem to have no problem displaying a “current itinerary” down the side at every stage yet with yours this place is instead full of such great things as “You saved £10 booking online!” in giant text and other less important details than a reminder/confirmation of what I have chosen thus far.
The next page, that of your details, then completely omits GUERNSEY as a country forcing us to choose UNITED KINGDOM. For a business that used to be called Jersey European it seems you have forgotten that the Channel Islands are not and have never been part of the UK. Would it be that hard to get it right? After all you’ve even got VATICAN CITY listed although I doubt you get many bookings from it’s residents.
The next part automatically includes travel insurance – which is of course completely unnecessary if you are booking on credit cards or have a travel policy but it there it is and switched on as default. This adds to the whole spiraling-supplements experience that seems to be FlyBe.
Also here is a “I’m a UK resident” check-box. What do I select being from Guernsey? Do I tell the truth and uncheck it or leave it checked as you forced me to choose UNITED KINGDOM as my country?
An option here lets me choose my seat for an extra £5.00. There is no indication of course that it is £5.00 PER PART not per booking so for return trip will be an extra £10. The conditions also make it clear that you can renegade without refund on this arrangement if you feel it’s not safe or that you didn’t make it to the front of the queue within the allocated check-in time.
We struggled through and elected to pay the £2.50 per-person-per-leg-per-hold-item charge. If there’s one thing that’s really annoying about commercial flights it’s the time it takes to get into your seat while people try to stuff over-sized items in their overhead lockers, other people’s overhead lockers then under the seat in front of them. With a supplement on hold baggage I can only assume it’s going to get worse.
Finally, the payment screen and one that seems okay apart from the fact that you’re about to pay for something you can’t get a refund on and there is no final confirmation as to what it is you are buying in contrast to every other e-commerce site I have ever used.
In order to ensure we both got our flights we clicked okay at the same time.
One completed, the other came back with a card error despite the details were okay. I can only assume your system was not happy about processing two different transactions with the same credit card details.
Hitting “retry” to return us to the previous payment screen led us to a page saying our booking was now invalid as that level of seat had gone and now only more expensive ones were available.
Joy, we get to do it all over again for one of our tickets.
Luckily for us we managed to get the second booking through, albeit at a more expensive price.
Using your site is like playing Russian roulette.