I randomly came across this article that I wrote in 2015 for my teammates in the Intelligent Robotics Group but haven’t shared on the blog. Reading this article, on best practices for software engineering, as a filmmaker has been *really* interesting because there is a potential for crossover into filmmaking; namely, the concept of being “agile”, importance of “planning and reflection” for each iteration, and the cost of change increasing as time moves forward.
Since last August, I have been taking classes at Carnegie Mellon University, Silicon Valley (conveniently located at NASA Ames Research Park) as a Masters student. My co-workers are often eager listeners of the stories of my adventures in learning software engineering at CMU SV. They asked me to document what I learned on a blog, so here I go 🙂
For my graduate school class “Foundations in Software Engineering”, I built a project planning tool as a team of five, using Extreme Programming Practices. I enjoyed the experience so much and I learned a lot. Now, I would like to share with you what I learned from programming in XP style.
So what is extreme programming?
It’s an Agile software development methodology with focus on programming technique, clear communication, and teamwork.
You should consider XP if your code is a mess, many bugs, and has integration problems. Release causes lots of stress, it is difficult to release more frequently, difficult to add new functionality, and testing takes too long (or non-existant).
XP is special because of the XP Practices, emphasis on simplicity, quality, and testing, and can keep the cost of change low.
Here’s a chart that shows the cost of change with respect to time. Using traditional software engineering methods, as we do in this group, it is extremely expensive to change the code towards the end of the cycle. With XP, the cost of change is low.
Here are all the XP Practices. Some XP Practices aren’t very special. I’ll focus on the ones my team, Rail Byters, learned the most from 🙂
First practice is “whole team”. These are my teammates for CMU, “Rail Byters”
For the class project,
the Whole team negotiatesfeatures list
the Whole team estimates each feature
the Whole team implements the features by rotating pairs
Whole team is also about having a sense of wholeness, and feeling like “we belong”, “we are in this together”, “we support each other’s work, growth, and learning”.
I would like to share with you a quote from a book called “Extreme Programming Explained” that maybe (sarcastic) relevant to IRG:
“Some organizations try to have teams with fractional people: “You’ll spend 40% of your time working for these customers and 60% work for those customers.” In this case, so much time is wasted on task-switching that you can see immediate improvement by grouping the programmers into teams. The team responds to the customers’ needs. This frees the programmers from fractured thinking. The customer receives the benefit of the expertise of the whole team as needed.
People need acceptance and belonging. Identifying with this Program on Mondays and Thursdays and that program on Tuesdays, Wednesdays, and Fridays, without having other programmers to identify with, destroys the sense of “team” and is counterproductive.” – from Page 914 of Extreme Programming Explained
Energized Work is another XP Practice. It’s about working only as many hours you can be productive and only as many as you can sustain. I particularly like this quote: “Software development is a game of insight, and insight comes to the prepared, rested, relaxed mind.”
In this chart, you see 5 constraints of software development: Scope, Resources, Quality, Sanity, and Time. The only negotiable constraint is scope.
Rail Byters decided early on to not sacrifice quality over quantity of the implemented features. And in order to do so, we would de-scope rather than be in the crunch mode. This discussion helped us stay sane and healthy during our last iteration. Often times we were tempted to implement as many features as we could, but we went back to what we agreed on and decided to set out a scope, not deviate from the scope, and polish the code for the final presentation.
Here’s a really important XP Practice: Pair Programming.
Here are some advantages of pair programming are:
- Keep each other on task
- Brainstorm refinements to the system.
- Clarify ideas.
- Take initiative when the partner is stuck, thus lowering frustration.
- Hold each other accountable to the team’s practices.
My team pair programmed every single line of code we wrote for the tool we built. Ideally, you would sit side by side and look at one monitor together. But since our team is partly remote, a majority of our pair programming sessions were done remotely via Google Hangout. For the first two weeks of developing our tool, we held all-hands programming session with one driver who shared the screen with the rest of the team. This helped establish a general process and guidelines for later programming sessions that were performed in pairs or triplets. Once we got used to pairing, we rotated the pairs at each pair programming session and chose the least experienced person at the current task as the “driver”. This practice spread the knowledge so that all members of the team to understand the entire codebase. And it really saved us when some team members became unavailable. Other members were able to step up and continue the task that was left off. Another thing pair programming was good for was keeping each other accountable for following XP Practices, especially writing the tests first. I will talk about test first programming in the later slides.
We planned using stories, which are units of customer visible functionality. For example this would be a story: “Provide a tool tip for astronauts in the surface telerobotics workbench”. Requirements are usually set in stone. But stories are not definite even when they are written down. In XP, you plan with the full expectation that these stories will change as you make progress. In XP, stories are estimated very early in the process.This early estimation was really helpful because it gives you a chance to interact with your customer and discuss priorities. And when you know the cost of each feature, you can split, combine, or extend the scope based on what you know about the feature’s value. With Rail Byters, we estimated each story card by using something called “story poker”, where each member of the team draws a card with numbers between 1 and 8. These numbers on the cards are story points, and higher the points, more complex the story card. The number with the majority of votes becomes the estimate assigned for that user story.
We tracked our progress each week and all the meetings were held on a weekly basis. Planning meetings were in the beginning of the week and reflection meetings were at the end of the week. The weekly cycles were helpful for us to set up a routine of planning and reflection, as well as an expectation of how many story cards we should be able to accomplish at each cycle. And the value of weekly reflection was paradigm shifting. It really ensured that we improve our process every week since we reviewed the reflection notes from the past week during current week’s planning meeting.
Continuous Integration is important because it can prevent large merges and merge conflicts, and help us identify bugs early in the process. In Rail Byters, we integrated after each pair programming session. We programmed, ran all the tests and made sure they all passed, then we committed the changes, and automated build was triggered by the commit. When the build passed we proceeded to the next task.
Test Driven Development is about writing a failing, automated test before changing any code. This practice addresses many problems:
- Scope creep– it’s easy to get carried away and start working on something that’s cool but not a priority. If you really want to put that extra code in, you have to write another test. This extra step is effective in preventing scope creep.
- Modular Design: If it’s hard to write a test, it means you have a design problem. Break the design down into modular chunks.
- Trust: It’s hard to trust the author of the code that doesn’t work. When your tests are passing, you give reasons to your teammates to trust you.
Once you start, the rhythm of test, code, refactor is fun and enjoyable.
There is no one right place to start.
Start by changing one thing at a time.
Change starts at home. Only person you can actually change is yourself.