In any software development process, there are multiple activities that are involved in the process of creating software.
For instance, there are design sessions, architecture, development, testing and deployment amongst many other activities that are crucial to building a successful software.
In this article, I’m going to talk about the process of developing software, specifically speaking writing code and contributing this code to a source control medium to ensure the code is stored at a centralized server where everyone else in the project can copy it, use it and build on top of it.
In the software industry today the most dominant source control medium being used is git – which is a distributed version control system for tracking change in the source code of any project. It was designed by Linus Torvalds to coordinate the work amongst software engineers to ensure no loss in code may occur and ensure everyone is working with the same code base.
But when developing software, it’s important to engineer not just the software being built, but the very process of developing the software itself.
The way I’ve seen some features being developed and committed to source control today is that it goes from WIP to DONE without any indication of how the software was actually written and the code was developed.
The problem with this practice, especially in a test-driven environment, is that there is no way the history of the code being committed could indicate whether the tests for this code were written before or after the implementation code was actually written.
This becomes even more problematic when engineers rely on tools like code coverage to use as definite indicator of whether the code is fully tested or not.
I have also seen more and more declining interest in being descriptive about the code commits, and what they actually indicate – which makes it even harder to find a particular feature implementation commit, when it was committed and who the subject matter expert to discuss code changes with.
Coding is a Social Activity
Coding just like any other activity that involves more than one individual, is a social activity. An activity where the success of it relies heavily on the proper communication between the individuals involved in that activity.
In software development, committing code with proper messaging and content is a key to the successful communication amongst software engineers developing the software.
When the communication is clunky, unclear or vague, the entire process faces the risk of being lossy. Lossy in the sense that some information will be lost, some features will be hard to traces, and some engineers won’t get the credit and appreciation they deserve.
When I look at any code repository, I can very easily determine the level of communication and cooperation between the team involved in developing in that repository so easily by simply looking at the commit history.
Working Code is Not Enough
Some engineer once told me: “It doesn’t matter how the code was committed, what matters is that it works!”
And I couldn’t disagree more with this statement, simply because a “working code” isn’t just the code that fulfills a particular business need, but also the code that is easy to maintain and easy to understand.
The maintenance and understanding of any code base rely partially but crucially on the history of how this software was developed, and who was involved in the development process of that software.
Especially in enterprises where engineers might get shuffled around often or move on to other teams and some of the domain knowledge that governs why particular features where the developed in a particular why.
A given piece of code could tell you how a particular goal can be achieved, but it can’t tell how why that goal needs to be aimed for in the first place. This is why communication is crucial, documentation is crucial and being clear and explicit about the purpose of your code and what stage it was in when it was committed is even more important than most other communication activities.
And because of the importance of code history, multiple teams and I have decided to purify our code history, by making short commits to describe the development process of each and every feature we are developing.
In other words, when an engineer writes a failing test, they have to make a commit, that puts out a clear title of what that failing test is, and that its status is that it’s failing as follows:
ShouldRetrieveStudentByIdAsync -> FAIL
The next commit should indicate that the very same test has passed, and there should be no other code involved in that commit except for what makes the test pass, as follows:
ShouldRetrieveStudentByIdAsync -> PASS
A commit history that follows that pattern is what I call Pure Code, and the activity that produced it is what I call Pure Coding.
It’s pure and beautiful simply because it’s clear about its origins, how it was developed, who developed it, and what their thought process while they were building it.
It makes it even easier for other engineers on the team waiting for a feature to be developed to have a real-time track of where the code being developed is at, looking at a DRAFT pull request.
It opens the door for another form of well-engineered communication methodology of letting other engineers on the team know which direction a particular feature is being developed in and where it’s headed, therefore allows even faster feedback for other engineers to reach out and help with some insights before a particular feature development goes off-rails.
This pure coding approach, becomes even more meaningful and magnificent when two engineers are pairing on the same feature – it follows the following pattern:
ShouldRetrieveStudentByIdAsync -> FAIL [by Alice] ShouldRetrieveStudentByIdAsync -> PASS [by Ken] ShouldThrowExceptionOnRetirveIfStudentIdIsInvalidAsync -> FAIL [by Ken] ShouldThrowExceptionOnRetirveIfStudentIdIsInvalidAsync -> PASS [by Alice]
You can easily see in the above history, the ping pong pairing pattern at its finest as the history of the code itself is telling the story of how two engineers built a particular feature in a TDD approach and ping-ponged the development between them until it was finished.
Communication All the Way
Pure coding clears out all the miscommunications that may occur in a development team about understanding the pain points and the complexity of developing a particular feature.
The most common issue that happens is when a feature is delayed, or surpasses it’s expected delivery date.
Naturally questions will be asked why a given feature is taking too long?
Pure coding makes answering this question much easier, it even makes tech leads have better understanding of where pain points are when developing a similar feature and helps them work with data to streamline the future development process in similar future features.
It also makes the estimation process of features even easier and more accurate than others.
And so is the case with the standardization and adaptation and commitment to any pattern, it helps streamline the processes and when cultivated it becomes a guarantee for a resilient industrial software development teams, and more communicative software engineers.
These patterns and practices that we develop, help us shape the future of the industry, as our software industry grows, more measures and standards have to take place to ensures the quality of the software we develop. Especially that it’s becoming more and more involved in our daily lives, and more involved some of the most crucial decisions being made about our future.
It’s not enough to write code that works, and it’s not enough to write a beautiful piece of code, it’s also important that very process of committing the history of that code to also be just as beautiful – that’s software craftsmanship and that’s what every engineer should aspire to achieve in their journey in this industry.