This is a design-based question. I'm not at liberty to discuss the actual case I'm dealing with, but the example I provide is representative to the actual problem.


Let's say we are creating books that have different endings based how somebody progresses through the book. For simplicity, our system generates a complete story without any choices for the actual User to choose, in effect creating a normal book. From the end-user's point of view, the book has no choices.

When we want to generate a book for the user to read, a book with choices is "rendered" by the system by navigating through the choices in the book and randomly selecting one of the choices at each branch. We want to store this rendered version for the user to go back to in the future, if they so choose.

The Problem

My current solution is to create two, parallel hierarchies, one for the original version and one for the rendered version. This allows us to keep the original version, the one that can be rendered again for another user (or the same user if they want to see a different version), and keep a record of the versions generated for a specific user.

While this solution seems appropriate considering the circumstances, I'm wondering if there is a better solution or design pattern that may apply here. The parallel hierarchies introduce coupling that seems unavoidable, but I would be interested in hearing other perspectives.

I think I covered the basics of my scenario, if you need any more specifics, just ask.

  • If there is a finite amount of choices then you can enumerate all of them, i.e. assign a number to each set of choices. You can decode this number to get the choices back. If rendering a book is cheap/fast, you can simply store the template + choice ID, and translate between the ID and the rendered version on the fly. Does this possibly go in the right direction, or are there any details that prevent enumeration of all possible choices?
    – amon
    Aug 11, 2017 at 17:53
  • Good suggestions, but in the real use case, the number of choices are very high (e.g. think of rendering random values for an equation). I consider storing information about what choices are made as opposed to the whole "book" an implementation decision, how that is implemented could still result in a parallel hierarchy. For example, RenderedBook may contain the title and version/edition while RenderedChapterBook could contain the chosen chapters. From those 2 classes I could generate the textbook. Alternatively, I could just duplicate the information from Book and ChapterBook.
    – c1moore
    Aug 11, 2017 at 18:19

1 Answer 1


From the sound of it, our ability to give you advice is limited by your ability to tell us what the question is. We can use the book metaphor, but if "the number of choices are very high," then you may need to craft a solution to fit your data. In particular, never use OO hierarchies inside a FFT kernel. Fit the solution to the problem.

As written, it sounds like OO is a valid solution. Fundamentally you need to have a "book" for your user, and a "book-with-options" to store all of the possibilities, so you're going to need to store 2 sets of data no matter what.

Have you considered a flyweight pattern? Have your Book class include the functions to explore choices the user could make, have a ConcreteBook which contains all choices, and a SelectedBook that only has one path. Have all of the sub-components of the book use the flyweight pattern to deal with choices.

Let's say you have a Page. It has a getNextPages() function to do choose-your-own-adventure style stories. However, we tweak it slightly. Instead we have a getNextPages(Book myBook) function, which can be passed a reference to your book. Then, all of the selection choices can be handled in the SelectedBook class. Each sub-component like a Page just needs to know how to get enough information from the book to do the job. That way you only need one Page, one Bookmark one Letter and one ChapterHeading. The only class that has to be duplicated is the Book itself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.