Replace a cart whose item classes each hold tax and discount methods with visitors and double dispatch, so a new operation is a new class, then pay the price of a new kind of item.
A shopping cart holds four kinds of item: Grocery, Gadget, Book, and a Bundle that holds other items. The code in the editor puts every operation on every item class: subtotal(), tax() and discount(), and a function that checks each item's kind for the export. It works. It just can't grow: a new operation, such as a shipping weight, means a new method in all four classes. Refactor it into the Visitor pattern.
Build this API:
Visitor: a base class with visit_grocery(g), visit_gadget(g), visit_book(b) and visit_bundle(b). Each one raises NotImplementedError("<VisitorClass> cannot visit <kind>") (the kind is grocery, gadget, book or bundle), so a visitor that does not know a kind fails loudly instead of skipping it. Use self.__class__.__name__ for the class name.accept(visitor) that calls the visit method for its own kind and nothing else: Grocery(name, price, qty), Gadget(name, price, qty), Book(name, price, qty) and Bundle(name, items). They hold data only: no tax, discount, subtotal or export method. A bundle's accept does not walk its children; the visitor does.run(items, visitor) calls accept on each item and returns the visitor.Subtotal: total is the sum of price * qty, bundles included.Tax: total of 5 percent for groceries, 18 for gadgets and 0 for books, taken on each line (price * qty) and rounded down per line.Discount: total of 5 rupees off each unit of a grocery line when its qty is 2 or more, and 10 percent off a gadget line, rounded down. Books give none.Export: lines has one row per item, kind,name,qty,line total, such as gadget,earbuds,1,1499. A bundle's row is bundle,<name>,1,<sum of its children>, followed by its children indented by two spaces for each level of depth.JavaScript and TypeScript use visitGrocery, visitGadget, visitBook and visitBundle; the error is an Error with the same message, using this.constructor.name.
The tests check the cart's numbers, the export, the call each item makes, a new operation written inside a test, the refusal of a kind a visitor does not know, nested bundles, and that the item classes hold no operations.
Write your code, then run 8 example tests and 3 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.