Pass the Dictionary, Please

Dave Brueck dave at pythonapocrypha.com
Mon Dec 9 17:06:47 EST 2002


On Mon, 9 Dec 2002, beno wrote:

> At 11:42 AM 12/9/2002 -0800, you wrote:
> >On Mon, 9 Dec 2002, beno wrote:
> >
> > > If one follows the Law of Demeter, doesn't it make more sense to pass
> > > dictionaries of data instead of containing data in classes that are called?
> >
> >No, that's no different than using C (structs only, no classes).
[snip]
> Would you mind helping me clarify what you just said by means of an example?

Sure. Here's a simplistic example: you write an app to track info about 
coworkers:

class Person:
  def __init__(self, lastName, firstName):
    self.lastName, self.firstName = lastName, firstName

  def GetFormattedName(self):
    return '%s, %s' % (self.lastName, self.firstName)

You use the GetFormattedName in several places. Later you decide to amend 
it also track people's nicknames, so you have the constructor take an 
additional parameter and modify GetFormattedName like this:

    return '%s, %s (%s)' % (self.lastName, self.firstName, self.nickname)

No caller of GetFormattedName has to change. Had you passed all the data 
around in just a dictionary then each time you display the formatted name 
you need to change it.

> ClientData() has method
> assembleGatewayData(paymentVehicle : int, **customerCreditInfo: dict, 
> **gatewayData: dict)
> which it calls upon itself.
> 
> ClientData() has method
> assembledDataPackageToGetCreditApproval(**sendToGateway : dict)
> which it calls upon Object Payment.
> 
> Payment() has method
> startProcessToGetCreditApproval(**sendToGateway : dict)
> which it calls upon Credit()
> 
> Credit() has method
> startGatewayContactToGetCreditApproval(**sendToGateway : dict)
> which it calls upon ConnectToBank_html()

I'd need far more context than this to understand what is going on in your 
program, much less make any intelligent suggestions, sorry.

> How would you tighten this up and stick to the Law of Demeter?

Well, I don't know enough about your program to know the degree to which 
you're sticking to LoD...

Also, the Law of Demeter is just a guide to implementation, not a true 
law, and going overboard on it is bad too. If two classes are conceptually 
close and have lots of interaction, then it's not necessarily wrong for 
them to know more about each other than two classes normally would. Going 
too far in one direction produces code like:

self.GetA().GetB().DoC(self.foo, objD.GetF())

(most likely the caller here knows too much those other objects)

...but too far in the other direction produces either interface bloat:

self.GetA().DoWorkC_OnYourBMember(self)
self.GetA().DoWorkC_OnYourEMember(self)

or it simply moves the problem somewhere else:

self.GetA().DoWork(self)

(where DoWork in turn knows too much about 'self')

A C struct is completely transparent, budding OO users often make their
classes overly opaque, and somewhere in between is the level that works
best.

-Dave





More information about the Python-list mailing list