Over the last few years, the industry has lurched toward adopting better bits and pieces of software development and deployment. Practices such as Continuous Integration and Continuous Delivery, commonly abbreviated as CI/CD, are hailed as a breakthrough in establishing consistent, reliable delivery.
But CI/CD is only part of the picture, and a relatively mechanical one at that. There are many more aspects of development that must happen continuously. In fact, pretty much every aspect of development should happen in a continuous manner, not in an “episodic” manner. For example, we know we need CI/CD, but how about:
Development is hard enough as it is, how can we possibly do everything, all the time, all at once? The secret is simple. Take SmallBitesAlways.
GeePaw Hill (@GeePawHill@mastodon.social) phrases this as taking “Many more, much smaller steps.” (See the full write up beginning at https://www.geepawhill.org/2021/09/29/many-more-much-smaller-steps-first-sketch/). The key to taking smaller steps is to make many more of them.
In the early days of the agile movement, we used the analogy of walking through a vast, pitch black cave system with only a small, weak, flashlight. You have to take small steps, literally. Running as fast as you can through the dark is great if you don’t mind falling off a cliff into the void, slamming into a wall, tripping over a boulder, and so on. You know, the stuff we do on a project all the time.
In The GROWS Method®, we use Experiments to drive development and process adoption. The key to a successful experiment (and slinging code especially) is a really short feedback loop. In other words, a very small step.
How small? That depends on the task. But consider these guidelines:
What do we mean when we say “code in less than two hours?” We mean that you’ve broken down an assignment into steps such that you can reach each next step in about an hour or two. That means writing the tests, writing the code, having the tests pass, and committing to trunk. It may be small, it may not do much—yet, but it’s successful.
Your goal isn’t to work faster, or produce better quality, although those will probably happen anyway. Your goal is to:
Shorten your Success Horizon
This allows you pursue true Trunk-Based Development, and eliminate any long-running feature branches, which can often be disastrous. Instead, this model lets you experience a code base that is always shippable, always working.
With that as a base, now we look at the other aspects that we must do continuously:
“In times of change, learners inherit the earth, while the learned find themselves beautifully equipped to deal with a world that no longer exists.”—Eric Hoffer
The very center of GROWS cites the two most important skills a programmer needs: Learning and Communication.
Surprise! Those probably aren’t the first two that sprang to mind. You were probably thinking of math skills, or the ability to abstract, or problem solving, and so on. Those are important, but the most important skills are learning and communication.
We are learning all the time. Not just the new technology which seems to drop daily, but also learning the problem domain, the solution space, the evolving behavior of the software itself, the nature of your teammates and organization, the ever-changing competitive and possibly regulatory landscape, … the list goes on. And these are almost all moving targets, subject to rapid and often dramatic change. We have to be able to keep up.
Programming involves active learning: experimenting with tests, toy programs, and prototypes. Making mistakes, deliberate or otherwise, to learn how the system reacts and validate your understanding—your mental models that represent the system. Learning more about your user’s needs.
And as you might guess, learning goes hand-in-hand with communication. We communication all the time: with the computer and software, with team members, with sponsors and leadership, with the users.
The GROWS Method® emphasizes the importance of learning by including learning and related activities as first-class practices (which we prefer to call habits).
And unlike school or university, this learning is on-going and continuous as things change. Which means that as much we need to learn that’s brand new, we need to unlearn old, outdated concepts and facts just as readily. The flow of learning and unlearning is continuous, ever-changing and dynamic. A static mindset that applies the same old thinking, same old tools, just doesn’t cut it anymore.
While learning is continuous in the sense of it being ever-changing, we talk about Continuous Value a little differently. Continuous Value is important because it’s not batch value.
In older, traditional organizations, software may have only been delivered annually at best, or even every few years, in a massive new release. That means that the organization only sees new business value in a big batch once a year or every couple of years.
Even worse, the organization realized revenue only after the release. But the organization has to pay for developers and the needed infrastructure throughout the long development cycle. This negative cash flow continues right up until the “gold disc” is burned, duplicated and distribution can finally start. Sometime after that, the organization will eventually realize revenue.
The CHAOS studies from the Standish Group showed consistent data over many years, leading to a simple but iron-clad conclusion: more frequent releases produce greater return on investment (ROI), less risk, and greater ability to generate business value.
But to accomplish that, you need robust feedback mechanisms and a culture of exploration, discovery and learning. And that environment may be a lot harder to create than you think.
That’s where the GROWS Method® can help. The GROWS Method® emphasizes the idea of business value as a continuous stream of small events instead of a single large, high-risk, rare event.
First, your users.
A successful organization depends on the value it provides. Your goal is to enable your users with a new “superpower:” something that helps them do their jobs and meet their goals better, faster, more creatively or more efficiently.
Second, the team gets value. With robust feedback mechanisms, teams understand the difference between the users’ needs and their own understanding. As the batch size gets smaller (implying delivery happens more often), the ability to change the prior release and engineer a better starting point for the next set of work increases. Interacting with users and collaborating with team members requires vision and psychological safety. This means less time dealing with failure demand (fixing defects and reworking delivered features) and more time delivering feature demand—new features and value.
Ultimately, this all adds up to making the organization itself more valuable, with real, long-term, resilient, measurable value. Not with short-term accounting tricks that may look good on paper but cheat or damage users, teams, society, the planet, or other stakeholders.
This is the real stuff.
Taking small steps will keep you from smashing into a wall or falling into a hole, but that’s not quite enough. You need to also make sure you’re still headed in the right direction.
A traditional project retrospective, or “post-mortem,” is aptly named. It’s too late. The patient is dead. Even a bi-weekly retrospective may be too late to prevent collateral damage. Instead, you want to create an environment of Continuous Review & Repair.
We use After Action Reviews (AAR) whenever needed. It’s critical to be able to perform an AAR in a psychologically safe, blame-free environment otherwise they do not work. The goal is not blame, but learning. Learning what needs to change; what needs to be fixed or changed.
In a similar spirit, “code reviews” should never really be about the code. If you’re worried about less experienced developers making mistakes that might need code review, you should be using pair programming or ensemble (“mob”) programming instead. What we will do for a “code review” should instead be focused on a decision review.
In other words, discuss what trade-offs were made, and why, and whether that is still appropriate. The results of this discussion are worth documenting, either in the code, or in a project wiki, etc. In addition to reviewing the decisions made now, set a date in the future to revisit these decisions, to ensure that you are still headed in the right direction.
That’s the continuous part. These decisions made sense at the time, but are they still appropriate a year from now? Five?
Similarly for everything from relationships to process to code. We know we need to fix defects in code, and improve code by refactoring (which doesn’t change functionality), but the same thing needs to happen with everything else as well.
Review your relationships. Is there a defect that needs repair? What about your process? Your environment? Regularly take a look, hold an AAR if needed, and formally schedule any repairs needed.
Taken all together, we can move beyond a simple CI/CD approach and move toward an effective Continuous Paradigm.