Untestability of monolithic systems
Enable various parts of the system to be tested independently of other parts of the system
Enable various parts of the system to be tested independently of other parts of the system
People sometimes ask me what do I mean when I say that thinking in terms of a monolith results in a system that is untestable (or, to be more fair, largely untestable). Maybe a hypothetical example (albeit far fetched) could help?
Suppose some software development team was tasked with automating the processing of foreign visitors to an emergency service. People travel abroad, accidents happen, and some unfortunate visitors end up in the emergency ward. Now the healthcare business wants to automate that critically important processing.
So, the team goes ahead and designs and builds a system that automates the border crossing checking process (passport and visitor visa validation). The team also automates the process of admission to the emergency ward by checking whether the inpatient has valid health coverage; if not, the emergency ward will have to charge the inpatient for the services.
The team delivers the system, the healthcare facility accepts the system, and pays for the services. The team disengages.
However, as it often happens, the business policy rules change and the system now needs to be updated to accommodate new rules.
Suppose our team gets hired to improve the patient admission functionality. Let’s say we sell our services as an expertly provisioned suite of fully automated tests. We guarantee to our client that we will make necessary improvements to the system and will deliver the solution that is fully covered by automated tests.
How to automate testing of a monolith?
Suppose, for argument’s sake, that the original team had designed and implemented a true monolith. What do I mean by the ‘true monolith’? Basically, a system where all constituent concerns comprising the functioning of the system are tightly knit and interwoven.
Maybe a concrete example would help: say we want to write an automated test that checks if the inpatient has valid health coverage. The monolithic system needs to know that the person who is visiting the country and who now wants to be treated in the hospital is a valid visitor. Toward that end, the system also needs to check whether the inpatient has obtained the necessary clearance upon arriving at the border crossing.
To ensure the validity of the visitor’s status, the only way a monolithic system could automatically check the status is to simulate the landing event. In other words, the automated test script for the monolith cannot simply simulate admission to the hospital; it needs to rewind the incident all the way back to the point where the visitor is at the border crossing and their passport and visa are being processed.
Only if the visitor obtains that clearance at the border crossing can they proceed toward the hospital admission processing.
The automated testing of the monolithic system is excessively convoluted, tedious, expensive, error prone, and wasteful.
Contrast that with the automated testing of the properly modularized system. Such system would not require the rewinding of the incident. It would be easy to simply provide necessary values to the emergency ward module, from which point the localized business processing logic would proceed with checking the valid health coverage.
Moral of the story: it is important to enable various parts of the system to be tested independently of other parts of the system. That independence also applies to the order, or sequence, of business operations. When devising a monolithic system, such possibility of independent testing is not achievable.