read the attachment and answer the question

profileSauraha1996
HeadFirstSoftwareDevelopmentbyDanPiloneRussMilesz-lib.org_compressed_compressed1.pdf

Head First Software Development

by Dan Pilone and Russ Miles

Copyright © 2008 O’Reilly Media, Inc. All rights reserved.

Printed in the United States of America.

Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.

O’Reilly Media books may be purchased for educational, business, or sales promotional use. Online editions are

also available for most titles (safari.oreilly.com). For more information, contact our corporate/institutional sales

department: (800) 998-9938 or [email protected].

Series Creators: Kathy Sierra, Bert Bates

Series Editor: Brett D. McLaughlin

Design Editor: Louise Barr

Cover Designers: Louise Barr, Steve Fehler

Production Editor: Sanders Kleinfeld

Indexer: Julie Hawks

Page Viewers: Vinny, Nick, Tracey, and Corinne

Printing History:

December 2007: First Edition.

The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. The Head First series designations,

Head First Software Development, and related trade dress are trademarks of O’Reilly Media, Inc. Java and all Java-

based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc., in the United

States and other countries. O’Reilly Media, Inc. is independent of Sun Microsystems.

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as

trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trademark

claim, the designations have been printed in caps or initial caps.

While every precaution has been taken in the preparation of this book, the publisher and the authors assume no

responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.

No sleepovers were conducted in the writing of this book, although one author did purportedly get engaged

using his prototype of the iSwoon application. And one pig apparently lost its nose, but we’re confident that had

nothing to do with the software development techniques espoused by this text.

ISBN-10: 0-596-52735-7

ISBN-13: 978-0-596-52735-8

[M]

Russ and Cor inne

This book uses RepKover™, a durable and fl exible lay-fl at binding. TMTM

Vinny, Tracey, Nick and Dan

table of contents

ix

Table of Contents (Summary)

Table of Contents (the real thing) Intro

Who is this book for? xxvi

We know what you’re thinking xxvii

Metacognition xxix

Bend your brain into submission xxxi

Read me xxxii

The technical review team xxxiv

Acknowledgments xxxv

Intro xxv

1 great software development: Pleasing your customer 1

2 gathering requirements: Knowing what the customer wants 29

3 project planning: Planning for success 69

4 user stories and tasks: Getting to the real work 109

5 good-enough design: Getting it done with great design 149

6 version control: Defensive development 177

6.5 building your code: Insert tab a into slot b... 219

7 testing and continuous integration: Things fall apart 235

8 test-driven development: Holding your code accountable 275

9 ending an iteration: It’s all coming together... 317

10 the next iteration: If it ain’t broke... you still better fix it 349

11 bugs: Squashing bugs like a pro 383

12 the real world: Having a process in life 417

Your brain on Software Development. You’re sitting around trying

to learn something, but your brain keeps telling you all that learning isn’t important. Your

brain’s saying, “Better leave room for more important things, like which wild animals to

avoid and whether naked rock-climbing is a bad idea.” So how do you trick your brain

into thinking that your life really depends on learning how to develop great software?

table of contents

x

Pleasing your customer

1 If the customer’s unhappy, everyone’s unhappy! Every great piece of software starts with a customer’s big idea. It’s your job as a professional software developer to bring those ideas to life. But taking a vague

idea and turning it into working code—code that satisfies your customer—isn’t

so easy. In this chapter you’ll learn how to avoid being a software development

casualty by delivering software that is needed, on-time, and on-budget. Grab

your laptop and let’s set out on the road to shipping great software.

great software development

Tom’s Trails is going online 2

Most projects have two major concerns 3

The Big Bang approach to development 4

Flash forward: two weeks later 5

Big bang development usually ends up in a big MESS 6

Great software development is... 9

Getting to the goal with ITERATION 10

Each iteration is a mini-project 14

Each iteration is QUALITY software 14

The customer WILL change things up 20

It’s up to you to make adjustments 20

But there are some BIG problems... 20

Iteration handles change automatically (well sort of) 22

Your software isn’t complete until it’s been RELEASED 25

Tools for your Software Development Toolbox 26

You’re this far down the path towards delivering great software

...but now the goal has moved!

The original goal...

You’ve been iterating to aim for the goal...

The Goal

table of contents

xi

Knowing what the customer wants

2 You can’t always get what you want... but the customer better! Great software development delivers what the customer wants. This chapter is all about talking to the customer to figure out what their requirements are for your software.

You’ll learn how user stories, brainstorming, and the estimation game help you get

inside your customer’s head. That way, by the time you finish your project, you’ll be

confident you’ve built what your customer wants... and not just a poor imitation.

gathering requirements

Orion’s Orbits is modernizing 30

Talk to your customer to get MORE information 33

Bluesky with your customer 34

Sometimes your bluesky session looks like this... 36

Find out what people REALLY do 37

Your requirements must be CUSTOMER-oriented 39

Develop your requirements with customer feedback 41

User stories define the WHAT of your project...

estimates define the WHEN 43

Cubicle conversation 47

Playing Planning Poker 48

Put assumptions on trial for their lives 51

A BIG user story estimate is a BAD user story estimate 54

The goal is convergence 57

The requirement to estimate iteration cycle 60

Finally, we’re ready to estimate the whole project

0 days

5 days

3 days

2 days

1 day

1/2 day

100 days

40 days

20 days

13 days

8 days ?

table of contents

xii

Planning for success

Every great piece of software starts with a great plan.

In this chapter you’re going to learn how to create that plan. You’re going to learn how to

work with the customer to prioritize their requirements. You’ll define iterations that you

and your team can then work towards. Finally you’ll create an achievable development

plan that you and your team can confidently execute and monitor. By the time you’re

done, you’ll know exactly how to get from requirements to milestone 1.0.

project planning

Customers want their software NOW! 70

Prioritize with the customer 73

We know what’s in Milestone 1.0 (well, maybe) 74

If the features don’t fit, re-prioritize 75

More people sometimes means diminishing returns 77

Work your way to a reasonable milestone 1.0 78

Iterations should be short and sweet 85

Comparing your plan to reality 87

Velocity accounts for overhead in your estimates 89

Programmers think in UTOPIAN days... 90

Developers think in REAL-WORLD days... 91

When is your iteration too long? 92

Deal with velocity BEFORE you break into iterations 93

Time to make an evaluation 97

Managing pissed off customers 98

The Big Board on your wall 100

How to ruin your team’s lives 103

3

Managing pissed off customer

table of contents

xiii

Getting to the real work

4 It’s time to go to work. User stories captured what you need to develop, but now it’s time to knuckle down and dish out the work that needs to be done so that you can bring those user stories to life. In this chapter you’ll learn how to break your user stories

into tasks, and how your task estimates help you track your project from inception to

completion. You’ll learn how to update your board, moving tasks from in-progress, to

complete, to finally completing an entire user story. Along the way, you’ll handle and

prioritize the inevitable unexpected work your customer will add to your plate.

user stories and tasks

Introducing iSwoon 110

Do your tasks add up? 113

Plot just the work you have left 115

Add your tasks to your board 116

Start working on your tasks 118

A task is only in progress when it’s IN PROGRESS 119

What if I’m working on two things at once? 120

Your first standup meeting... 123

Task 1: Create the Date class 124

Standup meeting: Day 5, end of Week 1... 130

Standup meeting: Day 2, Week 2... 136

We interrupt this chapter... 140

You have to track unplanned tasks 141

Unexpected tasks raise your burn-down rate 143

Velocity helps, but... 144

We have a lot to do... 146

...but we know EXACTLY where we stand 147

Velocity Exposed 148

Laura the UI Gur u.

Mark, database expert and SQL blackbelt.Bob the junior

developer.

table of contents

xiv

Getting it done with great design

Good design helps you deliver. In the last chapter things were looking pretty

dire. A bad design was making life hard for everyone and, to make matters worse, an

unplanned task cropped up. In this chapter you’ll see how to refactor your design so that

you and your team can be more productive. You’ll apply principles of good design,

while at the same time being wary of striving for the promise of the ‘perfect design’.

Finally you’ll handle unplanned tasks in exactly the same way you handle all the other

work on your project using the big project board on your wall.

good-enough design

iSwoon is in serious trouble... 150

This design breaks the single responsibility principle 153

Spotting multiple responsibilies in your design 156

Going from multiple responsibilies to a single responsibility 159

Your design should obey the SRP, but also be DRY... 160

The post-refactoring standup meeting... 164

Unplanned tasks are still just tasks 166

Part of your task is the demo itself 167

When everything’s complete, the iteration’s done 170

5

table of contents

xv

Defensive development

6 When it comes to writing great software, Safety First! Writing great software isn’t easy... especially when you’ve got to make sure your code works, and make sure it keeps working. All it takes is one typo, one bad decision

from a co-worker, one crashed hard drive, and suddenly all your work goes down the

drain. But with version control, you can make sure your code is always safe in a

code repository, you can undo mistakes, and you can make bug fixes—to new and

old versions of your software.

version control

You’ve got a new contract—BeatBox Pro 178

And now the GUI work... 182

Demo the new BeatBox for the customer 185

Let’s start with VERSION CONTROL 188

First set up your project... 190

...then you can check code in and out. 191

Most version control tools will try and solve problems for you 192

The server tries to MERGE your changes 193

If your software can’t merge the changes, it issues a conflict 194

More iterations, more stories... 198

We have more than one version of our software... 200

Good commit messages make finding older software easier 202

Now you can check out Version 1.0 203

(Emergency) standup meeting 204

Tag your versions 205

Tags, branches, and trunks, oh my! 207

Fixing Version 1.0...for real this time. 208

We have TWO code bases now 209

When NOT to branch... 212

The Zen of good branching 212

What version control does... 214

Version control can’t make sure you code actually works... 215

Tools for your Software Development Toolbox 216

2.0!

BeatBox Pro 1.0

BeatBox Pro 1.x

table of contents

xvi

Insert tab a into slot b...

6 / It pays to follow the instructions... ...especially when you write them yourself. It’s not enough to use configuration management to ensure your code stays safe. You’ve

also got to worry about compiling your code and packaging it into a deployable unit. On

top of all that, which class should be the main class of your application? How should that

class be run? In this chapter, you’ll learn how a build tool allows you to write your own

instructions for dealing with your source code.

building your code

Developers aren’t mind readers 220

Building your project in one step 221

Ant: a build tool for Java projects 222

Projects, properties, targets, tasks 223

Good build scripts... 228

Good build scripts go BEYOND the basics 230

Your build script is code, too 232

New developer, take two 233

Tools for your Software Development Toolbox 234

log4j

.jar

apache-

commons

.jar

Pieces of your project Build process Working system You’ve got

folders

of source c ode and

unit tests.. . ...probably some

binary files, like images or icons...

...deployment de scriptors,

HTML files, app .

configs, etc...

...libraries, ja rs,

dlls, so’s... The build magic happens here.

And out pops your system, ready to run.

Here’s wh at we nee

d

to work o n now.

This is what we’ve been focusing on so far...

table of contents

xvii

Things fall apart

Sometimes even the best developer breaks the build.

Everyone’s done it at least once. You’re sure your code compiles, you’ve tested it over

and over again on your machine and committed it into the repository. But somewhere

between your machine and that black box they call a server someone must have changed

your code. The unlucky soul who does the next checkout is about to have a bad morning

sorting out what used to be working code. In this chapter we’ll talk about how to put

together a safety net to keep the build in working order and you productive.

testing and continuous integration

Things will ALWAYS go wrong... 236

There are three ways to look at your system... 238

Black-box testing focuses on INPUT and OUTPUT 239

Grey-box testing gets you CLOSER to the code 240

White-box testing uses inside knowledge 243

Testing EVERYTHING with one step 248

Automate your tests with a testing framework 250

Use your framework to run your tests 251

At the wheel of CI with CruiseControl 254

Testing guarantees things will work... right? 256

Testing all your code means testing EVERY BRANCH 264

Use a coverage report to see what’s covered 265

Getting good coverage isn’t always easy... 267

What CM does... 270

Tools for your Software Development Toolbox 274

7

Black-box testing

Grey-box testing

<<interface>> DBAccessor + getGC(gcId : int) :GiftCard + saveGC(card : GiftCard) :void

TestGoodDBAccessor + getGC(gcId : int) :GiftCard + saveGC(card : GiftCard) :void MySqlDBAccessor

+ getGC(gcId : int) :GiftCard + saveGC(card : GiftCard) :void

TestInsufficientDBAccessor + getGC(gcId : int) :GiftCard + saveGC(card : GiftCard) :void

TestInvalidDBAccessor + getGC(gcId : int) :GiftCard + saveGC(card : GiftCard) :void

Order DB Utilities

processOrd er(...)

saveGC(...) updat e amnt ...

check balan ces, etc.

saveOrder(. ..) insert in

to ...

White-box testing

table of contents

xviii

Holding your code accountable

8 Sometimes it’s all about setting expectations. Good code needs to work, everyone knows that. But how do you know your code works? Even with unit testing, there are still parts of most code that goes untested. But what if testing was a

fundamental part of software development? What if you did everything with testing in

mind? In this chapter, you’ll take what you know about version control, CI, and automated

testing and tie it all together into an environment where you can feel confident about

fixing bugs, refactoring, and even reimplementing parts of your system.

test-driven development

Test FIRST, not last 276

So we’re going to test FIRST... 277

Welcome to test-driven development 277

Your first test... 278

...fails miserably. 279

Get your tests to GREEN 280

Red, green, refactor... 281

In TDD, tests DRIVE your implementation 286

Completing a task means you’ve got all the tests you need, and they all pass

288

When your tests pass, move on! 289

Simplicity means avoiding dependencies 293

Always write testable code 294

When things get hard to test, examine your design 295

The strategy pattern provides formultiple implementations

of a single interface 296

Keep your test code with your tests 299

Testing produces better code 300

More tests always means lots more code 302

Strategy patterns, loose couplings, object stand ins... 303

We need lots of different, but similar, objects 304

What if we generated objects? 304

A mock object stands in for real objects 305

Mock objects are working object stand-ins 306

Good software is testable... 309

It’s not easy bein’ green... 310

A day in the life of a test-driven developer... 312

Tools for your Software Development Toolbox 314

table of contents

xix

It’s all coming together...

You’re almost finished! The team’s been working hard and things are

wrapping up. Your tasks and user stories are complete, but what’s the best way

to spend that extra day you ended up with? Where does user testing fit in?

Can you squeeze in one more round of refactoring and redesign? And there

sure are a lot of lingering bugs... when do those get fixed? It’s all part of the

end of an iteration... so let’s get started on getting finished.

ending an iteration

Your iteration is just about complete... 318

...but there’s lots left you could do 319

System testing MUST be done... 324

...but WHO does system testing? 325

System testing depends on a complete system to test 326

Good system testing requires TWO iteration cycles 327

More iterations means more problems 328

Top 10 Traits of Effective System Testing 333

The life (and death) of a bug 334

So you found a bug.... 336

Anatomy of a bug report 337

But there’s still plenty left you COULD do... 338

Time for the iteration review 342

Some iteration review questions 343

A GENERAL priority list for getting EXTRA things done... 344

Tools for your Software Development Toolbox 346

9

table of contents

xx

If it ain’t broke...you still better fix it

10 Think things are going well? Hold on, that just might change... Your iteration went great, and you’re delivering working software on-time.

Time for the next iteration? No problem, right? Unfortunately, not right at

all. Software development is all about change, and moving to your next

iteration is no exception. In this chapter you’ll learn how to prepare for the

next iteration. You’ve got to rebuild your board and adjust your stories

and expecations based on what the customer wants NOW, not a month ago.

the next iteration

What is working software? 350

You need to plan for the next iteration 352

Velocity accounts for... the REAL WORLD 359

And it’s STILL about the customer 360

Someone else’s software is STILL just software 362

Customer approval? Check! 365

Testing your code 370

Houston, we really do have a problem... 371

Trust NO ONE 373

It doesn’t matter who wrote the code.

If it’s in YOUR software, it’s YOUR responsibility. 373

You without your process 378

You with your process 379

table of contents

xxi

Squashing bugs like a pro

Your code, your responsibility...your bug, your reputation!

When things get tough, it’s up to you to bring them back from the brink. Bugs, whether

they’re in your code or just in code that your software uses, are a fact of life in software

development. And, like everything else, the way you handle bugs should fit into the rest

of your process. You’ll need to prepare your board, keep your customer in the loop,

confidently estimate the work it will take to fix your bugs, and apply refactoring and

prefactoring to fix and avoid bugs in the future.

bugs

Previously on Iteration 2 386

First, you’ve got to talk to the customer 386

Priority one: get things buildable 392

We could fix code... 394

...but we need to fix functionality 395

Figure out what functionality works 396

NOW you know what’s not working 399

What would you do? 399

Spike test to estimate 400

What do the spike test results tell you? 402

Your team’s gut feel matters 404

Give your customer the bug fix estimate 406

Things are looking good... 410

...and you finish the iteration successfully! 411

AND the customer is happy 412

Tools for your Software Development Toolbox 414

11

table of contents

xxii

Having a process in life

12 You’ve learned a lot about Software Development. But before you go pinning burn down graphs in everyone’s office, there’s just a little more you need to know about dealing with each project... on its own terms. There are a lot of similarities

and best practices you should carry from project to project, but there are unique things

everywhere you go, and you need to be ready for them. It’s time to look at how to apply

what you’ve learned to your particular project, and where to go next for more learning.

the real world

Pinning down a software development process 418

A good process delivers good software 419

Formal attire required... 424

Some additional resources... 426

More knowledge == better process 427

Tools for your Software Development Toolbox 428

Story and Burn Down board

User Stories

Configuration

Management (CM)

Continuous Integration (CI)

Test Driven Development (TDD)

Test Coverage

Each class is l isted individua

lly

(broken up by package) One measure of test

ing coverage is line coverage-what

percentage of the total lines

of code are we executing

through our tests?

Another m easure is

branch co verage-

hat perce ntage of

the alter nate flow

s

(ifs, elses , etc.) ar

e

we execut ing?

table of contents

xxiii

The top 5 things (we didn’t cover)

Ever feel like something’s missing? We know what you mean...

Just when you thought you were done... there’s more. We couldn’t leave you without a few

extra things, things we just couldn’t fit into the rest of the book. At least, not if you want to

be able to carry this book around without a metallic case and castor wheels on the bottom.

So take a peek and see what you (still) might be missing out on.

appendix 1: leftovers

#1. UML class Diagrams 434

#2. Sequence diagrams 436

#3. User stories and use cases 438

#4. System tests vs. unit tests 440

#5. Refactoring 441

i

Airplane - speed :int

+ getSpeed() :int + setSpeed(speed : int) :void

Send a picture t o

other users

Click on the “Se nd a Picture”

but ton to send a picture (only JP

EG needs to be

supported) to th e other users. Th

e other user

should have the option to not a

ccept the file.

There are no siz e limits on the f

ile being sent.

Descriptio n:

Priority: Estimate:

Title:

20 4

table of contents

xxiv

Tools for the experienced software developer

Ever wished all those great tools and techniques were

in one place? This is a roundup of all the software development

techniques and principles we’ve covered. Take a look over them all, and

see if you can remember what each one means. You might even want to

cut these pages out and tape them to the bottom of your big board, for

everyone to see in your daily standup meetings.

appendix 2: techniques and principles

Development Techniques 444

Development Principles 446

ii

this is a new chapter 177

Alright guys, listen up. Bob’s writing new code. You’ve got to keep him safe, no matter what happens, understand?

version control6

Defensive development

When it comes to writing great software, Safety First! 

Writing great software isn’t easy...especially when you’ve got to make sure your code

works, and make sure it keeps working. All it takes is one typo, one bad decision

from a co-worker, one crashed hard drive, and suddenly all your work goes down the

drain. But with version control, you can make sure your code is always safe in a

code repository, you can undo mistakes, and you can make bug fixes—to new and

old versions of your software.

When it comes to writing great software, Safety First! 

Writing great software isn’t easy...especially when you’ve got to make sure your code

works, and make sure it keeps working. All it takes is one typo, one bad decision

from a co-worker, one crashed hard drive, and suddenly all your work goes down the

drain. But with version control, you can make sure your code is always safe in a

code repository, you can undo mistakes, and you can make bug fixes—to new and

old versions of your software.

178 Chapter 6

You’ve got a new contract—BeatBox Pro Congratulations—you’ve been getting rave reviews from iSwoon, and you’ve landed a new contract.

You’ve been hired to add two new features to the legendary Head First Java BeatBox project. BeatBox

is a multi-player drum machine that lets you send messages and drum loops to other users over the

network.

Like every other software development project out there, the customer wants things done as soon as

possible. They even let you bring along Bob, one of your junior developers, to help out. Since the

stories aren’t big enough to have more than one person work on them at a time, you’ll work on one

and Bob will work on the other. Here are the user stories for the new features you’ve got to add:

You’ll take

tasks associa ted

with this sto ry.

The BeatBox program from Head First Java, our starting point.

*You can download the code that we’re starting with from http://www.headfirstlabs.com/books/hfsd/

Bob will pull tasks from this story.

Send a picture to other users

Click on the “Send a Picture” but ton to send a picture (only JPEG needs to be supported) to another user. The other user should have the option to not accept the file. There are no size limits on the file being sent.

Description:

Priority: Estimate:

Title:

20 4

Send a Poke t o

other users

Click on the “ Send a Poke”

but ton to sen d an audible a

nd visual aler t to the

other membe rs in the chat

. The alert sh ould be

short and not too annoying

—you’re just tr ying

to ge t their a t tention.

Descript ion:

Priority: Estimate

:

Title:

20

3

introducing beatbox pro

you are here 4    179

version control

Task Magnets Let’s get right to the new features. Here’s a snippet from the

BeatBox client code. Your job is to map the task stickies to the

code that implements each part of the “Send a Poke...” story. We’ll

get to the GUI work in a minute.

// ... more BeatBox.java code a bove this

public class RemoteReader imple ments Runnable {

boolean[] checkboxState = nul l;

String nameToShow = null;

Object obj = null;

public void run() {

try {

while((obj=in.readObject( )) != null) {

System.out.println("got an object from server");

System.out.println(obj. getClass());

String nameToShow = (St ring) obj;

checkboxState = (boolea n[]) in.readObject();

if (nameToShow.equals(P OKE_START_SEQUENCE)) {

playPoke();

nameToShow = "Hey! Pa y attention.";

}

otherSeqsMap.put(nameTo Show, checkboxState);

listVector.add(nameToSh ow);

incomingList.setListDat a(listVector);

} // close while

} catch (Exception ex) { ex .printStackTrace(); }

} // close run

private void playPoke() {

Toolkit.getDefaultToolkit() .beep();

}

} // close inner class

Task 1 MDE

Sound an audible alert

when receiving a poke

message (can’t be

annoying!) .5

Task 2 LUG Add support for checking for the Poke command and creating a message.

.5

Task 3 MDE

Implement receiver code to read the data off of the network. 1

Task 4 BJ D

Merge Poke visua l

alert into messag e

display system.

.5

Stickies ask Magnets

180 Chapter 6

// ... more Bea tBox.java code

above this

public class Re moteReader impl

ements Runnable {

boolean[] che ckboxState = nu

ll;

String nameTo Show = null;

Object obj = null;

public void r un() {

try {

while((ob j=in.readObject

()) != null) {

System. out.println("go

t an object fro m server");

System. out.println(obj

.getClass());

String nameToShow = (S

tring) obj;

checkbo xState = (boole

an[]) in.readOb ject();

if (nam eToShow.equals(

POKE_START_SEQU ENCE)) {

playP oke();

nameT oShow = "Hey! P

ay attention.";

}

otherSe qsMap.put(nameT

oShow, checkbox State);

listVec tor.add(nameToS

how);

incomin gList.setListDa

ta(listVector);

} // clos e while

} catch (Ex ception ex) { e

x.printStackTra ce(); }

} // close ru n

private void playPoke() {

Toolkit.get DefaultToolkit(

).beep();

}

} // close inne r class

Task Magnets Solution We’re not in Head First Java anymore; let’s get right to the new features.

Here’s a snippet from the BeatBox client code. Your job was to map the task

magnets to the code that implements each part of the “Send a Poke...” story.

This is th e inner cl

ass

that rece ives data

from

the serve r.

Here’s the code that will run in the new thread context for BeatBox.

This is original

code-it reads

messages sent

from the serve r.

If we get the POKE_START_SEQUENCE, we play the poke sound and replace the message with our alert text.

Here’s our new playPoke() method that just beeps for now. If you want a real challenge, add MP3 poke-sound support.

All of this co de goes into

BeatBox.java .

digging into code

Task 1 MDE

Sound an audible alert

when receiving a poke

message (can’t be

annoying!) .5

Task 2 LUG Add support for checking for the Poke command and creating a message.

.5

Task 3 MDE

Implement receiver code to read the data off of the network. 1

Task 4 BJ D

Merge Poke visua l

alert into messag e

display system.

.5

Stickies ask Magnets Solut

you are here 4    181

version control

Bob’s making good progress on his end, too. Can you think of

anything else you should be worrying about at this point?

Q: This isn’t a Java programming book. Why are we wasting time looking

through all this code?

A: Software development techniques cover everything related to a project, from

organization and estimation down through

code. Earlier, we talked about the planning

and execution parts of a project, and then

we got a little closer to code and talked

about design. Now, we need to dive all the

way down and talk about some tools and

techniques you can use on your code

itself. Software development isn’t just about

prioritization and estimation; you’ve still got

to write good, working, reliable code.

Q: I don’t develop in Java. I’m not sure what some of the code in there does.

What do I do?

A: That’s OK. Do your best to understand what the code is doing, and don’t worry

about all the Java-specific details. The main

thing is to get an idea of how to handle

and think about code in a solid software

development process. The tools and

techniques we’ll talk about should make

sense whether you know what a Java thread

is or not.

Q: I think I must have...misplaced... my copy of Head First Java. What’s this

whole BeatBox thing about?

A: BeatBox is a program first discussed in Head First Java. It has a backend

MusicServer and a Java Swing– based client piece (that’s Java’s graphical

toolkit API). The client piece uses the Java

Sound API to generate sound sequences

that you can control with the checkboxes

on the form’s main page. When you enter a

message and click “sendit,” your message

and your BeatBox settings are sent to any

other copies of BeatBox connected to your

MusicServer. If you click on the received message, then you can hear the

new sequence that was just sent.

Q: So what’s the deal with that POKE_START_SEQUENCE thing?

A: Our story requires us to send a poke message to the other BeatBoxes connected

to the MusicServer. Normally when a message gets sent it’s just a string that is

displayed to the user. We added the Poke

functionality on top of the original BeatBox

by coming up with a unique string of

characters that no one should ever type

on purpose. We can use that to notify the

other BeatBoxes that a “poke” was sent.

This sequence is stored in the POKE_

START_SEQUENCE constant (the actual

string value is in the BeatBox.java file in the code you can download from http://

www.headfirstlabs.com/books/hfsd/).

When other BeatBox instances see the

POKE_START_SEQUENCE come through, they replace it with our visual alert

message, and the receiving user never

actually sees that code sequence.

Q: What’s all this threading and Runnable stuff about?

A: BeatBox is always trying to grab data from the network so it can display incoming

messages. However, if there’s nothing

available on the network, it could get stuck

waiting for data. This means the screen

wouldn’t redraw and users couldn’t type in a

new message to send. In order to split those

two things apart, BeatBox uses threads.

It creates a thread to handle the network

access, and then uses the main thread to

handle the GUI work. The Runnable interface is Java’s way of wrapping up some

code that should be run in another thread.

The code you just looked at, in the last

exercise, is the network code.

182 Chapter 6

// The code below goes in BeatBox.java, // in the buildGUI() method JButton sendIt = new JButton("sendIt");

sendIt.addActionListener(new MySendListener());

buttonBox.add(sendIt);

JButton sendPoke = new JButton("Send Poke");

sendPoke.addActionListener(new MyPokeListener());

buttonBox.add(sendPoke);

userMessage = new JTextField();

buttonBox.add(userMessage);

// Below is new code we need to add, also to BeatBox.java public class MyPokeListener implements ActionListener {

public void actionPerformed(ActionEvent a) {

// We'll create an empty state array here

boolean[] checkboxState = new boolean[255];

try {

out.writeObject(POKE_START_SEQUENCE);

out.writeObject(checkboxState);

} catch (Exception ex) {

System.out.println("Failed to poke!");

}

}

}

First we need to create a

new

button for o ur Poke featu

re.

Then we set up a listener so we can react when it’s clicked.

Finally, add the button to the box holding the other buttons.

Here we create an array of booleans for our state. We can leave them all false because the receiving side ignores them when it gets the POKE command.

Here’s the magic : to send a poke

we send the

magic POKE_ST ART_SEQUENC

E and our array

of booleans to t he server. The s

erver will relay

our magic seque nce to the othe

r clients, and

they’ll beep at the user becaus

e of the earlier

code we wrote (back on page 1

80).

finish the story

And now the GUI work... We need one more piece of code to get this story together. We need to add a

button to the GUI that lets the user actually send the Poke. Here’s the code to take

care of that task: Task 5 <YOU>

Add button to GUI to send Poke sequence to other BeatBox instances. .5

you are here 4    183

version control

And a quick test... Now that both the client and server are implemented it’s time to make sure

things work. No software can go out without testing so...

First compile and start up the MusicServer.11

Then start the new BeatBox—we’ll need two instances running so

we can test the Poke.

22

Now send off a Poke by clicking the “Send Poke” button on the instance

we named PokeSender.

33

Hey! Pay attention.

Here’s our new Poke button.

Here’s our aler t message. DIN

G! (Se riously

,. it

sounds like t

hat.)

Excellent! Your changes work as advertised. We’ll copy the code up to the demo server, and all that’s left

is for Bob to merge his stuff in. Time to call it a night.

We use different names here

so we know which is which.

The MusicServ er

will listen for

connections and

print out a line

each time it

gets one.The “-d” tells the java compiler to put the classes in the bin directory.

hfsd> mkdir bin

hfsd> javac -d bin src\headfirst\sd\chapter6\*.java

hfsd> java -cp bin headfirst.sd.chapter6.MusicServer

File Edit Window Help Buildin’

hfsd> java -cp bin headfirst.sd.chapter6.BeatBox PokeReceiver File Edit Window Help Ouch

hfsd> java -cp bin headfirst.sd.chapter6.BeatBox PokeSender File Edit Window Help Hah

Here’s our PokeReceiver instance.

184 Chapter 6

Title: Send a Pok

e to

other user s

Task 1 Implement sender

side Poke button and

sequence.

1

Task 2 Implement

server sid e

reception and playin

g

of alert m essage.

1.5

Completed

Title: Send a picture to other users

Task 3 Implement imag

e

selection dialog .

5

Task 4 Implement sender side send picture button and loading code.

1

Task 5 Implement receiver

side image reception

and displaying code.

2.5

And Bob does the same... Bob finished up the tasks related to his story and ran a quick test on his end. His task

is working, so he copies his code up to the server. In order to do the final build he

merges his code in with ours, gets everything to compile, and retests sending a picture.

Everything looks good. Tomorrow’s demo is going to rock...

Here’s Bob’s version of BeatBox—the SendPicture button is implemented.

Bob’s happy with the code so he copies it up to the demo server. After the build is done, things are ready for tomorrow.

Once the tasks are finished move the stories over to Completed.

Q: I’m not familiar with networking code. What’s happening in that code we just added?

A: On the sending side we represent the sequence settings as an array of checkboxes. We don’t really care what they’re set

to, since we won’t use them on the receiving side. We still need

to send something, though, so the existing code works. We use

Java’s object serialization to stream the array of checkboxes

and our secret message that triggers the alert on the other side.

On the receiving side we pull off the secret sequence and the

array of checkboxes. All of the serialization and deserialization

is handled by Java.

Q: Why did we make the bin directory before we compiled the code?

A: We’ll talk more about this in the next chapter, but in general it’s a good idea to keep your compiled code separate

from the source. It makes it a lot simpler to clean up and rebuild

when you make changes. There’s nothing special about the

name “bin”; it’s just convention and is short for “binaries”—i.e.,

compiled code.

Q: Wait, did Bob just merge code on the demo server? A: Yup...

merging changes

you are here 4    185

version control

Demo the new BeatBox for the customer We’re all set to go. Your code is written, tested, and copied up to

the demo server. Bob did the final build, so we call the customer

and prepare to amaze the crowds.

Here’s our button—and the “Send Picture” button is from Bob’s code.

Uh oh, this doesn’t loo

k good.

What’s goin g on?

I’m not hearing any alert. And what’s SECRET_POKE_

SEQUENCE? I’m not impressed.

So what went wrong?

Our code worked just a few pages ago. So what

went wrong? More importantly, what would

you do differently in the future to make sure

nothing like this ever happens again?

Unhappy cu stomer.

Not good.

Think beyond, “Do more testing.” How can you prevent this problem from occurring in the first place?

186 Chapter 6

Something’s clearly gone wrong. Below is some code we compiled on our machine

and the same section of code from the demo machine. See if you can figure out what

happened.

Here’s the code from

our machine—it worke d

fine when we ran it.

And here’s the code on the demo server—the code that tanked.

What went wrong?

How did this happen?

What would you do?

public cla ss RemoteR

eader impl ements Run

nable {

boolean[ ] checkbox

State = nu ll;

String n ameToShow

= null;

Object o bj = null;

public v oid run()

{

try {

whil e((obj=in.

readObject ()) != nul

l) {

Sy stem.out.p

rintln("go t an objec

t from ser ver");

Sy stem.out.p

rintln(obj .getClass(

));

St ring nameT

oShow = (S tring) obj

;

ch eckboxStat

e = (boole an[]) in.r

eadObject( );

if (nameToSh

ow.equals( POKE_START

_SEQUENCE) ) {

playPoke()

;

nameToShow

= "Hey! P ay attenti

on.";

}

ot herSeqsMap

.put(nameT oShow, che

ckboxState );

li stVector.a

dd(nameToS how);

in comingList

.setListDa ta(listVec

tor);

} // close whi

le

} catc h (Excepti

on ex) { e x.printSta

ckTrace(); }

} // clo se run

public class RemoteReader implements Runnable { boolean[] checkboxState = null; String nameToShow = null; Object obj = null;

public void run() { try { while ((obj = in.readObject()) != null) { System.out.println("got an object from server"); System.out.println(obj.getClass()); String nameToShow = (String) obj; checkboxState = (boolean[]) in.readObject(); if (nameToShow.equals(PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); } } // close while } catch (Exception ex) { ex.printStackTrace(); } } // close run

disaster recovery

you are here 4    187

version control

Mark: Wow. Bob really blew it with that demo.

Bob: What are you talking about? My code worked!

Laura: But you broke the other story we were trying to demo! It

worked fine before you got to it.

Bob: Wait a minute—why am I getting blamed for this? You asked me

to copy my code up to the demo server so we could build it. When I did

that, I saw you guys had changed a lot of the same stuff. It was a mess.

Mark: So you just overwrote it??

Bob: No way—I spent a bunch of time comparing the files trying to

figure out what you had changed and what I had changed. To make

things worse, you guys had some variables renamed in your code so I

had to sort that out, too. I got the button stuff right, but I guess I missed

something in the receiver code.

Laura: So do we still have the working Poke code on there?

Bob: I doubt it. I copied my stuff up with a new name and merged

them into the files you had up there. I didn’t think to snag a copy of

your stuff.

Mark: Not good. I probably have a copy on my machine, but I don’t

know if it’s the latest. Laura, do you have it?

Laura: I might, but I’ve started working on new stuff, so I’ll have to

try and back all my changes out. We really need to find a better way to

handle this stuff. This is costing us a ton of time to sort out and we’re

probably adding bugs left and right...

Standup meeting

Your team , after t

he big

flop at t he custom

er demo

Not to mention we’re going the wrong way on our burn- down rate again.

188 Chapter 6

Let’s start with VERSION CONTROL

Keeping track of source code (or any kind of files for that matter)

across a project is tricky. You have lots of people working on

files—sometimes the same ones, sometimes different. Any serious

software project needs version control, which is also often called

configuration management, or CM for short.

Version control is a tool (usually a piece of software) that will keep

track of changes to your files and help you coordinate different

developers working on different parts of your system at the same

time. Here’s the rundown on how version control works:

“Check out” means you get a copy of BeatBox.java that you can work on.

I need the BeatBox.java file.

The server runn ing

version control s oftware

Bob’s Mac hine

I need the BeatBox.java file, too.

Found it, here ya go…

The version control server looks up files and returns the latest version to the developers.

Other people can get

a copy of the origin al

file while Bob works

on his changes on his

local machine.

Bob checks out BeatBox.java

from the server.

11

Bob makes some

changes to the code and

tests them.

22

The rest of your team can check

out Version 1 of BeatBox.java

while Bob works on his version.

1.51.5

Foun d it

, he re y

a go …

version control in action

You’ll also see this refe rred to as

configuration managem ent, which is a little

more formal term for the same thing.

you are here 4    189

version control

All done!

Checking the code back in means your changes are sent to the server so others can get them.

Some systems prevent other people from modifying the file that’s being edited by someone, while other systems handle merging the changes.

I need the latest BeatBox.java file.

Foun d it

, he re y

a go …

Q: So if version control is a piece of software, which version control product

should I use?

A: There are lots of choices out there for version control tools, both commercial and

open source. One of the most popular open

source ones is called Subversion, and that’s

the one we’ll use in this chapter. Microsoft

tools such as Visual Studio like to work

with Microsoft’s version control tool, called

Visual SourceSafe, or Microsoft’s new Team

Foundation product.

Version control tools all do pretty much the

same thing, but some offer different ways

to do it. For example, some commercial

systems have strict access control on

where you can commit code so that your

organization can control what goes into what

build. Other tools show you the different

versions of files as virtual directories.

Q: You’re only showing one file and two developers. I’m guessing it can do

more than that, right?

A: You bet. In fact, a good version control tool is really the only way you can scale

a team. We’ll need some of those more

sophisticated features (like merging changes,

tagging versions, etc.) in just a minute...

Bob checks in his changes.33

After Bob checks in his changes, the team

can get an update from the server with

the new code.

3.53.5

190 Chapter 6

hfsd> svn import Chapter6 file:///c:/Users/Developer/Desktop/ SVNRepo/BeatBox/trunk -m “Initial Import”

Adding Chapter6\src

Adding Chapter6\src\headfirst

Adding Chapter6\src\headfirst\sd

Adding Chapter6\src\headfirst\sd\chapter6

Adding Chapter6\src\headfirst\sd\chapter6\BeatBox.java

Adding Chapter6\src\headfirst\sd\chapter6\MusicServer.java

Committed revision 1.

hfsd>

File Edit Window Help Tariffs

First set up your project... The first step in using a version control tool is to put

your code in the repository; that’s where your code is

stored. There’s nothing tricky about putting your code in

the repository, just get the original files organized on your

machine and create the project in the repository:

We’re assuming you’ve got your version control software installed. If not, you can download it from the Subversion web site.

* You can get the full Subversion documentation here: http://svnbook.red-bean.com/

First create the repository—you

only need to do this once for

each version control install.

After that you just add projects

to the same repository.

11

...in this directory. This tells Subversion to create a new repository...

After that runs, we have our repository. Next you need to import your code into the

repository. Just go to the directory above

your code and tell your version control

server to import it. So, for your BeatBox

project, you’d go to the directory that

contains your beat box code. If you’re using

the downloaded files, that directory is called

Chapter6:

22

Now you w ant all you

r

code in tha t repositor

y, in

a project c alled BeatB

ox.

Here you tell Subve

rsion

to import your cod

e. This is the repository you crea

ted

in step 1. On Windows you’ll nee d to

use forward slash notation.

Here’s what we want our project to be called—ignore the “trunk” thing for right now.

This is just a comment describing what we’re doing; we’ll talk more about this later, too.

Subversion adds each file it finds into your repository for the BeatBox project.

hfsd> svnadmin create c:\Users\Developer\Desktop\SVNRepo

hfsd>

File Edit Window Help TakeBacks

creating a repository

you are here 4    191

version control

...then you can check code in and out. Now that your code is in the repository, you can check it out, make your changes, and check

your updated code back in. A version control system will keep track of your original code, all

of the changes you make, and also handle sharing your changes with the rest of your team.

First, check out your code (normally your repository wouldn’t be on your local machine):

To check out your code,

you just tell your version

control software what

project you want to

check out, and where

to put the files you

requested.

11

Subversion pulls your files back out of the repository and copies them into a new BeatBox directory (or an existing one if you’ve already got a BeatBox directory).

Now you can make changes to the code

just like you normally would. You just work

directly on the files you checked out from your

version control system, compile, and save.

22 You can re-implement t he Poke

story, since Bob broke tha t

feature when he wrote co de for

the Send Picture story.

Then you commit

your changes back into

the repository with a

message describing what

changes you’ve made.

33

// ... the code below is from BeatBoxFinal.java buildGUI() ... JButton sendIt = new JButton("sendIt"); sendIt.addActionListener(new MySendListener()); buttonBox.add(sendIt);

JButton sendPoke = new JButton("Send Poke"); sendPoke.addActionListener(new MyPokeListener()); buttonBox.add(sendPoke);

userMessage = new JTextField(); buttonBox.add(userMessage);

// ... this is new code we need to add to BeatBoxFinal.java ... public class MyPokeListener implements ActionListener {

public void actionPerformed(ActionEvent a) {

// We'll

create an empty state array here

boolean[]

checkboxState = new boolean[256];

try {

out.writeObject(POKE_SEQUENCE);

out.writeObject(checkboxState);

} catch

(Exception ex) { System.out.println("Failed to poke!"); }

} }

This is a normal .java file. Subversion doesn’t change it in any way...it’s still just code.

hfsd> svn checkout file:///c:/Users/Developer/Desktop/SVNRepo/ BeatBox/trunk BeatBox

A BeatBox\src

A BeatBox\src\headfirst

A BeatBox\src\headfirst\sd

A BeatBox\src\headfirst\sd\chapter6

A BeatBox\src\headfirst\sd\chapter6\BeatBox.java

A BeatBox\src\headfirst\sd\chapter6\MusicServer.java

Checked out revision 1.

hfsd>

File Edit Window Help Gimme

This tells Subversion to check

out a copy of the code. This pulls code from the BeatBox project in the repository and puts it in a local directory called BeatBox.

hfsd> svn commit -m “Added POKE support.”

Sending src\headfirst\sd\chapter6\BeatBox.java

Transmitting file data .

Committed revision 2.

hfsd>

File Look What IDid

This tells Subversion to commit your

changes; it will figure out what files

you’ve changed. This is a log message, indicating what you did.

Since you only changed one file, that’s all that subversion sent to the repository—and notice that now you have a new revision number.

192 Chapter 6

public class RemoteReader implements Runnable {

boolean[] checkboxState = null;

String nameToShow = null;

Object obj = null;

public void run() {

try {

while ((obj = in.readObject()) != null) {

System.out.println("got an object from server");

System.out.println(obj.getClass());

String nameToShow = (String) obj;

checkboxState = (boolean[]) in.readObject();

if (nameToShow.equals(PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); // now reset the sequence to be this } } // close while } catch (Exception ex) {

ex.printStackTrace();

}

} // close run

} // close inner class

public class RemoteReader implements Runnable {

boolean[] checkboxState = null;

String nameToShow = null;

Object obj = null;

public void run() {

try {

while((obj=in.readObject()) != null) {

System.out.println("got an object from server");

System.out.println(obj.getClass());

String nameToShow = (String) obj;

checkboxState = (boolean[]) in.readObject();

if (nameToShow.equals(POKE_START_SEQUENCE)) { playPoke(); nameToShow = "Hey! Pay attention."; } otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); } // close while } catch(Exception ex) {ex.printStackTrace();}

} // close run

private void playPoke() { Toolkit.getDefaultToolkit().beep(); } } // close inner class

Most version control tools will try and solve problems for you Suppose you had a version control system in place before the great BeatBox debacle

of ’08. You’d check in your code (with commit) to implement Send Poke, and then

Bob would change his code, and try to commit his work on Send Picture:

// ... the code below is from BeatBoxFinal.java buildGUI() ... JButton sendIt = new JButton("sendIt"); sendIt.addActionListener(new MySendListener()); buttonBox.add(sendIt);

JButton sendPoke = new JButton("Send Poke"); sendPoke.addActionListener(new MyPokeListener()); buttonBox.add(sendPoke);

userMessage = new JTextField(); buttonBox.add(userMessage);

// ... this is new code we need to add to BeatBoxFinal.java ... public class MyPokeListener implements ActionListener {

public void actionPerformed(ActionEvent a) {

//

We'll create an empty state array here

boolean[] checkboxState = new boolean[256];

try

{

out.writeObject(POKE_SEQUENCE);

out.writeObject(checkboxState);

}

catch (Exception ex) { System.out.println("Failed to poke!"); }

} }

Here’s your code—safe and sound in the repository.

svn commit -m "Added pictures."

public class RemoteReader implements Runnable { boolean[] checkboxState = null; String nameToShow = null; Object obj = null;

public void run() { try { while ((obj = in.readObject()) != null) { System.out.println("got an object from server"); System.out.println(obj.getClass()); String nameToShow = (String) obj; checkboxState = (boolean[]) in.readObject(); if (nameToShow.equals(PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); // now reset the sequence to be this } } // close while } catch (Exception ex) { ex.printStackTrace(); } } // close run

Bob tries to check in his code...

Bob’s picture sending implementation

...but quickly runs into a problem. You and Bob both made changes to the same file; you just got yours into the repository first. Bob’s cod e

The code on the server, with your changes

Bob’s BeatBox.java BeatBox.java

merging changes

you are here 4    193

version control

The server tries to MERGE your changes If two people make changes to the same file but in different places,

most version control systems try to merge the changes together. This

isn’t always what you want, but most of the time it works great.

Nonconflicting code and methods are easy In BeatBox.java, you added a playPoke() method, so the code

on the version control server has that method. But Bob’s code has no

playPoke() method, so there’s a potential problem.

Bob’s BeatBox.java

Nothing here... Bob has no code for playPoke() at all.

BeatBox.java

The version on the server has a playPoke() method.

Your version control software will combine files

In a case like this, your version control server can simply combine

the two files. In other words, the playPoke() method gets

combined with nothing in Bob’s file, and you end up with a

BeatBox.java on the server that still retains the playPoke()

method. So no problems yet...

But conflicting code IS a problem

But what if you have code in the same method that is different? That’s

exactly the case with Bob’s version of BeatBox.java, and the

version on the server, in the run() method:

if (nameToShow.equals(PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); }

BeatBox.java Bob’s BeatBox.java

These two bits of code are in the same place, but it’s not clear how to merge them.

private void playPoke() { Toolkit.getDefaultToolkit().beep(); }

if (nameToShow.equals(POKE_START_SEQUENCE)) { playPoke(); nameToShow = "Hey! Pay attention."; } otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector);

194 Chapter 6

public class RemoteReader implements Runnable {

boolean[] checkboxState = null;

String nameToShow = null;

Object obj = null;

public void run() {

try {

while ((obj = in.readObject()) != null) {

System.out.println("got an object from server");

System.out.println(obj.getClass());

String nameToShow = (String) obj;

checkboxState = (boolean[]) in.readObject();

if (nameToShow.equals(PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); // now reset the sequence to be this } } // close while } catch (Exception ex) {

ex.printStackTrace();

}

} // close run

} // close inner class

public class RemoteReader implements Runnable {

boolean[] checkboxState = null;

String nameToShow = null;

Object obj = null;

public void run() {

try {

while((obj=in.readObject()) != null) {

System.out.println("got an object from server");

System.out.println(obj.getClass());

String nameToShow = (String) obj;

checkboxState = (boolean[]) in.readObject();

if (nameToShow.equals(POKE_START_SEQUENCE)) { playPoke(); nameToShow = "Hey! Pay attention."; } otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); } // close while } catch(Exception ex) {ex.printStackTrace();}

} // close run

private void playPoke() { Toolkit.getDefaultToolkit().beep(); } } // close inner class

If your software can’t merge the changes, it issues a conflict If two people made changes to the same set of lines, there’s no way for a

version control system to know what to put in the final server copy. When

this happens, most systems just punt. They’ll kick the file back to the

person trying to commit the code and ask them to sort out the problems.

Subversion rejects your commit. You can use the update command to pull the changes into your code, and Subversion will mark the lines where there are conflicts in your files... after you sort out the conflicts, you can recommit.

BeatBox.java

Bob’s BeatBox.java

Your version control software doesn’t know

what to do with this conflicting code, so to protect everyone, it refuses to commit the new code, and marks up where problems

might be.

identifying conflicts

you are here 4    195

version control

Conflict Resolution: Here’s the file the version control software kicked back to Bob, with all the

conflicts marked. What should the final code look like that Bob commits back in?

Files with conflicts get both the loca l changes (Bob’s

changes) and the changes from the se rver. The ones

between “<<<<<<< .mine" and the == =’s are Bob’s—

the ones after that up to the “>>>> >>> .r2” are the

ones from the server.

public class RemoteReader implements Runnable {

// variable declarations

public void run() {

try {

// code without problems

<<<<<<< .mine

if (nameToShow.equals( PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { otherSeqsMap.put( nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); // now reset the sequence to be this } ======= if (nameToShow.equals( POKE_START_SEQUENCE)) { playPoke(); nameToShow = "Hey! Pay attention."; } otherSeqsMap.put( nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); >>>>>>> .r2 } // close while // more code without problems

} // close run

} // close inner class

public class RemoteReader implements

Runnable {

// variable declarations

public void run() {

try {

// code without problems

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

} // close while // more code without problems

} // close run

} // close inner class

196 Chapter 6

Conflict Resolution: Here’s the file version control kicked back to Bob with both changes in it.

What should the final section look like that Bob commits back in?

Make these changes to your own copy of

BeatBox.java, and commit them to

your code repository:

hfsd> svn resolved src/headfirst/sd/chapter6/BeatBox.java

Resolved conflicted state of ‘BeatBox.java’

hfsd> svn commit -m “Merged picture support with Poke stuff.”

Sending src\headfirst\sd\chapter6\BeatBox.java

Transmitting file data .

Committed revision 3.

hfsd>

File Edit Window Help Tranquility

First, tell Subversion you resolved the conflict in the file using the “resolved” command and the path to the file.

Now, commit the file to your server, adding a comment indicating what you did.

You can skip this step if you didn’t really get a conflict from Subversion.

public class RemoteReader implements Runnable {

// variable declarations

public void run() {

try {

while ((obj = in.readObject()) != null) {

System.out.println("got an object from server");

System.out.println(obj.getClass());

String nameToShow = (String) obj;

checkboxState = (boolean[]) in.readObject();

if (nameToShow.equals(PICTURE_START_SEQUENCE)) { receiveJPEG(); } else { if (nameToShow.equals(POKE_START_SEQUENCE)) { playPoke(); nameToShow = "Hey! Pay attention."; }

otherSeqsMap.put(nameToShow, checkboxState); listVector.add(nameToShow); incomingList.setListData(listVector); // now reset the sequence to be this } } // close while } catch (Exception ex) {

ex.printStackTrace();

}

} // close run

} // close inner class

We need to support both the picture sequence and the poke sequence so we

need to merge

the conditionals.

Make sure you delete the conflict characters (<<<<<<<, =======, and >>>>>>>).

resolving conflicts

you are here 4    197

version control

Q: I see how checking out and committing works, but how do other people on the team get my changes?

A: Once you’ve got your project checked out, you can run svn update. That tells the version control server to give you the latest versions of all files in the project. Lots of teams run an update every

morning, to make sure they’re current with everyone else’s work.

Q: This whole conflict thing seems pretty hairy. Can’t my version control software do anything besides erroring out?

A: Some can. Certain version control tools work in a file locking mode, which means when you check out files, the system locks

those files so no one else can check them out. Once you make your

changes and check the files back in, the system unlocks the files.

This prevents conflicts, since only one person can edit a file at a time.

But, it also means you might not be able to make changes to a file

when you want to; you might need to wait for someone else to finish

up first. To get around that, some locking version control systems

allow you to check out a file in read-only mode while it’s locked.

But that’s a bit heavy-handed, so other tools like Subversion allow

multiple people to work on the same file at once. Good design, good

division of labor, frequent commits, and good communication help

reduce the number of manual merges you actually have to do.

Q: What is all this trunk business you keep saying to ignore? A: The Subversion authors recommend putting your code into a directory called trunk. Then, other versions would go into a

directory called branches. Once you’ve imported your code, the trunk thing doesn’t really show up again, except during an initial

checkout. We’ll talk more about branches later in the chapter, but for

now, stick with the trunk.

Q: Where are all of my messages going when I do a commit? A: Subversion keeps track of each time you commit changes into the repository and associates your message with those changes.

This lets you look at why people made a certain change—for

instance, if you need to go back and figure out why something was

done. That’s why you should always use a sensible, explanatory

message when you do a commit. The first time you go back through

old commits and find “I changed stuff” as the log message, you’ll be

pretty cranky.

Q: Do I have to commit all of my changes at the same time? A: Nope! Just put the path to the filename on the commit command like you did for the resolved command. Subversion will commit just the file(s) you specify.

Now show the customer...

Ah—there’s that alert sound— and nice pictures too. You guys

really got your stuff together.

Send Poke and Send Picture work.

198 Chapter 6

User Stories

Title: Save a log

file

of chats Task 10 Implement iChat

format and test with

iChat log viewing.

1.5

Task 9 Implement

code

to determ ine host

platform type.

5

Task 8 Implement Wind

ows

Messenger log f ormat

saving and test with

Messenger XSL T 1.5

Task 7 Implement native format log saving and XSLT

1

Task 6 Refactor chat code

to capture messages

for log 1

More iterations, more stories... Things are going well. The customer was happy with our Poke and

Picture support, and after one more iteration, felt we had enough

for Version 1.0. A few iterations later and everyone’s looking

forward to Version 2.0. Just a few more stories to implement...

The customer gave u s

this new user story

(which we’ll have to

break into tasks).

Since we’re get ting into a

new iteration, don’t forget

to update your board.

Just like every other iteration, we start

pulling tasks off of the stories and assigning

them to people. Things are moving along

nicely until...

Save a log file of chats

The user should be able to save a histor y of their chat me ssage s to a file. The file should be compatible with Windows Li ve Me ssenger on Windows, and iChat on a Mac.

Description:

Priority: Estimate:

Title:

40 6

dealing with older code

you are here 4    199

version control

Bob: Hey guys. Good news: I’m just about done with the Windows

Messenger version, and it’s working well. But there’s bad news, too. I just

found a bug in the way images are handled in our Send Picture feature

from way back in the first iteration.

Laura: That’s not good. Can we wait on fixing it?

Bob: I don’t think so—it’s a potential security hole if people figure out

how to send a malicious picture. The users will be pretty annoyed over

this.

Mark: Which means the customer is going to be really annoyed over

this. Can you fix it?

Bob: I can fix it—but I’ve got a ton of code changes in there for the

new story, the log files, that aren’t ready to go out yet.

Laura: So we’re going to have to roll your changes back and send out a

patched 1.0 version.

Mark: What do we roll it back to? We have lots of little changes to

lots of files. How do we know where version 1.0 was?

Bob: Forget version 1.0, what about all of my work?? If you roll back,

you’re going to drop everything I did.

Standup meeting

The team’s in a tough spot—there’s a pretty serious bug in the released

version, but there’s a lot effort invested in the new version. The new

version isn’t ready to go out the way it is. What would you do?

200 Chapter 6

We have more than one version of our software... The real problem here is that we have more than one version of our software—or

more accurately, more than one version of our source code—that we need to make

changes to. We have version 1.0 of the code built and out there, but Bob found a

pretty serious bug. On top of that, we’ve got version 2.0 in the works, but it’s full of

untested, unworking features.

We need to separate them somehow...

You started y our first

iteration here , with

the initial ver sion of

the BeatBox from

Head First Ja va.

Here’s where you wrapped up: Version 1.0 of the software... big shipping party...lots of drinking...how could there be bugs??

BeatBox Pro 1.0

You are here.

The team is wo rking hard

toward 2.0, bu t it’s still too

early in impleme ntation to

consider releasin g anything.

The goal

You’ll always have tension between bugs cropping up in released versions, and new features in upcoming versions. It’s up to you to work with the customer to BALANCE those tensions.

2.0!

Bugs to released versions are usually a higher priority to

the customer than implementing new features.

Your bug fixes should affect released software and still be

implemented in in-progress versions of your software.

Effective bug fixing depends on being able to locate

specific versions of your software and make changes to

those versions without affecting current development.

dealing with multiple releases

you are here 4    201

version control

You keep saying “Version 1.0,” but what does that mean? We’ve committed tons of changes since then into the repository....

By default, your version control software

gives you code from the trunk.

You’re right. When you check out the code from your version control

system, you’re checking it out from the trunk. That’s the latest code

by default and (assuming people are committing their changes on a

regular basis) has all of the latest bugs features.

Version control software stores ALL your code.

Every time you commit code into your version control system, a

revision number was attached to the software at that point. So, if

you can figure out which revision of your software was released as

Version 1.0, you’re good to go.

Remember the trunk

thing that ke eps coming

up? That’s th e place

where all the latest and

greatest code is stored.

But we do have the 1.0 code somewhere, even if it’s not labeled, right? We just have to find it on our server somehow...

Here’s the revision number for this set of changes; it increases with each commit.

Some systems ca ll this the

HEAD or the m ain line.

202 Chapter 6

Good commit messages make finding older software easier You’ve been putting nice descriptive messages each time you committed

code into your version control system, right? Here’s where they matter.

Just as each commit gets a revision number, your version control software

also keeps your commit messages associated with that revision number,

and you can view them in the log:

Play “Find the features” with the log messages You’ve got to figure out which features were in the software—in this case,

for Version 1.0. Then, figure out which revision that matches up with.

Using the log messages above, which revision do you think matches up

with Version 1.0 of BeatBox Pro?

Write down the rev ision

number you want to check

out to get Version 1.0.

hfsd> svn log src/headfirst/sd/chapter6/BeatBox.java

--------------------------------------------------------------------------

r5 | Bob | 2007-09-03 11:45:28 -0400 (Mon, 03 Sep 2007) | 52 lines

Tests and initial implementation of saving message log for Windows.

--------------------------------------------------------------------------

r4 | Bob | 2007-08-27 11:45:28 -0400 (Mon, 27 Aug 2007) | 3 lines

Quick bugfix for 1.0 release to handle cancelling the send picture dialog.

--------------------------------------------------------------------------

r3 | Bob | 2007-08-24 11:45:28 -0400 (Fri, 24 Aug 2007) | 23 lines

Merged picture support with Poke stuff.

--------------------------------------------------------------------------

r2 | Mark | 2007-08-21 11:45:28 -0400 (Tues, 21 Aug 2007) | 37 lines

Added POKE support.

--------------------------------------------------------------------------

r1 | Mark | 2007-08-20 20:08:14 -0400 (Mon, 20 Aug 2007) | 1 line

Initial Import

--------------------------------------------------------------------------

hfsd>

File Edit Window Help HeDidWhat?

To get the log

we use the “log ”

command...

...and specify which file to get the log for.

Subversion responds by giving us all of the log entries for that file.

Here’s the revision numb

er...

And here’s the log message to go with it.

Subversion keeps track of who made the changes and when.

viewing logs

you are here 4    203

version control

Now you can check out Version 1.0

Once you know

which revision to

check out, your

version control

server can give you

the code you need:

11

This puts the

code in a new

directory, for

Version 1.0.

Now you can fix the

bug Bob found...

22

With the changes in

place, commit the

code back to your

server...

33

What happened?

Why?

So now what do we do?

BeatBox.java

hfsd> svn checkout -r 4 file:///c:/Users/Developer/Desktop/ SVNRepo/BeatBox/trunk BeatBoxV1.0

A BeatBoxV1.0\src

A BeatBoxV1.0\src\headfirst

A BeatBoxV1.0\src\headfirst\sd

A BeatBoxV1.0\src\headfirst\sd\chapter6

A BeatBoxV1.0\src\headfirst\sd\chapter6\BeatBox.java

A BeatBoxV1.0\src\headfirst\sd\chapter6\MusicServer.java

Checked out revision 4.

hfsd>

File Edit Window Help ThatOne

hfsd> svn commit src/headfirst/sd/chapter6/BeatBox.java -m “Fixed the critical security bug in 1.0 release.”

Sending src\headfirst\sd\chapter6\BeatBox.java

svn: Commit failed (details follow):

svn: Out of date: ‘/BeatBox/trunk/src/headfirst/sd/chapter6/ BeatBox.java’ in transaction ‘6-1’

hfsd>

File Edit Window Help Trouble

In Subversion, -r indicates you want a

specific revision of code. We’re grabbing revision 4.

Once again, the version control server gives you normal Java code you can work on.

Uh oh, looks like

the server isn’t

happy with your

updated code.

204 Chapter 6

Laura: We could check out the version 1.0 code just fine, but now

the version control server won’t let us commit our changes back in.

It says our file is out of date.

Mark: Oh—ya know, that’s probably a good thing. If we could

commit it, wouldn’t that become revision 6, meaning the latest

version of the code wouldn’t have Bob’s changes?

Bob: Hey that’s right—you’d leapfrog my code with old version 1.0

code. I don’t want to lose all of my work!

Laura: You still have your work saved locally, right? Just merge it in

with the new changes and recommit it. You’ll be fine.

Bob: Uggh, all that merging stuff sucks; it’s a pain. And what about

the next time we find a bug we need to patch in Version 1.0?

Mark: We’ll have to remember what the new 1.0 revision is. Once

we figure out how to commit this code, we’ll write down the revision

number and use that as our base for any other 1.0 changes.

Laura: New 1.0 changes? Wouldn’t we be at Version 1.1 now?

Bob: Yeah, that’s right. But this is still a mess...

(Emergency) standup meeting

Write down three problems with the approach outlined above for

handling future changes to Version 1.0 (or is it 1.1?).

1.

2.

3.

A n sw

er s

on p

ag e

21 7.

tagging revisions

If you’re having a problem , don’t wait for

the next day. Just grab everyone and

have an impromptu stand up meeting.

you are here 4    205

version control

Tag your versions The revision system worked great to let us get back to the version of the code we

were looking for, and we got lucky that the log messages were enough for us to

figure out what revision we needed. Most version control tools provide a better

way of tracking which version corresponds to a meaningful event like a release

or the end of an iteration. They’re called tags.

Let’s tag the code for BeatBox Pro we just located as Version 1.0:

So what did that get us? Well, instead of needing to know the revision number

for version 1.0 and saying svn checkout -r 4 ..., you can check out Version

1.0 of the code like this:

svn checkout file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/tags/version-1.0

And let Subversion remember which revision of the repository that tag relates to.

So what?

First you need to create a directory in the repository for the tags. You only

need to do this once for the project (and this is specific to Subversion; most

version control tools support tags without this kind of directory).

Now tag the initial 1.0 release, which is revision 4 from the repository.

1

2

hfsd> svn mkdir file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/tags

-m “Created tags directory”

Committed revision 6.

hfsd>

File Edit Window Help Storage

Instead of trunk, specify the tags directory here.

You can use the

mkdir comm and

to create t he

tags direct ory.

Here’s the log message - and notice it creates a r evision.

This is a change to the project, so Subversion trac ks it.

hfsd> svn copy -r 4 file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/ trunk file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/tags/version-1.0

-m “Tagging the 1.0 release of BeatBox Pro.”

Committed revision 6.

hfsd>

File Edit Window Help YoureIt

With Subversion, you create a tag by copying the revision you want into the tags directory. Subversion actually just relates that version tag to the release.

We want revision 4 of the trunk...

And we want to put that code into a tag called version-1.0

206 Chapter 6

So now I know where Version 1.0 is, great. But we still only have the 1.0 code, and need to commit those changes. Do we just commit our updated code into the Version 1.0 tag?

No! The tag is just that; it’s a snapshot of the code at the point you made the tag. You don’t want to commit any changes into that tag, or else

the whole “version-1.0” thing becomes meaningless. Some version control

tools treat tags so differently that it’s impossible to commit changes into tags

at all (Subversion doesn’t. It’s possible to commit into a tag, but it’s a very,

very bad idea).

BUT we can use the same idea and make a copy of revision 4 that we will commit changes into; this is called a branch. So a tag is a snapshot of

your code at a certain time, and a branch is a place where you’re working

on code that isn’t in the main development tree of the code.

Just like with tags, we need to create a directory for branches in our project.11

Now create a version-1 branch from revision 4 in our repository.22

hfsd> svn mkdir file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/branches

-m “Created branches directory”

Committed revision 8.

hfsd>

File Edit Window Help Expanding

Use the mkdir

comman d again

to crea te

the bra nches

directo ry.

Instead of trunk, we specify

the branches direc tory here.

hfsd> svn copy -r 4 file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/trunk file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/branches/version-1

-m “Branched the 1.0 release of BeatBox Pro.”

Committed revision 9.

hfsd>

File Edit Window Help Duplicating

With Subversion you create a branch just like a tag; you copy the

revision you want into the branches directory. It won’t actually co py

anything; it just stores the revision number you supplied.

We want revision 4 of the trunk...

And we want to put it into a branch called version-1 (not Version 1.0, because we’ll use this for Version 1.1, 1.2, etc.).

branches and tags

you are here 4    207

version control

Tags, branches, and trunks, oh my! Your version control system has got a lot going on now, but most of the

complexity is managed by the server and isn’t something you have to

worry about. We’ve tagged the 1.0 code, made fixes in a new branch, and

still have current development happening in the trunk. Here’s what the

repository looks like now:

The trunk is where your active

development should go; it should

always represent the latest version

of your software.

A tag is a name attached to a

specific revision of the items in your

repository so that you can easily

retrieve that revision later.

Sometimes you might need to

commit the same changes to a

branch and the trunk if the change

applies to both.

Branches are copies of your code

that you can make changes to

without affecting code in the trunk.

Branches often start from a tagged

version of the code.

Tags are static—you don’t commit

changes into them. Branches are

for changes that you don’t want

in the trunk (or to keep code away

from changes being made in the

trunk).

Tags are snapshots of your code. You should always commit to a branch, and never to a tag.

2.0! BeatBox Pro 1.0

version-1

trunk

Now we’ve got a tag in our

code that mark s this exact

revision as versi on-1.0

We’ve got a branch for 1.x fixes, and we can work on that code separate from new development.

You’d commit fixes to version 1.0 code here.

All of Bob’s fixes are still in the main branch, which is called the trunk.

BeatBox Pro 1.x

208 Chapter 6

version-1

trunk

Fixing Version 1.0...for real this time.

First, check out the version-1 branch of the BeatBox code:11

// ... the code below is from BeatBoxFinal.java buildGUI() ... JButton sendIt = new JButton("sendIt"); sendIt.addActionListener(new MySendListener()); buttonBox.add(sendIt);

JButton sendPoke = new JButton("Send Poke"); sendPoke.addActionListener(new MyPokeListener()); buttonBox.add(sendPoke);

userMessage = new JTextField(); buttonBox.add(userMessage);

// ... this is new code we need to add to BeatBoxFinal.java ... public class MyPokeListener implements ActionListener {

public

void actionPerformed(ActionEvent a) {

// We'll create an empty state array here

boolean[] checkboxState = new boolean[256];

try {

out.

writeObject(POKE_SEQUENCE);

out.

writeObject(checkboxState);

} catch (Exception ex) { System.out.println("Failed to poke!"); }

When we had everything in the trunk, we got an error trying to commit old

patched code on top of our new code. Now, though, we’ve got a tag for version

1.0 and a branch to work in. Let’s fix Version 1.0 in that branch:

Now you can fix the bug Bob found...22

BeatBox.java

hfsd> svn checkout file:///c:/Users/Developer/Desktop/SVNRepo/BeatBox/ branches/version-1 BeatBoxV1

A BeatBoxV1\src

A BeatBoxV1\src\headfirst

A BeatBoxV1\src\headfirst\sd

A BeatBoxV1\src\headfirst\sd\chapter6

A BeatBoxV1\src\headfirst\sd\chapter6\BeatBox.java

A BeatBoxV1\src\headfirst\sd\chapter6\MusicServer.java

Checked out revision 9.

hfsd>

File Edit Window Help History

Notice we didn’t need to specify a rev ision here.

The branch is a copy of the version 1. 0 code.

We’ll put this in the BeatBoxV1 directory this time.

These revisions numbers stop meaning as much, because we’re using tags to reference revisions instead of revision numbers.

We’re working here, in the

version-1 branch.

This time, we’re working on code from the version-1 branch.

working with branches

you are here 4    209

version control

...and commit our changes back in. This time, though, no conflicts:33

With all these changes, we’ve actually got two different sets of code: the

1.x branch, where fixes are made to Version 1.0, and the trunk, which has

all the new development.

Our trunk directory in the repository has the latest and greatest code

that’s still in development (and Bob applied the security fix there, too).

We have a version-1.0 tag in our tags directory so we can pull out

Version 1.0 whenever we want.

We have a version-1 branch in our branches directory that has all

of our critical patches that have to go out as a 1.x version without any

of the new development work.

Don’t forget: whe n you actually

do release v1.1 with these

patches, create a version-1.1 tag

in the tags directo ry so you can

get back to that version later if

you have to.

We have TWO code bases now

hfsd> svn commit src/headfirst/sd/chapter6/BeatBox.java -m “Fixed the critical security bug in 1.0 release.”

Sending src\headfirst\sd\chapter6\BeatBox.java

Committed revision 10.

hfsd>

File Edit Window Help Sweet

The fix is in

the branch.

210 Chapter 6

Q: I’ve heard branches are a bad idea and should be avoided. Why are we

talking about them?

A: Branches aren’t always a bad thing; they have an important place in software

development. But, they do come with a price.

We’ll talk about that over the next few pages.

Q: What else can tags be used for? A: Tags are great for tracking released versions of software, but you can also

use them for keeping track of versions

as software goes through testing or

QA—think alpha1, alpha2,

beta1, ReleaseCandidate1,

ReleaseCandidate2,

ExternalTesting, etc. It’s also a good practice to tag the project at the end of

each iteration.

Q: Earlier, you said not to commit changes to a tag. What’s that supposed to

mean? And how can you prevent people

from doing it?

A: The issue with commiting changes to a tag is really a Subversion peculiarity; other

tools explicitly prohibit commiting to a tag.

Since Subversion uses the copy command to

create a tag, exactly like it does a branch, you

technically can commit into a tag just like any

other place in the repository. However, this

is almost always a bad idea. The reason you

tagged something was to be able to get back

to the code just as it was when you tagged it.

If you commit changes into the tag, it’s not the

same code you originally tagged.

Subversion does have ways of putting

permission controls on the tags directory so

that you can prevent people from committing

into it. However, once people get used to

Subversion, it’s usually not a major problem,

and you can always revert changes to a tag

in the odd case where it happens.

Q: We’ve been using file:///c:/... for our repository. How is that supposed to work

with multiple developers?

A: Great question—there are a couple things you can do here. First, Subversion

has full support for integration with a web

server, which lets you specify your repository

location as http:// or https://. That’s when

things get really interesting. For example,

with https you get encrypted connections to

your repository. With either web approach,

you can share your repository over a much

larger network without worrying about

mapping shared drives. It’s a little more work

to configure, but it’s great from the developer

perspective. If you can’t use http access for

your repository, Subversion also supports

tunneling repository access through SSH.

Check out the Subversion documentation

(http://svnbook.red-bean.com/) for more

information on how to set these up.

Q: When I run the log command, I see the same revision number all over the

place. What’s that about?

A: Different tools do versioning (or revisioning) differently. What you’re seeing

is how Subversion does its revision tracking.

Whenever you commit a file, Subversion

applies a revision number across the

whole project. Basically, that revision says

that “The entire project looked like this at

revision 9.” This means that if you want to

grab the project at a certain point you only

need to know one revision number. Other

tools version each file separately (most

notably the version control tool called CVS

which was a predecessor to Subversion).

That means that to get a copy of a project

at a certain state, you need to know the

version numbers of each file. This really isn’t

practical, so tags become even more critical.

Q: Why did we branch the Version 1.0 code instead of leaving Version 1.0 in the

trunk, and branch the new work?

A: That would work, but the problem with that approach is you end up buried in

branches as development goes on. The

trunk ends up being ancient code, and all the

new work happens several branches deep.

So you’d have a branch for the next version,

and another branch for the next...

With branches for older software, you’ll

eventually stop working with some of those

branches. (Do you think Microsoft is still

making fixes to Word 95?)

Q: To create tags and branches with Subversion, we used the copy command.

Is that normal?

A: Well, it’s normal for Subversion. That’s because Subversion was designed for

very “cheap” copies, which just means a

copy doesn’t create lots of overhead. When

you create a copy, Subversion actually just

marks the revision you copied from, and

then stores changes relative to that. Other

version control tools do things differently. For

example, CVS has an explicit tag command,

and branches result in “real” copies of

files, meaning they take a lot of time and

resources.

branches, tags, and subversion

you are here 4    211

version control

WIth the security fix to Version 1.0 taken care of, we’re back to our

original user story. Bob needs to implement two different saving

mechanisms for the BeatBox application: one for when the user is on a

Mac, and one for when a user is on a Windows PC. Since these are two

completely different platforms, what should Bob do here?

What should Bob do?

Why?

212 Chapter 6

When NOT to branch... Did you say that Bob should branch his code to support the two different features? Modern

version control tools do make branching cheap from a technical perspective. The problem

is there’s a lot of hidden cost from the people perspective. Each branch is a separate code

base that needs to be maintained, tested, documented, etc.

For example, remember that critical security fix we made to Version 1.0 of BeatBox? Did that

fix get applied to the trunk so that it stays fixed in Version 2.0 of the software? Has the trunk

code changed enough that the fix isn’t a straightforward copy, and we need to so something

differently to fix it?

The same would apply with branching to support two different platforms. New features would

have to be implemented to both branches. And then, when you get to a new version, what do

you do? Tag both branches? Branch both branches? It gets confusing, fast. Here are some rules

of thumb for helping you know when not to branch:

Branch when...

You have released a version of the software that you need to

maintain outside of the main development cycle.

You want to try some radical changes to code that you might need

to throw away, and you don’t want to impact the rest of the

team while you work on it.

Do not branch when...

You can accomplish your goal by splitting code into different files

or libraries that can be built as appropriate on different platforms.

You have a bunch of developers that can’t keep their code compiling in

the trunk so you try to give them their own sandbox to work in.

There are ot her ways

to keep peopl e from

breaking othe r people’s

builds. We’ll t alk about

those in a lat er chapter.The Zen of good branching

Branch only when you absolutely have to. Each branch is a

potentially large piece of software you have to maintain, test,

release, and keep up with. If you view branching as a major decision

that doesn’t happen often, you’re ahead of the game.

avoiding unnecessary branches

you are here 4    213

version control

We fixed Version 1...

Version 1.1 is released, and the security bug is no more.

... and Bob finished Version 2.0 (so he says)

Guys, all of my code is checked in but nothing’s working. It should compile, but let me know if you have problems building something—I might have missed a file.

We’ve come a long way in this chapter, but there are people that

version control alone just can’t fix...Can you list some troubles

that Bob can still get into, even if he uses version control to

manage his code?

things

Good catch on the security bug! You guys even got a patch

out before we hit the news!

214 Chapter 6

What version control does...

Lets you create a repository to keep your code in a single place to

ease backup and recovery.

Lets multiple people check out copies of the code and work

efficiently as a team.

Lets multiple people check changes back into the repository and

distribute them to the rest of the team.

Keeps track of who changes what, when, and why.

Branches and tags code so you can find and change versions of code

from way back when.

Rolls back changes that never should have happened in the first place.

...and what version control doesn’t do

Makes sure your code compiles.

Tests code.

Thinks for you.

Makes sure your code is readable and well-written.

These are pretty important...looks like our tool set is nowhere near complete.

you are here 4    215

version control

Version control can’t make sure your code actually works...

Wouldn’t it be dreamy if there was a tool that made sure my code actually compiled and worked before it showed up in a broken customer demo? But I guess it's just a fantasy…

216 Chapter 6

Development Techniques

Use a version control tool to t rack and

distribute changes in your soft ware to

your team

Use tags to keep track of maj or

milestones in your project (ends of

iterations, releases, bug fixes, e tc.)

Use branches to maintain a sepa rate

copy of your code, but only bra nch if

absolutely necessary

Development Principles Always know where changes should (and shouldn’t) go

Know what code went into a given release - and be able to get to it again Control code change and distribution

Back up your version control

repository! It should have all

of your code and a history of

changes in it.

Always use a good commit

message when you commit

your code—you and your

team will appreciate it later.

Use tags liberally. If there’s

any question about needing

to know what the code

looked like before a change,

tag that version of your code.

Commit frequently into

the repository, but be

careful about breaking other

people’s code. The longer

you go between commits,

the harder merges will be.

There are lots of GUI tools

for version control systems.

They help a lot with merges

and dealing with conflicts.

Here are some of the key techniques you learned in this chapter...

... and some of the

principles behin d

those techniqu es.

CH A P

T E

R 6

Tools for your Software Development Toolbox

Software Development is all about developing

and delivering great software. In this chapter,

you learned about several techniques to keep

you on track. For a complete list of tools in the

book, see Appendix ii.

you are here 4    217

version control

Write down three problems with the approach outlined above for

handling future changes to version 1.0 (or is it 1.1?).

1.

2.

3.

You need to keep track of what revisions go with what version of the software. It’s going to be very difficult to keep 2.0 code changes from slipping into v1.x patches.

Changes for Version 2.0 could mean you need to delete a file or change a class so much that it would be very difficult to keep a v1.x patch without conflicting.

  • Head First Software Development
  • Table of Contents (Summary)
  • Table of Contents (the real thing)
  • The Authors
  • Intro
  • Chapter 1. great software development: Pleasing your customer
  • Chapter 2. gathering requirements: Knowing what the customer wants
  • Chapter 3. project planning: Planning for success
  • Chapter 4. user stories and tasks: Getting to the real work
  • Chapter 5. good-enough design: Getting it done with great design
  • Chapter 6. version control: Defensive development
  • Chapter 6.5. building your code: Insert tab a into slot b...
  • Chapter 7. testing and continuous integration: Things fall apart
  • Chapter 8. test-driven development: Holding your code accountable
  • Chapter 9. ending an iteration: It’s all coming together...
  • Chapter 10. the next iteration: If it ain’t broke... you still better fix it
  • Chapter 11. bugs: Squashing bugs like a pro
  • Chapter 12. the real world: Having a process in life
  • Appendix I. leftovers The top 5 things (we didn’t cover)
  • Appendix II: techniques and principles Tools for the experienced software developer