There is no doubting that DevOps is the new kid on the block; every organization I talk with these days has a vague notion of what DevOps is and a sense of which DevOps practices they would like to introduce. There are, however, three recurring concerns that are often expressed:
- The introduction of DevOps is seen as too big a step.
- It’s unclear where to start with a DevOps transformation.
- Practitioners are anxious about changing their ways of working.
All of these concerns can be addressed by recognizing that the shift to a DevOps world is not a revolution, but an evolution of the rich heritage of delivery practices, some of which you are probably already applying. It goes without saying that I have a low opinion of evangelists who suggest that transforming to DevOps (or agile, for that matter) requires you to rethink everything you do to deliver solutions successfully. To paraphrase Oscar Wilde, “A cynic is a man who knows the price of everything but the value of nothing”. Don’t be a cynic!
I often explain this evolution as a chronology of five eras of “best practice” (although I don’t personally like “best practice” as a phrase, since even the best of practices can normally be improved upon):
- Traditional Development practices
- Iterative Development practices
- Agile Development practices
- Scaled Agile Development practices
- DevOps practices
Each of these eras, together with representative practices, is shown in the table below.
Traditional Development Practices
In 2008 I co-authored the book “The Process of Software Architecting” with my colleague Peter Cripps. In it we explored those practices embraced by successful architects by trawling through many different methods and interviewing many successful architects. The core architecture-centric practices that we repeatedly encountered (which, in the context of this blog post, exemplify traditional practices), are:
- Multiple Views: When communicating the architecture, ensure that all relevant views of the architecture are considered. For example, you might have a view to show the key components of the system, and another to show the hardware on which those components are deployed.
- Quality Attribute-Driven Development: The architecture of a system is not only focused on realizing the functional requirements, but also the non-functional requirements. Non-functional requirements include quality attributes such as scalability and availability, and constraints, such as the mandatory use of particular technologies.
- Component-Based Development: This practice defines a system's functional architecture by breaking the system up into a number of collaborating components. It focuses on identifying the major abstractions of the system and making decisions on how the system will be built.
- Asset Reuse: There is almost always an opportunity to reuse assets when developing a solution, but there is often an inconsistent understanding of the different types of assets at the disposal of the architect. Asset types include reference architectures, patterns and component libraries.
- Decision Capture: When it comes to defining a solution, we often need to explore different options before, based on appropriate rationale, selecting a preference. Capturing decisions in an appropriate form can help us recall why we made a decision, and also help others that may need to evolve the solution.
- Architecture Proving: Several approaches can be applied to prove that an architecture is fit-for-purpose. This includes the creation of an architecture proof-of-concept (which may be on paper, or in executable code), as well as through appropriate verification, validation and review activities.
I suspect that none of these practices appears to be particularly novel to you and that, to a large degree, is the point; just because you might be thinking of moving to a DevOps approach to delivery, this does not mean that the practices discussed above are no longer relevant. From this architecture-centric perspective, the exact opposite is true; I personally don’t see how you can practice DevOps (or agile, come to that) without also placing a focus on creating solutions that are easy to change because they are well architected. I intend to write a blog post in the near future that will discuss this in more detail.
Iterative Development Practices
The next era of software delivery practices is focused on an iterative approach to development. Of these, the practice of “iterative development” itself is the most difficult to implement, since it requires a fundamental rethink of several project elements, such as how projects are resourced, measured and funded. This is touched upon in my previous blog.
- Iterative Development: As the project progresses, releases provide incremental improvements in capability until the final system is complete. An iterative development process is similar to "growing" software, where the end product matures over time. Each iteration results in a better understanding of the requirements, a more robust architecture, a more experienced development organization, and a more complete implementation.
- Risk-Value Lifecycle: There is more to an iterative development process than a stream of iterations; there must be an overall framework in which the iterations are performed, which represents the strategic plan for the project and drives the goals and objectives of each of the iterations. Such a framework is provided in the Rational Unified Process, whose phases are labeled Inception, Elaboration, Construction, and Transition. Each phase concludes with a major milestone and an assessment to determine whether the objectives of the phase have been met. A satisfactory assessment allows the project to move to the next phase.
- Shared Vision: This practice ensures that all stakeholders, both consumers and producers of the solution, share a common view of the problems being solved and the key characteristics of the solution (albeit at a high level). In essence, this practice is focused on aligning expectations and the understanding of the product strategy team and the development team.
- Use Case-Driven Development: The practice of describing primarily functional requirements with use cases is well documented. Aside from the technique itself, use cases (and flows through each use case) make natural units of implementation in an iterative development approach since use cases influence planning, architecture, development, and testing.
- Release Planning: This practice is focused on the just-in-time project planning needed to scope the release of executable software within an iteration. This iteration-specific planning complements any high-level planning that considers the project as a whole.
Agile Development Practices
Agile development practices have proven to add incredible value. In particular, I believe they ground us in what matters most in building software in a timely, cost-efficient and quality manner, with a particular emphasis on teaming and collaboration. Whether we’re talking Extreme Programming (XP), Scrum or some other agile method, they each live and breathe certain principles and each draw upon practices that have stood the test of time.
- Test-Driven Development (TDD): The “test first” approach advocated by TDD is primarily targeted at programmers, but is a cornerstone of any agile method. Creating tests that, essentially, define the specification of what the code should do first, helps focus programmers on meeting this specification.
- Continuous Integration: This practice encourages frequent the integration and testing of programming changes.
- Refactoring: This practice is focused on changing an existing body of code in order to improve its internal structure. In a sense, this practice is focused on addressing technical debt, albeit at a local level (since it is typically applied to isolated bodies of code, rather than the system as a whole). In practice, any teams that also perform a level of design (and create models) also update these designs where relevant.
- Whole Team: Agile methods focus on the value of highly collaborative teams as exemplified by Scrum’s daily standup meeting. It is also the team that decides how the project goals will be met and will self-organize accordingly. This means that team composition may change over time since the team, as a whole, should always have the right skills at any point in time to complete the tasks at hand. This practice also instills of sense of collective ownership and responsibility.
- User Story-Driven Development: This practice describes the capture of both functional and non-functional requirements in a lightweight manner (more lightweight than use cases) and encourages collaboration with the relevant stakeholders throughout a project. User stories influence planning, development, and testing.
- Team Change Management: This practice supports the logging of defects or new requirements, by any member of the team, that are within the scope of the current iteration. Such requests are captured as work items and placed on a product backlog (as exemplified by Scrum), which is ultimately reviewed by the team as part of their planning.
Find resources for agile development. Discover how IBM solutions help enterprises be more productive.
In part 2, I shall look at Scaled Agile Development and DevOps practices, and address the questions asked at the start of this post.