Thinking about the user, even in the details

User experience is a term we hear a lot as developers, but it can mean different things depending on the context. We discuss a recent project where decisions around which HTTP status code to return was focused on improving the user's experience and trust in the application.

Joel Clermont (00:00):
Welcome to No Compromises, a peek into the mind of two old web devs who have seen some things. This is Joel.

Aaron Saray (00:08):
And this is Aaron.

Joel Clermont (00:16):
Aaron, let's get a little philosophical here. Why do we do what we do? Like, when we're writing code, why do we do that? And I know you have opinions on this, so I'm just setting up a question to hear your stream of wisdom coming out of your mouth.

Aaron Saray (00:34):
Well, at the very core of it we do this work, programming, for the user who's going to consume the work in its final form. So there's a lot of times when you can get confused because you think maybe... I mean, because there's some conflicting goals that we have. Getting work done, get better quality code, more beautiful ways of doing stuff-

Joel Clermont (00:55):
Sure, yeah.

Aaron Saray (00:55):
... learning new things. There's all these different things where we have to balance, but in the end results we're no different than tech support, in a way, because we're providing a support for the user, support for the business, all those different things. The business has a business way of do... Like, they figured out how to make money and pay us and do all these things. In order to do that, we have to support them by making the product that they're asking for.

Joel Clermont (01:19):
Okay. Yeah, fair enough. And as you were saying that, I was even thinking too. The user consuming, or using the thing we built, is maybe not even the person that's paying us to do it, right? Like, there's kind of a level of indirection there, but it's good to have that in mind when building the product.

Aaron Saray (01:39):
Yeah. A lot of the decisions that you make, I think are more important to focus on the user experience. I'm not just talking about like a nice box here or like pretty colors, I'm just talking the holistic user experience. So, understanding what's happening, how that user might react to a success or an error. All these different things and planning on what would a brand new user, or even a power user, or understanding your different types of users, what would they expect out of something like this?

Joel Clermont (02:06):

Aaron Saray (02:06):
And knowing that, for the most part, they don't have the insight into the internal process. Like, if you give an error they're not going to know what step of the process the error came from unless you told them. You know, all these different things like that. So, understanding as you go through that process that you have to be a little bit more verbose to people because they're on the outside. And that's really who we're serving when we're building software, it's these people that can't see our software.

Joel Clermont (02:30):
So, you're saying I should never return a 429 to somebody in the browser and they'd be like, "I don't know what that is, I don't know what's happening." Like, "I thought I was doing good. I know what a 404 is, but... " That's a good point. I had an example in mind, maybe we kind of could use it to investigate this a little further. And it does actually have to do with error conditions, and status codes, and things like that.

Aaron Saray (02:54):

Joel Clermont (02:54):
So I'll set it up first without going too deep into the specific thing we were building. But let's just say you can apply to a job listing but a job is going to expire at some point, right? So, what if I've bookmarked that job, I want to come back to it and I want to apply to it tomorrow, and in the meantime it's expired? So when I was working on this feature, at first the internal way we built it using Laravel, I think it was in a form request method, it would return a 403, right? Like, "Oh no, you can't create a job application against that job because that job is expired." That's a business rule we enforce. But then I thought about it, it's like 403 really isn't... First of all, user is not going to know what to do with that because there's nothing they can do with that, and it's just a little jarring. And so-

Aaron Saray (03:49):
Well, even as a developer too, if I had some API and I'm interacting with that I don't understand what that 403 really is because I'm just like, "Well, I thought I had access to this job listing, now you're saying I don't have access to the job listing?"

Joel Clermont (04:01):
Yeah. "I had access to it yesterday, what happened?" What would you do in that case? Because I know what I did and but I'm just kind of thinking it through as a thought experiment. What would be a better use case or UX experience for the person getting that to deal with?

Aaron Saray (04:20):
Well, that feels like a trap. I don't know.

Joel Clermont (04:26):
Aaron, I want you to take this thing I thought deeply about for like a whole day and I want you to solve it on the spot, right now.

Aaron Saray (04:31):
Well, what did you do first of all?

Joel Clermont (04:34):
Okay. So what I ended up doing was doing a 302, so a redirect. And I coupled that with a banner message explaining what had happened. So this wasn't an API, just to be clear.

Aaron Saray (04:49):

Joel Clermont (04:49):
In the first iteration of this, it was a browser driven UI and so it would... maybe they were on a list of jobs or they had a bookmark or something. When they clicked through to it and if it expired in the meantime, it would just bounce them back to the list with a banner saying that job has expired, or that job is no longer available. It was something generic, you know? Because even it didn't mention expiration, because again, it's a business rule that a user doesn't care about. But it's no longer available, sorry.

Aaron Saray (05:20):
Okay, that makes sense. And then what about... So you said it wasn't an API, how would you handle something... Because I can understand that, you know?

Joel Clermont (05:28):

Aaron Saray (05:28):
Just not saying 403 or whatever, but actually handling those use cases. I think a lot of Laravel developers actually can understand that and they've done that. We get into more philosophical debates on where should you put that logic and how should you do that?

Joel Clermont (05:44):
Sure. Right, yeah.

Aaron Saray (05:44):
Whether it's part of a form request and then you redirect with an error. But what about when it's something like, I brought up kind of like an API and you can't really redirect them to somewhere?

Joel Clermont (05:54):
Yeah, that is trickier. And I'll just share before I answer that to give myself time to think. I also considered a 404 because the job isn't there. And maybe in the API scenario, that would be a little more useful because the client consuming the API knows how to handle a 404, and the way it handles that would probably make sense in this case. But, yeah, just returning to 403, a client might bounce them to a login page or show some generic error. I guess it depends on the quality of your API client. But if it's out of our control, I think I might actually opt for the 404 in an API case. And even for some of those 400 type errors, you can include a body, right? You can include more information that hopefully the API client would pass on to the user.

Aaron Saray (06:49):
Yeah, Laravel has built-in things on some of the error generation now that you can kind of say, in a middleware or even a form request, or something like that. Like, return this type of response so you don't have to just throw an error. It can return like a 403 response with some content. And so, yeah, you kind of went down that whole thing as what I was going to say is I'm a huge proponent of having an error data object, in a way as well, from an API. So when you send these, because we're only talking about status codes, but I'd say sending that error message as well is probably pretty useful.

And I guess one quick tangent, I'm going to go on just a side thing, it's kind of really kind of not. I like to also, because, again, we're focusing on the user, probably the human, I like to write messages that make sense to a human or have a lot of context. I actually disagree with your comment you made earlier that the expiration doesn't matter, it's just not available or whatever. You said that's an internal business rule. I would include that in the message in saying like, "This job posting has expired and so it's no longer available," because otherwise I just think it's a little bit more jolting for a user saying, "Why is it just gone? I don't trust this site, they're always just deleting stuff."

Joel Clermont (08:05):

Aaron Saray (08:05):
Versus saying, "Oh, I guess I didn't know there was expiration. Some of these expire." Maybe you've then encouraged the user to move faster because they know now that things expire. Versus an unsettling thing, which is things just get deleted randomly.

Joel Clermont (08:20):
I was just thinking if only the person who reviewed this code would've suggested that at the time, I wonder who that was.

Aaron Saray (08:26):
Well, maybe the person who's reviewing this code wanted to make sure the project was done on time and so make little concessions. I mean, who knows who we're talking about?

Joel Clermont (08:34):
Yeah, this is hypothetical.

I know one of the things you really admire about me, Aaron, is my excellent memory.

Aaron Saray (08:48):
Oh, yes.

Joel Clermont (08:48):
I never forget things. You tell me something and it's in this steel trap, it's there for good.

Aaron Saray (08:56):

Joel Clermont (08:58):
So it might surprise you to know that there are certain foods I forget I like. Where we'll be ordering food or trying to agree on something and I'll be like, "I don't want that." And then my wife will say, "No, you like that." I'm like, "I do?" And then I get it, and I'm like, "Oh, yeah, I do like that." So, like the two examples.

Aaron Saray (09:18):
Well, you're like that old couple in the restaurant where he is like, "What should I get?" And she points it there, "Get this." "Oh, okay I'll get that. I love biscuits and gravy."

Joel Clermont (09:29):
I do actually. So one of them is pecans. I love all nuts, so why wouldn't I like pecans? But at the store I'm like, "No. Get cashews or macadamia nuts." And she's like, "You like pecans." And then I get them, I eat the whole can. I do like them. The other one is a pizza topping, artichoke hearts. I like them, but whenever she suggests them I'm like, "I don't want that." So, Aaron, does that surprise you or do you have any foods that you forget you like?

Aaron Saray (09:18):
Well, that doesn't surprise me about you. But I'll tell you a thing that you may not know about me.

Joel Clermont (10:00):
Okay, and I'll forget it later.

Aaron Saray (10:02):
Yeah. And I'm saying it up to the whole world now, so you can... This is true but it's embarrassing. But I also say this because just in case there's anyone else who does this so they can feel not alone in the world.

Joel Clermont (10:14):

Aaron Saray (10:14):
Many years ago I had a very similar sort of process in my brain. I was like, I would buy things and forget I liked them, or... It started out with something, I think it was like beef jerky. I ended up buying the same beef jerky over and over that I didn't like. So I would buy it and I would-

Joel Clermont (10:32):
Oh, you didn't like it?

Aaron Saray (10:33):
... like horrible. Yeah, I didn't like it. I'd throw it out and then like two, three months later I'd buy it again because it just was like, "Oh, what's that?" I'm like, "What's wrong with me, man?" Or, other things like sometimes I want a special treat but for some reason now I'm hungry. I don't want to go to the grocery store when I'm hungry, but I want to get something special but I don't remember what I like now. So I'm just, "Oh, hungry."

Joel Clermont (10:53):
Too hungry.

Aaron Saray (10:54):
So I ended up, it started really small but now it's grown huge. Is I have a list of things I like and things I don't organized into topics.

Joel Clermont (11:02):
Oh, that's...

Aaron Saray (11:03):
Like, household related stuff, foods, drinks. Because I find out I go through a lot of stuff and so I have a list of teas I like, brands and types, and teas I don't. Same thing with like... Yeah, maybe I'm weird but I replace my pillows every three years or something. And I started realizing like, "Oh, I better keep track of the brands and types of pillow I like. So that in three years from now," because maybe you couldn't find them on Amazon anymore or whatever, "I bought them at Bed, Bath and Beyond." And it's the same thing as like, okay... There's one that I made use of the other day which was canned gravy. There's a lot of brands of canned gravy.

Joel Clermont (11:42):

Aaron Saray (11:42):
Most of them are atrocious, there's like two or three that are good. And you don't want the crappy canned gravy when you want to have some gravy.

Joel Clermont (11:48):

Aaron Saray (11:48):
So, yeah, I keep... So it's not weird to me that you'd forget these things because, I guess, I must do too. So I keep a list of things I like and things I don't, and I hope no one ever sees it.

Aaron Saray (11:58):
When we're not recording podcasts, we're updating content on

Joel Clermont (12:09):
Head over there, and we have a couple free books that you can download with Laravel tips and tricks that'll make your applications better. It's

No Compromises, LLC