This article for is for those of us tasked with refactoring/rewriting an existing application. A significant application. Not only in size, but importance to the organization. The type of apps:
There are plenty of articles on refactoring an app from a monolithic to microservice architecture. However, until there is a button to press, this strategy will continue to be slow in acceptance execution wise.
Many legacy applications have internally tightly coupled layers, and externally tight coupling with their dependents and dependencies.
Even if the application is fine architecturally with no defects or operational deficiencies, it can make sense to refactor to a no-to-low cost tech stack and compute environment. Lack of documentation and since retired code authors will always make this a more difficult task.
A few hundred thousand to a few million lines of codes are in the mix.
Obscure build and deployment methods don't help. No one person who really knows all of it's workings. Requesting an "as-is" architecture diagram is asking a bit much.
At some point, legacy was synonymous with COBOL and mainframe, then Windows Desktop, and 4GLS. I now include JEE (prior J2EE) applications in this category.
Interestingly, Java remains one of the top languages so refactoring a JEE app to a better Java tech stack allows for keeping much of the code base as is.
Applying the term "legacy" should not be associated with anything negative necessarily. Our lives are still powered by these apps (not to be confused with mobile apps) so for better or worse, they continue to provide tremendous value.
But every large organization weighs and measures the effort vs risk vs value of keeping or refactoring these apps. The unknowns are enough to sway opinions to keep things as is instead of refactor. Moreover, these decisions are made based on the strategies and tools of what are considered "best practice".
These practices are best for a reason, often by consensus, whether theoretical or practical.
Allow me to introduce another practice you may decide is a better practice to consider adding to the best category.
I ask a lot of questions. They don't always get answered, but here were I few I considered:
To answer these questions (and others you might add) in a consistent manner for most applications requiring refactoring, we need an agreeable common pattern.
Pattern 1 : CRUD First and Business Functions Will Follow
CRUD, which is short for Create/Read/Update/Delete, represent the core functions of many applications (including legacy). They are often the lowest level services, tasked with reading/writing data from/to a persistence store, most often for a relational database. This is good news and the start to commonality we need.
Back to my questions. If we can use automation to refactor the CRUD service layer capabilities of an application without touching the app, such that others could leverage the results, then I contend we have a win. Quick sustainable technical wins go a long way to demonstrate value.
Pattern 2 : Database Scheme Is The Key
Every relational database has schema, and all the popular RDBMS systems can present that schema in a standardized SQL script file. This is more good news for us. Database schema contains the formal details needed to determine what to CRUD.
Using database schema will allow us to refactor the CRUD for any application regardless the language it was originally written in. This means we can initiate refactoring for all types of applications which is what every enterprise is full of.
Regardless the purpose of the app or whether or not traditionally it is ready to be refactored, using schema as the primer to refactoring means everything and anything is in a position to be refactored.
Rather than say refactor, let's say re-purpose
Quick CRUD Arithmetic - Why We Need Automation
Consider an application domain model with a couple of business entities and standard CRUD functions.
Let’s grow the domain model a bit so we can continue to better size up the energy involved to create discrete functions for each CRUD operation.
With this small change to the domain model, we can now create a table and equation to better estimate the total number of required discrete CRUD functions.
Imagine if we expand our model to 10 business entities each having one (1) single association and one (1) multi association. We suddenly have 240 (100+60+80) CRUD functions in total. For a typical enterprise application, this # will be in the thousand to tens of thousands and more.
Don't despair!! Necessity is the mother of invention, right? We need a process that takes SQL Script as input to output executable CRUD functions.
I started with 3 questions. So far, if we can pull this off, we have addressed the 1st two questions, but not the 3rd. This is when I turned to Serverless. By their very nature, Serverless functions will help provide reliable secure access to others. Allow me to restate things just to tidy up a bit:
Use automation to turn an application's database schema, captured in a SQL Script file, into an ecosystem of Serverless CRUD functions.
Serverless functions are intended to be stateless discrete well defined pieces of reusable short lived work running in a distributed scalable environment . Sounds like Serverless is a perfect candidate for implementing our CRUD functions. This will give partners, vendors, and other projects access to now inaccessible hard to reach functionality.
Today, Serverless functions are basically created one at a time. In order to accelerate the rate of adoption and entrench Serverless as part of an Enterprise's execution model, vendor supported automation tooling is inevitable.
Hopefully this article offers you an improved lens on application refactoring. To think "(CRUD) functions first" overcomes many of the shortfalls in today's refactoring strategies. Even though the number of CRUD functions will be substantial for the category of important applications to refactor, having automation to turn them into Serverless CRUD functions will simplify things significantly. Also, with the right facade pattern, the number of exposed CRUD functions is easily limited.
Once the path to initiate refactoring is made clearer, more of an application's functionality, and more applications in general, will be refactored (re-purposed).