Written By: Steve Zagieboylo, Senior Architect at Calavista
This is the fourth part in the series, “Technical Debt Patterns.”
Tree Rings occur whenever you have wrappers around wrappers, sometimes several layers deep. Sometimes this happens because a core of important code is too complex or too fragile for anyone still around to be prepared to edit it. Maybe the core represents an API that is called by code outside.
Developers have been afraid to edit a fragile bit of code, so new functionality is made by putting a layer around it and calling in. This can happen multiple times, and you can tell the age of a library by the number of rings around it.
Unit Tests (As Always) Analysis Step One
First, identify the rings, if there are two, or three. This is not as straightforward as this simple instruction makes it sound. Sometimes there are layers to an API that make perfect sense and are a good architectural choice — as Mark Richards says in Software Architecture Patterns, it is a good idea to have a clear separation between the Presentation, Business, Persistence, and Database layers in the software. You don’t want to look at these layers and declare that they are tree rings.
Where you are likely to see Tree Rings is inside the Business Layer, and then it bubbles up to the Presentation or layer. In a web application, this is the REST API layer. When you see more than one Resource file (or REST API file) that sit over a given set of entities in the Persistence layer, that’s one sign that you might have a problem. Sometimes it isn’t a separate file or set of files, just an entirely separate section within the files, with a bunch of APIs that no one really owns any more, but then a bunch of new ones that replicate or overlap significantly the old ones. Sometimes they will even call the old ones, then filter or merge or otherwise transform the results.
The other time you will see this problem is in the Persistence Layer, when too much Business logic has gotten pushed into it, or, more likely, there was not initially a clean separation of Business and Persistence, but then someone added another layer because it was too muddled.
Analysis Step Two
Now that you’ve identified where the grunge is, figure out where you want to head but don’t start those changes yet. This is where you probably need to add unit tests before you proceed. Work out what the outside world really depends on from these inner pieces, and make thorough unit tests for them. If there are other parts of your own code that have been sticking their fingers into your inner rings, then make wrappers for those inner parts, possibly in the outer part where the API should have been in the first place, and change them to call the new API.
Finally Making Changes
Finally, you can work out what the right layers are. Make sure that the business logic is no longer in the Persistence Layer, and that you have only one, cohesive business logic class for each concept. If those classes are getting too big, then you possibly want to refactor your architecture so that the concepts are more cleanly defined and delineated.
If your unit tests are comprehensive, this is something that you can do over time. But that means you’ll have to budget that time in. You can’t just do the analysis and then congratulate yourself. Pick the worst one, where there are two or even three Business Logic wrappers around some set of the persistent entities, and clean up that one mess. Then you’ll have a good idea of how much time and effort it takes, plus you have improved your average code cleanliness by quite a bit, since you took your worst section and (hopefully) made it one of your best.