Monday, January 12, 2009

The essence of "good design" is it's ability to be absorbed by a human mind. Design is "good" when it can be easily-learned.

The term "testability" refers to how easily the objects in a design can be learned, albeit in a roundabout way. "Testability" is also a catch-all term for good design, and encompasses design qualities that are reflected in the SOLID acronym. Each of the solid principles talks about a specific goodness of software design. The essential, root cause of those goodnesses is the readiness of the design to be turned into knowledge that a person can immediately turn into effort and action.

We have good, simple techniques for getting software to the point where its design is optimally-learnable, and where it's structural qualities aren't compromised. We can create designs that are easy to learn and understand by approaching design from the roundabout course of "testability". The word itself is misleading unless you already know what "testability" means when used to describe design.

Testability isn't a term that describes whether software can be tested. It refers to software that is easily tested. The more "testable" something is, the easier it is to learn.

Use What You Know

If you can't learn something, you won't understand it. If you can't understand something, you can't use it - at least not well enough to avoid creating a money pit. You can't maintain a system that you don't understand - at least not easily. And you can't make changes to your system if you can't understand how the system as a whole will work once the changes are made.

Testability is all about how little effort I need to make to understand how the system works, and what changes I need to make to the system's modules to make a needed change.

To make an object or component easily testable, you have to be able to create one with little fuss, and poke and prod it to see how it works. But if you don't design your software so that it's easy to set up scenarios that help you learn, then it's going to be harder to maintain your system.

For example, if you need to understand logic that might save a new database record in one branch of an if statement, and update an existing row in another branch of the if statement, and if you can set up that scenario to prove that the logic works without also having the set up the database and create sample data and then query the database to verify whether the if statement routes to the right actions under the right conditions, then you've got a testable design. It's also likely that you used the Dependency Inversion Principle and the Interface Segregation Principle to get there (the "D" and "I" letters of the SOLID acronym).

If it's hard to set up an object in order to learn what it does and whether it does it right, then you've probably got a poorly-designed object. This suggests that you can use test code to prove that you've got the right design. And this is what testability means. If I can easily create a scenario that helps me learn what my objects do, then I have also very likely applied SOLID principles - whether I planned to or not.

Even without tests or test-driven development, code that follows SOLID principles is easier to understand and easier to work with. However, if I don't consistently write sample code that concretely and completely demonstrates the desired level of ease that I'm after, I'll consistently over-estimate the ease of setting up an object, and I won't arrive at the best design.

No matter how good I become in object-oriented design, the only proof that a design is good is code that proves concretely that I have achieved the highest level of ease of setting up an object for use. If that object is easy to set up in the example code, it will be easy to set up in the system's functional code, lending ease to the functional code.

The most insidious aspect of poor design is that when two poorly-designed objects are used together, the resulting code is even worse than the sum of the poorly design code in each object. As more poorly designed code is added to the system, more of it will interact, causing an exponential decline in ease of learning, understanding, and using that code.

To Test, or Not

If you choose to ignore testability because you're not interested in jumping on the unit testing bandwagon, then you're falling prey to an unfortunate side-effect of esoteric jargon.

"Testability" means: "Designed well enough that it can be easily tested - if an only if I am one of those people who's into testing." Don't be set back by the jargon. Object-oriented design terminology is often over-the-top at best and rarely self-evident until you've been initiated into the workings of the minds of people who name things.

Despite the jargon, well-designed code has benefits above and beyond testing. You can test code that is poorly-designed using tools like TypeMock (.NET), but you don't get the essential benefits of good design just because you can test. Be careful not to equate "testability" with the mere ability to test something.

Remember, testing is about making observations, and observations are about learning. Using runtime interception to get at the innards of a system that hasn't been designed to readily offer up knowledge of itself is like making an appendectomy incision with a hand grenade.

The necessary use of force on a system to derive understanding from it is one of those tell-tale signs that the system is poorly-designed. And even if you find a way to test an object that is difficult to test, the object will remain more difficult to maintain because the object has not been shaped to have greater ease. A system of objects that are poorly designed will be much more difficult to maintain the the sum of the difficulty of the individual objects.

Design needs to be supple. Supple so that you can easily peel back layers and partitions like rose petals that fit intricately into each other and learn from what's inside. Blasting open a design with a profiler is probably a sign that your system takes its design hints from a chunk of inert rock rather than a living rose - at once intricate as a whole and simple in its components. Regardless of whether you succeed in testing such an inert, rigid design, the essential qualities of design that generate tremendous leaps in productivity and value will not be present.

Make It

Good design is about knowledge. We wrap it up in all kinds of terminology, but in the end it's about making smallish bits of software that are easy to understand on their own, and that fit together exquisitely to make things bigger than themselves, and that can still be as easily understood.

Design so that you can pick up an object, set it up with ease and with little fuss, and see how it works. Design an object so that you can easily introduce it to another object so that both objects are capable of achieving something greater than the sum of their parts without sacrificing an ability to understand either the parts or the system they form.

An object or a system of objects that is easy to understand also very likely reflects SOLID principles, but make sure of this by writing a bit of code that proves it. If you don't constantly endeavor to prove that your code is SOLID, it won't be. No matter how good you are at software development, software is always more complex than what you can hold in your mind at any time.

Write the code that demonstrates the ease of using your objects. If you write this demo code first, you'll have better results because you'll be writing the objects to fulfill your expectations for ease, rather than trying to force-fit ease into your objects later. Once you've over-stepped the window of opportunity to create ease and productive designs, it's often too costly to ever get it back.

It's hard to work with things that are hard to understand. In the extreme, you simply can't work with something you don't understand. Things that are SOLID are easy to understand because they're easy to observe and they're easy to explore. They make sense. They're logical, and rational, and clean.

When you hear someone say "testability" have some sympathy for the poor bugger - he's usually not aware that he's speaking gibberish. He's been through hell and back trying to discover all this OO stuff on his own, and it takes a great toll over the years. Be thankful that there are people who've made the trek to hell who are willing and able to teach. Your aren't required to loose yourself in the wilds on your own, potentially loosing your own ability to communicate with other humans.

If you achieve the ease in software design, you'll find that other desirable qualities will come along for the ride almost incidentally. The qualities that make design easy to learn also make it reusable, adaptable, distributable, and lend the software you already have to changes in architecture, new non-functional requirements, and the necessary changes to the software that result from changes to the competative environment where your business does its work.

Thursday, January 01, 2009

Today, I had an issue with a software product that I've been evaluating over the past week. I made a mention of it on Twitter, and in fine contemporary form, the vendor was alerted to a mention of the product name in Twitter stream and got in touch with me. The Twitter contact turned into an email conversation conversation and we dug further into the issue I was having from there.

This kind of customer service interaction is increasingly common with the growing ubiquity of lifestream services like Twitter. It's a form of interaction that is much more human-centric than the technology-centric interactions we've been getting from web self-service silos in the past ten years.

Initiating customer service on Twitter doesn't require me to go to a vendor's customer service silo and hunt and peck for that vendor's particular way that they expect me to contact them. Instead, I just stand right where I am and do the lifestream equivalent of saying, "Acme Co's product is giving me fits," and someone from Acme Co gets in touch with me. It makes traditional web self-service seem quite primitive, and compared to the kinds of customer interactions that are being initiated in Twitter, traditional web self-service is indeed primitive.

Unfortunately, the quality of the interaction with the vendor degraded and became more frustrating (to me) as we got further into the exchange.

The software product in question is a text editor. There is a bug in the copy and paste feature of the editor. Text can be copied to the clipboard easily enough, but after positioning the cursor to where I want the text pasted, the text would actually paste in another location in the document, usually some distance beneath the cursor, or even beneath a subsequent paragraph.

It's quite frustrating to work with a text editor that doesn't get this basic interaction pattern down. Upon further explanation it turned out that the feature was coded this way on purpose to enable some other novel form of copy and paste interaction that was unlike anything that I had seen or used in the myriad text editors that I've used over the paste twenty years.

So, I was a bit irate at this point. It seemed to me like the vendor was trying to prove the point of a new interaction pattern for an interaction that is so well-established that it's not only a well-understood standard, but a standard that is an enabler for end users. But what got my customer experience hackles up came next.

The vendor asked me to post my thoughts on this to the online customer service application, Get Satisfaction so that interest from other customers on this issue could be gauged which would indicate to the vendor whether they should change the behavior. There are two mistakes here - a customer service mistake and a product management mistake.

First, the customer service mistake:

I had already provided the feedback to the vendor. In my customer experience, I had taken the time to describe the problem in an email, and now the knowledge is in the hands of the vendor. Because the vendor's customer service channels had not been integrated, the vendor asked me to do the double entry on the problem report. This is not an example of meeting me where I am, it's an example of lack luster customer experience. It's not my responsibility as a customer who is already contending with ill-conceived aspect of the vendor's product to also contend with ill-conceived aspects of the vendor's customer service systems.

Secondly, the vote:

I appreciate the new democratization of just about everything on the web, but if you're a product maker and you're making product decisions by referendum carried out on electronic media then are typically attractive to only a subset of your user population then your shooting yourself in both feet.

As a product designer, you should already know what it is you're building. You should have a strong vision for the product and already have a visceral sense of the customer's expectations, needs, and desired customer experience. If you don't have these, then by all means fall back to voting systems, but if you don't know what it is that you're building, and you're not clear on who you're building it for, then you might consider not building it!

Customer input is vital input to product design, but it's only one form of input. It should be a clarifying input to a solid product design vision and ability to execute. There's nothing wrong with taking customer input but if it's the primary means of making product design decisions, then it's possible that the strong sense of design that should be within the product team is missing.

Meeting me where I am means meeting me where I am in all stages of customer experience, from my flow through customer service information systems, services, and communication infrastructure to the representation of my expectations in product design through the product designer's visceral sense of me as a customer, and of the things that I value.

Responding to a spate of criticism from Digg customers, founder Kevin Rose shared his sense of the negativity leveled against Digg and its people. He assured his customers that Digg reads their feedback and that their ideas help to shape Digg.

It can be rough to take negative feedback from customers for a product that you're pored a lot of time into, and maybe Kevin is responding with fatigue rather than from unchecked, personal bias, but his response provides a good example of a product management anti-pattern:

"While we don't respond to every comment thread, do know that we do read them and your constructive suggestions do make it into our product roadmap."

While I would certainly hope that all product managers are blessed with constructive feedback, it's not the role of product management or product design to dictate feedback protocol to customers - especially irate customers. A product manager who does dictate protocol is stepping over the lines and allowing his personal biases and sensitivities to color some of the most valuable customer feedback that he can get.

Irate customers are either people with pervasive anger management issues, or people with higher sensitivities to your product experience that cause them to have greater adverse reactions than average customers. Those angry customers who are truly angry people might well be easily dismissed - as long as you know them well enough to know that their anger stems from something unrelated to your product experience. If you can't differentiate between angry people who happen to be your customers and angry customers, then you're in no position to discount angry feedback. And if you're the kind of person who requires all interactions to be positive in nature, then you're in no position to be in a customer-facing role.

You need serious "people skills" to play a customer engagement role, and by "people skills" I don't mean some sterile naivety that trivializes the range of human expression into a narrow band of emotion that includes only the safest and most genial modes. I mean skills in being a person who is comfortable with the complete range of human expression. In a customer-facing role with clear responsibility for why your product behaves the way it does, you're bound to come across a very broad spectrum of human responses as a result of the intersection of your product and real people who've used it.

Those irate customers are the early warning system for your products flaws. They know now about the things that are going to hurt you later. If you chose to project your personal belief that all interaction must be genial, then you're choosing to cut off a vital flow of critical information that you can't afford to ignore.

The products that we create are expressions of ourselves. Like it or not, these expressions affect people emotionally. They might evoke satisfaction or they might evoke anger. We have to be willing to accept that sometimes the product experiences that we create are indeed offensive to our discerning customers. The appropriate reaction to having imposed on a customer with offense even when the customer responds in-kind - is reflection rather than retaliation.

We have no right as product makers to express offense to our customers through our products and we should be prepared to take our lumps when we do so - especially because it will lead us to valuable insights into our products that we may not have yet been privy to. Reflection will train our awareness to be able to more clearly see what our more astute customers see, and will inevitably teach us to detect and avoid flaws during product design.

It's up to us to see the wide spectrum of customer response as inherently constructive, whether we feel the response is positive or negative or even irate and possibly even as offensive as the product is itself. When we put product in the world that brings frustration into the lives of our customers, then we darn well better be equipped to deal with them when they honor us with their input and not seek to dismiss, dismantle, redirect, or trivialize.

As a product manager, Kevin Rose is on the right path with this open dialog with his customers, but he failed to insulate the sanctum of customer relationship from his own exigencies where the niceties of protocol are concerned. He may have aggravated the situation with the already-irate customers, and this could end up isolating him from valuable, actionable, and vital information about his product.

We have to be willing to see the truth of our products. We have to be willing to discipline ourselves to meaningfully engage with customers regardless of the timbre of their feedback. Feedback is a privilege, not a right, and it's certainly not an annoyance - even when it feels annoying, or even downright aggravating.