Coding in a Monolith
Tags: laravel, tips, webdev, testing
Published: 2022-05-30 20:24:58

In my experience, I found that web application monoliths are very common in a lot of successful businesses. There are probably many reasons for this, but I found that most companies start out, and continue to build upon, their [minimum-viable product](https://www.productplan.com/glossary/minimum-viable-product/). This type of product is usually prototyped quickly, using full-stack web-frameworks like Django, Laravel, of even ASP.NET's MVC framework. Developers then continue to build on top of that MVP as new feature requests are asked from them -- this is largely due to finding [product-market fit](https://www.productplan.com/glossary/product-market-fit/), leading to an app that is sometimes built on a wobbly foundation... so, what do you do if you are working with a product like this?

### To Rebuild or Continue the [Majestic Monolith](https://m.signalvnoise.com/the-majestic-monolith/)?

It almost feels like a video game. Now that you've progressed in the game, do you restart your character and add points to the areas you know you need to be successful (now that you know what the game is like), or do you continue from where you left off, and try to adapt your acquired skills as the game continues to take you to uncharted places? 

#### To Rebuild:
##### Pros
- No more legacy code 😸
- You can now use the latest technologies 📡
- You understand the business better, so your architecture will be significantly better thanks to the advantage of hindsight. 👀
- Overall, better development experience 🎉
- Higher flexibility to adapt to future business changes. With better architecture comes better flexibility. ⚡️

##### Cons
- Your customers are not going to wait until a new build is complete, they will continue to ask for more features. Now you have a problem - adding features to the old app _while_ building the new. 😤
- Introduction of a new system of bugs 🐛. Despite the old system having a lot of legacy garbage, its had years of bug fixes & testing. This rebuild will not have that out the gate, leading to some instability in the new system.
- Questions from stakeholders asking you - when is it going to be done? 💀 This is the most challenging thing to predict. It took years to get you to the legacy system - how does one estimate a rebuild of an entire system?

#### To Continue? 🚌
Continuing an app doesn't really require Pros/Cons. If you're considering a rebuild, you already know the cons of continuing the current monolith. The Pros are usually straight forward - features continue to be built, albeit at a slower pace.

#### Third Option? 🏗
This last option is a combination of the other two -- you build parts of a brand new system, while also continuing your existing monolith. For example, say you have a subsystem to handle notifications. I can imagine your monolithic folder structure would look something like this:

```
app/
   Events/
      NotificationDelivered.php
   Mail/
      OrderSuccessfulEmail.php
      ItemShippedEmail.php
   Jobs/
      ProcessOrder.php
      ShipItems.php
   Actions/
      SubmitOrder.php
      ShipOrders.php
```

In this example, `SubmitOrder.php` will dispatch the `ProcessOrder.php` job. This job then delivers an Email to the user (`OrderSuccessfulEmail.php`), which then fires a generic event called `NotificationDelivered.php`. You can consider these 3 files as part of a larger "[domain](https://martinfowler.com/bliki/DomainDrivenDesign.html)", such as "Orders". Some of the other files can be considered as part of another domain called "Shipping". Let's refactor these classes around domains.

```
app/
   Events/
      NotificationDelivered.php
   
domain/
   Orders/
      Mail/
         OrderSuccessfulEmail.php
      Jobs/
         ProcessOrder.php
      Actions/
         SubmitOrder.php
   Shipping/
      Mail/
         ItemShippedEmail.php
      Jobs/
         ShipItems.php
      Actions/
         ShipOrders.php
```

So what do we gain from this? 

1. Your domains are clearly defined within these domain folders. 
2. All these features are just groups of related domain functions. 

Having these domains split into their own feature folders allows us to detach these domains in the future. For example, the entire Shipping feature could be copied into its own Laravel instance, run separately as a micro-service someday 😵‍💫. Of course, it doesn't need to happen right away, but moving your monolith to a pattern like this will put you in the right direction for slowly breaking it apart in the future 😸. 

At my current company, this has been our approach. It allows us to bite chunks out of this elephant a little bit at a time. It’s a huge challenge considering we’re also growing as an organization and introducing new processes all at the same time. Growth pains of a startup 😬. 

Just wanted to share some of my experience. If you’ve worked with monoliths in the past, I’d love to hear how your company was able to adapt! The more knowledge we can share, the better ❤️.