I think the general convention of `generate_receipt_instructions` is more complicated than it needs to be. There are two kinds of instructions one might want for an OrderItem -- something specific to that order item (e.g. "for this class, go to this URL"), and something more general that you'd want to de-dupe (e.g. "visit your dashboard", a.k.a. all we have to implement right now). So let's separate those into different methods in OrderItem, and let the caller do the de-duping if necessary. For the OrderItem specific pieces, Order could make a dictionary of { OrderItem.id : [messages] }. For the general, Order could de-dupe by just throwing it all into a set. It just feels kinda weird that an OrderItem method should have to care what the other OrderItems before it have said -- it should just return its messages and let the caller sort it out.