Python Design Patterns - composition vs. inheritance

A.T.Hofkamp hat at se-162.se.wtb.tue.nl
Fri Nov 16 07:49:37 EST 2007


On 2007-11-15, snewman18 at gmail.com <snewman18 at gmail.com> wrote:
> inheritance when an object's relationship to another object is 'is-a'
> and composition when the relationship is 'has-a'.
>
> Since this is all new and I'm still learning, I was hoping someone can
> give me some pointers on best practices on applying these ideas. If my
> logic is incorrect on anything, please don't hesitate to tell me where
> I'm wrong - I'm completely open to any help offered.

>
> As a very simplified example, if I had two classes, Pet and Owner, it
> seems that I would not have Pet inherit from Owner, since a pet 'has
> an' owner, but not 'is an' owner. If this is correct, does my code
> below reflect this? I passed the owner object into the pet object's
> constructor - is this the right way to do it?

This is indeed one way. One of the things you enforce in this way that there is
no Pet object without an owner.

> Also, I've seen talk that ideally you shouldn't have too many "dots"
> in your method calls, instead using delegates to the methods and
> attributes. Can anyone elaborate on this? Ideally, should I be writing

As with most design stuff, they are right and they are also wrong. It's a
trade-off.

They are right in the sense that if you change the structure of your links, you
will break potentionally a lot of code. Imagine you have to ask a data base for
the owner rather than having a direct link. All "pet.owner" references will
need to be changed then. If you hide the connection inside your Pet, there is
only one place that needs to be changed.

They are wrong in the sense that it is not always appropiate for a Pet object
to perform such a function. By hiding "self.owner.address" inside Pet, you are
designing a smart pet that knows how to find the address of its owner.
Unfortunately, smarter also means more complex, and at some point you will
defeat the advantage of OO, namely spreading responsibilities, and having
several simple objects that work together to realize your application.

So there is a trade-off. There is no universal rule, it highly depends on your
application, your future plans, and the lifetime of the app (to name a few).

> getattr() methods so I can do pet.address instead of
> pet.owner.address? Should I be doing the same with owner's methods
> like I did with get_foo()?

I'd say no.
One of the 'rules' (guide lines) of Python is "Be explicit rather than
implicit" [1]. You may save a few dots, on the other hand, you obfuscate how
the link is realized (that is "pet.address" doesn't say it uses owner to make
the connection, unlike "pet.owner.address").
In the long run, the latter may be more important.


In general, I think you shouldn't need advanced trickery like __getattr__() for
your design. If you do, your design is most likely wrong.

[1]: The Zen of Python: http://www.python.org/dev/peps/pep-0020/


Sincerely,
Albert



More information about the Python-list mailing list