Agile Code is Clean Code!

2019 06 01 head

You are applying the agile, lean approach to your software product development.

Congratulations, you are applying state of the industry good practices.

Your teams use Scrum or Kanban to deliver running software every two weeks.

To create an agile architecture, you must write agile-worthy code. Agile code is always clean code.

Start early, do it continuously, and soon your code will be clean, legible, and free of known defects.

Architecture versus Code

Be honest. Having a huge class with thousands of lines of code plainly demonstrates that your organization worked unprofessionally over months in the past. Such monsters are not born over a one-night coding session. It takes time and incompetence to create such maintenance nightmares.

As long as your product contains such code monsters, it is worthless to pretend to have a nice and thought through architecture. Your organization is still trying to achieve software craftsmanship.

Team discipline and early warning systems are the keys to avoiding such blunders and killing the monster in the egg.

Be honest.

Merge requests, code reviews, and pair programming done professionally should avoid such code monsters.

Train your developers to write clean code and refactor continuously. Have professional engineers in your teams to enforce the discipline.

Clean Code and Refactoring

The clean code test-driven development TDD approach to write code was defined last millennium. Professional developers adopted this approach to deliver high quality, legible, and maintainable code artifacts.

2019 06 01 red green refactor
Red

Write a test and run it, validating the test harness.

Green

Write the minimum amount of code to implement the functionality validated in the previously developed test.
Update the code and run the tests until the test suite shows successful execution.

Refactor

The code to reach a clean code level. Continuously run the tests for guaranteed compliant changes.

If you are a Java developer, you will

  • Use JUnit 5 and Mockito to implement the first step.

  • Use a powerful IDE such as IntelliJ IDEA to write and enhance the functional code.

  • Use tools such as SonarLint, JaCoCo, Spotbugs, ArchUnit to refactor your functional code and test cases. Clean code applies to productive and test code.

The described approach has been a good practice since the beginning of this millennium. All above-mentioned tools are open source and free to use.

Your organization has no excuse to write crap code.

Write well-engineered, legible, and maintainable source code. It is a matter of discipline. It is also a prerequisite to agile architecture.

Acceptance Test Driven Development

How do you know what the requirements of a specific feature are? Either write a huge amount of outdated documentation or find a better way. The better way is acceptance test-driven development ATDD.

For each feature, you need acceptance criteria; this approach is also called specification by example [1]. For each acceptance criteria, write an acceptance test which is executed each time the application is updated in the continuous delivery pipeline. The acceptance tests are the living documentation describing the behavior of your product.

To implement this approach, you need

  • Acceptance criteria which imply using specifications by example techniques. You need to train your business analysts and product owners.

  • Cucumber for Java (or equivalent tools) - to write acceptance tests, Mock all external systems including the database. You want to have a fast build and test time and avoid external dependencies.

  • A continuous build and delivery pipeline to automatically run your acceptance validation tests upon each application change,

  • Avoid user interface tests; they are slow and brittle.

  • Use an in-memory database only if you have to. They are a fast solution to write acceptance tests but are intrinsically slower than mocks.

Code Sociology

The most simple engineering practices are the most powerful. Practice consolidates changes in the behavior of your development organization.

  • Pair Programming is a training on the job and crowd wisdom approach to steadily improving knowledge and quality.

  • TDD and ATDD - are a safety net to guaranty quality attributes in your source code.

  • DevOps starts with git, docker, continuous integration, delivery, and deployment to speed up development and eliminate tedious manual errors.

  • Lack of accountability equates to lack of trust. Your teams are accountable for the quality of your product. You should trust them.

Once good practices are established, you can move to more sophisticated tools. For example, you can perform git history code analysis to uncover weaknesses in your development department.

Teams ready to learn from the likes of Google could evaluate Trunk-Based Development and consider long-lived branches as waste.

Code Review

A code review can be done in different ways. Many teams use GitHub, GitLab or Bitbucket. A widespread approach for our code reviews is using merge requests. However, there are situations where pull requests are not necessary. For example, if a feature is implemented in pair programming or mob programming, then the code is already reviewed while it is written.

We decided that it does not have to be reviewed again, but everybody may look at the commits later on in GitHub and add comments. A rule of thumb we agreed upon is that every line of code has to be approved by at least one other developer before it is pushed into our main branch.

Pull Requests in Trunk-Based Development

The approach is different when using trunk-based development. Since we want to merge our commits into the main branch as quickly as possible, we cannot wait until the complete feature is finished.

Unlike in the original trunk-based development approach, we still use feature branches, but we have much less divergence from the main branch than in Git Flow. We create a pull request as soon as the first commit is pushed into the feature branch.

Of course, that requires that no commit breaks anything or causes tests to fail. Remember that unfinished features can always be disabled with feature toggles.

Now, with part of the new feature committed and the pull request created, another developer from the team can review it. In most cases, that does not happen immediately because the developers do not want to interrupt their work every time a team member pushes a commit. Instead, the code reviews are done when another developer is open for it. Meanwhile, the pull request might grow by a few commits.

The code is not always reviewed immediately after the commit. In most cases, it reaches the main branch much quicker than in Git Flow.

Agile Architecture Series

The agile architecture track contains the following blogs

We also published our agile architecture course (3 ECTS) used for teaching computer science students at bachelor level at Swiss technical universities.

References

[1] G. Adzic, Bridging the Communication Gap. Neuri Limited, 2009 [Online]. Available: https://www.amazon.com/dp/B008YZ993W/