Thursday, October 28, 2010
Remote Pair Programming
I have been successfully pair programming remotely almost every day for the last 3 years. It is very much like local pair programming with some minor differences.... OK. Some major differences, too.
Major
Instead of sitting down with your partner and sharing the same monitor and possibly the same keyboard, the screen will need to be shared virtually. There are many options including GNU Screen, iChat, Skype, yuuguu, yugma, and TeamViewer. Also, something like Google Talk or Skype should be used for voice chatting.
Minor
You know when you are talking on the phone that your attention is more focused on the conversation than when you are locally talking to someone? The same happens in remote pair programming. It is very intense and productive because both developers are extremely focused. You really need to remind yourself to take breaks, switch navigators, and go to lunch!
Labels: Agile
Teamicide

Up until after the 1.1 release our highly productive team absolutely loved coming to work in the morning. We were eating up storing points with an insatiable appetite and pressure to perform came from inside the team. Frequently our roles would cross. Developers would help out Testers and BAs as needed and the Testers and BAs worked very closely together to document proper story acceptances.
When agile was dropped for a more traditional process, things deteriorated very quickly (teamicide). I noticed major negative consequences in user stories, project planning, management, and software development.
Stories
The agile team that was together from inception through release 1.1 benefited from testable stories with high value features. Developers worked with Business Analysts to identify tasks within a story that would require significant development time so that the Product Owner could make informed decisions on whether or not a particular feature provided enough business value to warrant the cost. The BAs also enjoyed lower cost alternatives provided by developers. Only minor changes to a story were allowed after a pair of developers started on it. Significant changes required a new story.
After release 1.1, pseudo-stories were created with many nice to have, but not critical requirements with no developer input. Story requirements changed throughout the iteration including after the story delivery.
Planning
The agile team assigned points to stories during the inception. The amount of points completed during an iteration determined the team's velocity. The average velocity over the last two iterations was used to predict release dates.
The new project manager on the post-1.1 team planned out the next four releases in Microsoft Project with no input from the developers. The releases had unrealistic delivery dates for features that were not yet defined. This is the classic "phony deadline" technique used by managers to (de)motivate developers.
Project Management
The agile project manager was deliberately inattentive to enable the team to self-organize. This resulted in very high morale because developers felt free to contribute ideas and felt a sense of project ownership. The agile project manager's primary role was to remove obstacles that would otherwise distract the team.
The new project manager micromanaged all aspects of the project. We continued to have a stand-up every morning, but as each person gave a status, the PM would ask further questions like "how much longer until the story is completed?".
Development
Pre-teamicide, pairing time was protected, the velocity was high, the code quality was good. Pressure to perform came from other developers. All of this was achieved a sustainable pace with little or no overtime.
Post-teamicide, development time was highly fragmented through frequent meetings, phone calls, and IMs. The velocity was very low and pressure to perform came from the project manager who had set unreasonable deadlines. Large amounts of overtime were required, which led to many more bugs in design and code.
Conclusion
This project thoroughly convinced me of the effectiveness of the agile methodology. It was a great learning experience, but I hope it is not repeated!
Labels: Agile
Monday, July 13, 2009
When is "last"?
Do not optimize until the end. Never try to guess what the system's bottle neck will be. Measure it!
Make it work, make it right, then make it fast.
- Obtain non-functional performance requirements for the system very early in the project. If there is know target, are we not wasting our time optimizing? By the way, "as fast as possible" is not a sufficient requirement.
- Set up automated performance tests. You may even want to go as far a having it run as part of your continuous integration build and having the build fail if certain performance thresholds are not met.
- Near the end of story completion, profile the new code. I use ANTS Profiler for C# and JProfiler for Java. Obvious bottlenecks with minimal code changes for optimization should be implemented without hesitation. Continue to fix bottlenecks until the application is meeting its performance requirements.
- Near the end of the iteration, profile the whole application. Consider having team members rotate through application-wide optimization responsibilities every iteration.
Labels: Agile
Tuesday, July 7, 2009
Selling Agile Development Practices to Your Manager
- Incremental development practices prevent defects and catch them early
- The cost of a defect drastically goes up the further along it is in the project life cycle

Tuesday, May 19, 2009
Chicago Code Camp
I will be doing a presentation entitled TDD in the Real World. There will be a lot of real-time coding! It should be fun.
Labels: Agile, Conference, Redpoint, TDD
Monday, February 23, 2009
Do The Simplest Thing That Could Possibly Work (DTSTTCPW)
DTSTTCPW means not writing code to "future requirements" and not implementing the current requirements in a fancy-overly-complicated-cool-sure-to-impress-peers manner. I am convinced that many designs are driven by how cool they would look in a power point presentation rather than pragmatism!
Some examples of DTSTTCPW violation include writing unnecessary reusable code, writing unneeded highly decoupled code, writing code that goes above and beyond requirements, and introducing a design pattern into the code with no immediate benefit (e.g. strategy pattern with only one strategy). The remainder of this blog entry will focus on writing unnecessary reusable code as this is the most common mistake.
On a recent project, we were losing a lot of time trying to integrate with an unsupported web service. Up to seven people were involved from different sides of the planet. I started asking questions like 1) what does the web service do? 2) where does it get its data? 3) what business logic does it perform? It turns out that the web service was just executing a stored procedure and performing no business logic. Even worse, the stored procedure what local to our application's database!
Apparently the motivation was that at some point in the future other applications would potentially reuse this web service. Many readers of this might think that this is smart because someone was planning for the future. Most people have been in meetings or peer reviews where a developer is congratulated on his forward thinking for implementing a highly reusable design. Only a few years ago, I would have been impressed, too. Now, ......not so much. The reasons:
- Reusablity comes at a high cost - Implementing requirements in a way that takes into account other uses requires a lot of brainstorming and iterations to get right.
- You are not going to need the reusability anyway. Writing from experience, these sure to happen future requirements seldom happen. In lean terms, reusability provides no value to the customer.
- Added complexity - necessarily, a reusable design requires more complexity and probably more lines of code. This results in not only higher up front costs, but higher
maintenance costs.
Common objections:
Yeah, but I once wrote this reusable code that was used by many other developers on a wide variety of applications!
- How many times did you write reusable code that wasn't reused?
- How much did the reusable code cost the customer?
- Did the customer benefit from the reusable code or just people within your organization, team, or department?
- Were other teams forced to use your code even though it didn't really meet their requirements?
Sometimes DTSTTCPW results in poor performance or non-functional requirements not being satisfied.
- Then you did not DTSTTCPW. Instead you DTSTT. Non-functional requirements need to be taken into account when deciding on the simplest thing that could possibly work.
Tuesday, November 11, 2008
A(nother) Case for Pair-Programming
- Faster
- Fewer bugs
- Higher quality code (continuous peer review and brainstorming)
- Shared understanding of code-base
- Can learn from partner
- Better design
- Team building
- Higher confidence in code
- Higher satisfaction
Drawbacks:
- Scheduling problems (developer schedules are different)
- Personality conflicts
Most studies show that a pair is 40 to 80% faster than an individual, which means that two individuals are faster than a pair. However, the resultant code is higher quality in that it has a better design and fewer bugs. It has been extensively documented that the cost and time it takes to fix bugs found by testers or customers is many times larger than the cost of the originally written code, which effectively means that over the whole project life-cycle pair-programming is faster.
Scheduling problems can be solved, but personality conflicts can be a real problem. A good pair programmer leaves his/her ego at the door, is flexible, and most importantly communicates well. One mitigation strategy is to frequently rotate pairs.
Labels: Agile, Pair-Programming, Redpoint
Monday, November 3, 2008
Testable Code
One of the best ways to ensure testable code is practice Test Driven Development. How can code not be testable if it is already tested?
Another good idea is to write code that is easy to test in isolation, which is mostly done by mocking its dependencies. "Mockable" classes are achieved with:
- Injecting dependencies with an Inversion of Control framework such as Spring
- Avoiding singleton and static methods
- Favoring composition over inheritance
Labels: Agile, Mock, Redpoint, TDD
Tuesday, September 30, 2008
TDD vs TAD (Test After Development)
- Bugs are prevented or found early. Finding bugs late is expensive!
- Refactoring can be done with confidence. If the code has proper test coverage, it is unlikely that future refactorings will break it.
- Thinking of and designing for edge cases up front promotes a better and more stable design.
- One is forced to think about how the code will be used first, which should lead to code that actually meets its requirements.
- Less code! TDD is usually coupled with DTSTTCPW.
- Many TAD project just test the "complex" parts of the code.
- Most TAD projects start out well, but end up with unit tests that just increase code coverage with little thought to quality.
- Testing after development requires the developer to figure out the intent of the code again.
- TAD does not benefit from 3, 4, and 5 above.
Labels: Agile, Redpoint, TDD, Test
Wednesday, September 24, 2008
Slow Adoption of TDD
- Developers are not seeing the benefits.
- Developers believe that it slows them down and since they are under constant pressure to produce a lot of functionality they take shortcuts.
Labels: Agile, Mock, Redpoint, TDD
Tuesday, September 23, 2008
The inaccuracy of software project estimation
- When developers estimate a particular requirement or feature, they seldom think of everything especially on large tasks.
- Customers seldom think of all the requirements up front.
- Requirements change throughout the project. With traditional software processes, this is mitigated by change-control, but is this really change-prevention? Is a project really succesful if it delivers what the customer wanted at the beginning, but not what is really needed at the end?
- Skill levels of BAs vary greatly. Developers can implement a requirement perfectly, but if the requirement is wrong the implementation is useless.
- Skill levels of Developers vary greatly. It has been documented in many places such as The Mythical Man-Month and Peopleware that good developers can be up to 10 times more productive than average developers and bad developers actually contribute "negative-work" to the project.
Thursday, September 18, 2008
BadBoy
On my current project, we recently switched from Watin to BadBoy for functional testing. Watin is an excellent testing framework, but we ran into a lot of timing related "issues" because our application is AJAX intensive. A brief description of BadBoy follows.
BadBoy is a functional web application testing tool for non-programmers. It is a record-then-playback testing tool that builds up a “Script Tree” while in record mode, which allows for a variety of assertions, then in playback mode it simply runs the script and tests the assertions.
BadBoy offers Navigation and Request recording modes. Navigation mode is the traditional recording mode found in most record-then-playback tools; it records all of your mouse and keyboard activity. Request mode records just the HTTP requests and posts, which is ideal for load testing.
BadBoy is a good choice for functional testing on a project that has QA resources tasked with automated testing. If the primary functional testers are developers, a better choice is probably Watin or Watir as they are not just recorders, but they also allow for test configuration in code.
Monday, September 15, 2008
Less is More
- Less code because only enough code is written to satisfy a Story requirement.
- Less defects while writing code through TDD.
- Less time spent fixing defects because considerable effort goes into early detection of bugs (Continuous Integration).
- Less regression bugs because code is protected by good unit tests with adequate code coverage.
Subscribe to Posts [Atom]