Increase Codebase Quality and Customer Satisfaction with the Extreme Programming methodology
The vast majority of online articles are about being efficient with your time and resources in order to deliver as much as possible. Being efficient of course is a key factor in being productive but sometimes in large corporations, the most important thing is to have a high-quality and easily maintainable codebase, while keeping your customers happy by quickly responding to their feedback. This is why agile methodologies are so popular nowadays with Extreme Programming being one of them.
Extreme Programming
Extreme Programming (XP) is successful because it stresses customer satisfaction. Instead of delivering everything you could possibly want on some date far in the future, this process delivers the software you need as you need it. Extreme Programming empowers software engineers to confidently respond to changing customer requirements, even late in the life cycle.
The values
Extreme Programming improves a software project in five essential ways: Communication*,* Simplicity*,* Feedback*,* Respect*,* and Courage.
Good communication is essential to any project. Everyone is working together on everything, from requirements to code. Honest and regular communication allows adjusting to change and stirring in the right direction on time.
Keep your design simple and clean. This means doing what is essential, thereby reducing waste. Address only the known issues and keep the codebase simple for future additions and maintenance.
Feedback means asking questions and learning from the answers. The only way to know what the customers really want is to ask them. Demonstrate your work early and often, then listen carefully and make any changes needed.
Every small success deepens the respect for the unique contributions of each and every team member.
With this foundation, Extreme Programmers are able to courageously respond to changing requirements and technology. This can include speaking up against what does not work and anything that affects the project’s effectiveness, accept feedback and improve methodologies.
The Practices
The core of XP is an interconnected set of software development practices. While it is possible to implement these practices in isolation, their interactions help you achieve higher levels of productivity and quality and can enable you to fully eliminate the risks you often face in software development.
These practices can be divided into three groups. The practices of coding, the interactions between developers during development, and the relationship between business and technical interests.
Coding Practices
The code is the most important artifact of every project. The first 4 practices focus on producing code that is maintainable and easy to be extended.
1. Simple Design and Code
Code and design simply. Solve customer’s current needs and resist the urge to guess future needs in order to avoid unnecessary complexity and over-engineering. Follow these three principles:
Do the simplest thing that could possibly work.
You aren't gonna need it (YAGNI)
Once and only once (DRY)
Flexibility is the goal. Simplicity is the means to that end. Simple designs are easier to understand and explain. Simple code is easier to test, maintain and change.
2. Refactor often
Refactor is a fancy word for rewriting parts of the codebase that are not well designed. Refactoring improves existing code by making simplifications and removing code duplication when possible.
Refactoring should be done regularly. After finishing a task refactor the new code. Eliminate repetition. Break long functions in smaller ones. Clarify the method and variable names. Simplify. Leave the code easier to understand. (Boy Scout rule)
3. Coding standards
Code is the primary form of communication within a technical project. You should have well-defined coding standards and conventions and follow best practices whenever possible. They should represent the project’s shared values and should evolve with it. Usually, languages and frameworks have existing style guides you can embrace and adapt to your own needs.
4. Common vocabulary
Documentation should exist for every major component in the project. It should be available to everyone including stakeholders, which means it should use simple language or metaphors for people who don’t know how to code or read a UML diagram.
Developer Practices
Collaboration between developers is almost always needed in every task to be done. The next principles focus on improving teamwork, reinforce good programming habits and help onboarding new or inexperienced developers on the team.
5. Test-driven development
The habit of writing the test before the code ensures that the acceptance criteria are well understood and every line of code is written to fulfil them. Untested code is eliminated. Tests should run fast and in every opportunity. They are a huge vote of confidence that everything works as expected and that the latest changes haven’t produced any unexpected side-effects. Failed or flaky tests should be fixed with high priority to avoid neglecting the whole codebase.
One mistake to avoid is skipping the third and final step of TDD. Refactoring. First, you write the test, then you write the code to make the test pass, and lastly, you have to refactor the code to ensure coding standards are met and code duplication is eliminated.
6. Pair programming
In pair programming, two developers work together to accomplish a single task. The person with the keyboard (Driver) focuses on the implementation details of the task while the other person (Navigator) focuses on the big picture, ensuring that the task fits into the project as a whole and ensuring that the team guidelines are followed. Both roles are important and both roles are fluid. Feel free to switch positions during the task. Two brains on a task produce fewer bugs leading to cleaner code. In addition, this is a great way to onboard new or inexperienced developers.
7. Collective code ownership
Any developer should be able to change any line of code as needed to complete a task. It is common for a single developer to be the only one familiar with some parts of the codebase and every new task being assigned to him/her automatically. This is extremely dangerous. Collective code ownership reduces risk and encourages knowledge sharing across all members of the team.
8. Continuous integration
Shipping code to production should be easy, quick and painless. Each task should be small enough to be completed in no more than a few hours. Automation is the key for this to work. Every time the upstream is updated, the test suite should be triggered to verify that everything works as expected. If tests pass the code should be shipped to production as soon as possible.
Another important aspect is that the state of the developer's machine should not affect how the code is run in any case. Every code or artifact needed to run the application should live in the repository. You should be able to work from a different computer without much hassle. The most popular way to achieve this nowadays is Docker.
Business practices
A clean codebase with a solid testing suite doesn’t serve much if the customer’s actual needs are not met. Furthermore, resources (time, people, etc.) are almost always limited. It’s up to the customer to decide if having a good enough product is better than having a perfect product later. Close communication and immediate feedback are the means to make this happen.
9. Add a customer to the team
An actual user of the product should be part of the team. Their feedback is invaluable in order to clarify needs to reduce guesswork and misunderstandings. The customer should be always available for clarifications and it’s up to him/her to decide if the deliverable is accepted or not.
10. Planning game
One common ritual of all agile methodologies is the Planning game. It is the process of deciding which features to implement and in what order. The goal is to maximize the value of the features produced. Planning takes place at the beginning of each iteration. Business owners set the priorities, taking into account the value and the risk of each feature. Developers deal with the technical challenges of each task and make estimations based on some arbitrary value (usually story points) that represent the complexity of each task. Given the priorities and the associated estimations, the work of the next iteration can be planned.
11. Continuous delivery
The release cycle should be short. Features and bug fixes should be delivered as soon as possible. This makes releases less painful in the long run, reduces pressure, and enables early customer feedback. A popular technique is release trains when the main branch is deployed to production in short intervals usually once a week.
12. Work at a sustainable pace
Everyone has a definite amount of mental and creative energy. Every working hour consumes some of this energy and pushing these limits is counterproductive and not sustainable in the long run. Working hours are part of the company culture. When working overtime to meet a deadline you inflate your velocity which will define your capacity for the next iteration. Overcommitting doesn't solve the problem because you are actually promising more than you can deliver. Long working hours decrease productivity, tempt you to take shortcuts, and force you to make a judgment or trivial error.
The solution for this is to take regular breaks during the day, unplug when working hours are over and resting on weekends. When overcommitting, adjust your scope to reflect your actual velocity. Sometimes you will need to work overtime for a critical bug fix. This is fine as soon as it happens occasionally and doesn’t become part of everyday routine. Maintaining a healthy mental state will directly affect the quality of the results you produce.
Adopting Extreme Programming
Extreme programming works because all the practices complement each other. But usually going all-in in a new methodology or framework is not realistic. Your best bet is to adopt it gradually by prioritizing what makes more sense for your team. Identify your most pressing need and adopt the most related practice first. Improve and keep adding new practices until all the practices are in place.