2

Let's say I have an Object Structure like this that I import data into from a source:

Reporting:
  Body:
    ReportingEntity:
      DocSpec
    Reports[]:
      ConstEntities[]
      DocSpec
    AdditionalInfo[]
      DocSpec
  MessageSpec 

Whenever I import the data I have to check for changes in any of the objects and update the DocSpec objects within dependent of the type of change (no change, correction, added data, removed data). Then I have to split the object and filter the correction and removed data into one object and filter added data into a second object. Each of them will be written to its own XML file and sent to an authority.

On first glance this looks like a great opportunity to use the Visitor Pattern for UpdateReportingVisitor and FilterReportingVisitor but I also see a major difference here: A visitor only traverses one object structure and does its operations on it. It doesn't work on a second object simultaneously. An accept() method for UpdateReportingVisitor would look like this:

class Body(object):
    def accept(self, visitor, other):
        """rough draft to communicate the concept. This is not the actual implementation!"""
        visitor.visit_body(self, other)
        for self_report, other_report in zip(self.reports, other.reports):
            self_report.accept(visitor, other_report)
        for self_info, other_info in zip(self.additional_infos, other.additional_infos):
            self_info.accept(visitor, other_info)

while FilterReportingVisitor wouldn't need that extra argument.

I'm a bit uncomfortable with this solution because of that other argument in each accept() method that clearly doesn't belong to the pattern. Would this approach still be considered a visitor pattern? (If no: Does it have a different name?) is there a different (better?) pattern to solve the problem i have?

  • 1
    So, wait. You've come up with what appears to be a perfectly sensible solution to a computing problem you're having, and you're hesitating to use it because it doesn't fit the exact mold of a well-known software pattern?? – Robert Harvey Aug 2 '18 at 15:37
  • I'm hesitating because it seems to break the idea of the visitor pattern. Instead of having one common accept() for all visitors in each class i will need at least 2 of those methods in each class. Maybe there will be a third case that will need a third implementation of the visitor pattern one day so I was wondering if this pattern might be wrong abstraction. Your reaction helped me a lot though. Thanks! :-) – Tekay37 Aug 2 '18 at 15:49
  • (e.g. there could be a visitor that translates data from an old set of data into a newer version of it) – Tekay37 Aug 2 '18 at 15:51
1

Your accept seems to strictly associate children by their position. I'm not sure it is what you really want. It may behave unexpectedly if a child is inserted in middle. Seems like you cannot abstract the specific task from the implementation of accept, if you go this way.

There is an alternative way to define visitors, which leaves descending into children to the visitor. This way, you have much finer control over how do you traverse the data structure. You can process node before visiting children, or after. Or, as in your case, traverse 2 data type in parallel, abstracting the specific logic from the class - for example, you could search for matching children in the list. This, however, would require you to create a many visitor classes, to dispatch in - roughly as many as node types you have, plus one for the first argument dispatch. It's quite a bit of writing, so I cannot provide you an example now.

  • I'm sorry the accept method is just a rough draft, not the actual implementation of it. I should have mentioned that. The actual version has some operations for elements in both lists and also for elements that are only in one of each list. – Tekay37 Aug 3 '18 at 10:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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