I agree that there are some inconsistencies that we will need to work
through. I've taken a quick look at your three PRs and they seem reasonable
to me. I will officially review them soon.

On Thu, Apr 20, 2023 at 9:28 AM Oleksandr Porunov <
alexandr.poru...@gmail.com> wrote:

> Hi Ken,
>
> This is a great input. Thank you for the feedback. I believe you are right
> and we should check each case separately.
> That said, I was just worried if Graph Providers start blindly replacing
> steps with optimised versions of those steps then it becomes hard to track
> how it affects TinkerPop side optimization strategies and custom Steps.
> For example, let's take a look at any random optimization strategy on
> TinkerPop's side. For example EarlyLimitStrategy
> <
> https://github.com/apache/tinkerpop/blob/3.6-dev/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/EarlyLimitStrategy.java
> >
> .
> This strategy specifically has specific logic regarding usage of
> `RangeGlobalStep`.
> I.e.  `if (step instanceof RangeGlobalStep)`.
> If we check this step it's `final` (`public final class RangeGlobalStep`).
> In such a case nobody could actually easily replace this strategy without
> affecting `EarlyLimitStrategy` because we can't extend / overwrite
> RangeGlobalStep due to being final.
> Moreover `if (step instanceof RangeGlobalStep)` could actually be replaced
> by `if (RangeGlobalStep.class.equals(step.getClass()))` because we know
> there are no instances of `RangeGlobalStep` other than `RangeGlobalStep`
> itself, but the strategy tells that any instance of `RangeGlobalStep` is
> valid for optimization.
>
> The above relation of Optimizations and Steps affects many Step classes and
> many optimization strategies. Moreover it's kind of inconsistent that some
> of the steps are `final` and some of them are non-final even without having
> any other classes extending them in the TinkerPop codebase. For example,
> PropertiesStep and PropertyMapStep are non-final, but they don't have any
> classes extending them inside TinkerPop codebase. Logically Graph Providers
> extend and replace those steps, but then why do we keep those steps open if
> their codebase is bigger and more likely to be changed then the other
> `final` steps which are more likely to stay as is? (i.e. I would expect
> PropertyMap step to be changed more often then the IsStep for example, even
> so the latter one is non-final).
>
> I do agree with you that we should probably be curious of any methods /
> fields which we open with `protected` and don't blindly replace `private`
> fields / methods to `protected` fields / methods (as I did in the PR), but
> I doubt any Step should be `final`.
> Taking your input into account I think the way we could do, is:
> 1. Open all Step classes for extension by removing `final`. (do this in a
> single PR for all steps)
> 2. Move all `private` / `protected` utility methods out from Step classes
> into some utility classes. (do this case by case depending on the step)
> 3. Add public getter methods and / or public constructors to be able to
> copy necessary step fields from the original step into a new extending
> step. (do this case by case depending on the step)
>
> Thus, I believe the original PR
> <https://github.com/apache/tinkerpop/pull/2027> should be closed and
> separate PRs should be opened. So far I opened 3 separate small PRs to make
> extensions for the specific steps.
> https://github.com/apache/tinkerpop/pull/2029
> https://github.com/apache/tinkerpop/pull/2030
> https://github.com/apache/tinkerpop/pull/2031
>
> Would be great to know what you think about it.
>
> Thanks,
> Oleksandr
>
>
> On Thu, Apr 20, 2023 at 4:42 PM Ken Hu <k...@bitquilltech.com.invalid>
> wrote:
>
> > Hi Oleksandr,
> >
> > Thanks for bringing this idea to the community. However, I would be very
> > hesitant to include such a large change to TinkerPop. The Gremlin
> language
> > doesn't really have a specification which means that what a Step does is
> > more susceptible to change. I also feel like the current implementation
> of
> > Steps wasn't designed to be a stable and open interface so I would
> consider
> > them to be internal TinkerPop classes. From what I've heard, some of
> these
> > classes have intentionally been marked as final to prevent misusage which
> > is something that has happened in the past. Another concern I have is the
> > increased potential to break other's changes during refactoring or bug
> > fixing. It's easy to run into a situation where you make a fix for an
> issue
> > but don't realize that you have accidentally broken someone else's
> > implementation because you didn't know their code had a specific
> functional
> > dependency on the current implementation. This scenario is much more
> likely
> > to occur when you open up this many classes and there is no way to
> predict
> > what others will do with it.
> >
> > I think we can revisit this idea in the future once we have a firmer
> > specification for the Gremlin language. For now I think it is better to
> > take these changes on in a case by case basis.
> >
> > Thanks,
> > Ken
> >
> > On Tue, Apr 18, 2023 at 6:27 PM Oleksandr Porunov <
> > alexandr.poru...@gmail.com> wrote:
> >
> > > Hello everyone,
> > >
> > > I would like to get some opinion from the community regarding relaxing
> > > strictness of Step classes for better extensibility.
> > > The problem I encounter while making some optimizations for JanusGraph
> is
> > > that many steps are not quite extensible due to being marked as `final`
> > or
> > > simply having important fields as `private` without any `public`
> getters.
> > > Thus, making it complicated to replace original TinkerPop Steps with
> > Graph
> > > Provider's optimized Steps.
> > > In this discussion I would like to know community opinion on relaxing
> > Step
> > > classes strictness with making the following changes:
> > >
> > > 1. Remove `final` keyword from all Step classes, so that it would be
> > > possible to extend / overwrite them. Without this change Graph
> Providers
> > > might need to duplicate some logic during their custom Step
> > implementation
> > > (because they won't be able to extend an already existing step and
> > instead
> > > will need to re-implement it from scratch).
> > > Real example:
> > > We want to optimize the `ProjectStep` step to be able to query all
> > included
> > > traversals in parallel instead of sequentially (
> > > https://github.com/JanusGraph/janusgraph/issues/3559 ). Current
> > > TinkerPop's ProjectStep if `final`. Thus, if we want to replace this
> step
> > > with the optimized version of this step we will need to create our
> custom
> > > step which will have most of the logic duplicated with ProjectStep
> (most
> > > likely the only difference will be in the `map` step).
> > >
> > > 2. Convert all methods and fields from `private` to `protected` to be
> > able
> > > to access them in extended Step versions. In case the extended version
> > > overwrites some of the original TinkerPop functionality then the child
> > > class may potentially need to access some of the parent's class fields.
> > If
> > > those fields are private and don't have any getters then it might be
> > > complicated to retrieve that information (it will require using
> > > Reflection API).
> > > Having fields as `protected` will allow for extended child classes to
> > > access parent's fields.
> > > Another solution could be to have `protected` getters available for
> those
> > > fields.
> > > Real example:
> > > We would like to optimize PropertyMap step to pre-fetch elements
> > properties
> > > ( https://github.com/JanusGraph/janusgraph/issues/2444 ).
> > > For that we have to overwrite the `map` method and re-implement it
> (could
> > > be considered as anti-pattern, but it's complicated to do that
> > otherwise).
> > > In the overwritten method we may have some duplicated logic to be
> > > re-implemented and for that we will need to access parent fields /
> > methods.
> > > This was fixed for PropertyMap here (
> > > https://github.com/apache/tinkerpop/pull/2022 ), but there are many
> > other
> > > Steps which have private properties without getters.
> > >
> > > 3. (optional) Add public getters for fields which may be required to be
> > > copied from an original Step into an extension Step.
> > > Real example:
> > > Again about `PropertyMapStep`. Even though we changed the fields to
> > > `protected` (which now allows us to set and read those fields from the
> > > child class), we can't easily replace the original Step with the
> extended
> > > version of this Step because we will need to provide all the
> information
> > we
> > > have from the original Step into the new Step. Without having public
> > > getters available for those fields we won't be able to retrieve data
> for
> > > protected fields (unless we place the optimization class to the same
> > > package).
> > > I.e. If we implement a replacement Step for PropertyMap step we will
> need
> > > to access `tokens` and `traversalRing` from the original step, but we
> > won't
> > > be able to do that because currently PropertyMap doesn't have public
> > > getters for those fields. Thus, it will require us to place a new
> > > implementation class to the same package, so that we could access
> > protected
> > > fields.
> > >
> > > Overall, I think relaxing Step classes' strictness can benefit Graph
> > > Providers as they will be able to overwrite functionality they need.
> That
> > > said, due to small optimization strategies experience, I might miss
> some
> > > development patterns regarding developing optimizations. Potentially,
> it
> > > could be that replacing original Steps is a bad idea but it's hard for
> me
> > > to find good optimization solutions otherwise.
> > >
> > > These changes don't look to me as breaking changes because no code
> > changes
> > > will be required from current Graph Provides sides, but maybe I missed
> > > something.
> > >
> > > As for now, the JanusGraph community has plans to optimize usage of:
> > > PropertyMap, ElementMap, Coalesce, Has, Project steps. Thus it drived
> > this
> > > thinking and discussion.
> > >
> > > Ticket regarding relaxing step classes strictness:
> > > https://issues.apache.org/jira/browse/TINKERPOP-2927
> > > PR to relax step classes strictness:
> > > https://github.com/apache/tinkerpop/pull/2027
> > >
> > > Any feedback is appreciated.
> > >
> > > Best regards,
> > > Oleksandr
> > >
> >
>

Reply via email to