David Scott Bernstein's Blog, page 23
January 4, 2017
Ping-Pong Pairing
Another pair programming configuration I like is called ping-pong pairing.
In ping-pong pairing the driver writes a test for a behavior then asks the navigator to implement the behavior and make the test pass. Once completed, the keyboard is passed from driver to navigator and the new driver writes the next test for the new navigator to implement.
This back and forth between test and code, driver and navigator, can offer rich feedback when building a system. It also supports developers in doing test-first development.
One of the challenges with ping-pong pairing is making the time to refactor both code and tests. It’s easy to get on a forward momentum where features are being implemented but we also have to take the time to step back and make sure our code is clean so it’s straightforward to maintain and work with in the future. This also applies to our tests.
I find that when doing TDD I spend a fair amount of time refactoring my tests. Sometimes I spend more time refactoring my tests than refactoring my code, but this is natural. Exercising a feature can be complex so testing can be complex too, but it’s well worth it to make tests straightforward and easy to read.
The two things I typically do to make my tests more readable is factor common set up behaviors into a common setup method, and for any additional functionality that is not shared among all tests I write helper methods that my test can call.
You might have heard me rant in the past about how helper methods have no place in the domain model. They’re orphaned behaviors because the developer who wrote them didn’t take the time to discover what object should actually possess those behaviors and instead they made a helper object hold those behaviors. Doing this distorts the domain model. It means that objects in our domain model are not being called out correctly and therefore the domain model is distorted and difficult to understand. So it’s true, I am against helper methods in production code.
But helper methods do have a place in test code. Test code is, after all, different than production code. It has a different purpose. It’s intended to exercise production code and so it makes complete sense for tests to have helper methods.
Tests are, after all, code, and they’re important code because they exercise a production system. We should write our tests with every bit as much care as we use to write production code.
Ping-pong pairing helps us keep an emphasis on both test and production code and can support pairs in doing TDD well.
December 28, 2016
Pairing versus Mobbing
I was talking to some friends at Agile 2016 about which they thought was more effective, pair programming done well or mob programming done well, but we ended up deciding that the jury is still out on this question, at least for the time being.
In terms of learning and spreading knowledge across a team we felt that both pairing and mobbing were comparable, with mobbing a bit more efficient. The same, we felt, is true for the quality of code produced, with both paring and mobbing yielding significantly higher code quality than software developed by a programmer working alone.
But in terms of productivity we weren’t sure which was better. We thought it probably depends upon the team and the type of problem they’re solving.
I find that pairing done well can be much more productive than having developers work by themselves. We’re far less likely to make mistakes and introduce bugs into code when we work in pairs.
Debugging is still the number one time sink in developing software so if we can reduce the time required by debugging by writing fewer bugs, it can greatly boost the amount of features we can deliver.
I have personally not had enough experience with mob programming to get a sense of how productive a team can be when they’re working with the same problem at the same time but I do have a lot of experience with pair programming and I am always surprised at how much more productive we can be together than just working on our own.
One might think that mob programming is highly inefficient because the whole team is working on the same story at the same time but it turns out there are a lot of parallel tasks that can be worked on by different team members as a story is being implemented. The result is that most everyone is engaged most of the time when mobbing. To see a time lapse video of a team mobbing for a day condensed into five minutes, visit http://mobprogramming.org/mob-programming-time-lapse-video-a-day-of-mob-programming/.
In my experience, as soon as you have people start to work together they spend much more time focused on solving problems and much less time doing other things. Pair programming boosts productivity on any team—as long as they learn how to do it well.
Writing software can be a personal activity so learning how to build software collaboratively and out of a conversation rather than out of our heads can be a different skill set for some developers, but the benefits can be enormous. Pairing and mobbing are the fastest ways I know to propagate knowledge across a team, improve quality, and reinforce new habits.
I have heard a lot of people’s opinion about pairing and mobbing who have never tried either and I know from my own experiences that actually doing pairing is very different than I thought it would be like. So what about your experiences? Have you successfully done pairing or mobbing? Did you feel the team’s productivity increased or decreased?
December 21, 2016
Time Box to Scope Box
Both Extreme Programming (XP) and Scrum have the notion of time boxing. In XP, they call it iterations. In Scrum, they call it sprints. I am not a big fan of the term sprint because it connotes the idea of hurrying through. That’s not how I view iterative development. It is not a race but rather a process so I prefer the XP term iteration over the Scrum term sprint.
Both iterations and sprints are examples of time boxes where work is done during fixed time intervals and then it’s reviewed. Then the next batch of work is planned, executed, and reviewed, and so on. Iterations generally last from one to four weeks. This is a big improvement over annual release cycles, which is how many companies operated in the past, but it’s still not ideal.
The shorter the iterations, the less infrastructure is needed to support development. Building to quarterly releases is just long enough that it demands requirements be written down then later read and interpreted. Requirements consume a significant amount of resources to gather, write down, and then later read, interpret, and build. Requirements are also one of the largest contributors of bugs to a system. Therefore, improving the requirements process can significantly increase a team’s overall productivity.
Generally speaking we want to keep iterations as short as possible because the secret of iterative development is that it gets you into the discipline of working in the small.
Working in the small means breaking tasks down into their smallest components so they can be built easily and still show some value. Working in the small means we’re getting feedback constantly, and we’re building our features as we go instead of doing a big bang release.
Task breakdown is as much an art as it is a science. Breaking tasks down is not a matter of simply lopping them up into tinier pieces. How we break up tasks has a huge impact on how we reassemble them together later into a system. We want to make our tasks so that they’re simple to build and still show some value, so it’s a good idea to define tasks by acceptance criteria.
If you do time boxed iterative development, that’s great, but there’s more benefit to come once we get really good at task breakdown. Once we get really good at building small increments of value rapidly, we may not need to use the notion of iterations or sprints at all. Many teams find that it’s still valuable working in iterations because it gives them a cadence for retrospectives and other meetings. But other teams seem to prefer to go into a flow state, methods more like Kanban where they work on a short task until completed then go back to a board and pick another task to work on.
The goal of time boxing and scope boxing are the same: work on small pieces of functionality. Because smaller tasks are more straightforward to approach, they’re easier to understand, complete, and verify.
Plus, when we work on smaller tasks we have much greater opportunity to get feedback, and that’s really what it’s all about.
December 14, 2016
Time Boxes
Time boxes help teams develop the discipline of building small pieces of valuable software.
But time boxes are in some sense artificial. What if you finish early or late? Well, this is one of the uses for measuring velocity so we can schedule the right amount of work within an iteration.
Iterations should be as short as possible but some teams feel the need to work on bigger batches. This is usually because they have a big release mentality where they want to deliver a full feature or many features to the user at one time. But users often prefer to have change happen incrementally rather than all at once and some features are bound to be wanted more than others. But in long release cycles, all features are treated essentially the same and you have to wait for all of them to be done before you can start using any of them.
There is a term that we use called market cadence, which is the speed at which a market can assimilate new features in their software. Nowadays, with more and more companies having a strong online presence, the market cadence is nearly instantaneous so it makes sense to build for value, to always stay focused on creating the most value possible with the people you have available.
Some teams have legitimate reasons for long release cycles such as synchronizing with OEM hardware that’s on long release cycles. But most of the time we expect new features to come out and bugs to be fixed automatically and in the background, which is entirely possible and turns out to be highly cost-effective for most companies.
We want to keep iterations as short as we can make them while still producing some value. That gives us the greatest opportunity for feedback and learning, and it also gives our customers early access to features so they can start getting value from them early, and developers can start getting feedback on how to make them better sooner.
Iterations generally tend to be somewhere between one and four weeks in length, with the sweet spot for most teams being two weeks.
Some teams tell me it’s not possible for them to deliver value to their customers in a period of only two weeks, but this is generally a sign of a broken software development process.
There are forces that drive sprints to be longer and there are also forces that drive sprints to be shorter. Generally speaking, the shorter the sprint the better. One of the keys to being successful with Agile software development is being able to build software incrementally so we build what the customer needs and it’s built in a way that’s straightforward to maintain and extend in the future.
Regardless of how long your iterations are you should always strive to produce shippable software at the end of each iteration.
When teams are able to break tasks down to about four hours—half a day’s effort—they can then move to a scope box system such as Kanban and continually work on smaller tasks without time boxing.
Time boxing can be appropriate for many other tasks outside of software development. I know teams that do heating and air conditioning repair as well as system administrators who use Scrum successfully in the course of their work. Many of the ideas from Lean and other Agile methodologies are being assimilated in other industries and this is very exciting indeed.
December 12, 2016
Podcast on This Agile Life
Check out my podcast with Amos King on This Agile Life where we talk about Agile adoption issues and why technical practices are essential:
http://www.thisagilelife.com/123
Enjoy!
December 7, 2016
Duplication versus Redundancy
You may have noticed that I don’t use the XP term duplication when talking about code quality. I prefer to use the term redundancy instead. This is because duplication is the most obvious form of redundancy but redundancy can take many other forms that are far subtler and harder to detect.
When I ask developers if non-identical code can be redundant, they say yes. Think of a “for” loop and a “foreach” loop iterating through the same collection.
When I ask developers if identical code can be non-redundant they have a harder time answering me. But after some thought they realize it’s also true. For example, a line of code that reads, “index++;” can be used to iterate through a list of names in one part of the code and a list of numbers in another part of the code.
So, redundancy is not a repetition of form but rather a repetition of intent. We are trying to do the same thing in multiple places and that makes it redundant.
Sometimes I can’t see the redundancy in my code but I recognize when I write a redundant test that my code must also be redundant.
I say that 95% of all redundancy is easy to spot in code, but that last 5% is worth uncovering even if it takes an extra effort because I find that that last little bit of redundancy often hides the essence of a good design and when I remove it, I suddenly see patterns that I hadn’t noticed before.
In his deceptively simple and excellent book, Test-Driven Development By Example, Kent Beck says that if you pay attention to removing duplication in your code and in your test, you’ll end up with good quality code and good quality tests. He is right but the same could be said about any of the other good code qualities such as cohesion or encapsulation. When you improve one code quality, the others tend to also improve. That’s because they’re facets of the same gem, which is good code. So when you improve one aspect of code and you see other aspects of code also improve then you know you’re on the right track.
November 30, 2016
World-Class Communicators
I think we software developers get a bad rap. We are portrayed in the media as being antisocial and introverted, unable to carry on a conversation at a party. In my experience, these stereotypes do not hold true. Okay, maybe it holds true for some of us (like me) but most developers I meet don’t fit into that stereotype.
Software developers don’t easily fit into any stereotypical mold. We come in all shapes and sizes. When I teach a class of professional software developers at one of the leading companies around the world, I’m typically the only middle-aged white guy in the room. This wasn’t the case when I started teaching professional software developers over twenty-seven years ago. In those days, the US dominated software development, largely due to geeks like me.
But today software has a worldwide presence and even developing countries are turning out professional programmers very quickly. What was once a skillset largely confined to the US and UK, software development is now a popular profession in every country, especially developing nations where the cost of entry is affordable. The required financial investment is low compared to other careers, and the potential benefits are huge.
One of the top developers I know grew up in Nepal under extreme poverty but he was able to work his way out and finally get a job in Australia where his genius was recognized. From there he was able to become a US citizen and get a very senior position at a respected company.
The need for software has been growing rapidly and so has the number of people graduating college with degrees in computer related fields, both in the US and abroad. This trend will continue for many more years as we’re still recognizing the need for new software and realizing that existing software requires ongoing maintenance for fixing bugs and adding features. People all over the world are realizing that developing software not only pays well, it can also be very creative and engaging. This is attracting a large diversity of people, which is helping our industry become more stable and more valuable.
Software developers are among the best communicators I know—and we have to be. After all, software development is primarily a collaborative effort. There is an enormous amount of detail required when building a system in a team, so our job often demands communicating complex concepts to each other.
Not all software developers may be good at making small talks at parties. But that’s not the kind of communication we thrive on. We thrive on high bandwidth communication, and most of us love our work.
So the next time you see a nerd sitting alone at a party, go up to him and ask him what it is he loves to do. You may find it difficult to get him to stop talking.
November 23, 2016
Practices We Aren’t Taught
As a software developer I resonate with the technical practices of Extreme Programming. Software engineering, like other forms of engineering, should have common standards and practices, but we really don’t. Yes we all learn programming languages in school but we’re rarely taught how to apply them in ways needed to build enterprise systems. This is like teaching a class in grammar and spelling then expecting your students to go off and become great writers in the next few weeks. In his book On Writing, Stephen King wrote: “If you want to be a writer, you must do two things above all others: read a lot and write a lot.” As developers we have to study others in our field and learn common ways of doing things.
And we are making progress. Design patterns represent a different order of knowledge that helps us understand and communicate ideas in new ways. But there is another set of practices of equal or greater importance than the technical practices, but we aren’t always exposed to them in school—or even in the workforce—so they can be difficult to pick up.
I’m referring to communication and collaboration skills.
Communication and collaboration are important because that’s what we mostly do. Most software projects are collaborative endeavors, and how we communicate in our corporate culture, as well as the structure of our daily lives, is of vital importance.
We can learn about communication and collaboration on the job, making sometimes job-ending mistakes as we go, but it can be helpful to note that many other people have studied these issues and have had similar challenges. There are a lot of great ideas out there. There’s a whole science devoted to the study of human behavior and tons of books written on learning and self-improvement.
There are many ways to be a good software developer but the very best software developers I know engage their whole brain in the development process. They’re not only good at making fine distinctions but they‘re also good at seeing patterns and making connections. These are fundamentally different skills, both of which are needed to write good, maintainable software.
What does it mean to be a great developer? It does mean writing good, maintainable code but it also means supporting the team, it means being a great communicator, it means being a great problem-solver, and it also means being a great collaborator.
Good software development is one of the few human activities that involves and engages the entire brain.
November 16, 2016
Collaborate
Collaboration requires a set of skills that must be practiced and mastered. Most software development projects involve collaboration among many developers so being able to work as part of a team, and to communicate complex ideas effectively, are important skills to have.
Pair programming is one approach to collaborative development. Pair programming is not about taking turns at the computer but rather bringing two minds to bear on the same problem so that it’s solved more easily and with higher quality. Pairing might seem a little scary if you haven’t tried it but in my experience, once developers experience pairing correctly then they get hooked on it.
Here are three other forms of collaboration that I draw on from time to time:
Spiking: A spike is a predetermined time box that is used to answer one or more questions. These can be architectural questions, implementation questions, or anything else. Spikes are generally used for research but they can also be used for other activities like refactoring, or anything that takes us out of our normal iteration.
Swarming: A swarm is when the whole team temporarily works to solve the same problem. Swarms are typically used when there is a showstopper bug or some problem that impedes the whole team from doing their work. A swarm engages everyone in solving a problem that affects everyone.
Mobbing: A mob is like a permanent swarm. The whole team works together solving the same problems all day, every day. This may sound inefficient but in most cases it isn’t. Obviously there are limits to the size of a mob but for many kinds of problems, mobs can produce higher quality and propagate knowledge faster among a team than through pairing or standups or any other Agile activity.
Each of these different approaches to collaboration can be useful under different circumstances and all of them provide maximum opportunity to propagate knowledge throughout a team. I get into all three—four, including pair programming—in much greater detail in my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.
November 9, 2016
Change Your Mind
One characteristic I consistently see among outstanding software developers is that they’re not afraid to change their minds, to change their approach, or to change their designs.
In Agile we start building right away before we have all the requirements nailed down and we let new requirements emerge as we’re building. To those unfamiliar with Agile, it may seem inefficient or even reckless to write code without seeing all the requirements first. You wouldn’t build the first floor of a building without considering the rest of the structure. But building software and building buildings are very different from each other.
New requirements can pull us in new directions and show us that our current design is inadequate. This is actually a good thing because we only want to build for what we currently know. So what do we do when we know more? The answer is that we change our minds.
Refactoring is a disciplined way of changing your mind, of changing from one design to another design that’s more appropriate for your current situation. Refactorings are code transformations that let you safely go from one design to another design. This is how we should build software: through emerging designs as we go.
It was Martin Fowler who turned the idea of refactoring into a true discipline when he published his book, Refactoring: Improving the Design of Existing Code in 1999. This book is a catalogue of code transformations that allow you to go from one design to another design and improve your code in some way without changing its behavior. Since its publication, Fowler’s book has become a critical resource for Agile developers.
The interesting thing about refactoring is that most refactorings are pretty straightforward and don’t require a lot of effort. Contrary to what some people believe, though refactoring legacy code may be difficult if it’s in a poor state, refactoring your own code from one design to another design is much easier.
This is important to note because it means we can change our minds and change our designs when we know more, and do it without paying a huge price. When developers understand this, it helps give us a level of freedom we hadn’t known before. No longer do we have to get it right the first time, which is an enormous stressor. We can start with a very simple design, and as we learn more we can refactor to a more appropriate design.
This turns out to be a highly efficient and effective way to build software. It not only builds software for the right purposes, it also helps us build software that’s flexible and able to change as new needs emerge.


