ArticleS. MichaelFeathers.
TheNewGuy [add child]

The New Guy


1 2 3 4

Ramon came into the lab and took a look around. There wasn't much going on. The team had just finished a milestone and people were mulling around, catching up on some things that they'd put off, doing their timesheets, and cleaning up odd bits of work. Sally is sitting at a table flipping through a book.

"What are you reading?", Ramon said.
"Oh, it's this book about working with legacy code", said Sally.

Ramon bursts out laughing, spraying Sprite all over his shirt.

"Well, that was impressive", Sally said.

"No no, it's just that.... well, that's what it's come to? We spent five years working on this system and you're trying to get hints from a book on COBOL?

"You should read it, Ramon. It's not about COBOL at all. In fact, most of the examples are in Java. This guy is saying that there is a lot of code out there that feels like legacy code. He goes a bit further too. He says that code without tests is legacy code."

"Right. Sounds like hype."

"Well, I'm gonna try some of this stuff, want to pair?"

"Sure. Want me to change my shirt? I have my running shirt in my office."

"No way. I'll take the Sprite. Sit down."

Sally browses to the bug database and clinks into the third link on the page.

"Remember this one? I figured out how to fix it. We have to go to the TradeColumnHeader class and set the alignment on refresh."

"Oh," said Ramon, "who did that?"

"I don't know. Probably Randy, but anyway, you know this class, you know how to fix it, right?"

"Yeah."

"Well, let's write a test for it."

"Huh?"

"Yes, we can write a test for the correct behavior and show that it fails because there is a bug. Then when we fix the bug, the test will pass."

Ramon looks like he's bitten into a lemon. "What do you want to do THAT for?! It's a one line code change?!"

"Relax, Ramon. There are some very good reasons. For one thing, when we write the test we'll have some real feedback that we've solved the problem. How would you verify that we solved the problem without the test?"

"It's just an obvious fix, Sally. We'll see when the weekly reports are run."

"Uh huh. I'll bet Randy thought that he understood the code too."

"Okay, you've gotta point. Any other reasons?"

Sally smiles, "Well, we can find out whether we can get rid of our legacy code or not."

"You've been corrupted. How do we start?

Sally takes the keyboard and starts to write a junit test case. Ramon, wheels his chair around
and drops his chin into palms. "So, what are you going to test?"

"That's not the first step. The first step is to get the class to run in the test harness."

"Shouldn't be a problem, Sally. We had a review for this class a few weeks ago. It's good work."

"Okay," said Sally, "we'll see."

Sally starts to type in a test case in her IDE.

"So, Ramon, what do you think of the new guy?"


"I don't know, he's pretty quiet."

"He is, isn't he? I don't think he's right for this job. You should've seen how he was writing equals methods before I stopped him. The fool lowered the resolutions on two of the monitors in the lab last night also."

"Seyed hired him. He should know something."

"You'd think, but you're right; he's so quiet. Hard to tell. Here. Here's our first test..."


import junit.framework.*;

public class TradeColumnHeaderTest extends TestCase
{
public void testCreate() {
new TradeColumnHeader();
}

}



"That's it?" said Ramon, "it doesn't test anything."

"Well, it does in a way. If we can compile and run this thing, we know that we can write more tests, including the one we want to write, the one that shows the bug."

"So, you'll be using those techniques" said Ramon as he started to shuffle papers around on the desk.

"Yeah"

Sally hits the run button and gets an error message. There is no parameter-less constructor for the TradeColumnHeader class.

"So, the moral of the story is, look at the class to see what constructors it has, right?" said Ramon.

"Well, sometimes you get lucky," said Sally smiling.

Sally opens the class declaration in a browser pane and looks at the constructors. There are five of them and the simplest of them accepts a single parameter: a Configuration object.

"What does this one do, Ramon?"

"Not much. It just holds that configuration internally. If methods need to use it, they use it."

"What about the refresh method? Does it use the configuration?"

"I'm not sure", said Ramon.

"Let's see", said Sally.

Sally changes the test:


public class TradeColumnHeaderTest extends TestCase
{
public void testAlignmentOnRefresh() {
TradeColumnHeader header = new TradeColumnHeader(null);
header.refresh();
}

}



"Passing null?! You're passing null into the constructor! What the hell are you doing that for?!" said Ramon.

"It's just a quick way to see if we really need to create Configuration."

"Of course, we have to create a Configuration, Sally. That's what the class needs."

"In production, yes. But we're just writing a test here."

"What does it test, Sally?"

"Just the fact that we can run refresh by itself. The next thing we are going to have to do is see what we can do to sense the bug."

Sally changes the code:


public class TradeColumnHeaderTest extends TestCase
{
public void testCreate() {
TradeColumnHeader header = new TradeColumnHeader(null);
header.refresh();
assertEquals(TradeColumn.VERTICAL, header.getAlignment());
}

}


"See, now we have a real test." said Sally. Sally runs the test. "See, it fails."

"Okay, so how are you going to fix it?", said Ramon.

"It looks like we can change the bias factor like this, to 5.0 and it aligns.", said Sally as she typed in the code change.

Ramon gets up and walks to the window. "So, does that make sense? Passing in a null like that?"

"It's one of the techniques in the book, Ramon."

"But it's wrong! If you pass null into methods all over the place you turn your system into a mess. We'll have null pointer exceptions all over the place!"

Sally turns her chair to face Ramon. "Yes, if you pass null in production code. We are NOT passing null in production code, we are passing it in tests so that we don't have to create a Configuration."

Just then the new guy, Aiden, walks into the room. "What's up?" Aiden sits down as Sally and Ramon battle it out, not even noticing him.

"But you're going to need a Configuration eventually, aren't you?", said Ramon. "Most of the other methods on that class do use the configuration."

Just then, Frank, the Product Manager walks in, followed by the rest of the team.

"Yes, Ramon, but we can get to that when we need to. By passing null we were able to write an important test without confronting all of the dependencies all at once; you can make some progress.

"I'm not convinced yet. You're not even really testing the class if it doesn't have a Configuration." said Ramon.

Just then Frank spoke up. "Okay, team meeting. I doubt this is a surprise to you all, but Marco was let go this morning. As of today, Aiden is your new manager. I had him join your team as a programmer last week just to get to know you all while we were making the transition. If you have any questions, come by my office. Have a nice weekend."

Frank walks out the door, leaving the team in an uneasy silence.

Click here to visit with Ramon as he walks home.

1 2 3 4



Append comments below: