Posts Tagged ‘Software Development’
Making sense of entrepreneurship – a conversation with Craig Brown
KA: My guest for this instalment of my “sensemaker” series of interviews is Craig Brown. I have known Craig since about 2009 when he was a project and program manager. He has since transitioned to running his own software development company, Everest Engineering. So, welcome Craig, let me begin by asking you to introduce yourself and talk a little bit about your journey that got you to where you are now.
CB: Thanks Kailash. How far back do you want me to go? Would you like me to start right at the beginning or just the last few years?
KA: Mostly the transition from project and program management to entrepreneurship. What made you do it? What drove it?
CB: OK. Well, early in my career I worked at different companies and corporations, as many of us do. I even did a very small stint in consulting. These experiences were interesting because I learned a lot about how things happen in organisations – what works and what doesn’t. Early last decade, I started working at a SaaS company in a general management role. That was interesting because the culture in those places, the way they operate, is very different from the established corporate world. You’re much closer to “life or death” issues on a month-to-month basis. As a result, you’re much more invested in delivering customer outcomes and value than in compliance, rules and process. That was refreshing and super interesting because I had never been in that situation before.
Anyway, then the day came when it was time to leave that organisation. One of the guys that I worked with, Ranganathan, used to manage part of the team in India while I managed the team in Australia. The two of us decided we would start a software product development agency together, and so began Everest Engineering.
The switch from working for someone to working on your own business is a big one. Many of the differences are well-known, entrepreneurs have talked about them: it’s a lot of work, it can be very stressful, you’ve got to be multifaceted, you’ve got to be wherever the business needs you at any particular time. So, being able to switch modes and roles is really important.
As the company has gotten bigger, we’ve hired other people to help manage the business, grow it, support it. Ironically, this next stage is about breaking our old habits of being everywhere all at once, its about learning to delegate authority, share responsibility and all that sort of stuff. What I think is particularly interesting about what’s happening to us now is that it’s kind of the opposite journey to what large companies are trying to do: i.e. they try to reduce bureaucracy and increase entrepreneurship by giving people autonomy and responsibility. We’re headed the other way, not towards bureaucracy (I hope!), but towards more structure and order from what can be described as chaotic, freewheeling entrepreneurship. Yeah, it’s stressful but a lot of fun.
KA: OK, before we get deeper into the conversation, what does Everest Engineering do and where are you located?
CB: We are a software product development agency. Capability wise, we have software engineers, platform engineers, product people, designers, testers, business analysts etc. Our team members live in about half-half on the east coast of Australia (mostly Melbourne) and India. We also have a few team members in North America and have just started building a development team in Malaysia as well. So, we’re kind of distributed across the globe. At the moment, most of our customers are in Australia but we’re growing the customer base around the world as well.
KA: Hmm, there are a lot of companies in the software product development business. It must have been difficult to get traction. How did you do it?
CB: The traditional story (in software development) is that you either a) find a niche that no one is addressing well and zero in on that or, b) you come in cheap and claw your way to the top. When we started our business, we didn’t want to do either of those things. We also wanted to build a generalist software product company, not focusing on a particular domain or particular skill set as many small outfits do. Our vision is that we become a big global company that can engage with lots of different problems. At the same time, we knew that if we swaggered in to client discussions saying that, no one was going to be interested.
So, what did we do?
We started by focusing on the Melbourne market, primarily because that’s where I live. To get traction we decided that we would be compelling in terms of the match between price and quality. In the world of software, you can rent services from agencies which are poor or average quality on the cheap, or you can pay a lot of money for top shelf quality. What we wanted to do is not be the cheapest in the world, but be reasonably inexpensive while also really focusing on quality. Interestingly, over time the price-quality trade off has become less important, which has enabled us to focus on quality. I’m not sure why this happened but I guess it has to do with a common experience in life: when a piece of work is completed, what’s remembered is the good outcome, not the cost to get there.
There’s a kind of irony about day rates versus outcomes. It’s a weird one. For example, the price of some of our India software development teams might be double or even more than what some of our competitors provide. But the deal is that we’ll get it right the first time, within the timeframe and the budget that you’re asking for. Compare this to having an expensive rework nightmare, which often happens when the upfront focus is on cost. I’m aware that this could be sounding like an ad, but it’s really that focus on delivering a quality, delivering an outcome the first time that is the key. Our customers don’t necessarily understand this upfront because quality is hard to talk about, but it is easy to understand when you see it. So the deal is that after our customers have worked with us, they begin to appreciate the quality aspect we bring.
Another aspect of our strategy is maintaining relationships and sticking together over the long haul. It’s really simple to state: win over customers through doing good work and keep them through being compelling in our value proposition. However, it is not easy to do. Indeed, it is work in progress, we’re not perfect. These are aspirational goals, and we’re working our way towards them.
KA: I understand the price-value proposition. However, because it is such a crowded market, your first few gigs must have been hard to get. How did you go about doing that?
CB: Yeah, I think it’s a trust-based decision making process when buying expensive, large services. The customer will not know upfront what the quality is going to be like. Fortunately, over the last two decades, I’ve built good strong relationships with lots of people across our industry. So, a lot of people know me, and I’ve had interactions with them through my work or contributions to our professional community (Kailash’s note: For example, Craig is the founder of Last Conferences). That’s gotten me access to a lot of people. To add to that, in the early days of Everest, we would straight up give people a money-back guarantee. We could do this with confidence because we knew our team members – we knew they were smart people with a lot of enthusiasm for doing right by everyone around them. That enabled us to say to our customers, “if you don’t like the work, you don’t have to pay for it.” That combined with my personal connections meant that we were able to cut through and get that first round of trust that enabled us to build the company.
KA: It must be doubly challenging to maintain quality and align expectations with a distributed team. Can you talk us through some of the challenges that you have faced?
CB: Yes, and there some nuances around this. One is that the software labour market in Australia is older, on average, than in India. So, there’s an asynchronicity of experience, and with that comes a misalignment of expectations. A really important aspect of this is that we try to be explicit about expectations from different teams, and this is mostly about managing people’s expectations of what’s going to happen and when. Another aspect is for us to develop a shared understanding of what Agile means to us: things like transparency, focus on throughput, customer value, responding to feedback etc. Once we agree on what they mean, we have to do those things on a day-to-day basis.
It gets even more complicated when you bring the customer in. As you know, every organization has got its own version of what Agile looks like, and different understanding of what “good” means. So, we try very hard to moderate our version and meet the customers where they’re at. In other words, we co-develop shared Agile practices. A phrase that I think really resonates with the customers we work with is let’s improve together. When there are cultural differences, we don’t see them as barriers. Instead, we reframe them as strengths. It is like, “right, we see things differently, and that is interesting because I hadn’t thought of it that way.” These differences aren’t necessarily country to country, they can also be industry to industry or organisation to organisation. Of course, there are things that are cultural too. For example, if we’re doing retail websites, the online retail experience in India is different from one in Australia and, therefore, so are expectations of how things should work. You have to step back and go to first principles of user experience design and product management; you have to slow down and talk about what good looks like, and how we’re going to get there.
Lastly, there’s the issue of managing timezone differences. To be honest, we don’t find this a problem. The overlap between Australia and India is sufficient, and can lead to some good patterns where there’s like a half a day of focus time and a half a day of collaboration time. But again, this requires planning and preparation. You can’t just turn up to work and go; you have to be thinking ahead about what you are going to do. As long as you’re able to level up your planning you can take advantage of this. This also has general positive downstream effects: if everyone’s more organised, there’s less waste, better decisions are made better, and so on. However, it does take effort to get there.
KA: You used a phrase, “let’s improve together with our customers.” Can yougive me some sense of how this works in practice?
CB: The examples are quite mundane to be honest. When a bunch of people come together to work on a new project, there is some learning required on how you are going to work together. As I had mentioned before, patterns and practices will differ between organisations. For example, should you focus on Continuous Delivery and DevOps stuff. or should you focus on better product management or sensemaking and design work? The answer is: it depends. We (the customer and us) bring different strengths to the table, so we look at the situation in front of us and decide how to work together.
First of all, we agree on how we communicate, how our day and week runs – all that kind of normal sprint cycle stuff. Then we can get into specifics such as, how do we optimize (our ways of working) around the product that we’re working on? What is a good outcome? What are the constraints? In addition, we will have patterns and practices that we can kind of share with each other and learn together. This is not about telling people about your practices like you have some special access to the truth. Instead, we slow down and go, “Alright, cool. I see this problem here. Do you see it too?” And then you might go, “Yes, I do.” Or you might go, “huh, I see a slightly different problem.” Or you might even go, “I don’t see a problem.” That opens a dialogue and, before you know it, we’re solving the problem together instead of telling each other what to do. How that manifests could be as simple as changing how you run stand-ups, or set up sprint plans, good coding standards, or the emphasis you put on product design versus shipping a product. These are mundane, well-known things but the trick lies in how you customize them to the context of a specific relationship.
KA: Interesting. So, when you actually hire and get people in, you’d be hiring for technical smarts on the one hand, but you’d also be looking for, a kind of propensity to collaborate. Is that right?
CB: I hire certain kind of certain roles but the bulk of the workforce hiring is done by other people so I’m not actually close to the details. However, I do know that the notion of culture fit is taken pretty seriously in the recruiting process. From this perspective it is mainly about managing the tension between being an individual contributor and a team member. On a team, you will be an individual contributor so you do need to master your craft, be good at the job and all that sort of stuff. However, you also have to think about where your ego is. Do you have this deep need to be the hero, telling everyone what to do and being the master programmer. Or do you deploy value through a collective effort? By doing good work, but also looking around, seeing your teammates, recognizing their work and supporting them when needed. We draw these kinds of things out in interviews through storytelling, by asking for examples.
KA: When I look at what you’ve done, it seems like, such a simple idea: to not go on price or quality alone, but somehow marry the two. It’s like you saw a gap in the market, an anomaly that nobody else noticed – or if they did, they did not think it worth pursuing. I find that really interesting.
CB: Yeah, it is kind of like that. There are a bunch of software agencies that I used to work with, here in Melbourne, they are full of great people. They are also what you would call the premium software agencies in Melbourne or in Australia – quality is top shelf but so is price. Then at the other end, you’ve got these big factory warehouses of people who are lowly paid and not well supported. And then there’s this place in the middle that’s almost unseen. What we thought we should do is compete on the one hand, at the quality end, and then also come in cheaper by leveraging the cost differential between the two countries.
You might say we are reinventing the outsourcing experience by maintaining the connections and relationships like small agencies but being able to do things at scale by having the staff, skills and experience commonly found only in much larger outsourcers.
KA: Right, and the interesting thing is that you grew the business in some pretty challenging times. Could you tell us about how you handled the challenges thrown at you by Covid, for example?
CB: Yes, there’s been a few things right, there’s been the COVID pandemic and now we’re on the cusp of another economic crisis. Indeed, the pandemic hit right after we got started. One of the things that I think enabled us to be resilient has been spreading our bets. So rather than chasing after a handful of big customers, what we’ve done is pursue a relatively even spread of customers in different segments, sizes and organisations types. So, as these crises ripple through different parts of the world economy, it hits us at different times rather than all at once. Don’t get me wrong, the middle of 2020 was really tough, but the fact that we had our spread was what got us what got us through that. I’m not sure if I’m using the term antifragile, properly, but it kind of leans into that. By spreading your bets, you discover all these new people, markets and domains that can grow into opportunities.
KA: That makes good sense. So, what next for Everest?
CB: We’ve been fortunate to have attracted these really interesting and diverse bunch of people to work for us. Equally, we’ve attracted an interesting and diverse bunch of companies that work with us as customers. We’re only a few years old – four years this November – so we’re still focusing on our core business which is software development. I think in a year or two ahead, I think we will start to see that antifragility or diversity blossom into new opportunities. For example, we definitely want to work in the data space. We’ve got data engineers and some people who have done projects, with machine learning and so forth, but we don’t actually have it as a practice. It’s kind of ad hoc at the moment. So, maturing these things into proper business units that have got sustained impact on the world will be something for us to do. And then there are other things we’re looking at – for example how product management works in the industry. Specifically, the patterns and the strengths and weaknesses in the product management industry and whether there are ways in which we can contribute to that community.
At heart we are a bunch of explorers and experimenters still…and hope we will remain so. We are on a journey through adjacent possibles. It is the only way to stay fresh and ensure that we don’t get pigeonholed.
KA: So, you’re continually scanning the periphery and horizon to see what new things you can do by adapting what you have. That’s brilliant!
CB: A lot of it comes through the diverse talents and interests of the people we work with, right? We’ve ended up attracting quite interesting people to work with us. Interesting people have – well – interesting interests! So, for sure, the key thing is to get work done and ship products in time. But another important thing is to make the mental space so that you can actually invest time and energy into the things that you’re curious about. Ultimately that’s what spawns new ideas and new opportunities.
KA: That’s a nice place to close our conversation. But, before we do that I want to ask you one final question: what advice would you give someone who wants to start doing their own software development (or any other) business?
CB: The advice you hear from people that study new businesses is generally something along the lines of: it’s going to be harder than you think; it’s going to take longer than you think; you’re going to get very stressed and have these moments where you wonder why you’re doing it. But at the end of it, you’ll look back and love the fact that you’re doing it. And I think that’s actually true, right. That said, I think that embracing the chaos and uncertainty isn’t for everyone. Like, here I am, I grew up poor, in a single parent family in regional New South Wales. In my late 20s, early 30s, I started working in corporate Australia in tech. All along I have been burdened by the usual mortgages and lifestyle costs and all that sort of stuff. And I haven’t climbed out of that yet: I’ve still got a mortgage I can’t afford. But yeah, it took me a while to get started on the entrepreneurship thing. I was 48 when we started Everest, and it was driven partly by events outside my control. As I said at the start, the company I was working for got acquired and that gave me the push I needed to do my own thing. So, there you go. It’s not for everyone and, yes, the right circumstances have to be in place for you. But once you start, I think you’ll embrace it.
KA: That’s an inspiring story and some great advice Craig, particularly for older people who want to start doing their own thing. You were driven to entrepreneurship in a way but you stuck to it and made it your own. Brilliant stuff, thanks so much for making the time to have a chat.
CB: Thanks Kailash, always a pleasure.
The case of the missed requirement
It would have been a couple of weeks after the kit tracking system was released that Therese called Mike to report the problem.
“How’re you going, Mike?” She asked, and without waiting to hear his reply, continued, “I’m at a site doing kit allocations and I can’t find the screen that will let me allocate sub-kits.”
“What’s a sub-kit?” Mike was flummoxed; it was the first time he’d heard the term. It hadn’t come up during any of the analysis sessions, tests, or any of the countless conversations he’d had with end-users during development.
“Well, we occasionally have to break open kits and allocate different parts of it to different sites,” said Therese. “When this happens, we need to keep track of which site has which part.”
“Sorry Therese, but this never came up during any of the requirements sessions, so there is no screen.”
“What do I do? I have to record this somehow.” She was upset, and understandably so.
“Look,” said Mike, “could you make a note of the sub-kit allocations on paper – or better yet, in Excel?
“Yeah, I could do that if I have to.”
“Great. Just be sure to record all the kit identifier and which part of the kit is allocated to which site. We’ll have a chat about the sub-kit allocation process when you are back from your site visit. Once I understand the process, I should be able to have it programmed in a couple of days. When will you be back?”
“Tomorrow,” said Therese.
“OK, I’ll book something for tomorrow afternoon.”
The conversation concluded with the usual pleasantries.
After Mike hung up he wondered how they could have missed such an evidently important requirement. The application had been developed in close consultation with users. The requirements sessions had involved more than half the user community. How had they forgotten to mention such an important requirement and, more important, how had he and the other analyst not asked the question, “Are kits ever divided up between sites?”
Mike and Therese had their chat the next day. As it turned out, Mike’s off-the-cuff estimate was off by a long way. It took him over a week to add in the sub-kit functionality, and another day or so to import all the data that users had entered in Excel (and paper!) whilst the screens were being built.
The missing requirement turned out to be a pretty expensive omission.
—-
The story of Therese and Mike may ring true with those who are involved with software development. Gathering requirements is an error prone process: users forget to mention things, and analysts don’t always ask the right questions. This is one reason why iterative development is superior to BDUF approaches: the former offers many more opportunities for interaction between users and analysts, and hence many more opportunities to catch those elusive requirements.
Yet, although Mike had used a joint development approach, with plenty of interaction between users and developers, this important requirement had been overlooked.
Further, as Mike’s experience corroborates, fixing issues associated with missing requirements can be expensive.
Why is this so? To offer an answer, I can do no better than to quote from Robert Glass’ book, Facts and Fallacies of Software Engineering.
Fact 25 in the book goes: Missing requirements are the hardest requirements errors to correct.
In his discussion of the above, Glass has this to say:
Why are missing requirements so devastating to problem solution? Because each requirement contributes to the level of difficulty of solving a problem, and the interaction among all those requirements quickly escalates the complexity of the problem’s solution. The omission of one requirement may balloon into failing to consider a whole host of problems in designing a solution.
Of course, by definition, missing requirements are hard to test for. Glass continues:
Why are missing requirements hard to detect and correct? Because the most basic portion of the error removal process in software is requirements-driven. We define test cases to verify that each requirement in the problem solution has been satisfied. If a requirement is not present, it will not appear in the specification and, therefore, will not be checked during any of the specification-driven reviews or inspections; further there will be no test cases built to verify its satisfaction. Thus the most basic error removal approaches will fail to detect its absence.
As a corollary to the above fact, Glass states that:
The most persistent software errors – those that escape the testing process and persist into the production version of the software – are errors of omitted logic. Missing requirements result in omitted logic.
In his research, Glass found that 30% of persistent errors were errors of omitted logic! It is pretty clear why these errors persist – because it is difficult to test for something that isn’t there. In the story above, the error would have remained undetected until someone needed to allocate sub-kits – something not done very often. This is probably why Therese and other users forgot to mention it. Why the analysts didn’t ask is another question: it is their job to ask questions that will catch such elusive requirements. And before Mike reads this and cries foul, I should admit that I was the other analyst on the project, and I have absolutely no defence to offer.
Maintenance matters
Corporate developers spend majority of their programming time doing maintenance work. My basis for this claim is two years worth of statistics that I have been gathering at my workplace. According to these figures, my group spends about 65 percent of their programming time on maintenance (with some developers spending considerably more, depending on the applications they support). I suspect these numbers are applicable to most corporate IT shops – and possibly, to a somewhat smaller extent, to software houses as well. Unfortunately, maintenance work is often looked upon as being “inferior to” development. This being the case, it is worth dispelling some myths about maintenance programming. As it happens, I’ve just finished reading Robert Glass‘ wonderful book, Facts and Fallacies of Software Engineering, in which he presents some interesting facts about software maintenance (among lots of other interesting facts). This post looks at these facts which, I think, some readers may find surprising.
Let’s get right to it. Fact 41 in the book reads:
Maintenance typically consumes 40 to 80 percent (average 60 percent) of software costs. Therefore, it is probably the most important life cycle phase of software.
Surprised? Wait, there’s more: Fact 42 reads:
Enhancement is responsible for roughly 60 percent of software maintenance costs. Error correction is roughly 17 percent. Therefore software maintenance is largely about adding new capability to old software, not fixing it.
As a corollary to Fact 42, Glass unveils Fact 43, which simply states that:
Maintenance is a solution, not a problem.
Developers who haven’t done any maintenance work may be surprised by these facts. Most corporate IT developers have done considerable maintenance time; so no one in my mob was surprised when I mentioned these during a coffee break conversation. Based on the number quoted in the first paragraph (65 percent maintenance) and Glass’s figure (60 percent of maintenance is modification work), my colleagues spend close to 40 percent of their time of enhancing existing applications. All of them reckon this number is about right, and their thinking is supported by my data.
A few weeks ago, I wrote a piece entitled the legacy of legacy software in which I pointed out that legacy code is a problem for historians and programmers alike. Both have to understand legacy code, albeit in different ways. The historian needs to understand how it developed over the years so that he can understand its history; why it is the way it is and what made it so. The programmer has a more pragmatic interest – she needs to understand how it works so that she can modify it. Now, Glass’ Fact 42 tells us that much of maintenance work is adding new functionality. New functionality implies new code, or at least substantial modifications of existing code. Software is therefore a palimpsest – written once, and then overwritten again and again.
The maintenance programmer whose job it is to modify legacy code has to first understand it. Like a historian or archaeologist decoding a palimpsest, she has to sort through layers of modifications made by different people at different times for different reasons. The task is often made harder by the fact that modifications are often under-documented (if not undocumented). In Fact 44 of the book, Glass states that this effort of understanding code – an effort that he calls undesign – makes up about 30 percent of the total time spent in maintenance. It is therefore the most significant maintenance activity.
But that’s not all. After completing “undesign” the maintenance programmer has to design the enhancement within the context of the existing code – design under constraints, so to speak. There are at least a couple of reasons why this is hard. First, as Brooks tells us in No Silver Bullet — design itself is hard work; it is one of the essential difficulties of software engineering. Second, the original design is created with a specific understanding of requirements. By the time modifications come around, the requirements may have changed substantially. These new requirements may conflict with the original design. If so, the maintenance task becomes that much harder.
Ideally, existing design documentation should ease the burden on the maintenance programmer. However it rarely does because such documentation is typically created in the design phase – and rarely modified to reflect design changes as the product is built. As a consequence, most design documentation is hopelessly out of date by the time the original product is released into production. To quote from the book:
Common sense would tell you that the design documentation, produced as the product is being built, would be an important basis for those undesign tasks. But common sense, in this case, would be wrong. As the product is built, the as-built program veers more and more away from the original design specifications. Ongoing maintenance drives the specs and product even further apart. The fact of the matter is, design documentation is almost completely untrustworthy when it comes to maintaining a software product. The result is, almost all of that undesign work involves reading of code (which is invariably up to date) and ignoring the documentation (which commonly is not).
So, one of the main reasons maintenance work is hard is that the programmer has to expend considerable effort in decoding someone else’s code (some might argue that this is the most time consuming part of undesign). Programmers know that it is hard to infer what a program does by reading it, so the word “code” in the previous sentence could well be used in the sense of code as an obfuscated or encrypted message. As Charles Simonyi said in response to an Edge question:
Programmers using today’s paradigm start from a problem statement, for example that a Boeing 767 requires a pilot, a copilot, and seven cabin crew with various certification requirements for each—and combine this with their knowledge of computer science and software engineering—that is how this rule can be encoded in computer language and turned into an algorithm. This act of combining is the programming process, the result of which is called the source code. Now, programming is well known to be a difficult-to-invert function, perhaps not to cryptography’s standards, but one can joke about the possibility of the airline being able to keep their proprietary scheduling rules secret by publishing the source code for the implementation since no one could figure out what the rules were—or really whether the code had to do with scheduling or spare parts inventory—by studying the source code, it can be that obscure.
Glass offers up one final maintenance-related fact in his book (Fact 45):
Better software engineering leads to more maintenance, not less.
Huh? How’s that possible.
The answer is actually implicit in the previous facts and Simonyi’s observation: in the absence of documentation, the ease with which modifications can be made is directly related to the ease with which the code can be understood. Well designed systems are easier to understand, and hence can be modified more quickly. So, in a given time interval, a well designed system will have more modifications done to it than one that is not so well designed. Glass mentions that this is an interesting manifestation of Fact 43: Maintenance as a solution, rather than a problem.
Towards the end of the book, Glass presents the following fallacy regarding maintenance:
The way to predict future maintenance costs and to make product replacement decisions is to look at past cost data.
The reason that prediction based on past data doesn’t work is that a plot of maintenance costs vs. time plot has a bathtub shape. Initially, when a product is just released, there is considerable maintenance work (error fixing and enhancements) done on it. This decreases in time, until it plateaus out. This is the “stable” region corresponding to the period when the product is being used with relatively few modifications or error fixes. Finally, towards the end of the product’s useful life, enhancements and error fixes become more expensive as technology moves on and/or the product begins to push the limits of its design. At this point costs increase again, often quite steeply. The point Glass makes is that, in general, one does not know where the product is on this bathtub curve. Hence, using past data to make predictions is fraught with risk – especially if one is near an inflection point, where the shape of the curve is changing.So what’s the solution? Glass suggests asking customer about their expectations regarding the future of the product, rather than trying to extrapolate from past data.
Finally, Glass has this to say about replacing software:
Most companies find that retiring an existing software product is nearly impossible. To build a replacement requires a source of the requirements that match the current version of the product, and those requirements probably don’t exist anywhere. They’re not in the documentation because it wasn’t kept up to date. They’re not to be found from the original customers or users or developers because those folks are long gone…They may be discernable form reverse engineering the existing product, but that’s an error-prone and undesirable task that hardly anyone wants to tackle. To paraphrase an old saying, “Old software never dies, it just tends to fade away.”
And it’s the maintenance programmer who extends its life, often way beyond original design and intent. So, maintenance matters because it adds complexity to the legacy of legacy software. But above all it matters because it is a solution, not a problem.


