Style question: Nicknames for deeply nested objects

Discussion in 'Python' started by Gerald Britton, Jan 30, 2011.

  1. Hi all,

    Today I was thinking about a problem I often encounter.  Say that I
    have (seems I often do!) a deeply nested object, by which I mean
    object within object with object, etc.

    For example:

       x = some.deeply.nested.object.method(some.other.deeply.nested.object.value)

    Well, that's extreme but I've worked with code approaching that level
    of nested-ness.  Now, consider two scenarios:

    1. You need to call this thing many times with different arguments, so
    you wind up with:

       x = some.deeply.nested.object.method(some.other.deeply.nested.object.value1)
       y = some.deeply.nested.object.method(some.other.deeply.nested.object.value2)
       z = some.deeply.nested.object.method(some.other.deeply.nested.object.value3)

    2. You call it inside a loop:

       for item in some_iterable:
           x = some.deeply.nested.object.method(some.other.deeply.nested.object.value)

    For one thing, I find the long lines unattractive at best and
    error-prone at worst, especially if I also have

       some.other.deeply.nested.object.method

    that I might confuse with the first.  To make it look better I might do this:

       _o = some.deeply.nested.object
       _o.method(_o.value)

    which is fine, I suppose.

    Then, putting on my company hat, I remembered that, from VBA, you could do this:

       with some.deeply.nested.object
           .method(.value)
       end with

    I like the structure of this, since the subordinate block can be
    indented, which makes it stand out.  Also, it avoids temporary
    variables.

    So, I was thinking of how to get close to this in Python.  I came up
    with two approaches:

    1.

       _o = some.deeply.nested.object
       if 1:
           _o.method(_o.value)

    The "if 1:" forces me to indent the subordinate code, which sets it
    apart from the surrounding code. Note that I cannot just
    indent because I feel like it since Python is persnickety about indentation..

    2.

    for _o in [some.deeply.nested.object]:
           _o.method(_o.value)

    The "for..." sets up the iterator and forces me to indent the subordinate code.

    As an aside, approach 1 generates less byte-code since approach 2 sets
    up loop machinery which you don't really need in this case.

    I have a couple of questions:

    1. If you had to choose between approaches 1 and 2, which one would
    you go for, and why?

    2. What other techniques have you used in such a situation?


    --
    Gerald Britton
     
    Gerald Britton, Jan 30, 2011
    #1
    1. Advertising

  2. Gerald Britton

    rantingrick Guest

    On Jan 30, 11:51 am, Gerald Britton <> wrote:

    [...]

    > that I might confuse with the first.  To make it look better I might do this:
    >
    >    _o = some.deeply.nested.object
    >    _o.method(_o.value)
    >
    > which is fine, I suppose.


    It is very fine. And you "supposed" correctly!


    > Then, putting on my company hat, I remembered that, from VBA, you could do this:
    >
    >    with some.deeply.nested.object
    >        .method(.value)
    >    end with
    >
    > I like the structure of this, since the subordinate block can be
    > indented, which makes it stand out.  Also, it avoids temporary
    > variables.


    Yes it is a good idea! Well forgetting the horrendous VBA syntax this
    is. I brought this up many moons back as a feature request: Local
    Blocks. Here is how a pythonic local block would look

    with this as localvar:
    localvar.do_something()


    > So, I was thinking of how to get close to this in Python.  I came up
    > with two approaches:
    >
    > 1.
    >
    >    _o = some.deeply.nested.object
    >    if 1:
    >        _o.method(_o.value)


    bad idea!


    > 2.
    >
    >     for _o in [some.deeply.nested.object]:
    >        _o.method(_o.value)


    even worse idea!


    > I have a couple of questions:
    >
    > 1. If you had to choose between approaches 1 and 2, which one would
    > you go for, and why?


    neither! Stick with the original.
     
    rantingrick, Jan 30, 2011
    #2
    1. Advertising

  3. Gerald Britton

    Roy Smith Guest

    In article <>,
    Gerald Britton <> wrote:

    > 1. You need to call this thing many times with different arguments, so
    > you wind up with:
    >
    >    x = some.deeply.nested.object.method(some.other.deeply.nested.object.value1)
    >    y = some.deeply.nested.object.method(some.other.deeply.nested.object.value2)
    >    z = some.deeply.nested.object.method(some.other.deeply.nested.object.value3)


    I would probably turn that into:

    object = some.deeply.nested.object
    object.method(object.value1)
    object.method(object.value2)
    object.method(object.value3)

    i.e. make the temporary variable have the exact same name as the last
    component of the deeply nested thing you're trying to refactor. If the
    scope of use is small and the meaning is obvious from context, sometimes
    I'll shorten the name, i.e.

    obj = some.deeply.nested.object

    or even

    o = some.deeply.nested.object

    but I tend to avoid doing that. I'd rather be a little more verbose in
    preference to being a little more cryptic.
     
    Roy Smith, Jan 30, 2011
    #3
  4. On Sun, 30 Jan 2011 12:51:20 -0500, Gerald Britton wrote:

    > Hi all,
    >
    > Today I was thinking about a problem I often encounter.  Say that I have
    > (seems I often do!) a deeply nested object, by which I mean object
    > within object with object, etc.
    >
    > For example:
    >
    >    x =
    >    some.deeply.nested.object.method

    (some.other.deeply.nested.object.value)
    >
    > Well, that's extreme but I've worked with code approaching that level of
    > nested-ness.


    Then you're probably living in a state of sin, programming-wise, and you
    should stop doing that! You are violating the Law of Demeter. One dot,
    good. Two, acceptable. Three is a code smell. Four is a code reek.

    The Law of Demeter (more of a guideline than a law, really) says:

    If you want to get your dog to walk, call the dog. Don't talk to its
    legs, it confuses the dog and doesn't get it anywhere.

    http://en.wikipedia.org/wiki/Law_of_Demeter

    Another analogy: if you have to pay the paperboy for delivering the
    newspaper, you don't let him reach into your pocket, take out your
    wallet, open the wallet, take out whatever money he feels like, and put
    the wallet back.

    http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-
    boy/demeter.pdf


    Despite my comment above, the Law of Demeter is not *really* a dot-
    counting exercise, although that's a handy short-cut for detecting
    potential problems. It can also apply to other data structures. If you've
    every seen C or Pascal code where you have a pointer to a pointer to a
    pointer to a pointer to a pointer to a pointer to some data, you've seen
    a violation.

    Consider your example:

    some.other.deeply.nested.object.value

    This is very tightly coupled code: the caller, who knows about the object
    `some`, needs to know the internal details of not just `some` but also
    `other`, `deeply`, `nested`, and `object`. As a basic principle, this is
    poor design! Which would you rather deal with?

    car.start()

    car.ignition.turn(key).connect(car.starter(battery), car.spark_plug)

    In particular, using temporary variables merely disguises the problem:

    temp = some.other
    temp = temp.deeply.nested
    x = temp.object.value

    Even though you never use more than two dots, you still have tight
    coupling. The point of Demeter is not to save dots (they're a renewable
    resource) but to reduce tight coupling.


    --
    Steven
     
    Steven D'Aprano, Jan 30, 2011
    #4
    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.
Similar Threads
  1. Edward C. Jones

    Pickle vs. eval for deeply nested objects

    Edward C. Jones, Feb 18, 2004, in forum: Python
    Replies:
    0
    Views:
    495
    Edward C. Jones
    Feb 18, 2004
  2. Ori Y
    Replies:
    1
    Views:
    412
    Bob Ippolito
    Feb 28, 2004
  3. Kirk Strauser
    Replies:
    1
    Views:
    306
    Kirk Strauser
    Jun 11, 2004
  4. Kay Schluehr
    Replies:
    7
    Views:
    358
    Kay Schluehr
    Jan 20, 2006
  5. Stephen Hansen
    Replies:
    4
    Views:
    260
    Stephen Hansen
    Jan 31, 2011
Loading...

Share This Page