Using Micro UIs To Extend Legacy Web Applications
Tags: architecture, microservices, webdev
Published: 2020-07-10 03:25:53

---
title: Using Micro UIs To Extend Legacy Web Applications
published: true
tags: architecture, microservices, webdev
description: Extending legacy applications can be very difficult. By using micro UIs, you can confidently & quickly add new features to your system!
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/t8bbylxsgy3p895oboet.jpg
canonical_url: https://www.jamesmichaelhickey.com/legacy-micro-uis/
---

Many are coming to learn about micro UIs or [micro frontends](https://martinfowler.com/articles/micro-frontends.html) (which is [not a new thing](http://udidahan.com/2012/06/23/ui-composition-techniques-for-correct-service-boundaries/)).

In my [article about Microservices Architecture](https://www.jamesmichaelhickey.com/microservices-architecture/), it highlights a big issue with how many think about and design microservices. In most microservice designs, the UI layer isn’t considered as a part of the service.


![Typical microservice design](https://dev-to-uploads.s3.amazonaws.com/i/430teyxgo54ji066cdlr.png)


With this design, you end up coupling the UI layer with all the services.

## Team Coupling
By coupling the services to a single monolithic UI, you’ve essentially eliminated the largest benefit for using a microservice design:

**_The ability for teams to be autonomous and deploy their work independently of other teams._**

In other words, a microservice architecture enables loose coupling between teams.

However, teams will _conflict_ at the UI layer when UI concerns aren’t addressed.


![Teams who own their services but are still coupled when building their UIs](https://dev-to-uploads.s3.amazonaws.com/i/gzxxdgvggoz3aoo7ssdv.png)


Instead, we want to use what the SOA world has been doing for years: _give each team the ability to own their UI._


![Microservices with own UI components](https://dev-to-uploads.s3.amazonaws.com/i/k54ukbvogmbf0809eoze.png)


## Micro UIs
Micro UIs is an approach where each team or service will create the UI parts that they need for their features and functionality.

Eventually, teams _will_ have to co-ordinate their efforts when integrating their work.

Especially on user-facing web pages, we will have the need to display functionality from multiple teams at the same time. _This is un-avoidable._

However, the amount of coupling is minimal.

The approach is to create a collection of individual components per service. These components are then composed together in the UI layer.


![Each component on the user-facing page is owned by a different service and team](https://dev-to-uploads.s3.amazonaws.com/i/cbipd6lwavvnaokhn8b0.png)


## The Trouble With Legacy
Many developers have to maintain existing legacy systems. On top of that, they have to continue to add new functionality too!

These systems may have grown out-of-control due to a lack of design & architecture, planning, technical strategy or skillset of the team throughout the years.

In any event, adding new functionality into the system can be _very hard._

There are little to no automated tests: _how can you be sure you didn’t break any existing code?_

_Should you change the code that already exists?_

_Where do you even put the new code?_

Chances are, those are difficult questions to answer since most of these legacy systems are very hard to reason about.

## Using Micro UIs To Extend Legacy Applications
I’ve been using a technique that comes right out of the SOA world to enhance legacy systems.

It does depend on the kind of change you need to add.

If you need to add, let’s say, a new section of a screen or a new web page altogether then this might work for you.

## Case Study
Here’s one example of where I’ve done this successfully.

I was working on a system that had a combination of:

- User-facing VB.NET web application
- Internal VB.NET web application
- Public-facing product marketing web application
- .NET Framework web app used to render initial web pages
- 100% custom-built JS framework with 100% custom-built components (using JQuery)
- .NET Web API that would interact with the custom-built JS framework to return JSON, HTML and everything in-between
- Various shared libraries between them
- One massive shared database behind everything

There are other systems that are missing. But this should give you an idea.


![architecture](https://dev-to-uploads.s3.amazonaws.com/i/1o3zcz500cz6f9m0ahlp.png)


Oh ya, there were no automated tests. _Anywhere._

## New Features Requested!
As you can imagine, some existing features had logic spread across **all** of these systems and much of it in the database too.

The custom-built JS framework was also incredibly difficult to work with. What should have taken days to build was taking weeks and even up-to months of work.

I decided that a new approach to building new features was worth trying.

## Forming A Strategy
In my mind, there were _many_ issues to address. Relevant to this article, here are the solutions to the most pressing problems:

- Stop using the custom-built JS framework because it’s dragging everything down with it
- Enable automated testing for all new features
- Encapsulate business/domain logic in a common area that can be shared by all the different parts of the system

Slowly, over time, I started applying domain-driven design approaches and techniques to improve things. This involved a lot of learning and having to train other developers.

Here’s a rough sketch of how new features are designed from a conceptual look:


![Design enables shared domain logic that is testable](https://dev-to-uploads.s3.amazonaws.com/i/qjpz3876m6luusqutozd.png)


Of course, that’s step one in a massive process of improving things.

This is all excluding a new mobile application and API that I’ve been leading 😅.

## How To Integrate?
Some existing features needed to be enhanced. Using this design, we can, as much as possible, direct all new code into the domain project. Existing features will just call into the domain project and use it as needed.

By using refactoring techniques, we have been able to extract existing logic into the domain layer and improve existing functionality and add tests to them!

But what about times when you have _entirely new features or products to build?_

**_This is where micro UIs come in._**

Instead of integrating directly into the existing legacy codebase, we can build as much as possible into:

1. The domain project (which includes using DDD approaches and testable code)
2. Dedicated UI components that interact directly with the domain logic

Here’s a diagram of what this logically looks like:


![New features can be built independently and in an isolated fashion](https://dev-to-uploads.s3.amazonaws.com/i/xch8e1bgdbvfhzsm3496.png)


In practice, it technically looks like this:


![Shared micro UI component comes from shared CDN](https://dev-to-uploads.s3.amazonaws.com/i/jayuvhd54zxxhk9lr2o5.png)


In this case, we tried to minimize adding more infrastructure and complexity.

The data flow of each feature is:

1. Vue.js components are on a shared CDN.
2. These components send HTTP messages to the existing .NET MVC application.
3. The MVC application is split up into feature folders. Each feature is essentially a “mini-app” like structure.
4. Each HTTP handler simply passes the request through to a domain level command or query handler.

## About Bounded Contexts
In this case, the core of each of the new features was placed into the same .NET library. This is working with a small team that manages all the systems.

However, it’s worth noting that this is essentially an SOA-like approach, logically.

Some of these new features can potentially be bounded contexts. If so, then they are perfect candidates for becoming a microservice (if ever warranted) or a module in a modular monolith.

The diagram above looks very similar to the one at the beginning of this article about microservices that own their own UI. It’s logically the same thing.

## There’s No Recipe
Every team is different. Every situation is different.

Right now, I’m helping this team separate some of these concerns into separate modules acting as bounded contexts.

But, with these large legacy systems, it’s a long process of iterative improvements step-by-step!

You have to work with what you have and face the reality of:

- Infrastructural constraints
- Technological constraints
- Business constraints
- Developer skill constraints
- etc.

This takes some thinking and design skills.

## The Benefits
There’s no doubt though that everyone, especially the business folk, sees the benefit.

- Being able to build new features that took weeks/months in days is a huge win
- Able to apply automated testing to domain logic produces more predictable behaviours and allows safe refactoring
- Able to isolate changes to a cohesive area means less chance of errors breaking unrelated parts of the software
- Ability to integrate new technologies like Vue.js into ancient technologies enables a richer user experience and selling point when hiring new developers

## Next Steps
Are you working on a legacy application that is really hard to deal with?

Is the business wanting to build new features but, so far, the existing code and design are causing tons of drag?

The techniques in this article might help.

Sometimes, it can be immensely helpful and time-saving to have someone with expertise to help you build a strategy around these kinds of changes and approaches.

If you could use help, then you can [get in touch with me.](https://www.jamesmichaelhickey.com)

Till next time!