Monday, July 20, 2020

Repackaging and Refactoring


Software applications take on a lot of dependencies that go through revisions independent from the applications. These dependencies are fortunately external so the application can defer the upgrade of a dependency by holding on to a version but hopefully not for long otherwise it incurs technical debt. 
The application itself could be composed of many components that could be anywhere in the application architecture and hierarchy. When these components undergo rewrite or movement in the layers, then the changes could impact the overall functionality even when there is no difference in logic and purpose.
One way to eliminate the concerns from unwanted regressions in the application behavior, is to position the components where they can change without impacting the rest of the organization. 
For example, an application may depend on one or more storage providers. These providers are usually loaded by configuration at the time the application is launched. Since any of the storage provider could be used, the application ships all of them in a Java jar file. 
In this case, the positioning of the components could be such that the application separates the storage provider with a contract that can be fulfilled by in-house dependencies or those written externally and available to be imported via standard Java library dependency.
The contract itself could be in its own jar file so that the application is only aware of the contract and not the storage providers which gives more flexibility to the application to focus on its business logic that runtime / host / operational considerations.
The storage providers could now be segregated and provided in their own library which can then be established as a compile time or preferably runtime dependency for the application. This gives the opportunity to test those storage providers more thoroughly and independent of changes in the application.
The cost of this transformation is typically the repackaging, refactoring and reworking of the tests for the original libraries. The last one being the hidden cost which needs to be expressed not only as the changes to the existing tests but the introduction of new more specific tests for the individual storage providers that were not available earlier.
The tests also vary quite a bit because they are not restricted to targeting just the components. They could be testing integration which spans many layers and consequently even more dependencies than the code with which the application runs. 
As the repackaging is drawn out, there will be interfaces and dependencies that will be exposed which were previously taken for granted. These provide an opportunity to be declared via tests that can ensure compatibility as the system changes. 
With the popularity of docker images, the application is more likely required to pull in the libraries for the configurable storage providers even before the container starts. This provides an opportunity for the application to try out various deployment modes with the new packaging and code.

No comments:

Post a Comment