Replace a menu tree of one tagged Node and three if-ladders (one of which forgets the combo) with Item and Group classes behind one interface, so a combo, a feast inside a cart and a new voucher kind answer price, count and lines with no branch on the kind.
A food app holds its menu as one Node class with a kind tag (item, combo or category) and three functions that each branch on the tag: total, count and show_lines. It works, but every new kind of node means a new branch in all three, and count already forgot the combo: it says 2 for a category with 4 items in it. Rebuild it as a composite: a leaf and a group share one interface, and a group answers a question by asking its children the same question.
Build this API (names are Python's; JavaScript and TypeScript use lines and the same others):
Item(name, cost): a leaf. price() is cost, count() is 1.Group(name, off=0): holds nodes. add(child) appends the child and returns the group, so calls chain. price() is the sum of the children's prices minus off. count() is the sum of the children's counts.lines(depth=0) on both, returning a list of strings, one per node, in tree order: two spaces per level of depth, then the name. An item adds a space and its cost (Egg wrap 130). A group adds (<off> off) only when off is above 0.Group works with any object that has price(), count() and lines(depth): it must not check what a child is.Keep every old number: total was right (a category of a paneer wrap at 150, an egg wrap at 130 and a combo of a paneer wrap and a lassi at 60 with 20 off is 470), and so were the lines. The one change is count, which must now say 4 for that category, not 2.
The tests check every number, the nesting, the lines, a fake node that the test writes, a new kind of node (a voucher) defined inside a test and plugged in without editing anything, and that no code asks a node what kind it is.
Write your code, then run 9 example tests and 6 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.