Design & Development Principles - XP - Keyboard Circle
The Practices
I've found 2 images that I think reflect how Extreme Programming approaches software development.
These come from different perspectives; which drives their different layout.
The first shows the interconnectedness of all of the XP practices.
The interconnectedness means that utilizing "some" will not provide what XP is capable of. The missing practices will be stumbling blocks making it easier to argue to abandon all of it. This breakdown will be because it's not implemented as a whole.
Each practice reinforces the others. Just one isn't going to get a team very far. They will need to replace the support of the absent practice with something else.
The second is concentric by time.
I think this is useful to see as it communicates what practices are felt when.
Is it possible to implement the blue ring without the green ring? Yes...ish. The blue ring activities will break down the moment the green is needed. This will be Less frequently (though still frequently) and will block the blue ring activities from continuing until whatever issue is resolved.
Definitely nice to see the time based view of these; but not implementing green doesn't mean you'll be able to still do blue.
The ideal is that all of these are happening daily; if not MANY times a day. Yes - all of them.
If your team wants to be blocked and frustrated many times a day while trying to do XP; then by all means; do it piecemeal. For the power and productivity increase XP can provide; it needs all of the interconnected pieces in place.
My version of the graph is very similar; built using the concentric colors; but I like the tight interdependencies shown.
Let's Start
I'm going to utilize the circle form to start talking about the practices. These are the line by line practices that produce the code.
Because it's the underlying principle to what XP is - Frequent Feedback.
Frequent Feedback
Frequent Feedback allows changes to happen quickly. The faster the feedback the faster change can occur.
Code Reviews are one type of feedback. How often should code be reviewed? The sooner it's reviewed; the smaller amount that has to be reviewed; the better the review will be.
Writing tests is another type of feedback. This demonstrates that the code works. How often should tests be run? The sooner the developer sees the results; the sooner they know a test failed; the less hunting for what change caused the failure.
Getting frequent feedback is the driving factor to XP practices. If something can affect a decision; minimize the time between making a decision and the changes causing that decision to be required.
This will be the underlying theme to all further XP discussions.
One of the ways developers get frequent feedback is via Tests. Let's start with the XP practice regarding writing tests.
Test Driven Development
TDD is the practice of writing the test before you write the code. Your tests drive the development of the code.
This is a hard practice to enact all the time; I strive to; and it can be tough. The payoff though it's huge.
Value
What value does this provide? I can write crap code while writing tests first; but it's not TDD. TDD isn't about the tests; it's about the mindset; which is where the connected items will come into play.
TDD on it's own will ensure that code has a test. As a developer; we won't have to keep entire complex systems in our head. We won't spend hours and hours walking through every path in the code that we can find that touches our changes and HOPE that we didn't miss anything that could break.
When I have test coverage; I run ram-shod over the code.
I don't care.
It's not that I don't care; it's that I don't have to care. I trust the tests that are in place to turn red if I do something wrong. I have confidence that the code under test does what it is expected to. I trust the code to be as correct as the tests.
I'll allude or call out the mindset frequently with these practices. It's not the practices that cause the code to improve; it's the mindset. The mindset is that of a Software Craftsperson. It's someone with the desire to write the best code they can and always looking to improve what they produce. The practices are the tools we can employ to support the mindset. TDD is a Software Craftsperson's tool as much as a plane is a woodworkers tool.
The tools can lead to understanding and adopting the mindset; but without it - the tools alone won't produce the high quality of code.
Ruthless Refactoring
I like a post of Uncle Bob's that I read recently that highlights a distinction between refactoring for implementation and "transforming" for behavior. It draws a fine line between what I'd have previously considered just 'refactoring'; but I think it's a good line and keeping it in mind while TDDing (as he highlights in the post) helps drive a more productive TDD session.
His post The Transformation Priority Premise brings about new insight into how to develop the code. It's very much inline with the practices I've held and approached that you shouldn't try to write for all cases; write for the cases you know and generalize when you know more.
The post lays out a good example from the Bowling Kata of what's generally a "silly" example; or "taking TDD to the extreme".
As Uncle Bob puts it
I used to agree with them that this was brainless, and that we were just deferring decisions until we have more information.
I agreed with that; it was an extreme, as we "knew" what to do. With the idea of a Transformation - It's no longer so silly.
As I'm still trying to incorporate the Transformation Premise into my thought process; I'll likely write about refactoring as I did previously; which is "changing the code". Both 'refactor' and 'transform'.
Why do we refactor?
My most basic answer - Keep the code clean. Using the Gardner example, refactoring is the cleanup after planting something new. Any bags or debris around get taken care of. If we're running a hose the length of the garden; we go hook up new underground water pipes, etc. It's all about cleaning up the code so that it's inline and functions with the code already there. It's not putting in entirely new things; but putting them in (Tests are Green) and then changing them to be a part of the existing infrastructure/code (Refactor).
What do we get?
Speed. Ease.
The simplest gain from refactoring is that it becomes much easier to implement new features. You can implement new features much faster. The foundation is already there; you just hook into it. It's the difference of laying entirely new underground pipes for each plant or hooking into the existing pipes other plants use. Much faster to use what's there. Refactoring is the practice that puts the "something" into place and available for future features.
Refactoring is the practice that consolidates common/duplicate code. When you remove duplication, you have less code to fix if there's a bug. Less chance to miss the bug in one of the duplicates. These duplicated sections would start to drift over time, making it harder to fix a bug without introducing new ones; or even identifying if the bug exists.
Duplicate code reduces the confidence in the code base you'll have to write the same test for multiple pieces of code; so not just duplication of code, but duplication of tests... assuming that you have tests. If you have duplicate code; higher chance you're not employing the practices that drive tests.
We refactor because it helps keep the code clean. We won't be tripping due to hoses strew all over; or unused piles of dirt left out.
What's with the Ruthless?
The reason I call it Ruthless Refactoring is that it should be done A LOT. If you see something that should be refactored you do it. Don't think "that could be renamed to be clearer" and move on; rename it. If you have to figure something out; or go through a mental translation - Fix it. Be ruthless about improving the quality of the code. Ruthless about getting the code to clearly communicate intent.
There's an exception of BIG THINGS; where we don't do them RIGHT THEN. We make a note; and when at a good point; be ruthless. Don't go down a rabbit hole while working on something; but be sure to go back to it.
Simple Design
Simple Design is hard. I want to get that out of the way first. One of the frequent things I've seen used as an analogy is a quote oft attributed to Mark Twain; but some quote investigator seems to link it back to Blaise Pascal. I'll use the translation of his writing
I have made this longer than usual because I have not had time to make it shorter.
-Blaise Pascal
Which is what simple design embodies. It takes time, driven by refactoring, to get a simple design in place. It's hard to do because it does take experience to see how to solve problems; such as what pattern is emerging; and how to apply it. Once it's there, it's ... beautiful. A simple design is easier to understand, easier to work with, easier to refactor, and when the time comes, easier to replace.
Hyping up it's value; What is Simple Design?
The most common form of simple design comes from what's referred to as Beck's 4 Rules of Simple Design. The wording on these 4 points vary, but the idea behind them is aligned.
I think I covered these well enough in the first post in this series, talking about Beck's 4 Rules. I won't rehash those here, though I'm starting to favor calling "Communicates Intent" to "Eloquently Named".
Pair Programming
I've made mention of pairing in a number of my posts. Unfortunately this has been largely due to lamenting that I'm not doing pair programming.
I see pair programming as the keystone to all the practices mentioned in this post. It's the practice that keeps you honest with the rest of the practices.
Having the pair keeps the questioning happening. It allows a parallel thought process that's not at the front line of the code.
Code can be done without pairing; but it won't be as good.
A great aspect of pair programming is shared knowledge. This is sharing and spreading intimate knowledge of the code; not high level or even code review level. It is a shared knowledge of the decisions made and why.
This shared knowledge is what makes a team a team. Working with your team on a daily basis is what brings individuals together so they consider themselves a team.
Pair Programming allows conversations on the fine details of what's being worked on. This is huge. It doesn't take any time to get someone up to speed; filling them in on why the common suggestions aren't being used. You have someone RIGHT THERE to have conversations with; to ask questions to. To immediately review the code, and offer suggestions or criticisms.
The pair keeps the practices active. It's easy to slide back on occasion if working alone; even if you want to drive. Maybe trying things and not getting appropriate tests in place?
A pair helps keep the tools sharp.
Summary
As much as I'd like to go over all of Extreme Programming (XP) in a single post; I'm going to utilize the "layers" from one of the concepts and write about each individually.
This post looked at the day to day, hands on keyboard aspects of Pair Programming. It's what we do as craftspeople to ensure the code is easy to work with 6 months down the road.
I've written on a couple topics before; and even in this series; but the crux of being successful in these practices is Pair Programming. Without it; the rest can't produce the level of High Quality Code that pairing can produce.
A huge caveat that pairing alone doesn't do nearly enough. I suspect it would have an improvement on the code; but that just amounts to real time code-review. I've driven a team to do code reviews; and when we were able to do enforced code reviews; after MONTHS of complaints about the reviews slowing work down; everyone agreed that the quality of code was higher. Pairing is likely to produce higher quality code; but more minds are better; that's all.
The rest of the practices are what will make the code be a beautiful thing and easy to work with 6 months down the road.