Saturday, August 20, 2016

The Starbucks app update—an analysis

Reposted here although originally posted on medium

Shh. Here’s a secret. I think there’s a part of me that wants to be a hipster. It must be true because I sometimes work in coffee shops — just like the cool kids.

This morning I went to town to do some writing in Starbucks. I go there quite a lot. Enough that many of the staff know my name and my usual order. Also, for the sake of this story, enough that I have a Starbucks card to make payments and collect stars (for rewards including free drinks.) Because I’m me and because they have one I also have the app version of the card on my phone.

Here’s what happened today:

  • I entered the store.
  • There was no queue — yay!
  • Went to the counter and gave my order. (It was someone I didn’t recognize serving.)
  • I launched the app on my phone and was presented with a screen that showed I wasn’t signed in. :(

  • I quickly tried to sign in after giving them my order (Venti, vanilla, Latte if you’re interested)
  • Sign in failed.

Side note: notice the mixed use of “sign in” and “sign-in”. Don’t do that. Be consistent.

  • I go to re-enter the password but see my email address has been deleted. (It’s hard to check something that’s been deleted.)
  • I mutter something under my breath.
  • The barista at the till looks at me waiting for payment.
  • In frustration, I put down my phone and take out my wallet.
  • I hand them my card while mentioning that “the app logged me out.”
  • They say that “that’s happened to a lot of people this morning”.

I wonder how many people, at this store and across the country, have been affected.

That’s people who’ve been frustrated by the fact that what should have been a quick, simple process wasn’t.

I wonder how much it delayed people during busier periods earlier this morning. That’s individuals affected by the delay to them as they have to log in again. Also, people kept in queues longer while those in front of them struggle with the app. Was it enough for anyone to miss a bus or train? Was it enough that people left the queue early because it was moving too slowly?

Because I’m me, I wonder what had happened in the app and decided to take a few moments to investigate and see what lessons can be drawn from this.

As the people using an app are the most important factor in the UX of an app, let’s start there.
It’s not good. The experience created negative emotions towards the brand. I was made to feel frustrated and disappointed that:

  • paying for my coffee which is supposed to be simple and frictionless wasn’t.
  • I had to enter my email address more than once for no good reason. (They obviously don’t care about unnecessarily wasting my time.)

Ok, so what about the app?

My initial assumption that as the phone hadn’t been updated or rebooted since I last used the app the app must have been automatically updated.

A quick check and a helpful app store notification shows that’s the case.

I have automatic updates turned on because I want to get the latest versions of apps as they become available.

Having auto-updates turned on is good for the publishers of apps too. When they release updates they want people using them as quickly as possible so they don’t encounter bugs that are fixed and can take advantage of new functionality. You don’t want to spend time creating an updated version of your app only to have no one use it. (This is why, in my book, I claim that update notification is the most important feature that every app should have.)

Ok, so there was a new version that was installed.

Now let’s see about that sign in experience.

It looks like a regular sign in screen but let me poke at it a little.

“Username or Email Address” they appear regularly together on registration and sign in forms but they’re not always both needed. Well, email addresses are normally needed. But usernames? Not so much. As a credential for identifying myself to the service, an email address has the dual benefit of being unique and a token for contacting me outside of the app/service. I can’t think of any good reason for needing a username for my Starbucks account. If Starbucks want to address me they should use my actual name (which I told them when registering.) If this was an app that would allow me to connect with other people who use the app then a username would be a good, simple way of identify different people. For instance, on Twitter I have the username@mrlacey. You can use this to find, mention, or message me. It’s much easier than trying to differentiate me from all the other Matt Lacey’s in the world and it doesn’t make anything potentially private about me public. But I don’t communicate with other people who are using the Starbucks app. So, why do I need a username?

Maybe I can create a username to make it easier to sign in.

But (I think) this is only the second time I’ve logged into the app. Why add something I need to remember to perform a task I rarely have to do? I don’t know what my username is. I can probably guess but don’t want to have to. I know what my email address is so why wouldn’t I always use that?

If I’ve forgotten my Username there’s an option for that.

If I’ve forgotten my username I can use my email address to recover it. This is redundant!

The flow for recovering a forgotten username is:

  1. Select ‘Forgot Username’ option
  2. Enter email address
  3. Go to email client and (when the email arrives) retrieve the username
  4. Return to the app and enter Username and password to sign in

Or you could just ignore the username all together and log in with email address and password. The above flow requires entering them both anyway. It just adds a lot of extra, unnecessary steps too.

“Fun” side note: While writing this I went through the ‘Forgot Username’ flow as I was curious what my username was. It turns out it’s the same as my email address. There’s an acronym for this which starts with ‘W’ and ends with ‘F’.

What’s my username good for? I’m not sure.

While I’m here, let’s look at the forgotten password flow.

What the what!?
I need to enter my email address and my “Username or Email Address” to recover my password. So, can I enter my email address twice? Or is the label on the second text entry wrong? Either way, I’m starting to have serious questions about how or if this was tested. And the process that led to this situation.

Maybe the username exists as a way to try and prevent the malicious validation of email addresses registered with the system by deterring the automated, brute force entry of values in the password recovery process. If that’s what’s happening, it’s trying to solve the problem in the wrong way and is undermined by the username recovery option.

Despite what you might be imagining based on the above I manage to correctly sign in with my second guess at my password.

Now I’m logged in and using the app again, what’s new in this version?

A quick scan of the different parts of the app and I don’t see anything obvious.

I wonder if there’s any details listed in the app? ‘Settings’ is where I’d normally expect to find this (if it exists.)

Sadly, there’s just a version number. I don’t know what version I had before so this doesn’t tell me much but it looks like a small update (based on the number) so I wouldn’t expect much to have changed.

Let’s see if the store listing can tell me any more about what’s changed?

It can tell me something, but it seems little has changed. Just small changes relating to store selection and the displaying of maps. These are not features I use. This means I went through all this and got nothing from it apart from something to write about in this post.

Oh, they say “Thank you for all your feedback.”

Give all the above, what can be learned from this experience:

  1. Don’t force a person to re-authenticate with an app after it has updated.
  2. Don’t let an update cause saved data (including access tokens or cached credentials) to be lost.
  3. There is no functional or security related reason to delete an email address after a failed login attempt. It only ever creates more for the person using the app to do.
  4. Only require people to create a username for your service if they’re going to use it to communicate with other users of your service.
  5. Be sure that the labels for what people can or need to enter are correct.
  6. Use terms and labels consistently. (e.g. Don’t mix use of “sign in” and “sign-in”.)
  7. Don’t add arbitrary complexity on the assumption that it will help improve security.
  8. Test your registration, sign in, and credential recovery options thoroughly.(If you’re not confident in doing this then you could ask or hire me to help.)
  9. When an app is used for the first time after it has been updated, acknowledge the update and provide access to details of what’s changed.
  10. Make it easy (and obvious) for the people using the app to submit feedback.
  11. Bonus: I can tear apart and find issues with any app. ;)

The reason I write posts like this is because I don’t want to have experiences or use apps like what’s detailed above. I don’t just want to complain but help people learn how to identify and fix such issues. If you can see other people making mistakes and learn from them it will, hopefully, help you avoid similar issues in future.

Monday, August 15, 2016

Another reason your custom font may not display in a Windows app

Here's something that took me hours to uncover. I document it here to hopefully save someone else some time in the future.

Using custom fonts in apps is great. It can add some visual interest, draw attention to some specific text, serve as a way of handling multiple images or icons, and it can enable the consistent representation of brand identity.

There are a few gotchas for getting the font to display correctly in a Windows app, such as having the wrong build action, or trying to use a file which does not support embedding and these are quite well documented in various blog posts around the web.
After much head scratching, I finally found the cause of another reason a font may not display properly.

Here's the issue summed up in one image.

Here's what's going on.
When a custom FontFamily is specified it is done in two parts. The first is the name of the file and the second is the name of the font family. It should be quite simple and if you add the font to your project you can use Visual Studio (or Blend) to select the font from the dropdown list and it will set this for you.

Here's the gotcha.
On Windows, there is a way to specify multiple font families in a single file and a way to specify which is preferred. It seems the VS/Blend font selector does not handle preferred families correctly. Specifically, it appears to use the family name regardless of whether a preferred family is defined. I was using (as in the screenshot above) a corporate font that contained a single family but had a different value specified for the preferred family name. For the font to be correctly displayed it's necessary to use the preferred family value but this is not what was set by the tool. It's simple enough to change this in the XAML if you know what's up.

Identifying this was a challenge.
I normally use TTFEdit to explore the internals of font files but this doesn't have the clearest of interfaces. While investigating I discovered dp4 Font Viewer and this did help make it easier to see some of the less obvious properties of the file.

There's probably a little more subtlety to the actual issue and I'm not interested enough to read the TTF spec to see the full extent of what could be going on but hopefully, this is enough to help you if your font is not being used and you can't see why not.

Friday, August 05, 2016

What's next for apps? [361Podcast S13E07]

In writing my book and with some other writing I've been doing, I've been thinking a lot about what comes next in the world of apps.

To broaden my thoughts and opinions on the subject I reached out to Ben, Rafe, & Ewan of the 361Podcast with some questions to get their thoughts. They took a whole episode to respond to my questions and it was published last night.
Go and have a listen at

While, or before, you do here are a few notes I made while listening.

This is what the future looks like:

The norm will be for there to be a variety of interactions with a company/product/service across different devices.

The challenge will be to combine micro-interactions in a way that doesn’t feel fragmented, even though it’s disparate.

The way we think about apps will change.
There will be a move from the idea of siloed or contained experiences.
Apps can become the container and distribution process for functionality. They are likely to become less about the direct visual presentation of the interaction.

The current options for integrating with a mobile OS are a start but deeper integration with virtual assistants (Siri, Cortana, Alexa, etc.) are likely to be more important in the future.

There are lots of uncertainties about future virtual assistant (VA) interaction:
  • How will service integrations be configured? Will it need some custom UI?
  • How will service integrations be discovered? Not everyone can rely on being recommended by a VA.
  • What does this mean for the relationship between consumer and service provider when there’s another party sitting in the middle of all interactions?
  • If this becomes the standard way for consumers to interact with other services are there potential regulatory or anti-competitive issues to control what a dominant VA can or can’t do?
  • How transparent can or should such interactions be? Let’s consider wanting to buy some toothpaste.

“Siri, order me some more toothpaste.”
It seems a simple request but it’s a highly loaded task and full of uncertainty and possible variation.
  • What make and size of toothpaste?
  • What if that’s not available?
  • Where from?
  • What if they don’t have it?
  • Does it matter how much it costs? Even if it’s gone up since you last ordered it?
  • How will you pay? What if you have credit with one store but it costs more than
  • Does it matter if it comes from a retailer you’ve not used before?
  • Rules about what you should get from where based on cost and availability can soon get complicated. Do you really want to preconfigure all this for something as basic as toothpaste? Not everyone can afford to ignore things like price
  • How much information will be given to the company that fulfills the order? Does it matter if one retailer wants more than another? How will this be managed and controlled?

If you’re Amazon/Alexa a lot of the complexity is avoided. If you’re another retailer (even if really big) but don’t own the infrastructure of the VA there’s a lot more to think about.

Thinking about discovery, and commission on sales, maybe the VA or OS will monitor what you do on the device and make suggestions for things that might be of interest to you.

Data privacy is a big potential issue here. How much information will be shared with an “app”? And how much information will the companies behind the OS and VAs now have and what can they do with it?

The biggest issues for VAs and apps that will provide functionality is that of context.

Quick side note. I know context is important. I spend 82 pages on it at the start of my book ;)

As we ask more of the services behind apps they need to know more to be able to make the right choices and suggestions.

Creating great, refined apps will be the key to success and differentiation. As experiences won’t be able to rely on a strong visual identity to reflect their brand they will have to focus more on the quality of the user experience to maintain brand loyalty.

There will be a greater need to avoid assumptions about the people who will use the app and create something that is genuinely “consumer-centric” and tested with and by the real people who will actually use the app.
It’s not just the people using the app that it’s going to be increasingly important to understand. A deep knowledge of the devices, operating systems, and platforms that people use and directly interact with will become increasingly important for creating great, intuitive experiences.

Thursday, July 28, 2016

Book update

3 little updates on the book I'm writing.
  1. The title's going to be changed (slightly) - official announcement shortly
  2. It's half price today (July 28th 2016) - go to and use code dotd072816au - (if you're reading this in the future there's a different discount code here)
  3. It's half finished - I know the MEAP* still only shows 4 of 14 chapters available but I'm working hard to get you more chapters ASAP.
*MEAP - Stands for Manning Early Access Program. Think of it as a cross between the in-progress part of Leanpub and a traditional publishing process. You get the advantage of access to chapters while it's still being written but with the benefits of an editorial team helping improve what I write.

Tuesday, July 12, 2016

11 things you're doing wrong when testing code

Most developers I meet aren't big fans of testing. A few are but most don't do it, would rather not do it, or only do it begrudgingly. I love testing and happily spend more time on tests than writing new code. I'd argue that it's because of the focus on testing I can spend less time writing new code or fixing bugs and still be very productive.

If you're unsure of writing tests or don't do a lot of it the following will point you in a better direction.

  1. Not doing it. It's an easy trap to fall into but one without an excuse. Make plans to start adding tests to the code you're working on now and add them to future projects from the start.
  2. Not starting testing from the beginning of a project.
    It's harder to go back and add them in retrospectively and may require architecture changes to do so which will ultimately take longer for you to have code you can be confident in. Adding tests from the start saves time and effort over the lifetime of a project.
  3. Writing failing tests.
    The popularity of the TDD methodology has brought the idea of Red-Green-Refactor to the software testing world. The is commonly misunderstood to mean that you should "start by writing a failing test". This is not the case. The purpose of creating a test before you write the code is to define what the correct behavior of the system should be. In many cases this will be a failing test (indicated in red) but it may be that this is represented by an inconclusive or unimplemented test.
  4. Being afraid of unimplemented tests.
    A big problem in software development is the separation between code and any documentation about what the system should actually do. By having a test with a name that clearly defines the intended behavior that you will eventually implement, you will get some value from a test even if how it will be written is currently unknown.
  5. Not naming the tests well.
    Naming things in software is famously difficult to do well and this applies to tests as well. There are several popular conventions on how to name tests. The one you use isn't important as long as it's used consistently and accurately describes what is being tested.
  6. Having tests that do too much.
    Long complicated names are a good indication that you're trying to test more than one thing at once. An individual test should only test a single thing. If it fails it should give a clear indication of what went wrong in the code. You should not need to look at which part of the test failed to see what the problem in the code is. This doesn't mean that you should never have multiple asserts in a test but that they should be tightly related. For instance, it's ok to have a test that looks at the output of an order processing system and verify that there is a single line item in it and it contains a specific item. It's not Ok to have a single test that verifies that the output of the same system creates a specific item and it's logged to the database and it also sends a confirmation email.
  7. Not actually testing the code.
    It's common to see people who are new to testing creating overly complicated mocks and setup procedures that don't end up testing the actual code. They might verify that the mock code is correct or that the mock code does the same as the real code or just execute the code without ever asserting anything. Such "tests" are a waste of effort, especially if they exist to only boost the level of code coverage.
  8. Worrying about code coverage.
    The idea of code coverage is noble but often has limited actual value. To know how much of the code is executed when the tests are run should be useful but because it doesn't consider the quality of the tests that are executing the code it can be meaningless. Code coverage is only interesting if it is very high or very low. If very high it suggests that more of the code is probably being tested than will bring value. Very low code coverage suggests that there's probably not enough tests for the code. With this ambiguity, some people struggle to know if an individual piece of code should be tested. I use a simple question to determine this: Does the code contain non-trivial complexity? If it does then you need some tests. If it doesn't then you don't. Testing property accessors is a waste of time. If they fail there's something more fundamentally wrong with your code system than the code you're writing. If you can't look at a piece of code and instantly see everything it does then it's non-trivial. This doesn't just apply to code as you write it. If revisiting code at any point after it's been written then it needs tests. If a bug is ever found in existing code that's confirmation that there weren't sufficient tests for the complexity of that area of the code.
  9. Focusing on just one type of testing.
    Once you do start testing it can be easy to get drawn into just one style of tests. This is a mistake. You can't adequately test all parts of a system with one type of tests. You need unit tests to confirm individual components of the code work correctly. You need integration tests to confirm the different components work together. You need automated UI tests to verify the software can be used as it's intended. Finally you need manual tests for any parts that can't be easily automated and for exploratory testing.
  10. Focusing on short-term tests.
    The majority of the value from tests is obtained over time. Tests shouldn't just exist to verify that something has been written correctly but that it continues to function correctly as time passes and other changes are made to the codebase. Be they regression errors or new exceptions tests should be repeatedly run to detect problems as early as possible as that will mean they are quicker, cheaper and easier to fix. Having tests that can be automated and executed quickly, without variation (human error) is why coded tests are so valuable.
  11. Being a developer relying on someone else to run (or write) the tests.
    Tests have very little value if not run. If tests can't be run then they won't be and so bugs that could have been caught will be missed. Having as many tests run automatically (as part of a continuous integration system) is a start but anyone on a project should be able to run any tests at any time. If you need special setup, machines, permissions, or configurations to run tests these will only serve as barriers to the tests being executed. Developers need to be able to run tests before they check in code and so they need access to and the ability to run all relevant tests. Code and tests should be kept in the same place and any setup needed should be scripted. One of the worst examples I've seen of this being done badly was on a project where a sub-team of testers would periodically take a copy of the code the developers were working on, they'd modify the code so they could execute a series of test that developers didn’t have access to on a specially configured (an undocumented) machine and then send a single large email to all developers indicating any issues they'd found. Not only is this a bad way to test but it's a bad way to work as a team. Do not do this.
    Having code that executes correctly is part of what it means to be a professional developer. The way to guarantee the accuracy of the code you write is with appropriate tests that accompany it. You cannot be a professional developer and rely solely on other people to write tests for and run tests on your code. 

If none of the above apply to you congratulations. Carry on making robust, valuable software.

If some of the above do apply to you, now's a great time to start doing something about it.