ESCAPE FROM LOSS OF MONEY, LIFE AND CONFIDENCE WITH LEGACY CODE

Legacy Code: a dead end for your project?

Is this the end? Or should we change the way we think code and its core architecture?

Guilherme Magalhães
What Really Matters…

--

Photo by Randy Laybourne on Unsplash

Legacy code is source code that relates to a no-longer supported or manufactured operating system or other computer technology. Wikipedia

The definition is kind of self explanatory, it tell us about how a code become so hard to deal and so full of problems that this code is not maintainable, changeable or customizable anymore.

  • Have you ever stopped to think about how Legacy Code impacts your time and money?
  • How does it impact your products’ quality, hence, your customers?
  • How does it affect your employees?

As we stated in the questions above, there are many key points that is related with different personas and consequently with different perspectives in a company.

All I’m looking for is to bring to the table discussions about core problems in a company and alternatives to be able to solve it. Now, a real and painful problem comes to our talk — really problematic code.

Even though it is a subject apparently covered by articles and books, it has not yet been overcome and it happens more than it should.

Let’s dig in, have a better frame of it, understand how they are the root cause for many other problems and be able to propose better ways to escape from it.

"Legacy code is a real problem, where in a stream of value that needs to be delivered, everyone loses."

If we use the Maximum flow problem to try to find out how many problems can occur because of legacy code, we would have a big flow diagram to check.

Legacy code, legacy code everywhere

In this article I’ll try to cover some of the bad impacts of Legacy Code, impacts that actually cost the organization money and quite a lot of it. How most of the IT guys are trying to solve the problem and what we can do better to end up for real and starts a new era in our lives.

I see legacy code all the time. I'm tired of it. HELP ME!!!

Star Trek Help GIF on giphy

In his book, “Working effectively with Legacy Code”, Michael Feathers proposes a formal definition of what Legacy Code is:

To me, Legacy Code is simply code without tests

It's a point of view and maybe, a good start point to give a definition for legacy code. Untested code is often problematic code, as it does not have tests (🤦🏻!!!), documentation, or at most, poor documentation and any kind of pattern or good practice.

But I really do think this is not enough to describe how a software becomes a legacy one.

Tests (as a matter of fact) are really important as they allow the code to scream when something goes wrong on a refactor or change. Tests will break and you are going to notice and resolve the problem.

So, let's think and try to draw a hypothetical case:

Tickets Four Movies & Life

Tickets Four Movies & Life is a product for purchasing cinema tickets, it has almost fifteen years of production code, a lot of users and a reasonable revenue.

The development team has worked hard on tests through this years and they build an amazing amount of them in the codebase. Static analysis tool of the team has indicated that 87% of the cases are covered by tests.

In a pretty new day, a new product comes to life, Fun4Tickets. This product is beautiful, simple to use and all the information loads instantly for the user. And to end up, it is responsive, mobile users are able to have a delightful experience in their cell phones.

On the other hand, Tickets Four Movies & Life is not so beautiful, it demands sometime to understand how to use it, but it is functional. Responsiveness is not an option. Bye bye mobile users.

On purpose, there is a lack of information in home page, so the site can perform better.

The stakeholders of the Tickets Four Movies & Life got really scared about the newcomer. Many of our important customers were leaving our product for the Fun4Tickets. They were all about getting to a product that was better to find new movies that were related with their interests, also, it is so easy to buy from their cell phones a ticket to watch on a cinema.

Stakeholders asked the team to immediately understand and analyze why they were better than us in doing what we do for more than a decade.

Development team started to analyze the technology differences between the Tickets Four Movies & Life web app and the Fun4Tickets app.

Fun4Tickets stack is very different from what we have. Basically, the app is divided in two pieces:

  • Front end — Javascript Framework with Flux architecture and CSS Framework for the look and feel
  • Back end — Restful APIs fulfilling the front end with data and actions

Tickets 4 Movies & Life has a completed different architecture and technology stack:

  • Monolithic Java Application — Java Persistence API (JPA), Java Enterprise Beans (EJB), Java Server Faces (JSF) with PrimeFaces

Our technology stack has not evolved as it should have to be able to compete with the Fun4Tickets’ product. But, not only the technology has became a burden.

Architecture was so embedded in the technology, that any change to be more flexible and faster to delivery new features, it will mean that we'll need to choose other technology stack.

This choice to other stack means that we'll have to develop all our codebase from the ground up.

If this does not sound enough, team still need to deal with an angry board of stakeholders.

They won't be happy as they watch all looks like is falling apart. How to maintain users? How to keep track of the new and overpowering product? How to increase market share in the long term with this context?

This time, let's face it, we need to have a better solution instead of depending only on tests.

Tests have not saved us from this sad dead end 😭😭😭.

Any similarity with fictitious events or characters was purely coincidental…

Pepe the frog Feels bad man on Pinterest

Most part of the developers are going to work with projects that have some kind of old code, not always legacy, but code that many others have changed and added something new to it.

Developers are just a piece of the affected by the problem, come-on, sooner or later, we’ll have to empathize with the others guys in these chain.

Development Team

Development Team

The team need to deal with stakeholders to enhance the product and keep the costs low and to have an amazing product to maintain our customers happy.

This context is a real mess when the team has to deal with all the interests while they have to maintain a long live software.

Development team have always that feeling that they should rebuild everything from the ground up… But often, they need to continue and maintain the legacy.

What developers’ heart feels 💔

  • Low confidence to change

Think about a code that you’re working on, and it’s not covered by tests. If you’re a programmer with good instincts, then you’ll probably stop every few lines you add or edit, to test what you just did.

If you don’t have unit tests in place, then you’ll have to run the whole application to test your last changes, over and over again.

  • Long development cycle

Since the code is rotten, it’s probably not clear enough (the understatement of the year), and when a code is not clear enough, developers spend a lot more time on trying to understand it.

A rotten code is also fragile and since the code is unclear and fragile, developers spend more time on testing — just to be on the safe side (if they don’t, then the product is in danger)

A rotten code is also very rigid. When the code is rigid, developers spend more time on almost every change they do, trying to fit in their change.

  • Long QA time

Since there are no automated tests, the QA process is manual and consumes quite a lot of time (human hours instead of machines)

Since the code is fragile, more bugs sneaks into QA and the number of QA cycles is getting bigger.

  • Hard merges

Often, in a Legacy Code environment, the Continuous Integration is partial or doesn’t exist at all. By the way, having a build server, Jenkins or alike, doesn’t necessarily mean Continuous Integration. A build server is just a tool, Continuous Integration is a discipline.

Anyway, when that’s the case, developers commit their changes quite rarely and in large bulks, which leads to hard, risky merges that consume precious time and might produce bugs.

  • Low morale

Good employees like to be part of a winning team. StackOverflow made a survey that shows an obvious correlation between job satisfaction and checking in code. The more frequently developers are checking in code, the more satisfied they are. Meaning, developers like to work in a fluent, agile environment and Legacy Code isn’t that environment.

When employees aren’t satisfied, the retention rate drops. Moreover, it will become harder and harder to find new good employees.

Stakeholders

Stakeholders

The stakeholders of the project, they invest money and need to race against other competitors.

They always have the feeling that technology is a problem that only delivers to a path where money is going to be spend like a river that flows away from the mountain (or their pockets).

What stakeholders’ heart feels 💔

  • Loss of confidence in the team

Stakeholders look for ways to change some problem, and most part of the time, they try the simplest path.

Sometimes, the simples path is to guilty the development team and loss confidence on them.

This loss of confidence is an enabler for a horrible culture for the team. As the team can not fail anymore, they are going to be as conservative as possible, creating a lot of policies and process to any changes on code.

The product/system is going to evolve so slowly, that all competitors will thank the stakeholders' board.

  • Lower investments

As the product gets more expansive and the return of it decreases, stakeholders are going to give lower investments.

It is logical, less money in, less money out.

Customers

Customers

And last but not least at all, there is the customer that needs or desire to use your product/system and always feels that it is a completely piece of trash.

Why do we have to always make the life of our customer so miserable and sufferable?

What customers’ heart feels 💔

  • Long wait

When the development cycles are longer, the less releases you have in a given period. The less releases you have in a given period — the less happy your customers are.

  • Ignored

When the code is rigid, fragile, unclear and not covered by tests, you’ll find yourself too often saying ‘no’ to customers’ requests.

  • Unhappy

The lower the quality of the product — the less happy customers are.

  • Security risks

Cybercriminals have new technology and faster computing speeds at their disposal. Attackers are armed with knowledge of the weaknesses in older systems — such as the systems your legacy code requires to operate.

"This is not the end, it is still the beginning"

A broader view of the problem enable us to have a better understand of how harmful and destructive is a legacy project.

This is still not enough, problems, problems and more problems.

It sounds so bad that I need to give a break…. A break for more bad news! YEAP \o/\o/\o/

Tired Giving Up GIF on giphy

Check it out some statistics to see what legacy code and its arms are doing in IT economics.

Statistics

  • IDC Government Insights’ latest forecast predicted civilian agencies will spend $52 billion on technology by the time the fiscal 2018 ends.
  • IDC says 78.9 percent of that spending will go toward improving and maintaining legacy systems, commonly known as operations and maintenance (O&M).
  • Companies are misusing their most important resource, with too many developers tied up in projects designed to prop up legacy systems and bad software, at a cost of $300 billion a year — $85 billion just dealing with bad code.
  • Correctly deployed, the expertise of software developers could add $3 trillion to global GDP over the next decade.
The Cost of Poor Quality Software in the US: A 2018 Report (https://www.it-cisq.org/)

Up to now we've seen loss of money from stakeholders, customers, revenue and market share. Loss of life from everyone involved with the project, but mainly, the development team or product team. And loss of confidence from everyone, team, stakeholders and customer. Nobody is going to trust in the brand again.

Oh Gosh, what can be done? Am I going to cry forever and loose all the rest of life that lives inside of me?😫😢😭

Let's think for a while and propose some kind of solution for it. When a huge problem like that hits us, a so big opportunity come across.

I mentioned earlier that tests are not enough to properly solve the legacy code problem. It help us, but, alone it doesn't change the sad destiny for the project.

I'm going to quote other guy that propose something more ample to runaway from the dead end. Let's see what Jeffrey Palermo said.

We often don’t keep systems up-to-date because it’s impossible to do. If coupling prevents easily upgrading parts of the system, then the business has no choice but to let the system fall behind into a state of disrepair. This is how legacy systems become stale, and eventually they are rewritten. Jeffrey Palermo

That's really true, as we saw and checked, upgrading is hard, expansive and it causes more damage than good. As Jeffrey stated, legacy systems become stale and it needs to be rewritten.

What Jeffrey proposes is, what he calls Onion Architecture.

Onion Architecture Diagram

The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center. This architecture is unashamedly biased toward object-oriented programming, and it puts objects before all others. Jeffrey Palermo

Great mindset, and a real change on how we design and think about code, but there are some improvements in his proposal.

Uncle Bob used Jeffrey Palermo architecture and some others to propose this improvement, in what he called Clean Architecture.

Clean Architecture Diagram

Let's have a basic understand of this diagram and how to read it:

  • Layers: Each ring represents an isolated layer in the application.
  • Dependency: The dependency direction is from the outside in. Meaning that the entities layer is independent and the frameworks layer (Web, Database, etc.) depends on all the other layers.
  • Entities: Contains all the business and object entities that construct our application.
  • Use cases: This is where we centralize our logic for our features. Each use case orchestrates all of the logic for a specific business use case (for example, add a new movie in the catalog).
  • Controllers & Presenters: Our controllers, presenters, and gateways are intermediate layers. It is an entry and exit gate to the use cases of the application.
  • Frameworks: This layer has all the specific implementations. The database, web frameworks, logging, error handling frameworks, etc. Robert C. Martin describes this layer:

This layer is where all the details go. The web is a detail. The database is a detail. We keep these things on the outside where they can do little harm.”

At this point, you may be asking yourself: “Database is in the outer layer, a database is just a detail? The database is supposed to be my core layer!"

This architecture is so amazing because it has a smart motivation behind of it.

Instead of focusing on frameworks and tools, this architecture focuses on the business logic of the application. It is framework independent (as much as it can/should be).

This means it doesn’t matter which database, web framework, UI, or external services you are using, the entities and the business logic of the application will always stay the same.

We can change all of the above without changing our logic. This is what makes it so easy to test applications that are built with this architecture.

Entities & Use Cases

“The software in this layer contains application-specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise-wide business rules to achieve the goals of the use case.” — Robert C. Martin

In the core of the application, we have two essential layers:

  • Entities: Contains all the business entities/objects that construct our application. Like, MoviesEntity or ChartEntity
  • Use cases: Contains all the business scenarios/features that our application supports. Like, AddMovie or CleanChart

Controllers & Presenters

“The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the database or the web. It is this layer, for example, that will wholly contain the MVC architecture of a GUI. The Presenters, Views, and Controllers all belong in here” — Robert C. Martin

This layers is responsible to be the adapter's layer, so we won’t see any business logic or frameworks here.

Our controller, presenters and gateways are intermediate layers.

We can think of them as an adapter that glues our use cases to the outside world and back the other way.

Controllers

The responsibility of a controller in clean architecture is:

  • Receive the user input
  • Validate user input-sanitization
  • Convert the user input into a model that the use case expects. For example, do date formats and string to integer conversion
  • Call the use case and pass it the new model

The controller is an adapter and we don’t want any business logic here, only data formatting logic and middleware communication.

Presenter

The presenter will get data from the application repository and then build a ViewModel. Its main responsibilities include:

  • Format strings and dates
  • Add presentation data, like flags
  • Prepare the data to be displayed in the UI

Frameworks and Drivers

“The outermost layer is generally composed of frameworks and tools such as the Database, the Web Framework, etc.

This layer is where all the details go. The web is a detail. The database is a detail. We keep these things on the outside where they can do little harm” — Robert C. Martin

In the previous section, we talked about the adapters layer and how they act as the entry and exit gates to our use cases.

Now, this is the time that we are going to talk about the frameworks layer.

This layer includes all our specific implementations, such as the database, web frameworks, error handling, etc.

What is so amazing about this architecture after all?

It's not based on any frameworks or obsolete pieces of a legacy technology.

If for any reason, our database become obsolete, we can replace by any other, if our web framework is not updated any more, we can for sure replace for a new one.

We are not embedded with any external technology or framework anymore.

Our core business is in the correct layer, we can change code as we go. A new feature will be placed in the use cases, we are ready to test, develop and write our features as an API that is going to be used outside.

Really AMAZING!

Cat Catnip GIF on giphy

I should spend so much time and effort writing about clean architecture with some good example code and implementation. Often, just talk about architecture gets too abstract and it does not help us elucidate our line of thinking.

Maybe in a next post, I am going to show a sample of this wonderful architecture written in some platform like Java and we'll understand better how amazing it is in a real application.

Last words…

Legacy code is not a dead end for a project, but it is a common path. Like any common and wrong path, we have solutions for it.

We can and must be more proactive in dealing with it, we don't have to wait to happen, so we map the technical debt, creates an executive summary and ask for the stakeholders or managers to spend a lot of money to deal with it.

We are going to solve the problem for a while, but next time, they'll refuse to give more money and we will need to be prepare for a complete refactoring, sometimes of code, sometimes of team and even sometimes of product/system.

Let's spend some time on design and architecture, enough to get started and avoid this common path.

I’m pretty sure that your company is going to save a lot of money, your partners will be so much more happier and your loyal customers will complain when someone talks something bad about your product.

"We only move forward when all perspectives are pointing to the right direction."

--

--

Guilherme Magalhães
What Really Matters…

Passionate about code crafts and even more passionate about making a difference and following a clear purpose. I Started to write, no matter what.