Monday, April 30, 2012

What Does a Browser Actually Do?

I do a lot of my development using web technologies. Much of my code winds up running in a browser (or driving something that runs in a browser). Most of the time, the browser is just a convenient delivery mechanism. I write a few lines of code, and the web browser interprets them and does all sorts of great layout and rendering stuff.

And anyone who has watched me try to work with PhotoShop knows that it's a really good thing that the browser is handling the rendering instead of me!

But to get back to the point, I can write perfectly find HTML, CSS, and JavaScript and the browser will handle it just fine most of the time. Sometimes, though, mysterious things happen. Sometimes a page will simply not finish rendering. Sometimes parts of it will be really slow. Sometimes layouts won't do what I meant for them to do. And then I have to start debugging. We can start with the simple things: looking for JavaScript errors, checking load order, etc. Once it gets more complicated, though, we have to start understanding what's going on. What is the browser actually doing with our code?

I found this fascinating - and long - article describing how modern web browsers actually work. An Israeli researcher spent a whole lot of time looking at browser source code and reading published works on browser internals, and wrote up a summary. It's a must-read for any web developers out there.

For web developers, the browser is a tool. A hugely powerful and important tool. And the way to get the absolute best out of that tool is to really understand it. Knowing how your tool works will make debugging easier and great new features possible.

Monday, April 23, 2012

Happy Errors

I'm working on a system right now that interfaces with a third party system. That third party system is an aggregator, which means it interfaces with a number of other third party systems. You can think of it as a giant game of telephone.

Unfortunately, like most games of telephone, things get a little.... messy... along the way. What starts at one end as a useful message often comes out garbled. For example, "This account is disabled" comes across as "Unknown error".  (thanks!)

Now, most of the time, we can figure out what the error means in the end. Usually, we end up calling the originating system and saying, "what do you see?" We've built ourselves an informal table of likely translations.

There's one error, though, that we can't figure out:

Error 75: "Thank you for using "

That's the most cheerful error message I think I've ever seen. I'm not sure it's even an error! We haven't really figured out what to do with it, but boy did we at last get a laugh out of it.


Wednesday, April 18, 2012

User Interfaces Aren't Just For Pretty

I was reminded this morning that user interfaces aren't just about being pretty or looking good. They're about putting the right information in front of the user at the right time. Good user interfaces are also about helping users understand the meaning of that information in context: How has it changed? Is this a normal value or not?

Bad user interfaces can and do lead to disasters. If you're lucky, your user interface is to a web site and the disaster is that you lose users. If you're unlucky, your user interface is to some life-critical piece of equipment and someone dies. (Don't roll your eyes, it's happened.)

One of the more famous user interface disasters is Air Inter Flight 148, which crashed in 1992. Why? Bad user interface played a part. The pilots thought they were entering a rate of descent and they were actually entering vertical speed; 3.3 degrees down became 3300 feet down. That's an important distinction when a mountain is in your path. The problem was a bad user interface; it didn't show the pilots what they had actually entered, and they didn't figure it out until it was too late.

It's easy to talk about the user interface as the "making it pretty" step. And user interfaces can be pretty. They also need to be functional. Aim beyond "has all the data" and shoot for "conveys information". You users will thank you for it, even if no one dies.

Monday, April 16, 2012

Don't Push Always

I'm a manager. My job basically consists of getting other people to do things. Preferably they'll do the right things with reasonable timing. There are about a zillion ways to accomplish this, and I'm not going to get into too much detail about many of them here. Instead, let's look at one small detail: pushing.

We push people frequently. They'll say, "well, that'll take three days", and we say, "do you think you could do it in two?" They'll say, "I know we can do it in six months", and we say, "what can we take off the table so we can ship something in three months?" We often phrase it a bit less crudely than that, but the underlying message is there.

Now, there's nothing inherently bad about pushing a team. There's nothing wrong with saying, "what are the tradeoffs to get something faster/better/stronger?" There's nothing wrong with saying, "can we do better?" Burning out your team is almost always a terrible idea, but pushing doesn't have to mean burning out. It can mean trading off additional team members or money or features in favor of time.

But.

Sometimes pushing gets to be a habit. Every estimate is met with "how can we do that faster?" Every problem becomes something to throw people at. Every feature is something that gets cut to the bone in favor of shipping. It's pushing the team just for the sake of pushing. Even if you're not burning people out, they're still going to resent it. No one likes to be pushed all the time.

Don't push unless there really is a need to do so.

Time isn't always the most important thing. Sometimes there's plenty of time. Sometimes the feature is more important than time. Or keeping the team together is more important than time. Or the security implications or deployability is more important than time. These are all legitimate decisions.

Save the pushing for when you really need to push. Don't push just because you can.

Friday, April 13, 2012

"Sluggish"

There are some problem reports that are guaranteed to strike fear into the hearts of developers, testers, and support engineers alike. The top one of these:

"It's sluggish."


(Don't panic don't run away don't toss an innocent bystander in front of the problem.)

This is the kind of problem report that is probably going to end up being a bit angsty. But why is it so scary?

  • It's completely subjective. What the reporter sees as "sluggish" might seem "just fine" to you (or someone else).
  • There's no clear goal. If it's sluggish (read: too slow), then what's "snappy"? What is fast enough? How do we know we've fixed it?
  • Even if you get it fast enough, it's still pretty high risk that there's an environmental factor on the user's end that will make it continue to appear slow. For example, if their internet connection is slow, then it might still appear sluggish, no matter how fast we make our web application.
So, given that we've decided not to panic or throw innocent team mates at the problem, how can we handle these types of problem reports?
  • Get more information. Understand what "sluggish" means to the user. Asking them is surprisingly effective.
  • Discuss what you did rather than what the user will see. Since we don't get to say it's fixed - the customer does - we should say that it's better or that we've seen improvements.
  • Establish open lines of communication. This isn't always possible, of course, but if it is, then it both helps the user engage with you and makes the whole interaction friendlier.
Certain problem reports are scary. But they're handle-able. So don't run away, handle it.

Thursday, April 12, 2012

Decision Safety Net

Yesterday I was giving a talk for the STP online summit for Test Management. My talk was on getting your testing MBA and it was basically about how testers can and should consider the needs of the business, in order to work more effectively with business groups.

One of the questions I got was about what decisions it is appropriate for a test manager to make. The question actually applies to all engineering managers - test managers, development managers, support managers, etc.

First, a bit of background:

During my talk, I noted that there is some prominent thinking in the test field that testers and test managers should not make decisions. They are information providers and advisors, but they are not equipped with sufficient information to make decisions. The classic example is that the test manager shouldn't be able to block a release, because it's possible that releasing early with a huge bug is better than releasing later with no bug due to some contractual obligation with a client or potential customer. In that case, closing the deal by shipping (on, say, the last day of a quarter) might be more important than fixing the issue that would cause the test manager to say, "don't ship!"

My response to this is that there is a kernel of validity but that the overall message of "don't make a decision!" has gone too far. It's perfectly okay for test managers or development managers to make some decisions. There truly are times when the test manager or the development manager should be making a decision, and where not making the decision is simply a cop out.

And now to my actual point:
There is a decision safety net. The business will not allow you to make a decision you shouldn't be making - at least, not more than once.

That's the rub. NO ONE has perfect information in any business. The development manager doesn't know everything. The product manager doesn't know everything. The CEO doesn't know everything. Everyone knows some of the information that influences a decision, and no one knows all of it. That's the point of good management - to provide a safety net that maximizes the available information for someone to make a decision. Product managers do not have a monopoly on maximizing information; technical managers can do it, too!

So don't be scared of making a decision. And don't be scared of asking for opinions or offering opinions. Most business decisions are made by one person after being influenced by a lot of people. That's the job of a manger. Don't fear it. Embrace it.

Monday, April 9, 2012

Tips for Working With Others

Many of us software engineers work somewhat in isolation. Yes, most of us are on teams and yes, most of us are working in the same code base as other engineers. However, code bases contain thousands of lines of code, with dozens or hundreds of modules (or classes or files or whatever). The truth is that most of us kind of work off on our own most of the time.

For example, I have one project where I spend most of my time working in the reporting module. There are about 8 other engineers on this project, but I'm almost always the only one working on reporting. In the sense of the overall code base, I work with the rest of the team - it all gets combined together and deployed together. At the module level, though, I don't work with others very often.

Contrast that with another project, where I'm writing some Selenium tests for a client. There's another engineer here writing Selenium tests as well. This is a big project, so he and I have divided it up, but we're still both working within the same modules. I'm working on test A while he's working on the Page object, and I'm working on the Page object while he's working on test B. At the module level, we're working quite closely together.

This kind of close collaboration is a lot of fun; when it goes well you get a whole lot done quickly, and you can use each others' work to accomplish a lot quickly. It's also really easy for this kind of project to go poorly, for it to end with shouting and tears and a whole lot of deleting of code. So, if you ever find yourself in a situation where you're doing something like the Selenium project I'm working on, there are some things you can do to make it go a lot better:

  • Update your code often. git fetch or svn up frequently - every time you finish a small task. This will make sure that ya'll don't get too far apart, and will help prevent merge problems.
  • TALK. Talk about what ya'll are going to do frequently. Mention what you're doing. Describe what you're going to do next. You'll spend less time duplicating each others' effort and more time using each others' helpers.
  • Keep your checkins tiny. Don't check in dozens of files and hundreds of lines of code. That's just asking for a merge problem. Check in small changes, and remember that the "wip" convention in commits is a valid choice.

It can be a great joy to work together  - even on the same code - with someone, as long as you're careful about how you do it.

Thursday, April 5, 2012

In No Way Unusual

I'm sitting in a co-working facility and listening to a couple of engineers behind me. They seem to be working on an application in Rails that involves doing role-based security. I'm not sure exactly what the application does, but they keep saying things like: "Well, admins can see every user's profile. And members can see the profiles of other members of the same group. And guests can see only profiles marked as public." All in all, it seems pretty straightforward. I don't know Rails personally, but my understanding is that it's just fine for stuff like that.

But about 5 minutes ago, the conversation took a bit of a scary turn.

Developer A: "Well, I had to do this weird hacky thing to make this role see this object."
Developer B: "Hmm... but we're using devise" (a common Rails authentication solution)
Developer A: "And then once I did that, I had to do this other weird thing, and it doesn't really want me to do it, but I managed to coerce devise into letting me set this attribute here. It's all kind of brittle, but it seems to work."
Developer B: "Hmm..., but we're using devise"

I'm with developer B on this one.

The minute you say, "had to do this hacky thing" when you're not doing anything unusual, you've got a massive code smell. As long as what you're doing is within the opinions of the tools and framework you're using, then you should be able to do it without resorting to hacks, coercion and bypassing the very framework you're trying to take advantage of. Role-based security, by the way, is well within the bounds of what the devise framework can handle (promise).

And that's the overall lesson.

Most of the things we do are in no way unusual. There should not be a need to hack in most situations. Make sure that your problem is really truly unique before you go beyond the normal way of doing things for your framework.

Monday, April 2, 2012

What Makes a Good Designer

I have the privilege of working with a lot of different designers.  Some I enjoy working with, some I don't. I like some of the designs, some I don't. (Gosh, sounds like most groups of people, huh? Some are better or easier to work with than others!)

Now, here's my little secret - I'm no designer. That's for sure. If I'm asked to design something you're almost certainly going to get a look and feel thats.... well, we'll be generous and say "safe." Given a mood board or other work of a designer, I can iterate and come up with something cool, but the fundamentals are definitely designer territory, not Catherine territory.

The difficulty comes when I have to hire a designer. Hiring an engineer is easy: I know what to look for; I know what makes someone effective or ineffective; and I can look at a small sample of someone's work and extrapolate. Hiring a designer is a somewhat more difficult proposition. Over the years, though, I've developed a pretty good idea of what makes a good designer.

I think of design as being broken down into two parts, aesthetics and reasoning. Aesthetic is the designer's "style." Reasoning is how the designer intellectually approaches the problem.

This is one design aesthetic (thanks to http://www.jessewillmon.com/):

This is a very different design aesthetic (thanks to http://www.mariusroosendaal.com/):


These are both portfolio pages - accomplishing the same purpose - but with very different aesthetics. The first is casual and friendly, while the second is much more corporate.

In my experience, most designers work with one or two aesthetics comfortably. When hiring for a designer, choose one who's aesthetic matches your own; those designs will be much better for you than if you're asking the designer to work in an uncomfortable way outside their aesthetic. If you're corporate, choose a designer with a clean corporate aesthetic. If you're going for an urban vibe (let's say you're starting the next great urban shoe craze), then choose a designer with an urban aesthetic.

But really, most designers have an aesthetic. They have a style.

What makes a good designer?

Reasoning.

A good designer can analyze problems and analyze designs, and can explain the reasons behind the design. For most poor designers, the reasons behind the designs come down to, "Well, it just looks right. Trust me." A good designer will be able to explain the design decisions clearly, pointing out things like:
  • eye tracking, including how the user will get information and in what order
  • mouse movement and target size
  • use of white space for clarity or emphasis
  • inclusion of corporate branding elements
  • conformance to or knowing deviation from similar problem spaces, either within the company or competitors
  • the overall priority of the design (for example, guidance or creating excitement or accomplishing known workflows quickly)
  • how the design scales up or down across the various target interfaces
So when I'm hiring a designer, I'm looking for only two things: an aesthetic that matches that of my client; and the ability to reason. Simple, right?