gave Monday night's informal talk at XpImmersionTwo
Wow...I'd describe it as WabiSabi
, I think. Ward described the strange and unplanned emergence of several key XP processes. The talk included formation of the PortlandPatternRepository
, the evolution of CRC cards from HyperCard
stacks on the Mac, and so on.
One of the neat concepts in that talk was the notion that we like to talk about things that don't exist yet. For example, while we are designing, we'll decide we need some new class. We don't know the name for it yet, so we refer to it as "the new class" or "the mystery class", etc. If we are doing CRC, we'll have a bunch of cards on the table. There will be an empty spot on the table where the new class will be. The developers will point to that empty spot when referring to the new class.
Another example of pointing to things that aren't there yet is AsYetUncreatedWikiPages?
, which you can still reference on other Wiki pages. Ward also showed screen shots of a HyperCard
stack he wrote long ago that had this ability.
Kent chimed in to point out that test-first coding is an example of the same thing, since you're writing tests for code that does not yet exist.
Another theme was Climbing the Mountain. Programming is a series of peaks and valleys. You start climbing a peak, not really knowing what it's going to be like at the top. You have an idea, but you're not sure. Then when you get to the top, you know what it's like. It all makes sense, and so you wrap that episode up by easing back down to the next valley. Then you get ready to make the next ascent, or maybe you go to lunch first.
Ward compared OO to skiing. Skiers need to use their edges. (An OO programmer's edge is polymorphism, which became on of our words for the week.)
Reminds me of DebuggingSmalltalkCodeIntoExistence?
). Oh, to be young and develop in Smalltalk ... <sigh>. --RandyStafford
Reminds me of BigDesignUpFront, which is why I don't get it. Can someone explain how you know what methods belong to a class and what they're called before you're done writing it?
You'd need to figure this out even if you wrote the method first. Writing the test first just means that you first think about the method signature from the point of view of a client.
To figure out where the method goes, you use responsibility-driven design and CRC cards. For example, if you need to add the ability to cancel pending orders, that functionality should probably go in the class that's already responsible for tracking pending orders. Don't worry too much about getting the method in the right class, since you can refactor it later, if you end up with a case of FeatureEnvy
If you have a good SystemMetaphor
, it will suggest a SystemOfNames
that members of the team can use to make good guesses at what method names should be. This works both for existing methods that they haven't run across before, as well as ones they are in the process of writing. --JohnBrewer
"You'd need to figure this out even if you wrote the method first." Similarly, you need to figure out the final design of the system even if you wrote the system first. What's the logical difference between this and BigDesignUpFront?
This isn't big and it isn't up front. It's small because you're only dealing with one little test. It's immediate because you are dealing only with a feature that you know must go in. It isn't anticipatory because you're focusing only on the interface that's needed to write the test and then only with the code that's needed to make that interface work. -- PhilGoodwin
That's the semantic difference, but structurally, they both take the same premises that we know are bogus as true. Well, we should know are bogus. e.g. "It is possible to predict how well-factored code will be before you write it." Logically, I contend the two only differ in their premise of how large a scope to apply your psychic powers to.
Well, you do
have to design and build the system sometime. But to address your earlier question in perhaps a more useful way: the difference between this and big design up front is that here you test your hypothesies before you build on them. Also, you only build what you actually need. So you make a statement of what you need (ideally just an assert) then you start building what you think you'll need to support that starting from the interface (the rest of the test case leading up to the assert) and then the code. The key is that you avoid building on false assumptions, either about what you'll need or what will work. - pg
Moved to RefactoringUnitTestsIsExpensive