Wormholes

Discussion in 'Java' started by Roedy Green, Sep 4, 2012.

  1. Roedy Green

    Roedy Green Guest

    I run into this sort of problem fairly often.

    I have a method x that calls method y through a long chain of
    intermediate calls.

    I decide to add a feature. Method x has access to information to
    decide if the feature should be implemented. Method y is where the
    implementation is.

    Somehow I must pass information down the long chain from x to y. This
    means changing the signatures of all the intermediate methods, and
    adjusting code to the new way. This can cause ripples incommensurate
    with the triviality of the change.

    I imagined some sort of wormhole to allow information in one place to
    simply be known somewhere else without the excess exposure of public
    variables or tediously arranging transport. I read about Eiffel a
    long time ago. IIRC you could provide a list of precisely who could
    see any given information.

    I wondered if anyone had thoughts on ways of tackling such a problem.
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    A new scientific truth does not triumph by convincing its opponents and making them see the light,
    but rather because its opponents eventually die, and a new generation grows up that is familiar with it.
    ~ Max Planck 1858-04-23 1947-10-04
     
    Roedy Green, Sep 4, 2012
    #1
    1. Advertising

  2. Roedy Green

    EricF Guest

    In article <>, Roedy Green <> wrote:
    >I run into this sort of problem fairly often.
    >
    >I have a method x that calls method y through a long chain of
    >intermediate calls.
    >
    >I decide to add a feature. Method x has access to information to
    >decide if the feature should be implemented. Method y is where the
    >implementation is.
    >
    >Somehow I must pass information down the long chain from x to y. This
    >means changing the signatures of all the intermediate methods, and
    >adjusting code to the new way. This can cause ripples incommensurate
    >with the triviality of the change.
    >
    >I imagined some sort of wormhole to allow information in one place to
    >simply be known somewhere else without the excess exposure of public
    >variables or tediously arranging transport. I read about Eiffel a
    >long time ago. IIRC you could provide a list of precisely who could
    >see any given information.
    >
    >I wondered if anyone had thoughts on ways of tackling such a problem.


    Having a long chain of intermediate calls sounds like a bad idea, lots of
    coupling. Can you refactor to get rid of or at least prune the chain?

    Eric
     
    EricF, Sep 4, 2012
    #2
    1. Advertising

  3. Roedy Green

    Arne Vajhøj Guest

    On 9/3/2012 9:12 PM, Roedy Green wrote:
    > I run into this sort of problem fairly often.
    >
    > I have a method x that calls method y through a long chain of
    > intermediate calls.
    >
    > I decide to add a feature. Method x has access to information to
    > decide if the feature should be implemented. Method y is where the
    > implementation is.
    >
    > Somehow I must pass information down the long chain from x to y. This
    > means changing the signatures of all the intermediate methods, and
    > adjusting code to the new way. This can cause ripples incommensurate
    > with the triviality of the change.
    >
    > I imagined some sort of wormhole to allow information in one place to
    > simply be known somewhere else without the excess exposure of public
    > variables or tediously arranging transport. I read about Eiffel a
    > long time ago. IIRC you could provide a list of precisely who could
    > see any given information.
    >
    > I wondered if anyone had thoughts on ways of tackling such a problem.


    If you pass a single big object instead of multiple simple types values,
    then there should not really be any impact down the chain.

    Arne
     
    Arne Vajhøj, Sep 4, 2012
    #3
  4. Roedy Green

    markspace Guest

    On 9/3/2012 6:12 PM, Roedy Green wrote:
    > I run into this sort of problem fairly often.
    >
    > I have a method x that calls method y through a long chain of
    > intermediate calls.



    I think I'm with Eric F. on this. Given some long chain of calls: X, A,
    B, C D, ... Y, can that be refactored so that X calls Y directly?

    void methodX() {
    A();
    }

    to

    void methodX() {
    AResult result = A();
    X( result, otherData );
    }

    I'm thinking that if your methods have to pass data through a long chain
    of calls, then the code is badly structured period. You might as well
    use the opportunity to refactor rather than trying to invent a "wormhole."

    I can think of at least one way to implement a wormhole. I'm just not
    going to go there because it's a terrible idea.
     
    markspace, Sep 4, 2012
    #4
  5. On 04.09.2012 06:00, markspace wrote:
    > On 9/3/2012 6:12 PM, Roedy Green wrote:
    >> I run into this sort of problem fairly often.


    That sounds like a warning sign for the way you structure code.

    >> I have a method x that calls method y through a long chain of
    >> intermediate calls.


    > I'm thinking that if your methods have to pass data through a long chain
    > of calls, then the code is badly structured period. You might as well
    > use the opportunity to refactor rather than trying to invent a "wormhole."


    If there are public library methods involved the situation is much
    worse: then Roedy probably cannot refactor but has to add functionality...

    > I can think of at least one way to implement a wormhole. I'm just not
    > going to go there because it's a terrible idea.


    I am pretty confident I know what you mean. I would even go as far as
    to calling usage of that "opening a can of worms". There are also
    negative side effects on testability...

    Kind regards

    robert


    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Sep 4, 2012
    #5
  6. Roedy Green

    Zermelo Guest

    Roedy Green <> writes:

    > Somehow I must pass information down the long chain from x to y. This
    > means changing the signatures of all the intermediate methods, and
    > adjusting code to the new way. This can cause ripples incommensurate
    > with the triviality of the change.


    Add a static variable to x accessible to y.
     
    Zermelo, Sep 4, 2012
    #6
  7. Roedy Green

    Lew Guest

    Zermelo wrote:
    > Roedy Green writes:
    >> Somehow I must pass information down the long chain from x to y. This
    >> means changing the signatures of all the intermediate methods, and
    >> adjusting code to the new way. This can cause ripples incommensurate
    >> with the triviality of the change.

    >
    > Add a static variable to x accessible to y.


    Why static?

    Why not a getter method?

    What about the Law of Demeter?

    --
    Lew
    Honi soit qui mal y pense.
    http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg
     
    Lew, Sep 4, 2012
    #7
  8. Roedy Green

    Stuart Guest

    On 9/3/2012 9:12 PM, Roedy Green wrote:
    >> I run into this sort of problem fairly often.
    >>
    >> I have a method x that calls method y through a long chain of
    >> intermediate calls.
    >>
    >> I decide to add a feature. Method x has access to information to
    >> decide if the feature should be implemented. Method y is where the
    >> implementation is.
    >>
    >> Somehow I must pass information down the long chain from x to y. This
    >> means changing the signatures of all the intermediate methods, and
    >> adjusting code to the new way. This can cause ripples incommensurate
    >> with the triviality of the change.
    >>
    >> I imagined some sort of wormhole to allow information in one place to
    >> simply be known somewhere else without the excess exposure of public
    >> variables or tediously arranging transport. I read about Eiffel a
    >> long time ago. IIRC you could provide a list of precisely who could
    >> see any given information.
    >>
    >> I wondered if anyone had thoughts on ways of tackling such a problem.


    On 9/4/12 4:34 AM Arne Vajhøj wrote:
    > If you pass a single big object instead of multiple simple types values,
    > then there should not really be any impact down the chain.
    >
    > Arne


    +1

    I had to write some generic measurement routines that would be the same
    for almost all of our measurement machines (strategy pattern). However,
    some machines would acquire additional data on the way, so I had to pass
    this additional information to the internal measurement routines and the
    additional measurement data back to the calling routines. I turned all
    parameters and results into objects that could be subclassed as needed.
    I think that this is nothing too unusual and scales pretty well.

    Regards,
    Stuart
     
    Stuart, Sep 4, 2012
    #8
  9. On 04/09/12 02:12, Roedy Green wrote:
    > Somehow I must pass information down the long chain from x to y. This
    > means changing the signatures of all the intermediate methods, and
    > adjusting code to the new way. This can cause ripples incommensurate
    > with the triviality of the change.


    Assuming that you can't improve your structure or refactor, a
    ThreadLocal might be appropriate as your wormhole.

    I've had to do this lately. The intermediate steps were recursive calls
    through a hierarchy. y was a custom implementation of a node nested in
    that hierarchy. x started off the recursive call.

    If I was only using the hierarchy once, for one call by x, I would have
    simply embedded the context in y. But the hierarchy was to be re-used,
    and y needed a different context for each call by x. Also, calls by x
    could be concurrent.

    However, I could guarantee that any single call by x would invoke y by
    the same thread. That allowed the context to be passed by a
    ThreadLocal, set by x just before the call.

    I suppose you could do something similar without threads, e.g.:

    class Context {
    Map<ContextLocal<?>, Object> items = new IdentityHashMap<>();
    }

    class ContextLocal<T> {
    void set(Context ctxt, T val) {
    ctxt.put(this, val);
    }

    T get(Content ctxt) {
    return (T) ctxt.get(this);
    }
    }

    Then you'd refactor once to pass Context through the chain. x creates a
    static ContextLocal<MyContext> myContext, and one Context ctxt for each
    call, and sets up myContext.set(ctxt, value) before the call. y calls
    myContext.get(ctxt) to get the value.

    --
    ss at comp dot lancs dot ac dot uk
     
    Steven Simpson, Sep 4, 2012
    #9
  10. Roedy Green

    Zermelo Guest

    Lew <> writes:

    > Why static?
    >


    Because a static variable is accessible from every methods. The same is
    not true for an instance variable.

    > Why not a getter method?
    >


    I think the OP can reach this solution by himself.

    > What about the Law of Demeter?


    The OP seems unwilling to restructure his code.
     
    Zermelo, Sep 4, 2012
    #10
  11. On Tue, 04 Sep 2012 16:09:54 +0200, Zermelo
    <> wrote:

    >Lew <> writes:
    >
    >> Why static?


    >Because a static variable is accessible from every methods. The same is
    >not true for an instance variable.


    The horror of global variables raises its head.

    [snip]

    Sincerely,

    Gene Wirchenko
     
    Gene Wirchenko, Sep 4, 2012
    #11
  12. Roedy Green

    Zermelo Guest

    Gene Wirchenko <> writes:

    > The horror of global variables raises its head.

    Without substantial refectoring I don't see any other solution.
     
    Zermelo, Sep 4, 2012
    #12
  13. Roedy Green

    Nigel Wade Guest

    On 04/09/12 02:12, Roedy Green wrote:
    > I run into this sort of problem fairly often.
    >
    > I have a method x that calls method y through a long chain of
    > intermediate calls.
    >
    > I decide to add a feature. Method x has access to information to
    > decide if the feature should be implemented. Method y is where the
    > implementation is.
    >


    What about Properties? They might provide a suitably "global" solution
    without too much coupling. A class with its own internal static
    Properties variable, and static methods to set/get the properties. Then
    method x can set any property it likes, and method y can attempt to read
    any property it likes. Unset properties return null, or a default value
    if you implement a getProperty(key, default) method.

    --
    Nigel Wade
     
    Nigel Wade, Sep 4, 2012
    #13
  14. Roedy Green

    Daniel Pitts Guest

    On 9/3/12 6:12 PM, Roedy Green wrote:
    > I run into this sort of problem fairly often.
    >
    > I have a method x that calls method y through a long chain of
    > intermediate calls.
    >
    > I decide to add a feature. Method x has access to information to
    > decide if the feature should be implemented. Method y is where the
    > implementation is.
    >
    > Somehow I must pass information down the long chain from x to y. This
    > means changing the signatures of all the intermediate methods, and
    > adjusting code to the new way. This can cause ripples incommensurate
    > with the triviality of the change.
    >
    > I imagined some sort of wormhole to allow information in one place to
    > simply be known somewhere else without the excess exposure of public
    > variables or tediously arranging transport. I read about Eiffel a
    > long time ago. IIRC you could provide a list of precisely who could
    > see any given information.
    >
    > I wondered if anyone had thoughts on ways of tackling such a problem.
    >


    If you arrange to pass-through a Parameter Object instead of a bunch of
    related parameters, this could solve your problem in many (not all) cases.

    The primary benefit of a Parameter Object is that you can add new fields
    (if they have sensible defaults) without a rippling change to all
    existing users of the method which takes the Parameter Object.

    There are other potential benefits as well. Your Parameter Object might
    have a nice "Builder" counterpart which makes it easier to specify
    optional parameters (using call-chaining for example).

    A special case of the Parameter Object is often called the Context.
    Many types of frameworks pass around a Context object to all methods.
    The HttpServletRequest object is such an example (a.k.a The Request
    Context). This is a more generic form than Parameter Object, and I don't
    suggest it for most usages, as you can end up with name-collisions, type
    problems, and other problems that can't be diagnosed at compile time.
     
    Daniel Pitts, Sep 4, 2012
    #14
  15. Roedy Green

    Daniel Pitts Guest

    On 9/4/12 8:46 AM, Zermelo wrote:
    > Gene Wirchenko <> writes:
    >
    >> The horror of global variables raises its head.

    > Without substantial refectoring I don't see any other solution.
    >

    The solution is substantial refactoring. Global variables introduce all
    kinds of problems, including but not limited to: Packratting,
    concurrency issues, debugging problems, "action at a distance" problems,
    etc...
     
    Daniel Pitts, Sep 4, 2012
    #15
  16. Roedy Green

    Roedy Green Guest

    On Tue, 04 Sep 2012 02:06:22 GMT, (EricF) wrote,
    quoted or indirectly quoted someone who said :

    >Having a long chain of intermediate calls sounds like a bad idea, lots of
    >coupling. Can you refactor to get rid of or at least prune the chain?


    I think I misdescribed this. x knows a detail of how the
    implementation should work. The code that uses that detail in y is at
    the end of a long chain, not the implementation itself. The
    implementation is quite complicated, so if I shortened the chain, I
    woulds have to increase the size of the methods on the way there.

    --
    Roedy Green Canadian Mind Products http://mindprod.com
    A new scientific truth does not triumph by convincing its opponents and making them see the light,
    but rather because its opponents eventually die, and a new generation grows up that is familiar with it.
    ~ Max Planck 1858-04-23 1947-10-04
     
    Roedy Green, Sep 4, 2012
    #16
  17. Roedy Green

    Lew Guest

    On Tuesday, September 4, 2012 7:10:01 AM UTC-7, Zermelo wrote:
    > Lew writes:
    >> Why static?

    >
    > Because a static variable is accessible from every methods. The same is
    > not true for an instance variable.


    Yes, it is, if the OP follows the advice given by other respondents to pass
    around a data object.

    And static variables carry grave risks.

    >> Why not a getter method?

    >
    > I think the OP can reach this solution by himself.


    Perhaps, but it's not what you recommended.

    >> What about the Law of Demeter?

    >
    > The OP seems unwilling to restructure his code.


    So you recommend a land-mine strategy to what, punish him
    for that?

    --
    Lew
     
    Lew, Sep 4, 2012
    #17
  18. Roedy Green

    Roedy Green Guest

    On Tue, 04 Sep 2012 08:47:18 +0200, Zermelo
    <> wrote, quoted or indirectly quoted
    someone who said :

    >Add a static variable to x accessible to y.


    it would have to have default scope. I hoping there was a technique
    that would behave like that, but which would not expose the variable
    to the entire package, when really only one method should use that
    variable.

    The techniques that I can think of are default scope variable or pass
    value down call chain to where it is used. Are there any others?
    --
    Roedy Green Canadian Mind Products http://mindprod.com
    A new scientific truth does not triumph by convincing its opponents and making them see the light,
    but rather because its opponents eventually die, and a new generation grows up that is familiar with it.
    ~ Max Planck 1858-04-23 1947-10-04
     
    Roedy Green, Sep 4, 2012
    #18
  19. Roedy Green

    David Lamb Guest

    On 03/09/2012 9:12 PM, Roedy Green wrote:
    > I run into this sort of problem fairly often.
    >
    > I have a method x that calls method y through a long chain of
    > intermediate calls.
    >
    > I decide to add a feature. Method x has access to information to
    > decide if the feature should be implemented. Method y is where the
    > implementation is.


    Are these methods in many separate classes and objects, or just one? If
    x, y, and all the intermediate c1..cN methods are in the same class,
    it's pretty easy to create a private (or protected) variable to be set
    by x and used by y (and presumably other equivalents of y if x has to
    invoke a different long chain of intermediate calls). Though this isn't
    thread-safe if multiple threads can call x.

    If y is a method of a separate class, there ought to be some way to
    return the object z on which y would be invoked and have x invoke
    z.y(...). But perhaps for some reason you can't revise the code that way.
     
    David Lamb, Sep 4, 2012
    #19
  20. Roedy Green

    Arne Vajhøj Guest

    On 9/4/2012 10:09 AM, Zermelo wrote:
    > Lew <> writes:
    >> Why static?

    >
    > Because a static variable is accessible from every methods. The same is
    > not true for an instance variable.
    >
    >> Why not a getter method?

    >
    > I think the OP can reach this solution by himself.


    If one decide to go the "global route", then a singleton with
    a non static getter seems to be a much nicer solution than a
    directly accessible static field.

    Arne
     
    Arne Vajhøj, Sep 5, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page