0
Answered

You can use Visitor to execute an operation over an entire Composite tree.

anne erdtsieck 5 months ago updated by Alexander Shvets 1 month ago 5

I really like your book, since a lot of design pattern courses mis out on mixing design patterns. I think the real power in patterns is if you make them work torgether.


In your book, you told us that "You can use Visitor to execute an operation over an entire Composite tree.". I tried this for mapping an object structure to another object structure. Something that's pretty common in the world of API's and database models.

I would really appreciate it if you would take a look at my following post question: https://codereview.stackexchange.com/q/240738/22130

And if not, I still enjoyed your book and learned a lot.

Under review

Hi Anne!

Thanks for asking! When people ask me questions regarding their own projects & code, the first counter-question I ask is: what do you think is the answer? Sometimes people don't realize they have perfectly good answers for their own questions.

Well I think there are better ways to iterate over the postmodel composition elements by the means of an iterator or tree traversal method, like this: https://stackoverflow.com/a/30779962/1608705. This will remove iteration in the visitor class. 

This will however make it harder to connect child-parent relations in the resulting database models. I could keep track of relations by having a dictionary<original, mapped>, but it feels like that will make the solution more complex.

For my other question "Does casting inside the visit methods break the "program to an interface" design rule?". I think it does and I think the work around is creating another visitor or strategy for adding children to an entity.

Do you have a preferred method for mapping an entity tree to DTO's? 

From what I see, you'll have to depend on some of the concrete classes from the original tree anyway, unless it exposed methods to distinguish between leaf/component classes. So, the question seems to be where that dependency is least awkward to have. If you're building a universal mapper, certainly you should provide some means to inject that dependency to the mapper. But if it's a mapper built for a specific thing, which unlikely to be changed in the near future, I'd always go the easy route and hardcode the required tree classes in it. You can always refactor your way out of it if needed.

Btw, using an iterator along with the visitor is a very common thing.