words among

Saturday, September 18, 2010

I was just thinking about how I would write some test-first code in an interview, and it reminded me of using factories and mocking, and how I couldn't defend mocking to a smart young developer who had just given a talk about optimizing the performance of tests. I tried to explain why I liked it but my reasons seemed too abstract for him to buy into it. He said that letting his tests run through his whole app, it made him think everything was really working. I think he also suspected mocking would lead him to have to do more work on tests. Keep in mind that this was someone who had clearly already rewritten his tests many times in a relatively short testing career.

What if I told him it was like your app is a car, and you're testing the car. Wouldn't you want to test the individual parts, instead of waiting until the car is built? Unit testing does this, but what about when you are testing the conduit between two complex tools? Without mocking, you sacrifice your ability to inspect what is happening inside those two tools as they interact. I see the mock as a piece of specialized machinery that is designed to simulate part of your car, but is also letting you watch and measure things with as much precision as you need.

The app is also like a car in that some parts of it are there to go fast, some parts are there to keep you safe, and some parts are just there to smooth out the ride. They all need to be tested for different reasons, and sometimes it will make sense to test them in different ways. Conventions are important but if you think about it, every object has the potential for doing something unique; and you may be better able to express and use that potential if you don't hold to any presuppositions about how you are going to test something.

Cars have been made great largely because of the simplicity of decoupling the individual parts, at least to a certain extent, and seeing how each one performs in different environments. Maybe rubber tires were first used for horse buggies, and steel wheels were first used for streetcars. The tires for the Model T were sort of a hybrid; and the wheels for every car or vehicle made since then have been further hybridizations of that same tool. The point is partly that if your business is successful, your application is going to develop enough complexity to keep you coming back to the code and adding new ways to handle things. The real world is complex, and to make something truly useful you have to really marry it to the real world. Think of all the new safety regulations cars have had to meet over the years. Cars today can have 3000 or more parts. But a production application can have 3000 or more files. If you are successful, it depends on the app, but I'd bet most projects will get there if they are celebrating their tenth or twentieth birthday. Think of all the times you'll have to rewrite your tests to get through the next ten years. I think that's just how it is in a successful business, there's a lot of changes involved in achieving that appearance of stability. But that's one of the reasons that mockists like being able to describe their needs in more general, or abstract, terms, instead of only working with the side effects of a particular implementation. There is a circular logic problem, so using mocks does leave you the onus of verifying that your app pieces can actually work together. Even so, mocks can be the perfect method for combining several components in a test, and for limiting it to the ones you want. This is also a big reason why I like rr ("double r"). You can use mock.proxy to make sure your method is called the right way, and also pass the method down the chain to see what happens, right there in the same test. It's quite amazing.

So maybe this is just more abstract bs, but I think that mocking makes my app better by letting me see to it that everything makes sense, not just that it seems to work for some reason. Spending more time with the surfaces of my objects may be a hefty trade-off, but I think it will end up saving me time in the long run. Hopefully I will have a better idea after 10 more years of experience.

Friday, September 03, 2010

another patience lesson

Apple has really come to prominence, and a lot has changed this decade. But, not all that much. They are still doing most things in pretty much the same way that they were in 2000. In particular, they have a relatively slow, long-term rollout of new features. They would rather release a feature quietly and let it go unused for years, while people gradually figure it out, than promise a new feature that they end up failing to deliver.

One example is the accelerometer. Apple notebooks have had it for a long time, but it is only used to protect the hard drive if the computer is dropped. It has been possible for quite some time to install software that allowed you to use the accelerometer as an input; a couple of examples would be tilting the mac to control steering for a flight simulator, or tapping the side of the screen to start your favorite applications. It may be that the laptop is a little too heavy to make those applications useful, but I still think that one day they will surface and prove useful. The iPhone has, of course, made the accelerometer much more prominent, and uses it frequently. However, the use of the accelerometer is still rather primitive; it should be possible to devise a rich vocabulary of controls that are initiated by subtle movements or tilts. But, the public need time to adapt to that reality, and Apple seems to know this better than many other companies. The foundation of their success is shipping features that are polished to a shine, but not flashy in the least.

This is a strategy that has also been clearly communicated by 37Signals, which is a small company that specializes in design but also has published several of its own web applications. Both in their stewardship of the Rails platform, and their books and blogs, they explain that simple solutions are just more effective. There are many facets and corollaries to this thesis, but the most salient one may be the annoying trend that people will give up on trying to use a web app if it is not immediately intuitive. Although there may be complicated business logic hidden in there, the interface of it should be as natural and unfettered as possible. It's relatively clear that they learned this wisdom from Apple, and the two platforms have both benefitted from recent advances in the other (for example, Apple's Objective-C 2.0 incorporated several of Ruby's most time-saving features; Ruby only became popular after 37Signals began to use and evangelize it).

Keeping my product simple, and my interface natural, is a challenge for me. There are just a whole lot of features I can add that seem powerful to me. I know that I should wait until my user base has mastered a few things at a time, and I am striving to do so. I just wanted to mention that Apple's event this week provided another reminder of their enormous patience.

When they debuted the new iPhone this summer, the most suggestive remark was that they planned to ship X millions of "FaceTime devices" this year. It was pretty clear that this videoconferencing technology would be part of the new iPod, but many wondered if it would also be incorporated into the AppleTV box. There are several big advantages to having it there - for example, your TV is usually in a spot that has a very strong WiFi signal. It has a big screen, and you don't have to hold your arm out in front of you to see it. For users, like grandparents, that might not get the point of an iPod, or might not be able to find it if they have one, the TV is a less threatening interface. And, the enclosure of the AppleTV is big enough to house a good camera, with zoom, without a miracle of engineering.

Yet we will have to be patient to see that come our way. I think Apple preferred to keep the price point down, since the first AppleTV was a bit of a failure. There may have also been awkward issues with camera placement that Apple opted to avoid, or defer for now. After all, it is "face" time, not "edge of the coffee table" time. Apple is enhancing the beauty of its product with the beauty of faces. And, although it will be years before video calling is an everyday experience, they will patiently wait for us to catch up, and just keep working on their new ideas in private.