Beautiful Code [127]
Putting frameworks aside, there's a lot to say for adopting this "open" style of development in small projects. If you know all of the users of your code—if, for instance, they all sit with you on the same project—you can choose to lower the defenses in some of your code and make it as simple and clean as FIT's code.
Not all code is API code. It's easy for us to forget this because we hear the horror stories (the cases when one team locks down another by silently introducing dependencies that can't be eradicated), but if you are one team—if the clients of your code can and will make changes when you ask them to—you can adopt a different style of development and move toward quite open code. Language-based protection and design-based protection are solutions to a problem, but the problem is social, and it's important to consider whether you really have it or not.
Every once in a while, I show FIT's code to an experienced developer, and I get an interesting reaction. They immediately say, "Nice, but I would never write code like that." At that point, I ask them to ask themselves why. To me, FIT is a beautiful framework because it leads to that question and invites us to reflect on our answers.
Beautiful Tests > That Pesky Binary Search
7. Beautiful Tests
Alberto Savoia
Most programmers have had the experience of looking at a piece of code and thinking it was not only functional but also beautiful. Code is typically considered beautiful if it does what it's supposed to do with unique elegance and economy.
But what about the tests for that beautiful code—especially the kind of tests that developers write, or should write, while they are working on the code? In this chapter, I am going to focus on tests, because tests can be beautiful themselves. More importantly, they can play a key role in helping you create more beautiful code.
As we will see, a combination of things makes tests beautiful. Unlike code, I can't bring myself to consider any single test beautiful—at least not in the same way I can look at, say, a sorting routine and call it beautiful. The reason is that testing, by its very nature, is a combinatorial and exploratory problem. Every if statement in the code requires at least two tests (one test for when the condition evaluates to true and one when it evaluates to false). An if statement with multiple conditions, such as:
if ( a || b || c )
could require, in theory, up to eight tests—one for each possible combination of the values of a, b, and c. Throw in control loops, multiple input parameters, dependencies on external code, different hardware and software platforms, etc., and the number and types of tests needed increases considerably.
Any nontrivial code, beautiful or not, needs not one, but a team of tests, where each test should be focused on checking a specific aspect of the code, similar to the way different players on a sports team are responsible for different tasks and different areas of the playing field.
Now that we have determined that we should evaluate tests in groups, we need to determine what characteristics would make a group of tests beautiful—an adjective rarely applied to them.
Generally speaking, the main purpose of tests is to instill, reinforce, or reconfirm our confidence that the code works properly and efficiently. Therefore, to me, the most beautiful tests are those that help me maximize my confidence that the code does, and will continue to do, what it's supposed to. Because different types of tests are needed to verify different properties of the code, the basic criteria for beauty vary. This chapter explores three ways tests can be beautiful:
Tests that are beautiful for their simplicity
With a few lines of test code, I can document and verify the target code's basic behavior. By automatically running those tests with every build, I can ensure that the intended behavior is preserved as the code evolves. This chapter uses the JUnit testing framework for examples