At Wayfair, architects play a huge role behind the scenes. One component of our job is to identify gaps in designs and solutions and then create solutions to cover these gaps. If we identify a repeatable gap, we utilize a repeatable design pattern. This allows us to create a solution that addresses all of the gaps.
This blog describes a problem I found with a commonly overlooked gap in integrating external dependencies into apps and then walks through the design pattern solution I created to cover the void. The post also delves into the tradeoffs of using the solution, a how-to guide for implementing the design pattern, and the lessons our Wayfair team learned from using it.
As always, if solving problems is something you are passionate about, Wayfair is the place for you. After reading my post, I encourage you to check out current job openings at Wayfair.
As always, it is best to start with the outlining problem. Our team was recently testing a new external software dependency. The use of external dependencies is not anything new. In fact, teams often use them to serve as reusable building blocks when creating and testing new product solutions.
These reusable blocks help accelerate development, but some risks come with using them, specifically when it comes to the customer experience. For example, external software dependencies can cause app crashes or failures with services. At Wayfair, we experienced app crashes firsthand from integrating external dependencies.
In this instance, our team performed a unit test. What we found was an external dependency that was occasionally sparking unexpected and undeclared errors. To address the problem, we needed to create a repeatable strategy that would minimize the potential risk by catching and reporting unexpected faults.
This is where the Seismograph Design Pattern came to the rescue. It enables software engineers to implement fault tolerance, catch errors caused by external dependencies, and report them to issue management services for notifications and analysis.
How It Works
The Seismograph Design Pattern, a hybrid pattern, includes several elements: a decorator, new errors that map to external errors, an observer, a reporter, and a facade. I will delve into all of these below.
When working with external dependencies, the dependency class(es) requires an exterior package and class(es) that can encapsulate functionality. It does this by wrapping each function call to catch and report errors. This is why we use the decorator design pattern: to wrap a class and add new functionality to the class without changing the class's original structure.
The decorator wraps the class's function calls to catch unexpected errors and specifically faults in issues management systems. When errors are caught, those corresponding to the functionality are created and then released to the observer. At this point you might be asking, why create new errors? The answer is they provide context to stakeholders who then report these findings for further handling.
The class in one's app or service, the dependent class, interacts with a facade. The facade is responsible for hiding the fault tolerance complexity. The obscured complexity involves associating the decorator with the observer, including functions that redirect to the decorator's functions and possibly providing a function to release resources.
The How-to Guide to Implementing the Pattern
The design pattern is comprised of six main steps:
- Create an error base class with subclasses. These represent the different types of errors. This class type could be an enum, a sealed class, or something similar.
- Create a reporter class or component to report the errors.
- Create an observer class to monitor the errors and send the event to the reporter.
- Create a decorator class to add new fault tolerance functionality to an external class.
- Update the error base class to include subclasses for each scenario. These are all based on error type with the decorated functions.
- Create a facade interface and class to hide the complexities of communicating with the APIs as well as all error handling. This facade would be responsible for tying together the observer with the decorator and releasing resources.
This example that I present below uses Kotlin, which is quite similar to other modern programming languages like Swift. Here we begin with the External Class
The External Class
The class which is external to the current module or project can throw unexpected errors. The class below is based on the Gateway Design Pattern and is a single-point entry for all the APIs. Although the example explicitly throws IOExceptions, any type of error could be thrown by an external class without being trapped. With some classes, unforeseen errors can occur and result in adverse side effects. These side effects are the reason why I created the Seismograph Design Pattern.
The Decorator Design Pattern creates the decorator class. Once complete it wraps the external class reference with a guardrail for catching unexpected errors coming from the external class. It then emits corresponding errors to the observer, which in this example is an Rx Subject. Located in the facade, the Rx Subject observes errors and then sends them to the reporter.
The Error Class
This class and its subclasses represent the possible errors that occur when calling functions on the external class.
The Reporter Class
This class sends errors to destinations such as issue management systems.
Tip: In cases with repeated issues, we recommend adding a caching mechanism to avoid repeated reports of the same errors within a designated time frame.
The Facade and Observer Classes
The design of the facade class derives from the Facade Design Pattern, which hides the complexity of communicating with the APIs and using the decorator, observer, and reporter.
After using solutions created from this pattern at Wayfair, we have immediately experienced some major benefits. First off, the stability of solutions has increased. Second, error reporting has helped our teams resolve issues at a far quicker pace. The reporter may receive numerous repeated errors. If that’s the case, you may need to design the reporter solution to reduce repeated error reports.
If you enjoy solving problems by creating repeatable patterns like the Seismograph Design Pattern, check out the current job openings at Wayfair.