In the second part of our exploration of legacy displacement, we look at the practicalities of making upgrades work, from strategies for decomposing huge monoliths into manageable chunks as well as the methods for delivering those parts now that you've broken your monolith up.
Rebecca Parsons: Hello, everybody. My name is Rebecca Parsons. I'm one of your recurring co-hosts, and I am joined here for part two of the discussion of legacy displacement patterns, joined by Rob Horn, and Ian Cartwright, and James Lewis.
Last time we talked a little bit about two parts of the overall legacy displacement problem. The importance of understanding the outcomes, what is it we're actually trying to achieve as opposed to just dump the legacy technology. We talked last time as well about some of the organizational changes that have to happen to both allow for the success of the initial displacement, but also the ongoing support of whatever it is that comes into being as a result of the displacement.
There are two other clusters around legacy displacement that we want to talk about today, and this is really more the, "How do you actually make it work?" The first of these is breaking up the problem and the second of these is actually delivering those parts now that you've broken it up. Let's start first with breaking up the problem. Very often, when people look at these huge monoliths, it's like, "How in the world am I going to decompose this?" What are the strategies that you're recommending for how to get people past that fear and actually be able to decompose this into a bit more manageable chunks?
Ian Cartwright: Yes. We've got several. The three of us, we talk about finding the seams. We've got this big monolithic system that's running a huge part of the business. How can we find seams, like you might find seams in a piece of rock in order to break it apart from more easily? There's several different ways of finding those seams. I can give an example that's relatively straightforward, which is you can look at product lines. If you, for example, did some work with an online retailer who had a big legacy system who sold different product lines. They had men's wear, women's wear, garden stuff the garden stuff, for leisure, and so on.
One way to break that problem apart was to say, "Let's take one of the product lines or part of one of the product lines." Let's do, say, men and women sportswear and just extract that piece first and then show that's up and running. We've got measure success, like revenue or amount of sales that we're getting there. We can compare that perhaps to the old system by doing some AB testing. Product lines is one way to break the problem up, and it is probably one that's relatively straightforward, but there's definitely a downside, which is if a customer's doing some shopping on something that's been moved and something that hasn't been moved, they might see a discrepancy in their user experience.
That would be one of the pros and cons you'd have to talk about is that acceptable that during the transition period, some things might look like the old site, some things might look like the new site. That would be one way to come at it. I think another way is we mentioned on the previous podcast quite often, I think, feature parity where you just replicate what you had already. I think we spoke about that in ways that were, "Beware, don't do this." I think there are circumstances where it is legitimate to do it that way, but they're quite narrow and specific. Where, for example, you have to preserve exactly the current user experience.
Perhaps it's a safety-critical system or a control system for some hardware where you can't update that hardware, in those sorts of circumstances, building something with exactly the same look and feel, exactly the same set of APIs might be okay. In most circumstances we think feature parity because you don't really break the problem up at all. You just build. You say, "Let's build what we've got today." We'd not say never use it, but we just think where it's applicable is quite narrow.
James Lewis: I think another example would be. From a project we had a long time ago. I'm going to stop. Can you hear that echo?
James: It's just me. I'll start that again. Sorry. Another example will be from a newspaper project we worked on many years ago in the UK, where the choice is made to find the seams around types of content. A section of the newspaper website, whether that's lifestyle, or sports, or whatever it is, you pick that as the seam, and you migrate gradually to one of those types of types of content.
Rob Horn: There are other examples might be user cohorts or customer types, customer cohorts, you might find seams in between steps of a business process. You might do some event storming and find those critical events that may be signal a change in boundary between one context and another context. Extracting capabilities, like business capabilities, seeing how your legacy system supports maybe your finance team versus your logistics team, for example. Maybe you'd extract the logistics capability and provide them a new set of tooling.
I'd say there's quite a few other places that you can go looking for these seams. I think, for me, for in more general terms, as architects, I think this is really where we earn our money. It's bring all of our creativity and our tools to bear on this big lump of rock that seemingly can't be broken up. How can we use our visualization, and our abstract thinking, and the deep knowledge of what these systems do, and the business context that we have to crack this rock?
James: Sorry. Just move on. I think this point about business capability is probably the crucial one here. Because usually, what I found is people look at big pieces of legacy softwares. They don't really think about it in terms of what it's doing in terms of business capabilities. They might think about it in terms of integration, or layers of architecture, around technology, or databases, or data services. They don't think about the actual business thing that these things are doing. Trying to identify those business capabilities, I think, is absolutely a crucial first step I would argue. When we say in the writing business capability, we're not talking solely about how that's represented in the software.
We're also talking about this goes back to the user testing and the business users of the software. We're talking about the people, the processes, and the tools that go to make up this business capability where the tools might be the software part of it. To identify those things, I think is super important. I will, at some point, connect the town planning pattern to the repo, which hopefully will be published quite soon, which will give some good guidance around how to do that.
Rob: A number of projects I've been involved in, we've created the city plan, or the town plan with the the various business capabilities in it. Even after two or three years, that town plan has stayed pretty consistent. Because the business fundamentally hasn't changed and the capabilities that are needed to operate the business haven't changed. That town plan has stayed relatively stable and been a guiding light, a vision of something to aim for.
Rebecca: Very good. I assumed that something like the bounded contexts from domain-driven design are one aspect of something more concrete that people can use in this decomposition. Is there a time when you wouldn't take that particular strategy? How might somebody choose between a business capability seam, or business process seam, or a user cohort seam ? What kinds of factors go into that decision?
Ian: It's a very good question. I think to some degree, you've got to try multiple different approaches and then see how they stack up against your measures of success that you've agreed with your business. You might say, "We could do the user cohort thing, but maybe the user experience will be too inconsistent, and we've got some data that shows we'll see a lot of drop off, say, on an e-commerce site because of that." You might say, "We could split that product line off." Actually, logistically, because it's all in the same warehouse or delivered by the same set of fans, that's just going to create a huge amount of problems elsewhere in the business by splitting that up.
I think you won't know at the start which is the correct way to slice it up. I think what you have to do and what we often do with clients is say, "Let's look at three or four different strategies for breaking this problem up." Look at the pros and cons for each of them. Then together with the business make some decisions because there won't be a perfect way to do it. I think that's really important to stress. There's almost never a really simple, just slice it up and off we go, it'll be fine. There's always some trade offs to be made. Whether that's perhaps somebody having to enter something into two systems for a period because we got the older and the new, or somebody in the business having to look at two different sets of reports.
One from the old world, one from the new, or some impact on end users. Whatever it might be, there's always pros and cons. Unfortunately, I don't think there's a way to shortcut to the right strategy from the beginning. You've got to look at the different ways of slicing it and then be very honest with the business folks in the room, what are the pros and cons of each of those.
James: Sorry, Rob. I'm interrupting. I think going back to the capabilities thing, I remember a good 10 years ago Microsoft came out with a tool called Microsoft Vision. If anyone remembers this. This was one of their forays into the world of enterprise architecture. It was a tool to try and document the business capabilities of an organization. What was, I think, fundamentally quite interesting about that is if you squint, most organizations within the same domain, so most retailers or most insurers or most retail banks, they look pretty much the same. They've got a bunch of the same things in them.
Pretty much, in retail, you're going to have some way of delivering stuff to shops or to customers. You're going to have some ingress into a warehousing system and some egress out of that warehousing system. You can have some mechanism for delivering orders to the warehouse, so they can be shipped. You're going to have some mechanism of understanding what, who, or how things have been paid for. You're going to have some pulse system or some online checkout. That's going to have to be reconciled somewhere with those orders to make sure you're not selling too many or too few of the things that you've got.
Most retailers have some set of combinations of these things. To me, insurers have some set of combinations of slightly different capabilities, but they all have these capabilities. I think that's why we tend to focus quite a lot on this idea of business capability because they tend to be stable. When we talk about cohesion and coupling in software we talk about things we want to have to build cohesive software systems or buy cohesive software systems, are decoupled from one another so that changes don't roll across boundaries and so on. That's really what we're describing is in terms of the business, the capabilities that the business has.
They are cohesive. They do tend to be decoupled with quite formal boundaries between things. If we can concentrate on those and build software around those, that's a good start. Of course, you then layer on all the other things. We've talked about user cohorts, talked about product lines. We talked about whether we should have shared duplicated capabilities. Do you have the capability to sell male and female off the peg clothing? Do you duplicate that capability and have another selling capability that's just for fridges if you're in a multi product world? There's lots of nuance behind it, but thinking first firsthand about capabilities, I think it's a really useful start.
Rob: I was going to actually not come with an answer, but yet make the problem even more tricky. Because even when you've identified the parts, you need to think about which order you're going to start actually implementing them in and the order you take or the path you take from where you are now to your vision of the future. Each path also has its own trade offs as well. Each new thing you deliver, each new capability that you deliver, for example, is going to need to be integrated in some way, but with existing legacy, or the new world that you're building it's going to represent different levels of risk and maybe different sizes require different data migrations.
All of that stuff also needs to be factored in. Not only do you need to identify the parts, you need to also put some serious consideration into the tradeoffs to in which order are you actually going to deliver those parts as well.
James: Rob been developing a little bit of a notation around this. I've been desperately trying to get him to come up with this Rob Horn Feynman sum over futures path integral. [laughter]
James: It's not there yet, though.
Rob: I worry that I'm going disappearing off a spiral while I'm going to come out with a component diagram.
Rebecca: Then let's get to what some people might consider the meat of the problem, but I think it's fair to say that all of the things that we've talked about before are critical to making it possible to actually then start to deliver this. What are some of the kinds of things that you're talking about in the delivering the bits faster?
Rob: Maybe I could jump back in again and talk about maybe something that isn't immediately clear when we are talking about incremental delivery. That is you your as is, let's say, all red because it's risky. You have your new world, your vision, maybe all green, and you want to deliver parts. That means after your very first step, you are going to have some new green bits talking to red bits that don't exist in your vision of the future. In order to make that happen you're going to need to be doing integrations, let's say, that also don't have any place in your vision architecture for the future. You are going to have to be throwing stuff away.
What we talk about is we're calling it transitional architecture, it's essentially scaffolding that you need to put up to enable you to deliver increments or are required by the path that you're taking and to allow you to operate safely on your building site as you are displacing the legacy. I think it's quite an important thing to consider and to go into with your eyes open is that as you are incrementally displacing legacy, you will be putting in this transitional architecture, these software components that enable you to take a certain path. You will be throwing them away because they essentially will be debt or additional complications that you don't need in your nice clean new world. That's one of the patterns we're talking about is this transitional architecture.
Ian: Quite a lot of the patterns that we've got are about coexisting with legacy. Because that's the reality I think of lots of these displacement projects. There's a period where as Rob described you're not wholly in the new world. There's still quite a lot of things in the old world. One of the things we often find is that the mainframe or the big legacy set of systems becomes seen as the gateway tool, the key information within the organization. One pattern we find that is very useful is actually almost to do a bit of archeology and actually say, "How does that data get into the legacy system in the first place?"
When we find that out, maybe what we can do is going into the new system, instead of having to pull that out of legacy could actually go to the source of the data. We've seen examples of where that's been extremely useful. James and I worked together on a project where a lot of data came from retail stores. This data did actually put in a relatively modern toll system. There's quite a rich set of information available to the store manager within the store. It was being translated into the legacy world, which meant quite a lot of info had to be thrown away because there was nowhere to put it in the Db2 tables. It was only updated every 24 hours by a batch job.
In those circumstances, and we've called this pattern revert to source, for the new systems, it made far more sense to just do an end-run around the legacy and go straight to that source system. The nice thing now is that tools actually updated in near real time, so we could have much more up-to-date information, and they have much richer data than was available by a legacy. That was also nice because that was a nice way to say to the business, "Yes, you might have to look in two places for a while, but in the new world, you can have much richer information," and over time, that will get better and better.
That's what we've called revert to source. It sounds obvious, but I don't know where people see legacy and think, "Here be dragons. I dare not go past that. I don't want to go digging," but it is often worth working out where stuff really comes from.
Rob: Another related pattern, I suppose related, is where you want to keep legacy, say, updated, where you've built out a new component. You're not able to revert to source, but instead, your reports need to continue to operate or run from an existing legacy database. In that case, you need your new components to update the old world, and they're going to need to do that with minimum changes to legacy. They need to be talking to the legacy system, using the existing interfaces or existing semantics. In that way, your new component is essentially a mimic of legacy. That's another pattern that we've come up with is this concept of a legacy mimic.
That's where your new components essentially are, either exposing existing old interfaces, so that the legacy world is talking to new software but doesn't know it because it's using existing interfaces, or where your new software is talking back to legacy, again, in a way where the legacy software doesn't know that it's a new piece of software that's doing it. This having your new systems being able to mimic legacy is also proving really, really useful. Another pattern that goes hand in hand with this as well is that concept from Eric's book to domain-driven design around anti-corruption layers, often a legacy mimic.
We'll use an anti-corruption layer to provide you that seam or boundary to stop change going too far. That when you do need to take any of these components out of your architecture and decommission them, you don't have to change the new stuff that you've built. You can just get rid of that anti-corruption layer. Those two patterns are used quite regularly together.
Ian: I think one pattern that we've called out is not perhaps a pattern about legacy displacement. When we were all talking and when we were talking with Martin, we realized it was something that often happened in organizations. We needed to give it a name, give it a label so it's recognizable, and then we can describe how to deal with it because it's so common in these big monolithic systems. That's critical aggregator. This is the idea, is there's often somewhere in the organization where lots of data from different product lines or different parts of the business, different activities comes together into a single place.
Often that's the place where you're generating a bunch of key reports for the board members or for key business leaders where they want to see the aggregate view. There might be a set of managers who are just interested in one product line, but there's somebody somewhere who wants to get the aggregate view of how global sales are going. It's one of those things that often becomes a blocker or a big constraint when you're trying to do legacy displacement because these are very important people. Often they're key stakeholders also. You run the business of some of that information that's in this critical aggregator.
You might say, "What we've got to do, no matter what else we do, all the way through the displacement effort, we have to keep that updated. We have to keep the legacy updated with all this data in order that we can continue to generate those reports." We've called that critical aggregator. I think it's a pattern and a lot of people would recognize in many organizations. We've given that a name, and then what we've got is this idea of divert the flow. The idea of the flow pattern is actually to say, "You could leave that to last," and that will be a constraint all the way through because you've got to keep it updated.
What you might do instead is say, "How about we pull all the information out of legacy into a new place, and we make that our new critical aggregator," and we start to point folks there instead. Initially, it might use a legacy mimic or an event interception, which is some of the other patterns we've got. You could build it right at the beginning instead. We thought about this in a little bit, like when you're building a dam, actually what you need to do to build a dam is divert the river first. There's this little bit of our thinking was, "If it's going to be such a big blocker, maybe we move it first." It's an interesting one where technical constraints might lead us to do something right at the beginning, instead of right at the very end.
Rebecca: One question that has been coming up in my mind as I've been listening to you talk about this, and this also goes back to our discussion in the last episode about outcomes, what does done look like? How do you decide when to stop?
Ian: I think it's a very interesting question. I think there's two parts of it because you could define done as, one, are we done pulling stuff out of legacy versus when are we done building new things for our business stakeholders on the new set of systems. Tackling that last bit first, you're probably never done because you build a new set of systems, and those stakeholders are out there. You've still got competitors, you've still got regulatory change. In terms of building new systems that have a constant flow of requirements coming to them. You're not going to be done. Then you say, "When are we done pulling things out of legacy? When are we primarily taking our requirements--"
New as new requirements rather than requirements that were driven by how we used to work. There's different measures you could use there. I think one that's really interesting that often gets missed is just pure financial measures. You might say you are done when the cost of moving something is higher than the revenue you might make from that piece of functionality in your business over a certain number of years. You just literally say, "If we move it it'll cost five years of revenue. It's not worth it. Let's leave it where it is," and end of life that, and maybe even make a business decision that, "We don't offer that product line anymore."
That sounds quite radical. Why in earth are we talking about end of life product lines when we're meant to be talking about technical things like getting rid of legacy systems? Legacy isn't just a system. It's the legacy things within the business and if they don't make money for you, why would you move them? That's one way of looking at it. It's not the only way, but it's one way to come at it
Rob: Regarding the end of life outcome, wanting to avoid or stop these escalating support costs and reducing risks to the business of this unsupported software. Your measure of done there could be, we're able to operate this part of the business without reliance on that particular legacy software. That's one point. At the point you can run your business without reliance on it, without touching it, that's the point you no longer carry that risk. That risk has been mitigated. That might be a different point in time to the actual turn it off, the actual decommissioning and get getting rid of it from your estate.
You've got potentially different stakeholders with different measures there. You got the business who are no longer carrying the risk, and then you've put your ops people who are no longer having to pay the bill for the software. Those two things might happen at different points in time.
James: I've been at more than one client where people have had very complicated spreadsheets that were plotting things like when is this off our books from an asset perspective, versus the increase in transaction costs that we're facing every year because there are more transactions per year on the mainframe, versus when there's the license due up next. I'm trying to find some sweet spot where the end of life because you don't want to take on a new five-year license. It might be worth taking on a one-year license if it's going to get you over the red.
If it's on your books as an asset for another 10 years, then you might want to be taking advantage of whatever financial wizardry happens around that thing, which your finance department would be very interested in.
This is going back to what Ian was saying, that getting finance involved is often absolutely crucial to these kinds of conversations. I know there was one set of some former clients of ours who was really successful in moving partly off a mainframe that was implementing a core banking platform, very, very large global presence, retail bank. They decided to take the step of moving payment processing off because payment processing was where the large part of the cost has been incurred in terms of paying for increased MIPS every year.
If you can move payment processing off, then you can reassess how much money you're then spending on the rest of the core banking platform, the rest of the functionality minus the cost of the real-time transactions per second that you haven't the support on it. It's really, really hard, I think.
Ian: I think they actually turning it off bit is the bit that almost that often doesn't happen. I think quite often when we go and talk to clients, and they've got these different layers of systems going back over the different decades, which represent multiple attempts to get off various legacy systems. The challenge is, they never had a defined criteria for turning the power off to the old system. They didn't do it. Then they built something else, and something else, and something else, and something else. You just ended up with all these layers. It might be difficult, but you've got to agree with the business stakeholders, and with the operational colleagues, and with finance, "What are our criteria to turn that power switch off?"
Have the big celebration, "It's gone, we've turned it off." I think part of the challenge here is organizational. We talked in the last episode about organizational change and one of the common things that can prevent systems being turned off or can be a barrier to change is that the people using the system don't have any responsibility in terms of paying for the system. We work for a large client were this part of the business who were using the system, they were the last people left on this legacy system. It was costing tens of millions a year to run this bank. They really needed that part of the business to move and do something different.
They said, "That will mean retraining our staff and it might cost £100,000. We're not willing to spend that money." The organization as a whole stood to save very considerable amounts of money, but that part of the business, it wasn't their responsibility to do that. The fact that they had one huge big budget of IT budget, and then individual parts of the business who didn't see the cost of providing the services they used made it very challenging to get any migration done there at all. Really what the first step perhaps should have been is some way of saying some budget allocation or cost allocation to the business units as a very first step at the beginning, and then there's a much stronger motivation for them to be involved in getting off those systems.
James: I think this comes back to the transitional architecture point that Rob was making towards the start of this episode. Where the danger is you not only end up with the new thing that you've partially built, the old thing that you've partially decommissioned, but you also end up with all the transitional bits and bobs that you've had to put in place to bridge the two. It's almost like it's the worst of all possible worlds at that point because. as I say, you've got the old, the new, and the bits in the middle that you want to throw away.
That's why I think this stamina, the organizational stamina, to go on the journey is really important. One of the things I personally really struggle with is the explanation of how long these things are going to take because they take a lot longer than most organizations think they're going to take these programs of work. They're big programs of work, they're multiyear commitments that you're making. If you get towards the end of one of these multiyear commitments and circumstances change, and you never go on to see it through, then you can end up as, I say, in the worst of all possible worlds.
I know the core banking platform, they're talking about a four to six-year program to move away from that. It's not two years wipe your hands, and we're done. That's probably multiple CIOs with the program.
James: Maybe that's all we should think about in terms of metrics, how many CIOs.
Rebecca: Yes, it does remind me one of the advantages of feature parity is, it's easier to say you're done because you've checked off all of the features. I remember very early in our time in the UK, a legacy was actually a replacement, but it definitely wasn't feature parity. They did all of the right things, but the business users had this nagging suspicion that there was something that they'd forgotten, so they wouldn't turn off the legacy application and we kept saying, "No, really it's all there. It's all there." They went through the end of a month, they went through end of quarter, they went through end of year, and kept using the new system.
We kept going back to them, "Can we turn it off now?" This was one of those systems that was running on a desktop sitting under somebody's desk. One day, they realized that actually it had been disconnected for about six weeks or so, [chuckles] and no one had noticed. We were able to go to them and say, "Actually, this hasn't even been running." That was when they said, "You can actually leave it off." There is always that. I know we've talked about how very often business processes shape themselves around the vagaries of the legacy system.
Often people really don't know exactly what that system is. It sounds silly, but they had a legitimate fear that, "Maybe we did forget something." As long we know that thing is still running, we know that that functionality is still there. That is one of the issues when you don't have quite enough organizational knowledge to really know what constitutes done.
Ian: I think in my very first job, I remember that there was a very large mainframe that had been decommissioned and replaced. Under the false floor, there was absolute spaghetti of cables. Unfortunately, they hadn't been labeled, so no one quite knew where they went. They went to very traditional-- a VT 102 green screen type terminals. What would happen is each weekend quite a few would be disconnected, and you had till Wednesday to tell them that you actually still needed it. If you didn't complain by Wednesday, then they would leave that disconnected, and they'd move on.
I think there's actually one way to find out is to just not cut the cable, but to temporarily disable or to send something to a holding page or something like that because that's one way to mop up. That's the wrong phrase to use. The wrong way to find those last few folks who are using an old system is to do something like that. Make it temporary, because then if, say, they called the number or they send the email and say, "Hey, I'm still using that. "Then there's an opportunity to go and talk to them and figure out, "Oh, we'll enable it, but we really need to get you moved across to the new system."
Rob: Building confidence is a whole different ball game, though, as well, isn't it? It's like if someone's using it or not, it's black and white. To Rebecca's point, how do you get over that fear or help your business to build confidence in the new system. I feel like we'll have a bunch of patterns or tales to tell around parallel run, dark launching. Certainly around reconciliation of data. How can you tell if things are aligned and the systems are telling the same story just to help business to get the confidence in the new systems as they're being displaced?
Rebecca: In your experience, is there one key mindset shift that has to happen for this legacy displacement to be successful?
Ian: I think for me, it's to shift away from feature parity big bang release to an incremental approach that's delivering value all the way through. I think if you can get your head around that, that's half the battle right there and if you can bring your colleagues from the business along with you. The reason I say that is, when I've seen these things go wrong, it's almost always the feature parity. The challenge with feature parity is it just grows more and more because you go out into the business, and you have to document everything it does right now. If you're going to replace it, you have to understand it.
That's a movable feast because the business is always changing and doing new things. By the time, you've done and you go away, and you try and deliver that thing as a big bang release, you're going to do that magic cut over, but things are still changing in the meantime. You'll have missed something, and it becomes a one-shot scary event. Unfortunately, we read news headlines about when that's gone wrong. That's the key thing for me is that we we've got to find an alternative to spread the risk out, get more rapid feedback, and have more chances to get it right, rather than one big chance to get it wrong.
Rob: Building on that for me it's that breakthrough you need to make, that you can break this problem up into pieces. That it is going to be really hard, but that's where as an architect you need to bring all your tools to bear on making it happen. For me, that's a big shift that people need to make. It might seem impossible, but you look hard enough and apply enough creativity, you will be able to break the problem up into pieces.
James: I'll give a fun example of that with our friends at the core banking platform again and the payment processing. I just had a chat with them and they said, "The thing is we were looking for seams, it was really difficult. Then we realized that a lot of the processes were batched." Most of it was batched. You get a batch file, drop it in a particular place. Then a capability of the mainframe would pick the batch file up, process it overnight and drop another batch file somewhere else. We thought, "If you look at those batch files, they're individual transactions. If you squint, it looks a bit event-driven."
They had this this [makes sound] light bulb moment where actually we can treat the mainframe, particular one that they have, as an event-driven system. As long as they were continuing to drop "the events" where the mainframe was expecting to pick them up, then they could quite happily go off and hide off that particular capability to the side. I think it's those things. As Rob says, thinking maybe a bit laterally about some of this stuff is quite important. For me, I think it would be treating it as a business problem first and foremost rather than a technology problem.
Because even if you've got a technology problem, it's really a business problem anyway. [chuckles] Because if you're worried about paying too much money for your transactions to one of the big vendors, then that's a business problem. That's about taking cost out. If you're worried about licensing or end of life of your support, that's a business problem in terms of risk to the organization. All of these things, I think, we should look at them all as business problems.
Rebecca: Treat them as such. I'd like to thank you all again for joining me on the Thoughtworks Technology Podcast. Thank you, Rob, Ian, and James, and we look forward to continued drops on martinfowler.com of this continuing series. It will be interesting to see when you all decide that that project is done. [chuckles]
Rob: Brilliant. Thank you.
Rebecca: Thank you all.