Continuous Modernization: Tacking Across Headwinds

Eric Newcomer

September 21, 2023

Eric Newcomer (Guest Author – CTO and Principal Analyst, Intellyx)September 21, 2023


You have picked a new destination for your applications that will bring efficiency, ease of maintenance, and upgraded technology, but you are finding that you have to continuously tack due to headwinds such as:

  • Budget shortages
  • Required upgrades
  • Safety and security patches
  • Priority maintenance and enhancement requests
  • Conflicting business priorities
  • New applications for new revenue streams, or new customer acquisitions.

You can’t get where you want to go in a direct, straight line because of all the conflicting interests and priorities for application maintenance, enhancement, and replacement.

It is not at all clear how you will achieve your goals of modernization, paying down technical debt, and addressing architectural debt, despite the clear business value of doing so.

The first thing to do is identify a target state to codify the strategic business value of the modernization program. The target describes the future state of the IT systems post modernization and ties it to strategic business value such as increased revenue, improved cost efficiency, or supporting the launch of a new product.

If you’re sailing a boat, your target would be a landmark on the other side of the river. If reaching your target means you are sailing into the wind (i.e., you have headwinds), the only way to make progress is to tack across the wind from side to side and make progress incrementally. 

Of course you want to be sure that you don’t drift off course, especially not over the cliff, as my colleague Jason English warned about in the previous blog post in this series.

An IT practice called “Managed Evolution”1 describes in detail how to continuously make progress toward the business value achieved through modernization.

tacking headwinds figure 1
Figure 1, Central Principle of Managed Evolution

As shown in Figure 1, the central principle of managed evolution is to evaluate each proposed modification to the system in the context of whether or not it helps you to move you closer to the desired system state. The framework allows you to assess the incremental business value of doing so, and therefore help decide whether investments are strategic or not.

It is of course impossible to align every modification to achieving the target, resulting in the zig-zag journey shown in the diagram. It’s like sailing into the wind – you can see your destination, but you can’t head straight toward it. You have to make progress sideways and incrementally.

Modularity to Reduce Complexity

One strategy for implementing the managed evolution approach is to use abstract interfaces to modularize legacy system functionality so that it can be updated without impacting the user-facing part of the application.

For example, wrapping a legacy system function using a REST API transforms the legacy data format into a standard JSON payload for web and mobile applications. Once this is in place you can upgrade the back-end technology without disturbing the API consumers.

Once you have the abstract interfaces in place, the next step is to break out common components into individual services, such as microservices for example.

Recently there’s been a lot of debate about whether monoliths are better than microservices, but this really misses the main point, which is the advantage of modularity. Many studies over the past decade or so have clearly shown that modular systems are easier to maintain and change.

Of course, there’s no single right answer for every application, but in thinking about microservices it’s important to keep in mind how they align to the principles of modular systems.

The first step in moving from a monolith to a modular services architecture is to incrementally break out common functions into independent components, as illustrated in Figure 2.

For example, break out a common function or domain such as a customer lookup or price calculation, deploy it independently, and access it from multiple applications using a REST API.

Once you break out and modularize a critical mass of services, you can start constructing entire applications out of them, effectively replacing the monolith.

The most challenging part can be figuring out the modularity of the interfaces. Practices such as Domain Driven Design (DDD) and Service Oriented Architecture (SOA) can help.

Another very good reason for moving to modular systems is that services can be implemented using different programming languages and software systems. Some might be implemented using Java and deployed using a Java EE application server. Others might be implemented and deployed using .NET.

Modular systems are easier to maintain and evolve and are easier to update and deliver to production. Modular systems also improve developer productivity by dividing up the work.

Staying on Track

Even more important than defining the target state is documenting the current state and finding a way to measure progress from the current state to the target state, daily if possible.

Measuring progress frequently helps the modernization project stay on track and get a handle on how much architectural debt is being paid off. Paying down architectural technical debt is like paying off credit card debt – it has incremental benefits. The more you modularize your systems, for example, the easier they are to develop, maintain, and change.

So, this would be a good measure of progress for example to measure how many independent services have been created? How many abstract interfaces? What is the reuse count of independent services (i.e., how many applications consume them)?

First, get a good picture of what’s out there. Then decide on a methodology or architectural framework to guide the journey from current to target (and by the way, it’s always a target because it moves).

Adjustments to the target state should be made regularly as the modernization work progresses. Documents and designs must be kept up to date during the project to reflect changes that inevitably occur. Ensure that the implementation aligns to the architecture, and update continuously. 

How does vFunction Help?

vFunction analyzes the architecture of your Java and .NET applications to identify domains and score your technical debt. It also identifies candidates for modules or domains that can be broken out and hosted as independent, shareable services.

vFunction can help set the architecture baseline for the current state and uses architectural observability to detect drift, prescribe fixes, and send alerts to architects about architectural events and other actions on high debt modifications. In other words, it helps track progress toward the target state goal and regularly scans and reports on the evolving architecture.

vFunction also helps achieve modularization by refactoring monoliths into microservices and generating abstract APIs for them.

The Intellyx Take

Application modernization is a continuous journey across a jagged line of organizational headwinds. It’s more of a process than a technology, but the right technology can help a lot.

vFunction provides a unique set of tools to help architects understand where they are starting from in the journey, how far they have progressed (and whether course corrections are needed), and to automate the work around modularization, decomposition, and service abstraction.

The capabilities of these tools promise to be extremely valuable to anyone undertaking the continuous modernization zig-zag journey.

Copyright © Intellyx LLC. vFunction is an Intellyx customer. Intellyx retains final editorial control of this article. No AI was used to write this article.

Image by Tim Green, Creative Commons license


Eric Newcomer

Get started with vFunction

See how vFunction can accelerate engineering velocity and increase application resiliency and scalability at your organization.