The Agile Architect
Do You Really Need the Complexity of an Enterprise-Scale Agile Framework?
So you're running a big complicated enterprise-scale operation. You're doing agile at the team level and now you are ready to tackle enterprise-scale agility. You take your first steps to introducing an enterprise-scalable agile framework. Oops! You may have just made a big mistake.
Agile was originally introduced as a philosophy for how software developers work together to make great software. Implicit to the agile manifesto is an understanding that this requires individuals working together as a team. As larger companies adopted agile, they recognized that their teams also need to work together to create a larger integrated whole.
For instance, a smart thermostat company might need to coordinate releases of their new thermostats (with both hardware and firmware) with releases of their backend services and mobile apps that take advantage of those new features. A healthcare company might need to coordinate between teams supporting their electronic medical records, practice management system, and patient portal. A massive online game company may need to coordinate changes to their billing system with a new release of their game that now features in-app purchases.
These are all examples of initiatives that appear to require large-scale coordination across multiple teams performing different tasks. But do they really?
Do You Really Need Agile at the Enterprise Scale?
Before we dive this deep, let's first make sure we all have a common understanding of what we are discussing. I'm purposely using the term "enterprise-scale agile" as opposed to "enterprise agile." Of course you should strive for your entire organization to be agile: You want your entire organization to be able to deliver value and embrace change. By using the term "enterprise-scale agile," I am referring to the attempt by large organizations to manage the complexity of dependencies between large numbers of teams responsible for delivering different pieces of software, firmware and infrastructure, possibly within different parts of the organization so that, as a whole, they can deliver a large coordinated chunk of value at the same time with the understanding that if any piece is missing, it negates most or all of the business value being delivered.
In the three examples above, the only one that actually might need a large, complex, interdependent, coordinated effort is the smart thermostat. Hardware has fundamentally different rules from software. A supply chain needs to be established and parts need to be ordered. Once the thermostat is shipped, it's shipped. The hardware can't be updated. The firmware also most likely can't be updated unless the manufacturer is willing to increase manufacturing costs by paying for an over-the-air update capability.
But still... We should work to break dependencies and increase simplicity.
Look at it this way: Would you rather work hard to implement some form of enterprise-scale agility that increases the every day burden of delivering value; OR, would you rather work hard to reduce complexity by finding novel ways to reduce or eliminate inter-team dependencies, thereby reducing the every day burden of delivering value?
How Do We Do It?
Now, I never claimed this is easy. It's not. It takes time, effort and experimentation. Rather than tackle this with a big bang, take small impactful steps to continuously move to a better state.
Here are some ideas to think about.
Concept #1: Eliminate Release Dependencies by Decoupling Deployment from Releases
I've discussed Feature Toggles and Branch by Abstraction in a previous article. Perhaps the most powerful aspect of these is the ability to deploy code into production with its capability not yet enabled.
Consider a situation where multiple teams must release new capabilities to provide a new cross-team feature to their users. In a traditional approach, each team would coordinate their schedules attempting to release on time. If one team misses the deadline, they hold the other teams hostage, making it difficult or impossible to build and release other features. Why? Releasing a new feature developed after the cross-team feature would also release their piece of the cross-team feature and probably break the system.
By using feature toggles, each team continues to deploy independently. If one team is not ready by the deadline, the feature toggle is not enabled but each team can deploy their piece of the cross-team feature while continuing to release other features. When all teams are ready, the feature toggle is enabled and the users see the new functionality.
Concept #2: Take Advantage of Cloud Computing
Cloud computing, whether you use a public or private cloud, changes how we think about building and releasing our software. With compute power available on demand, the cost of supporting peak usage times during development decreases significantly. Important to enterprise-scale agile, a cloud-computing approach decouples commissioning new infrastructure and configuration of servers from the development and deployment of software.
With software that is cloud-native or cloud-ready, it is much easier to spin up new environments. This means that the individual teams have the ability to spin up a full-scale or partial production-like environment for testing independent of the other teams. If they don't have access to the software built by some of the other teams yet, perhaps because those teams are behind schedule, the team can build mocks in the interim. Teams can be integrating with each other continuously rather than on a pre-defined enterprise-wide cadence.
Another way to take advantage of cloud computing is to use blue-green deployments coupled with canary deployments to mitigate risk. The new release is deployed into a new production environment. The new production system can be tested as necessary. Once final testing is completed, a small number of users are redirected to the new environment to gather feedback before moving over all users.
Combining blue-green and canary deployments with feature toggles makes for a powerful rollback capability that allows each team to deploy their software independently while safely releasing features that span multiple teams..
Concept #3: Eliminate Code-Change Dependencies by Reducing Per-Team Code Ownership
Remove inter-team dependencies by allowing them to modify each other's code. We preach about whole-team code ownership, but this becomes very difficult as the number of developers and technologies increases. Consider adopting something like an open source model where a team may have ultimate ownership of a software module but other teams are allowed to submit patches. This helps with capacity management. The team that owns the code can continue working on their priorities while the team that needs the change can make it while respecting the boundaries and responsibilities of the other team.
Concept #4: Eliminate Architectural Dependencies Through Light-Touch Architectural Governance
Architectural governance often gets a bad rap. And rightly so. Heavy-handed architectures with strict top-down governance leads to unwieldy solutions that look good on paper but don't work in practice. Heavy-handed, monolithic architectures rarely work well and cause unnecessary coupling between teams.
Architectural governance works better when it bubbles up from the teams performing the work, informed by actual coordination needs across teams rather than architecture purism.
All that being said, there is a place for architectural governance in enabling enterprise-scale agility. The more consistency teams have at their interface points, the easier it is for them to integrate their software. Architectural and design consistency reduce the risk of incorrect integrations and unnecessary complexity.
Consider, for example, the case for adopting a microservice architecture. This is a well-known solution for supporting multiple self-sufficient teams with loose coupling between them. Service-based architectures, micro or not, allow for versioning of interfaces that can continue to support legacy functionality and new functionality simultaneously. Applying a global versioning strategy makes it easier for teams to know how to access the new functionality when they are ready. Tools like an API gateway can help facilitate a self-service approach to integration, with each available version of the API/service well documented and easily accessible.
Concept #5: Eliminate Organizational Dependencies by Changing Your Organizational Structure
Identify the dependencies between teams, departments and divisions. Where possible, reorganize so that they have fewer dependencies. This may mean shifting responsibilities between teams as well. Map your organization to your value streams. If they are misaligned, change them.
Agility across the enterprise does not require lock-step whole-company coordination. Drive your value streams from a user centric approach. Make adjustments as needed. Shift people and resources to stay in balance. It's not about doing all the smart thinking and planning up front, enforcing that everyone stays coordinated. It's about giving yourself the tools, visibility and flexibility to be able to drive the business and think through coordination challenges every day.
So do you need an enterprise-scale agile framework? Maybe. But I'd do all the things above, and more, first.