February 24, 2011 | John Rusk | 1 Comment As I posted recently, professionals in many fields work by having a “conversation with the situation”. What does this really mean, in software development? To answer that question, I’ve decided to share a recent design episode from a system I’m working on. I’ll try to capture the full “conversation with the situation” – both my side of the conversation, and also how the situation “talked back”. The design problem at hand is actually very small, just two user interface controls – a slider and a button – but this post is long. That’s kind of the point, to illustrate that even simple things involve a non-trivial amount of “discussion” with the situation at hand. Background I’m building a scope management tool for agile teams. This post is about one very small part of it: the portion of the user interface that controls zooming in and out. Like Word, Excel and virtually every “document” centric application, mine will have a slider near the bottom right corner to let the user zoom in and out. But unlike Word and Excel, my app suffers from two unique design constraints: The space available for the zoom controls is a square. It is much taller, but also much narrower, than the zoom controls which most other apps slot into their status bars. (Mine doesn’t have a status bar.) My app needs a really easy way for users to “toggle” between being zoomed in to see detail, and zoomed out to see the big picture. If I can’t make this easy… well I wouldn’t even want to use the app myself! My initial design sketch looked like this: My Conversation with the Situation Here’s how it unfolded as I did the coding. In the left hand column I’ve listed the actions I took. In the right hand column, I have represented the situation’s “back talk” – the unexpected things that I learned as I went along. Action Reflection/observation Part 1: Implement the Slider Began by dropping a “Slider” control into the square of available screen real estate Wow, that square is really small. It makes the slider really short.When the “+” and “–” buttons are added, it will need to be made even shorter, in order to make room for them. Wonder if I could put the + and – buttons above the slider, instead of to its left and right. After looking a bit harder at what I’ve got so far, I realise that putting them above would force the slider down, and cut into the space that I need for the button. Decide to omit the “+” and “-“ buttons, and let the slider have the maximum width available. So what about the “100%” label, where can it fit?Incidentally, why does it have to say “100%”? That’s not much use. Why not display the current value instead of simply labelling the 100% point! Try putting the current value literally right on top of the slider. Make the text grey to reduce its visual impact. That looks ugly.But hey, aren’t I working in a UI technology that supports partially-transparent controls? Yes! Can I use that? Try putting the label at the bottom, as normal black text, with a partially-transparent slider over the top. Yes. That’s nice.(And, as a bonus, it looks kind of cool when the number changes as you drag the slider.) Part 2: Fine-Tuning the Slider I run the app again, and play round with the slider. I find something I don’t like – I can drag the slider around, but then how do I get it back to 100%? It doesn’t automatically snap to 100%, so I end up with 90-something, or something-just-over-100. It’s annoying. Look up the documentation for the slider control, to see what my options are. I can make it snap to, say, multiples of 10%. That will let the user easily get it back to 100%.But, if I turn on the snap setting, then this particular slider control actually prevents the user from dragging it to any place between the 10% “snap” points. It seems wrong to have a slider than doesn’t actually slide. Come up with my own solution. Instead of using the built-in snap feature, I will let the user drag the slider wherever they like, but if they click on it, I’ll make it snap towards their click, onto the nearest 10% boundary.Takes a few lines of code. Works as expected.I’m concerned that the click functionality is counter-intuitive tho. Decide to leave it as is for now (since I don’t want to spend any longer on a what is actually a minor point). Decide to keep an eye on usability as I test the app in the future, and make changes if necessary. Part 3: Add “Auto Zoom” Put the auto-zoom button into the UI.Add the word “auto” and a basic “minus” magnifying glass. Fire the app up again to take a look. I see a problem. I have designed the auto-zoom button for cases where the document is very large (that’s when the user will need to zoom out for an overview). But my test document, which I use while running the app during development, is very small. I look at it and realise, “What does auto zoom out mean, in a document so small that you don’t actually need to zoom out”? I consider whether I might hide or disable the button on small documents. But, if you can’t see the button when your document is small, won’t it seem weird when a button suddenly appears as your document grows? How will you know what it is supposed to do, if you have never seen it before? Back to the drawing board… Can I come up with some kind of behaviour that will make sense no matter what the size the document? Something that can be always enabled…(My original thoughts involved an algorithm to compute the zoom out percentage – hence the name auto-zoom. But, the algorithm only made sense on large documents.) I decide to go for something simpler, the button will always toggle out to 33% of the current zoom level. E.g. if you are at 100%, it will take you to 33%. If you are at 120%, it will take you to 40%. I try it. I like the result. It seems easier to understand than my original idea, and appropriate (enough) for all document sizes. Part 5: Icon for the Auto Zoom But there is still a problem. The minus-in-a-magnifying glass icon just isn’t working for me. We never normally see that icon on it’s own, it’s normally paired with the plus-in-a-magnifying-glass icon. In my app, it looks confusing sitting there all by itself. In a flash of so-called inspiration, I create an icon for the button, that shows a document getting smaller (zooming out) It’s rubbish. Totally un-intuitive. (A fact that I confirm by asking my wife what she thinks the icon means.). Why so unintuitive…? I realise that the problem is simple. The icon shows the document getting smaller. But, when you zoom out by 33% you don’t necessarily see a smaller document. The document still extends to the edge of the visible screen – the only change is that there is less outside the screen.So basing the icon on document size is wrong, because the user doesn’t see the document change size. What does the user see? They see the text change size. So I make a new icon, this time showing a change in font size. Success! That feels intuitive to use. (And it passes a 30-second “spouse usability test”.) Here’s the end result: When you click the button, the app jumps to zoomed out, and the icon changes to this: Click it again, and it toggles back to the first state (with your original zoom level, whatever it was) [Update 5 months after initial posting: I have made more changes since writing this blog post. The conversation with the situation continued, even after I thought it was finished 😉 ] Done That’s it. My conversation with the situation (or my internal design monologue, if you prefer) in designing one small part of the UI. I hope it helps to demonstrate several points: We do a lot of this, when we build software. My simple example here has 14 cycles of action and reflection, and that’s just for two UI controls – and those 14 cycles don’t include the smaller act/reflect cycles involved in actually coding the functionally. In this case the coding consisted of hooking up these two controls to the rest of the UI, so they did actually make zooming happen. I did that coding as I worked, but have glossed over it in this post. Notice that, even before I started these 14 cycles, I had already done a so-called “design”. I had done gone though about 3 iterations of hand drawn sketches, finishing with the one at the top of this post. I had also designed the algorithm that would compute the right “auto zoom” level for large documents. Everything on this page happened after finishing “design”. That is normal. When a good software engineer does a professional job, he or she has a detailed conversation with the situation while they are coding. A good conversation with the situation includes asking yourself questions like, “How will the user feel about using this?”, “Is it still working out OK?”. It also includes being observant and noticing variants of the problem which were not explicitly thought about before – e.g. “What does auto-zoom mean in a small document?”. Finally, it includes responding to pleasant surprises, such as my realisation that I could solve the space problem by making the slider partially transparent. Imagine if I had not had this conversation with the situation, and had simply implemented the original design, exactly as it was. I would have ended up with something that was correct in theory, but annoying and confusing in practice. Does that remind you of anything? Most bespoke enterprise software, perhaps? 😉 FAQ Was I being too picky, doing all this for just two UI controls? Well, this example is from a personal project. In my day job, I don’t recall putting so much attention into UI design – because that is not the priority for the business customers I deal with. Instead, most of our “conversations with the situation” relate to business logic. Those conversations are both more important, and more intricate, than the example on this page. Unfortunately they’re much harder to write about because they’re so abstract. What about communication problems? Yes, in most real-world situations there may be information that falls through the cracks between the customer and the developer. This makes it all the more important for the developer to be alert to possible gaps and inconsistencies. I.e. to continue the conversation with the situation as they code the solution. In the example on this page, I am both the customer and the coder, so there were no communication gaps – and yet look how many action-reflection cycles were still required even after perfect (lossless) communication! Isn’t this just a lack of foresight on my part? The suggestion is that, if I’d had better foresight when thinking through the design, less “conversation” would have been needed during coding. Well, yes, and no. “Yes” because, if I’d had perfect foresight then the conversation would indeed have been reduced. But “no” because no-one actually has perfect foresight. All the resources I quote here, and doubtless many others too, confirm that this kind of “conversation with the situation” is completely normal and necessary for designers and other professional people. If there is anything usual about this page, it’s simply that software engineers don’t normally write down examples of their thought processes. Isn’t this just the normal feedback cycle of agile development? Again, yes and no. It is certainly part of the same concept. Firstly, the difference that I see is that the “conversation with the situation” is much more fine-grained than, say, running an acceptance test or demonstrating the software to the customer. The conversation with the situation covers lots and lots of tiny details (and big things too). For some of those details, the developer may indeed go back to the customer to discuss them. I suspect there’s a degree of experience and judgement involved in asking the customer when necessary, without drowning them in a deluge of micro-decisions. Secondly, the conversation with the situation is very much in keeping with the side of agile that Alistair Cockburn describes as “looking around, taking initiative, and doing ‘whatever is necessary’”. Finally, I would emphasise is that a conversation with the situation is almost the opposite of a blind rush to “complete” a user story as quickly as possible. Conversation is thoughtful. It may, and sometimes will, take you in unexpected directions for the good of the product. It will almost certainly result in better usability and fitness for purpose. Does it take more time, and so cost more money? Maybe, but probably not as much as you might expect. Why? Because good quality conversations with the situation, at coding time, tend to reduce the defect count later. So the conversation pays for itself to some degree, in terms of fewer problems later on. It also improves the overall value of the software, by improving its usability and fitness for purpose. After all, which is really more expensive – a $100k system that your staff hate and can’t use efficiently, or a $120k system that makes their jobs efficient and satisfying? Final Word I received some lovely feedback from a customer, after we ran a project that included lots of conversations with the situation. The customer’s system administrator said: Almost every day, another staff member asks for access to the system. Isn’t that great? A custom-built business application so satisfying to use, that it “went viral” amongst the staff. What a change from clunky systems imposed on users against their will.