Summary
In this episode, we discuss the cancer pattern, a technique for gradually replacing an existing system with a new one. We explore its benefits and challenges, and provide examples of how to apply it in software architecture.
Detailed Notes
The cancer pattern is a software architecture technique that involves gradually replacing an existing system with a new one. This approach is particularly useful when dealing with complex systems and legacy code, as it allows for a smoother transition and reduces the risk of errors. The cancer pattern involves identifying areas where changes can be made with minimal impact on the overall system, and then replacing those components with new ones. This approach is like replacing individual components of a machine without shutting down the entire system. By applying the cancer pattern, developers can minimize the risk of errors and ensure a smooth transition to the new system. The cancer pattern is not a replacement for proper planning and testing, but rather a tool to aid in the process of replacing an existing system with a new one.
Highlights
- The cancer pattern is a gradual replacement of an existing system with a new one, rather than replacing it in one shot.
- This approach allows for a smoother transition and reduces the risk of errors.
- It's particularly useful when dealing with complex systems and legacy code.
- The cancer pattern involves identifying areas where changes can be made with minimal impact on the overall system.
- This approach is like replacing individual components of a machine without shutting down the entire system.
Key Takeaways
- The cancer pattern is a technique for gradually replacing an existing system with a new one.
- This approach allows for a smoother transition and reduces the risk of errors.
- The cancer pattern involves identifying areas where changes can be made with minimal impact on the overall system.
- This approach is particularly useful when dealing with complex systems and legacy code.
- The cancer pattern is not a replacement for proper planning and testing.
Practical Lessons
- Identify areas where changes can be made with minimal impact on the overall system.
- Gradually replace existing components with new ones.
- Minimize the risk of errors by testing and validating each change.
Strong Lines
- A gradual replacement is like replacing individual components of a machine without shutting down the entire system.
- The cancer pattern is a tool to aid in the process of replacing an existing system with a new one.
Blog Post Angles
- The benefits and challenges of using the cancer pattern in software architecture.
- How to apply the cancer pattern to real-world examples.
- The importance of proper planning and testing when using the cancer pattern.
- The role of the cancer pattern in reducing the risk of errors and ensuring a smooth transition to a new system.
- Case studies of successful implementations of the cancer pattern.
Keywords
- cancer pattern
- software architecture
- legacy code
- complex systems
- replacement technique
Transcript Text
Welcome to Building Better Developers, the Developer podcast, where we work on getting better step by step, professionally and personally. Let's get started. Well, hello and welcome back. We are continuing our season where we're looking at patterns and any patterns for software architecture. We're getting towards the end and we're getting into a little bit of a gray area on some of these. This is no exception. The pattern we're going to talk about today is what I refer to as the cancer pattern. Or you could look at as the blob, but there is a blob pattern. It's a little different. It doesn't have the same connotation. When I'm thinking of a blob, I'm thinking of the, we'll call it like the horror monster blob thing that would basically just absorb stuff into it. The cancer pattern is like that. This one is specific for certain types of problems that we need to solve. It may seem, I don't know, like an outlier or something, but this is actually a problem I'm starting to see and have for many years more and more often. It is becoming something that we need to tackle fairly regularly as technologists. Now, if you don't bounce around very much, if you're in a single, have like a single employer, stay on a single project for a long period of time, it may not be that big a deal. But just being on a single product project for a long period of time may actually lead to a need for this pattern. Enough pomp and circumstance. Let's talk about what is the cancer pattern in general or the cancerous approach. What this is, it is an upgrade or enhancement or replacement of an existing system with a new one. In the way this pattern looks is that instead of just replacing the thing in mass, instead of, we're not going to just do the whole thing and just say, okay, now we had version 1.0, now we have version 2.0. Or we did this in, I don't know, we did this in Visual Basic. Now we're going to do it in Ruby on Rails, something like that. Instead in this approach, we're going to replace pieces as we go so that we can leave the original run one essentially up and running. But behind the scenes, we're going to start pulling pieces out, replacing it, updating and changing it so that over time we eventually get from point A to point B and we don't have to bring something down, bring our, in this case, the idea or the concept is most likely this is production software that we don't have to bring down for a long period of time while we're doing the upgrade, enhancement or replacement. You can also look at this as the idea of a train running down the tracks and we're replacing pieces of the engine to turn it into something better or newer or open heart surgery. The body has to stay alive while you are doing, while you're making these changes. And actually any surgery would be somewhat like this in a case where you're replacing something that's broken with something that's newer or that does work. And with this approach, in an architectural point of view, what we need to do is understand the existing architecture. This is a pattern that we use when we don't have a blank sheet of paper to start with. This is when we're saying this architecture, architecture A is what we have today. It exists. The application, the solution or solutions built on it need to still work, but we want to take architecture A and get to point B. We want to end up with architecture B. And when we do the cancerous approach, we're doing this on going from point A to point B and it's not going to be, it's not a small thing. This is a larger replacement. In a lot of these applications and solutions I've seen where this is needed, it is either we are on very old technology that has upgraded many, many times. And so we're now almost having to do like a migration or port or something like that, but it's not a simple thing. It may be multiple steps. For example, you may be on, maybe you're still on version one of software and now they're on version 15 and we don't have a direct way to go from version one to 15. So we have to find a way to go from one to two, two to three, three to four, so on and so forth. Or another thing I've seen is we have a solution built on a technology that is dead, dying or not our choice anymore. Maybe back in 10 years ago, we bet on Microsoft's dotnet platform and we loved it. It was great. We built a solution for it. It works. But now we are planning on, I don't know, going to Java. We want to build this thing in Java. Well, there's no direct path for that. So instead of saying, all right, let's stick with this. And there's a couple of ways you can do it. One would be maybe stick with the existing system. On the side, we're going to have this other project that is building this new solution in this new framework or in this new environment. And then we will essentially at some point switch from one to the other. While that is a viable approach, there are a lot of considerations. In particular, where you start on product A, assuming that it's a living, vibrant product, there's probably fixes and maybe even some enhancements that are being done in product A while you're working on product B. So now you have to incorporate those things into product B as well. So you're going to solve the solution in one environment and also have to solve it in a second one so that those things are essentially kept in tandem until you get to the point where you can replace one with the other. So based on that description of the cancer's approach, let's talk about how do we take this pattern and apply it to our problem? We have A and we're trying to get to B. Part of the challenge in this pattern, using this pattern, is we have to understand A fairly well, where we're coming from. So we know what is it that we can change that has very minimal effect on the overall A solution and what is going to be very key to change in the right way so that we don't destabilize that A solution. Because what we're going to start doing is we're going to start pulling components from B, that target solution, and start building those and pulling those into A. Almost like a get a little sci-fi on you like a cyborg is that you're going to start replacing pieces with these new things and you need to make sure that those new things plug in properly and ideally so that solution A doesn't really recognize that it's being slowly replaced. Hence the whole idea of cancer. Something comes in and it's easy, it comes in and starts changing stuff around. And for the longest time, depending on how it's set up or what kind of cancer it is, you don't even know it's there until it's like, boom, it's there and it's replaced to use chunks of cell structures. Same thing with this. So what we want to do is we want to be able to highlight when we're applying this pattern what is the, I guess, like the low hanging fruit. What are the things that we can change in A and it really doesn't impact A as a whole? For example, let's say that we have a solution that has some reports and in the, and we'll give it a UI. So you've got a graphical user interface. There's menu options for these three different reports. And when you click on it, it asks you for a couple of parameters and then it runs a report and let's say it emails you the report. Well that would be something that would be easy to replace because instead of those buttons calling the solution that exists in A, we're just going to say when you click that button, you call the solution in B. It may look the same. It may even feel the same to the user. But now we're swapping out our technologies. Now we are moving towards solution B from our starting point. The good news is we often, if we've built our application properly, we'll find these things available. The whole solution will not work that way probably unless you've got, for example, if you use a distributed architecture the first time around or the microkernel and buses and microservices and some of the other things we talked about that were breaking the big problem down into a lot of small problems that we solve, then that becomes actually, this becomes an easy thing to do because we just start working through those little like if it's microservice, we start working through each of those services and rewrite them and we're going to have the same inputs and the same outputs. And that is probably ideal for this kind of approach because we just whatever our regression test is, we can just keep running it and we should see no change. We should see the same inputs, give us the same outputs. We've just now done it differently. We've solved that problem with a different tool. So we're applying this pattern. We want to find those first, find the things where it is a ideally a very clean interface into it, very clean inputs and outputs into a section of code or a component. And those are, should be some targets for initial replacement. Those are things that we can get in. We can make some, make some progress and do it hopefully in the easiest possible way, prove that what we're doing makes sense, get ourselves comfortable with how this is going to have to work as far as particularly like deployment platforms and things like that. Because now if you've got different technologies, you may have to have these in multiple environments. You may have to have some sort of new communication structure built in, all kinds of little, details like that. So start simple and it goes back to the prior pattern. Keep it simple. Let's start with the simplest ones first. Now hopefully we're going to be able to get to a point where we can do enough of those well-defined simple integration points. We can build enough of those out that we can get to a point that we can sort of surround and almost like surround and cut out a big piece so that that big piece then we can just take all these little surrounding things and tackle a bigger piece and then basically just replace it as well. Now we've got all of our new pieces that possibly are handled two versions so that they have some way to either through configuration or some sort of insight or something like that, some introspection that they're able to recognize that they're working with the old technology or the new technology. And if they're working with the old technology, they send stuff one way. If they now see that the new technology is in place, they're going to have a different way to interface with it. You may even have a situation where you can sort of run an A component, an old, you know, that prior one, a source component and a target component at the same time and B, you know, eventually get to a point where you say, okay, the new one's working fine. So now we can just stop calling the old one. This would be an example. You may have a load balancer. So you got three servers out there and you have one that goes down and maybe you replace it with a, there's an operating system upgrade. So now it's got the new operating system and you can bring another one down and bring it up with the new operating system and then shut down the other one and do that. Or, you know, maybe you don't need all those servers anymore. So you eventually get to a point where you're not calling, you know, server number three anymore. And eventually, okay, now we can turn it off, delete it, whatever we need to do, reclaim those resources. It's the same thing with this approach is that we're going to find the areas that we can easily replace them because they have very few connections and communication paths back into the main system. And assuming that we build this out as a long-term solution, we're going to be able to also highlight where are their components or pieces or sections or functionalities that have a lot of integration points or very complex integration points. And in those cases, what we're going to want to do is try to sort of trim around or update that thing so that we can eventually get to a point where we can isolate it. And a lot of those complex integrations have been already replaced. And it just, again, it takes this big problem and turns it into a smaller one and something that's much more feasible, much more doable, for lack of a better term. And that's really what the cancer pattern does is it says, you know what, I'm not going to replace this thing in one shot. Instead, I'm going to go through and start replacing pieces of it and eventually get to a full replacement. But along the way, I'm not going to tackle any one big thing. And this solves a lot of issues that you will see in such a situation because testing in itself is often one of your big costs if you're going to do a replacement. You're going to have to replace all these tests or you're going to have to run through all of them. And it's just a lot. In some cases, there's a lot to change. So something breaks. There's a lot of places it could have broken. Well, if you can do this, if you can take this pattern and apply it, instead you get to do little changes, validate those. And if something breaks, you know that you've got a lot better idea of where it broke because there was such, you know, there's very minimal changes applied. So now we can go back to that, like, you know, that new component or whatever it is that we've plugged in and say, hey, that didn't work and we've got a bug over here. Let's make sure we didn't somehow introduce that bug with this new component that we've plugged in or that maybe we didn't understand the integrations or the flow properly. That seems to be a good place to wrap it up for this particular pattern. That being said, not done with the season yet. Soon to come back, talk about a few more, but we are getting towards the end and then we will move on to whatever our next series of topics are. So hope you are enjoying our continued look at patterns and anti-patterns and we will continue it next time around. But as always, go out there and have yourself a great day, a great week, and we will talk to you next time. Thank you for listening to Building Better Developers, the Develop-a-Nor podcast. You can subscribe on Apple Podcasts, Stitcher, Amazon, anywhere that you can find podcasts. We are there. And remember, just a little bit of effort every day ends up adding into great momentum and great success. One more thing before you go. Develop-a-Nor podcast and site are a labor of love. We enjoy whatever we do trying to help developers become better. But if you've gotten some value out of this and you'd like to help us, be great if you go out to developernor.com slash donate and donate whatever feels good for you. If you get a lot of value, a lot. If you don't get a lot of value, even a little would be awesome. In any case, we will thank you and maybe I'll make you feel just a little bit warmer as well. Now, you can go back and have yourself a great day.