Replacing a live front-end legacy code – The bottom to top migration strategy

This article is written about work done in 2016 – and the technoloigies mentioned match the time:

Here’s the deal – A company has an existing product with outdated technology, an old legacy code which is unmaintainable and unextendable, essentially, written with old technology. The company in question understands that it’s time to move forward, catching up with the present day and time.

Unlike the usual method of rewriting an entire product from scratch (top to bottom), there is a better way. This includes building a new front-end feature and immediately using it within the old legacy product. This methodology works even when the technologies are light years away from each other.

I used to work for a company like that. Before I started working there, their initial starting point included an old product which was an auto-generated HTML code out of a java backend, also known as “Automagically generated JS, CSS, and HTML”. This happens to be a front-end developer’s true horror.

This company decided to rewrite its product from scratch, with all new technology (Javascript and a Python API). They recruited developers, product specialists, used the best resources, and meeting hours. This was the first time that this company had a big front-end project ahead of them.

During the following year, they had an old legacy product that was live. It was making money but had minimum resources for maintenance, and no new features whatsoever.

On the other side of the development department, a new pile of fresh code and architecture was just beginning to be written. Unfortunately, it piled up and laid there without anyone knowing about the product or its users. The feature set wasn’t that big, but because this product was supposed to replace an already live product, no one could cut the scope of its features.

After more than a year, the freshly written code and architecture failed to reach its deadline, and there was no end in the horizon.

The project was canceled.

So there we were, with a year’s worth of development time and fresh code, but none that was usable. We had a product that was not maintainable and a business that needed to keep working and growing.

We all wondered, how could we all solve this horrible problem? What would have been the best way to make up for this lost project before us? How could we revive our motivation and bring back trust to the front-end department in the company?

I was called on to find a solution – and thankfully, did. The solution focused on the business. For a developer that always wanted the cutting-edge technology to be written from scratch – it was a difficult solution to understand, at the beginning.

The idea  was to reach goals in a better way:

The solution included giving the company the possibility to maintain and add features to its old applications. And, in such a way that also took the company forward in the direction of having a full new front-end application as needed. The solution enabled us to transparently transition from an old product to a new and cutting-edge front-end product.

Unlike the original method that was used which included rewriting the whole product from scratch (i.e. from top to bottom), the new method  was from bottom to top. I determined that we could build a new front-end feature and immediately use it, and we could make a profit and learn from it.

This also enabled us to stop at any point, and to shift resources at any time, without any loss. This was because every new feature was already in production, and embedded in the old application, but separated and detached from it.

This solution undertook important calculations and measurements:  

  1. Time / Resources
  2. Risks
  3. Scope
  4. Technical limitations

Technical Problem:

In all actuality, the legacy product was very limited from a UI perspective. We were bounded only by the UI elements and functionality that it provides. And, it is not a front-end friendly framework at all – it is a closed product.

Even worst –  it was mixed in with badly implemented JS code, on top of old product, which “helped” overcome the above problem in the past, this layer can be called: the hacks layer.

It was unscalable for code/feature extension, and since each update is global, it can easily break style and functionality.

We must keep developing the money-maker products, and we cannot merely rewrite it.

When addressing a migration from an old technology to another, we developers always think about a total new re-write. But if you are able, technically, to isolate your new code, components, and UI elements – you can do the re-write in a much more efficient way.

Infrastructure preparation:

On top of all feature requests, we must implement a few front-end infrastructure features:

The idea of this preparation job is to offer a set of front-end tools for easier maintenance, deployment, and development:

  • E2E tests (wooha, Selenium)
  • SASS compiling
  • Minifier / Concatenator
  • Angular
  • Bower

Now to the real work:

JS

We chose Angular.

Most importantly, the new code must be encapsulated, and most importantly, we must not rely on the DOM.

We found Angular the most encapsulated framework, allowing us to separate our JS code and HTML from the old container.

Each component must contain an angular view and have the ng-application root. We don’t want Angular to waste resources on listening to the whole DOM (and conflicts with the legacy lib). We encapsulated the page too small Angular apps.

CSS

Style separation: The Style lib

The style we came up with was the most complicated part.

CSS is inherited. There is no easy way to encapsulate an element from a CSS rule that applies to this selector (There is one way, but it is not supported by any IE, and we could use other tricks, that looked hacky).

So, we have an old framework, with a big pile of CSS, and with various rules that select tags, classes, states, and most importantly – deep rules, such as:

body form label input [type-text]{}

There is no way to write generic rules that can predict and override them.

Also – When we write a new feature, we cannot determine what overrides what. There is an option to check in the development tools, but this is a very long process, especially for each rule.

The solution was a separate UI lib. We generated two CSS files: The old Lib.css and the newLib.css.*
On our portal, we included both files.
On a separate static HTML page, we included only the newLib.css file.

When a new feature is being built, or an existing feature is being rebuilt, we must first build it inside the static HTML. Thus, creating it’s CSS rules in a clean, isolated environment.

At this stage, we know that the independent style we included on the page will work when we remove the oldLib.css file.

As for the rules from oldLib.css that are overriding the newly created rules (some !important or deep nesting rules from the legacy code that we cannot remove), they were minimal in numbers and got their special overridden section at the end of newLib.css

Once the oldLib.css file is removed, we can then remove the sections. We will then have an immediate working product, with minimum need to adjust and fix.

Results:

As for the time spent writing these lines, many of its features were overridden, and many new features were built, all with a new front-end code. They are all live, which immediately allows the company to earn money from the invested time they spent.

In this case, the old legacy product is maintained again, it is also extendable, and one day, it will get rid of the old code easily because of this separation.

What we created allows us to change resources without any problem whatsoever. No waiting on code that will never see the light of day or make any money.

And, on the developer side, we are able to do cutting-edge technology, using the tools that we would have used in a complete rewrite project. But, now we have an even better, harder, and more complicated task. This challenges us more and helps us to find solutions that other developers who use frameworks out of the box don’t need to deal with. It forces us to need a better developer, better learning processes, and a great backup and belief from the company management that this is achievable.

The above solution gives us the possibility to maintain and add features in such a way that will also take us forward in the direction of having a full new front-end product, in its old automagically generated front-end. It also enables us to have a transparent transition of the old product, to a new cutting-edge front-end product, which is miraculous.

* not the real names of the files

Saint Petersburg and the Siege of Leningrad

When Nazi Germany invaded the Soviet Union in the summer of

When Nazi Germany invaded the Soviet Union in the summer of 1941, a German army surrounded the city of Leningrad (today’s Saint Petersburg) in an extended siege.

The siege lasted nearly 900 days and resulted in the deaths of more than 1 million civilians.

During the siege, the city established supply lines from the Soviet interior and evacuated many citizens, often using a hazardous “ice and water road” across Lake Ladoga. In January 1943, the Red Army finally managed to break that siege.

I arrived in Saint Petersburg for a vacation and took one day to see the battle areas, and the most important “road of life” – a path that kept the city alive during these almost three horrible years.

My tour guide was Alexander from Histours. Alexander drove me in his car, and for almost 9 hours, we visited the main locations that formed the story of the siege and its breaking.

Armed with maps, photos and deep knowledge of the area and the people, Alexander took me through the road of life, to the battle that broke the siege through Neva River that starts at Lake Ladoga and ends in the Gulf of Finland, in Saint Petersburg.

The road of life:

The road of life was used to evacuate people from the city and bring supplies in. In the map, the gray color is the control area of the Nazis.

Road of Life. November-December 1941
Germash19 – the crossing marks with red.

This memorial is for kids. A young girl gives her sister a phone book, so she will be able to write a diary (normal notebooks were hard to get).

On these stones are the pages where she writes the death dates of her family. Each page indicates the dead (mother, dad, grandmother…) the time and date of death.

Pages from a little girls diary, describing the death of her family.

With these stones, we follow a young girl’s life during the siege, while all her family is fading away, one by one.

Following the road of life, we climb a hill that was used as a hospital. Here, mass graves of the wounded that died later, the women of war and all other forgotten brave ones, who did not die on the battlefield.

Original road of life
Original road of life
For the women of war

The main part of the road of life was the crossing of Lake Ladoga, which is frozen most of the year.

The crossing was done with trucks, with ice in any condition – many did not finish the journey.

Here is the memorial in the exact point where the trucks went down to the ice and started crossing the lake.

The memorial symbolizes the breaking of the siege.

After crossing the lake, a train was used to transfer the supply into the city.

Without the Chinese people.

Later, a bridge was built. The Germans kept bombing it, and the Russians fixed it. The Germans did not try to fight hard against the road of life since they were sure it was a waste of resources for the Red Army and the city wouldn’t survive with this small means of transportation.

Finally, the Red Army was able to break the siege in crossing the frozen Neva River; the battle began with an orchestra playing the “International.”

Diorama of the battle of Leningrad
Diorama of the battle of Leningrad

This point held the hardest battles.

And then the shock came.

This land saw the hardest battle. It was here where they broke the siege. Every piece of land saw so much blood and gunpowder.

It is still full of remains, and it is being dug. Everywhere you go, you see war items, such as gas masks, shoes, etc. At one point, we saw human bones that were discovered.

German shoe (with nails) and Russian (glue)
German shoe (with nails) and Russian (glue)
Human remains
Human remains
Human remains
Human remains
Nazi shoe.

Not far away from there, Russian soldiers buried the remains that were found.

 

It is amazing to see, that until today, we still haven’t covered out everything from that war.

The tour was given by Alexander, a private tour guide. I highly recommend him. It was a fascinating day, with stories that are not told enough in the west.

For the bravery of the people of Saint Petersburg, and the brave people that defended them.