We’re riveted by risk. Captivated by collapses and crashes. Humans are hardwired to be fascinated with failure.
This natural survival imperative can even influence our approach to the high-stakes game of application modernization, where learning or ignoring lessons from the project failures of others can determine an organization’s survival or failure.
What are some of the anti-patterns of application modernization worth watching, so that we can put failure in the rear-view mirror?
A team can set out to do ‘just enough’ to modernize their application suite by simply lifting-and-shifting it from on-premises or co-located servers to cloud infrastructure – and thereby assure the real goal of modernization is never met.
In my previous post “Flip the Script on Lift-and-Shift Modernization, with Refactoring” we discussed how the brute-force migration of code and data that were never intended for a future of elastic capacity and microservices agility would fail to deliver the expected benefits of cloud modernization every time.
While the path of least resistance is usually the most desirable one, we need to make sure we don’t set the bar for success too low – for instance, only making cosmetic changes to a user interface. If the underlying application code isn’t appropriately refactored to be microservices-ready for cloud autoscaling goodness, chances are you aren’t really modernizing at all.
Code-level observability of running functional threads within the ‘as-is’ application can show where call dependencies, memory and CPU usage, synchronization and data states are intertwined, so that resolving and refactoring these complexities can untangle knots that accelerate the modernization push.
A CTO friend of mine once referred to a large enterprise’s IT program management team as “huffing their own ROI fumes” when it came to evaluating technology initiatives.
There is a well-known ROI calculus to investment decisions for projects like better customer tracking, support call center systems, and logistics optimizers. Cost-of-ownership can be correlated to the improvement of rather discrete metrics such as transactions per second, productivity, or throughput.
Many leadership teams become addicted to value calculations that favor short-term cost cuts and transactional gains over longer-term results. Ideally, an application modernization initiative should transform the entire digital backbone necessary to support and grow the organization far into the future. So how can accountants derive value from something so broad?
On the bottom line, teams can measure and drive down labor and service costs incurred through constantly maintaining software estates, reducing issue resolution costs, SLA or regulatory penalties, labor spent managing disruptive upgrades, and paying capex to expand and reserve ever-increasing infrastructure to meet usage demands.
Replacing ongoing costs may sometimes free up enough cap room for smaller projects to proceed, but cost-based valuation scenarios will limit the scope of available improvements to whatever is most expedient.
Most companies still value top-line revenue growth over cost-cutting, especially if the curve grows at a faster rate than costs.
The ideal approach here would be to improve the feedback loop and better hone in on the most important functional needs of customers using the applications, whether they are internal or external. Modernization and refactoring efforts and tooling can be prioritized for quick wins on the revenue and productivity side that also contribute to faster release cycles and better long-term results.
The prioritization challenges continue, especially in facing down the looming demon of technical debt, which robs the business of agility and throws sand in the gears of any application modernization effort.
Technically, the day a piece of code is promoted to production, it becomes legacy code. Fast forward 5 years, 10 years, 20 years, and you find that the technology stacks the code was written for encountered generational shifts. Furthermore, most of the team members that specified infrastructure and wrote software will have already moved on.
Rip-and-replace is seldom a good option for dealing with such dependencies due to ongoing business activity. Before hitting the reset button and rewriting applications from scratch, it is incumbent upon the IT team to prove that they can generate quick wins by decoupling the software suite at a more granular level and service-enabling one function at a time.
Extracting valuable intellectual property–in the form of business logic and processes from existing systems–also allows the business to realize continued value from that IP after modernization.
Once you scratch the surface on any complex critical application, there are far too many moving parts for humans to perceive and address at once. Correlating the threads of an existing Java Struts application with its big-iron backend to say, an API-driven Spring Boot or Kubernetes architecture that talks to a cloud data lake requires factory-level automation.
The vFunction Application Transformation Engine (or, vAXE) offers an interesting AI-driven approach to auto-discovering all of the inputs and through-lines of functional threads within existing Java applications, dynamically detecting key business domains, and using those discoveries to decompose the monolith into microservices along those domains. Progress inputs from discovery, refactoring and scaling activities are fed into a factory-management style platform, with a dashboard to allow IT to prioritize and track modernization progress.
Failure is the only intergenerational constant in software development and integration. When two-thirds of application development and integration projects have historically failed to meet timeline or budgetary goals, why try harder?
Initiating an application modernization initiative without strong automated tooling in place inevitably leads to burnout and people leaving the project or company. Employees bear the scars of past modernization trials, which probably involved lots of screen-scraping of data, manual testing, from-scratch coding and sorting through reams of log data.
More importantly, all of the appropriate stakeholders of modernization within the organization and its partners should be aligned around a common source of truth around progressive delivery, and setting a regular cadence of quicker functional wins that deliver incremental value.
Rather than setting a big-bang replatforming requirement that may seem too daunting to reach, many companies instead opt for service level objectives (or SLOs) that improve fidelity and performance over time. This approach allows teams to regain a sense of shared trust, and the satisfaction of knowing that their individual efforts are contributing value to the business, and its end customers.
The counterintuitive secret of application modernization success?
Even the best performing teams will inevitably encounter some failures on their way to a future state of a modern, scalable and agile application estate. A team that never experiences failures at all – no breakdowns in communication, no project stoppages, no bugs in production – is probably too risk-averse to actually try and accomplish anything. But teams that use a data-driven and automated strategy for application modernization will be in a better position to understand and manage the risk and iterate much more intelligently and quickly.
And that brings us full circle. In the application modernization game, it’s okay to have ambitious long-term goals and a commitment to excellence–but to win, you still have to start somewhere. The modernization journey of a thousand apps starts with just one service.