It took a lot longer than I expected but this is first installment of my Design Principles To Live By series: Encapsulate Variation. This is a quick tour through the principles behind the design patterns. Following these allows will allow you to make the "right" choice in most situations. As with everything, there are exceptions to the rules. These are not set in stone. Violating them in okay, but only if you understand why doing so is better than following them.
Encapsulate Variation
A test for good software design is how well it can deal with future change. As the cliche truthfully claims, the only constant is change. Inevitably any piece of software the is in use will be asked to change. Business needs will evolve or the problem space will be better understood, etc. Whatever the reason, the software will need to change. A good design will allow for that change without too much work. A bad design will be very hard to modify.
While it is nearly impossible to predict the specifics of future requirements, it is much easier to understand what is likely to change. When designing software, look for the portions most likely to change and prepare them for future expansion by shielding the rest of the program from that change. Hide the potential variation behind an interface. Then, when the implementation changes, software written to the interface doesn't need to change. This is called encapsulating variation.
Let's look at an example. Let's say you are writing a paint program. For your first version, you choose to only handle .bmp files because there is no compression and they are easy to load. You know that if the program becomes popular, you'll want to load other files like .jpg, .gif, .png, etc. The naive way to implement the loading of a bmp is to write some functions that do just that. They load the bitmap file into your internal version of it. If you are using an api to load them, you might even be tempted to put the correct API calls directly in the Open button handler. Doing either will make life harder later. Every place that has to load the files (the button handler, the file recovery routine, the recently-used menu selections, etc.) will have to change when you add support for JPEGs and portable network graphics.
A better solution would be to create an interface IImageLoader and inherit from it for BMPLoader. Then all code handling loading files will call methods on IImageLoader and won't care (or know) about the specifics of the type of image being loaded. Adding JPEGLoader and PNGLoader will require changing much less code. If done right, changes will be isolated to just one place.
The point of this principle is to look ahead a little. See what is likely to vary, and plan for it. Don't plan for it by writing the handlers for JPEG. Maybe HDPhoto will have taken over the world by then. Rather, ensure that those things most likely to vary are encapsulated and therefore hidden from the rest of the program.
Wednesday, December 26, 2007
Encapsulate What Varies
Tuesday, December 25, 2007
Merry Christmas To All!
Merry Christmas everyone. I hope you are all able to spend some good time with family and friends. I'm off to see what Santa brought me.
[2 hours later] We finished opening presents and it started to snow! Not a little snow, but a lot of snow. Large flakes fill the air. A white Christmas in Washington. Uncommon but very cool.
Wednesday, December 19, 2007
What Is Test Automation?
I talk about it a lot, but I don't know that I've ever defined it. A reader recently wrote in and asked what exactly this was. I suppose that means I should give a better explanation of it.
Long ago in a galaxy far, far away, testers were computer-savvy non-programmers. Their job was to use the product before customers did. In doing so, they could find the bugs, report them to the developers, and get them fixed. This was a happy world but it couldn't last. Eventually companies started shipping things called SDKs which were Software Development Kits full of programming primitives for use by other programmers. There were no buttons to click. No input boxes to type the number 1 and the letter Q into. How was a non-programmer supposed to test these? Also, as companies shipped larger and larger products and these products built upon previous products, the number of buttons that needed pushing and input boxes that needed input grew and grew. Trying to test these was like running on a treadmill turned up to 11. The cost of testing grew as did the amount of time developers had to wait for the testers to give the green light to ship a product. Something had to be done.
The solution: Test Automation.
Test automation is simply an automatic way of doing what testers were doing before. Test automation is a series of programs which call APIs or push buttons and then programmatically determine whether the right action took place.
In a simple form, test automation is just unit tests. Call an API, make sure you get the right return result or that no exception is thrown. However, the real world requires much more complex testing than that. A return result is insufficient to determine true success. A function saying it succeeded just means it isn't aware that it failed. That's a good first step, but it is sort of the check engine light not being lit in the car. If there is an awful knocking sound coming from under the hood, it still isn't a good idea to drive. Likewise, it is important to use more than just the return value to verify success. Most functions have a purpose. That may be to sort a list, populate a database, or display a picture on the screen. Good test automation will independently verify that this purpose was fulfilled.
Other advanced forms of test automation include measuring performance, stressing the system by executing functionality under load, and what we call "end to end" testing. While unit tests and API tests treat methods and modules as discrete pieces and test them in isolation, end to end testing tries to simulate the experience of the user. This means pressing the buttons in Windows Media Player to cause a DVD to play and then verifying that it is playing. Sometimes this can be the most challenging part of testing.
Here's an example of something we had to automate. Think about how you might approach this. Windows Vista offers per-application volume. It is possible to turn down the volume on your World of Warcraft game while leaving Windows Media Player playing loud. To do this, right-click on the speaker icon in the lower-right-hand corner of your screen and select "Open Volume Mixer." Moving the slider for an application down should cause its volume to attenuate (get quieter). Testing this manually is easy. Just play a sound, lower the volume, and listen. Now try automating it.
Tuesday, December 18, 2007
Welcome Matthew van Eerde to the Blogosphere
Monday, December 17, 2007
Vista SP1 Release Candidate Available to the Public
Thursday, December 6, 2007
Dynamic Range and Color Spaces
Bill Crow, best known for his work on HDPhoto/JPEG-XR, has a great post about dynamic range and color spaces. If you are into photography or video, understanding this is important. As we try to aggregate video from more and more sources onto varying display mediums, color science is becoming every more important. Bill gives a great introduction to the subject. If you want to know more, there is a great book called Digital Video and HDTV: Algorithms and Interfaces by Charles Poynton that covers this all in great depth.