-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Closed
Labels
Description
If you try to build a CopyVisitor of some kind of object hierarchy, one has to build some kind of Stack structure, to give the actual visitor a hint, where it should write its copied data.
I suggest to extend all visitor methods with a return value:
MyType visitor(MyType param);
The standard implementation should return the actual object inserted.
public interface StatementVisitor {
Comment visit(Comment comment);
Commit visit(Commit commit);
Delete visit(Delete delete);
Update visit(Update update);
sivaraam, 0xxFF and mpokryva
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
wumpz commentedon Dec 2, 2019
Using this we would be able to create some kind of functional visitor implementation.
wumpz commentedon Dec 10, 2019
There is a thumbs up above, but I am more interested in textual comments :).
AnEmortalKid commentedon Jan 11, 2020
I'm having a bit of a hard time sort of visualizing this, so correct me if I wrong.
Let's assume we just had a
SelectVisitor
to copy theSelect
.Old Way:
With new pattern:
Or am I Missing something.
wumpz commentedon Jan 12, 2020
Correct. With this new style the visitors itself return the copy and the caller could immediately put it in the right place. So you don't need to organise your copied items in some sort of stack to find the last generated. Imho a global variable here should be avoided but cannot within the actual implementation.
AnEmortalKid commentedon Jan 12, 2020
Would it be valuable to have
CopyStatementVisitor
and the currentStatementVisitor
? If not, then changing StatementVisitor would be fine, probably just a big warning to all consumers that things no longer return void.wumpz commentedon Jan 13, 2020
Indeed this would be a massive api change. That is why we would go for version 4.
If there are two visitor interfaces then we would need to visit methods per class. So that is IMHO a no go.
AnEmortalKid commentedon Jan 13, 2020
sivaraam commentedon Feb 3, 2020
IIUC, the suggested change is that all the
visit
methods of the visitors would be extended to return a copy of the object they receive as the argument to help with implementing the copy visitor. Is that correct?If it is then, is my understanding that this is useful only to those who want a deep copy of an object, correct? I'm just wondering whether this huge API change is worth the migration burden on the users who want to move to version 4 of the library? That's because they would have to change every extension of every visitor they would have implemented as a consequence of this change. That sounds like a lot of work and might not be a good thing to bring upon the users. Just my opinion.
wumpz commentedon Feb 3, 2020
@sivaraam: that is correct. As well this change does not support replacement by different types, e.g. Column to literal or CaseExpression or you name it. That is why I am getting away from this. The problem here to solve IMHO the backreference to the parent object. How to replace an expression, while there is no reference to the parent? Now you have to adapt every possible parent. To make things worse you not only need the reference to the parent but to the attribute as well.
sivaraam commentedon Feb 3, 2020
Just for the sake of discussion, is it not possible to overcome this by making the visit methods return the appropriate super-classes? For example, in the case you mentioned we could just make the
visit
method corresponding to theColumn
of the appropriate visitor to return a genericExpression
object and the implementation of thevisit
method could think about what type ofExpression
should be returned. I think this would work for any given visitor, and the objects it is visiting. Of course, this would possibly make it difficult to comprehend why thevisit
methods return a different type. But otherwise, does this sound like plausible solution?That said, I still believe that modifying the existing visitor methods would place a huge migration burden on the users. To overcome this I think we can re-consider the following which was suggested before:
That would of course double the amount of visitor classes but at least it would not introduce any migration burden on the existing users. Also, having separate visitor classes would ensure that we don't add any additional (unrelated) responsibility to the
visit
methods. IOW, it would ensure SRP.wumpz commentedon Feb 6, 2020
So how to overcome this problems of the visitor pattern? Any ideas?
SerialVelocity commentedon Feb 10, 2020
I agree with @sivaraam but would go one step further and make the extra visitor generic:
This would:
implements GenericStatementVisitor<Statement>, GenericExpressionVisitor<Expression>
, etc.T
set toList<TableName>
(this has the added benefit of easily making the class thread-safe because you no longer have a field lying around).AnEmortalKid commentedon Feb 29, 2020
Would it be possible to invert things for consumption sake. Right now we have
And the proposed change is:
What if we introduced the CopyVisitor as a lower level stack, so we could have:
Since this is java 8, we could use the
default
feature to make this at least easy for consumers?14 remaining items