Replace one class per kind and channel pair (3 kinds x 3 channels = 9 classes) with two hierarchies joined by one reference, so every old message stays exactly the same, a new channel or kind written inside a test works with all the others, and the 40-character text limit lives in one class.
A notification app sends three kinds of message (an order update, a one-time code and a promotion) by three channels (email, text message and push). It was written as one class for every pair: nine classes that each repeat their kind's words and their channel's format. A fourth channel would need three more classes. Rebuild it as a bridge: what is said is one hierarchy, how it goes out is another, and a notification holds a channel.
Build this API (names are Python's; JavaScript and TypeScript use the same names):
Email(), Sms() and Push(): channels, each with deliver(to, title, body) that returns the finished line.Notification(to, channel): the base. send() returns channel.deliver(to, title(), body()). A subclass supplies title() and body().OrderShipped(to, channel, order_id), Otp(to, channel, code) and Promo(to, channel): the three kinds.The behaviour to keep, exactly (to is asha, the order is 77 and the code is 482913):
| Channel | The line it returns |
|---|---|
[email to <to>] <title>: <body> |
|
| Text message | [sms to <to>] and then <title>: <body> cut to its first 40 characters |
| Push | [push to <to>] <title> / <body> |
| Kind | Title | Body |
|---|---|---|
| Order shipped | Order shipped |
Order <order_id> is on its way |
| One-time code | Your code |
<code> is valid for 5 minutes |
| Promotion | Weekend offer |
20 percent off wraps till Sunday |
The tests check all nine messages, the 40-character cut, a fake channel that records what it is given, a new channel and a new kind written inside a test and used with all the others, and that no class per pair is left in the code.
Write your code, then run 8 example tests and 4 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.