Tdd for the iPhone: Continued 368
After a week in Israel and the UK, I got back to this series. I’ve switched to using XCode 4, but as it is not officially released, the videos I recorded using it were a bad idea to upload.
Back to XCode 3: http://www.vimeo.com/album/1472322
The 4-contact points of software development 178
- Write no production code without a failing test
- Write just enough of a test to fail
- Write just enough production code to get the test to pass
This list doesn’t include refactoring, which is typically an assumed activity. In fact, some people refer to these rules as “red, green, refactor”. An even older version of this, from the Smalltalk community, is Red, Green, Blue. (Why Blue for refactor? I think someone was thinking RBG for a color space, luckily they didn’t try to use CMYK or LAB!)
In this simple model, there two kinds of code: test & production. There are two kinds of activity: writing & refactoring. Interestingly, at one level it is all code. The thing that distinguishes both sets is intent.
The intent of a test is to demonstrate or maybe specify behavior. The intent of production code is to implement (hopefully) business-relevant functionality.
The intent of writing code is creation. The intent of refactoring code is to change (hopefully improve) its structure without changing its behavior (this is oversimplified but essentially correct).
If you mix those combinations you have the 4-limbs of development:- Writing a test
- Writing production code
- Refactoring a test
- Refactoring production code
An important behavior to practice is doing only one of these at a time. That is, when you are writing tests, don’t also write production code. Sure, you might use tools to stub out missing methods and classes, but the heart of what you are doing is writing a test. Finish that train of thought before focusing on writing production code.
On the other hand, if you are refactoring production code, do just that. Don’t change tests at the same time, try to only do one refactoring at a time, etc.
WHY?
First an analogy that almost always misses since most developers don’t additionally rock climb.
When rock climbing, a good general bit of advice is to only move one contact point at a time. For this discussion, consider your two hands and two feet as your four contact points. Sure, you can use your face or knee, but neither are much fun. So just considering two hands and two feet, that suggests that if, for example, you move your right hand, then leave your left hand and both feet in place.
This gives you stability, a chance to easily recover by simply moving the most recent appendage back in place and, when the inevitable happens, another appendage slips, you have a better chance of not eating rock face. If you move more than one thing at a time, you are in more danger because you’ve taken a risky action and reduced the number of points of contact, or stability.
Will you sometimes move multiple appendages? Sure. But not as a habit. Sometimes you need to take risks. The rock face may not always offer up movement patterns that make applying this recommendation possible. Since you know the environment will occasionally work against you, you need to maintain some slack for the inevitable.
Practicing Test Driven Development is similar. If you change production code and tests at the same time, what happens if a test fails? What is wrong? The production code, the test, both, neither? An even more subtle problem is that tests pass but the test is fragile or heavily implementation-dependent. While not necessarily an immediate threat, it represents design debt that will eventually cause problems. (This also happens frequently when tests are written after the production code as it’s seductively easy to write tests that exercise code, expressing the production’s code implementation but fundamentally hiding the intent.)
Notice, if you had only refactored code, then you know the problem is in one place. When you change both, the problem space actually goes from 1 to 3 (4 if you allow for neither). Furthermore, if you are changing both production and test code at the same time and you get to a point where you’ve entered a bottomless pit, you’ll end up throwing away more work if you choose to restore from the repository.
Are there going to be times when you change both? Sure. Sometimes you may not see a clear path that gives you the option to do only one thing at a given time. Sometimes the tests and code will work against you. Often, you’ll be working in a legacy code base where there are no tests. Given that the environment will occasionally (or frequently) work against you, you need to maintain some slack.
Essentially, be focused on a single goal at any given time: write a test. then get it to pass. clean up production code & keep the tests first unchanging and then passing.
I find that this is a hard thing both to learn and to apply. I frequently jump ahead of myself. Unfortunately I’m “lucky” enough when I do jump ahead that when I fail, I thoroughly fall flat on my face.
This approach is contextual (aren’t they all?). Every time you start working on code, you’ll be faced with these four possibilities. Each time you are, you need to figure out what is the most important thing in the moment, and do that one thing. Once you’ve taken care of the most important thing, you may have just promoted the second most important thing to first place. Even so, reassess. What is the most important thing now? Do that.
Good luck trying to apply this idea to your development work. I’m interesting in hearing about it.
A Few C plus plus TDD videos 155
Using CppUTest, gcc 4.4 and the Eclipse CDT.
Rough, as usual.
The Video Album
Might redo first one with increased font size. Considering redoing whole series at 800×600.
Parts 5 and 6 of the 4-part series 50
The title says it all. I was bothered by a few things in the Shunting Yard Algorithm (actually many more things), but I felt compelled to fix two of those things.
So if you have a look at the album, you’ll notice 2 more videos:- Video 5 of 4: Remove the need for spaces between tokens.
- Video 6 of 4: Remove duplication of operators in algorithm and tokenizer.
Hope these are interesting or at least entertaining.
Injecting Those Dependencies 171
Last week I was teaching a class with a good group of C++ developers in Chicago. They were up on C++, current standardization efforts, virtual machines, performance analysis and tuning. At one point I mentioned a metric for virtual method dispatch on the JVM and one of the students used my numbers to work backwards to determine the number of instructions on different processors.
I was teaching our Working Effectively with Legacy Code class. Michael Feathers usually teaches this class, but he was busy (probably working with legacy code somewhere, which, ironically, is why he wrote the book – to solve the problem once and for all and to stop working with legacy code).
public void addEvent(Event event) {
event.added();
events.add(event);
mailService.sendMail("jacques@spg1.com", "Event Notification", event
.toString());
display.showEvent(event);
}
public Scheduler(String owner, SchedulerDisplay display) {
this.owner = owner;
mailService = MailService.getInstance();
this.display = new SchedulerDisplay();
}
The display object is associated with a real device (OK, not in our simulation, but you get the point). We need to fix that dependency.
So we traditionally talk about a few ways to address that:- Create an interface and then have a concrete and test-double implementation
- Create a test subclass
#pragma once
template<class D> class Scheduler
{
public:
Scheduler(D &display);
~Scheduler();
void handleEvent();
private:
D &display;
};
- Link seam: link in a different version of SchedulerDisplay
- Compiler seam: use a template parameter
- Dynamic seam: create a test subclass that removes external dependency
- Dynamic seam: extract an interface from existing concrete class, and make Scheduler depend on the new interface.
For C++, the first option might be a good option if it allows a very quick build/test cycle. Imagine using a class that brings in several unwanted dependencies. By making a test version replacement and linking to it, you might be able to get up and running quickly. On the other hand, you have to have a custom build target, which is really outside of the language.
The second option is good for C++ and maybe C#, but not Java. Java’s implementation of generics is so bad, that it requires an interface for this particular case, so you end up with the final option anyway. Using templates puts the seam into the language rather than the build system. It will affect clients because either:- They will have to provide a template parameter
- Or, by providing a default value for the template parameter, clients will be aware of a class they were not previously aware of. Still, a viable option, but it will increase build time at least a little.
The third option may not work in any language without changing the original problem code. Imagine a no argument constructor that performs some static initialization. Without changing the constructor, you cannot guarantee that this approach will work. In any case, the problem as presented requires a change since the constructor was doing the initialization of the display; it did not allow for dependency injection.
The final option requires a bit more change, but is pretty flexible if you can afford the virtual method overhead. In Java this isn’t much of an issue (for a number of reasons, mostly related to effective JIT optimization). The cost is a bit more of a problem in C++ because introducing a first virtual method is a big deal. Personally, I don’t work on embedded systems, so I can generally ignore that problem. But this is not something to simply ignore, context does matter.
So which option is the best?
None of the above.
As a developer, you should probably be aware of all of these options (or maybe not the template option of you’re strictly a Java developer). Then, when you are faced with a legacy coding problem, you’ll have more tools from which to choose.
Name that refactoring: 2 - Version 2 48
A few updates applied to the second name that refactoring. Note that I’m using a star to represent a problem dependency. It is the “star” of the refactoring. I’m looking for a better image. I could go with a database icon, but the principle is more general than that. The cloud was confusing. So if you have an idea, please let me know what it is!
Again, thanks for taking a look and giving me the feedback.
Step 0: Problematic Dependency
Step 1: Capture dependency in a single class
Step 2: Raise the abstraction to a domain-level interface
Step 3: Introduce test doubles as needed
Name that refactoring: 1 - Version 2 48
Here is an update to the first name that refactoring based on feedback. How about this?
Step 0: Method with embedded dependency
Step 1:Extract method to move dependency to another method
Step 2: Subclass and override method with new code that does not have original dependency
So what do you think? Better or worse?
What about using the star in other image? In general, the star could represent the dependency we’re trying to get rid of.
Name that refactoring: 2 77
Ok, so I’m getting good feedback on the first picture. Now for a series of pictures.
How do you interpret this series?
Step 0
Step 1
Step 2
Step 3
Name that refactoring: 1 70
I’m working on writing up a few handouts I can use in a TDD class (and a few other places). There are a few drawings I keep doing and I’m trying to replicate them so I can refer to something.
Problem is, with many such drawings, the observation of the creation is as important as the end product. I’d like your feedback/recommendations (or links to better pictures). I’m curious about at least two things.- What does this picture suggest to you or what can you draw from it, if anything?
- Do you think this would be better served as a series of pictures showing the build-up?
Thanks for your feedback.
Improving Testability of GUI Code, an Eample 82
Just finished first draft. More to come, questions/comments appreciated.
http://schuchert.wikispaces.com/tdd.Refactoring.UiExample
Older posts: 1 2