Developers have been refactoring forever to gain efficiencies and avoid mistakes. Let’s apply more than just theory to ops to do the same.
There’s about a million articles, blogs, tweets and infographics available today that bespeak of DevOps as this or that or the other thing. But one core truth remains: DevOps in part attempts to apply methodologies like agile to operations in order to gain efficiencies and avoid mistakes. We need the efficiencies because the number of apps that need to be deployed, updated, migrated, and maintained is increasing, not decreasing, and there simply isn’t enough time in the day (or during the monthly change window) to get it all done.
We need to eliminate mistakes because they are, according to data from initialstate, very costly. It takes 30x longer to fix one bug (an error) than it does to write one line of code. Anyone who has ever spent time chasing a wild pointer will immediately say that’s too low an estimate, but anecdotally I’m willing to go with that figure. It is an average, after all. To put that in perspective, the same data indicates that developers must find and fix 100 product bugs per 1000 lines of code. That’s a 10% error rate.
I’ll let you ponder for a moment what that means to DevOps and the desire to treat infrastructure as code.
Exactly. You probably want to avoid that kind of error rate as you go about automating and orchestrating provisioning, configuration and general management of all that infrastructure. Just a few errors can effectively negate time gained by automation. So how do you avoid that?
One of the ways to avoid some of that is refactoring.
Refactoring is most commonly used to extract pieces of code (script) that repeat over and over into composable functions (in a procedural language) or methods (in an object-oriented language) or services (in a micro-service or SOA-based system). It’s a primitive form of abstraction that serves to produce more manageable, extensible code bases.
Basically, you’re taking a set of actions that you repeatedly perform and turning them into a reusable, repeatable “thing”. In the case of operations that “thing” is probably a script.
Say, for example, that every time you deploy an application you’re also deploying a load balancing service because, of course, you’ll want it scalable and/or reliable. You always perform the same set of steps to complete this task with only a few changes – usually IP addresses, host names, or other network and app-specific settings.
But you’re doing it manually, or writing a new script every time. Manually making changes are, in most cases, where errors are introduced. Fat fingers are a common cause, especially when you’re not paying close attention because, well, boring! You’ve done this fifty million times and quite frankly, you’re sick to death of the tediousness of it all.
We’ve all done it, don’t pretend you haven’t both thought it was boring and made a mistake. You’re in good company, trust me.
What developers do when this is the case is refactor the common code and reuse it across the system. Those bits that get changed are parameterized and everything else stays the same. Even DBAs do this, they just call the resulting code a stored procedure.
The result of such efforts are self-contained automated tasks that, when used to orchestrate a process, enable composable operations. You string together a set of these scripts and voila! Provisioning complete, minus the fat fingered errors or missed manual steps.
Refactoring code is much more complex than this, of course, as would also be the case within operations, but the general premise here is that the practical application of DevOps includes the process of refactoring operations. It’s about restructuring it into more composable, logical and discrete tasks that can be automated and orchestrated as a means to achieve more manageable and extensible operations. It’s about identifying those steps in a process that are repeatable and can be refactored into a single, shared executable task.
When starting an initiative that applies DevOps it is likely you’re going to have to prove the time you’re taking is worth the investment. One of the ways to do that is by refactoring those operations that are continually used and reused to enable a more consistent, predictable and repeatable provisioning and deployment process. By choosing those steps that are most often repeated and refactoring them into their own composable scripts, you can gain efficiencies as well as reduce errors (and eliminate the time they require to find and fix).