tags:

views:

40

answers:

1

3 class, A contains B, B contains C. So user want to use some service of C, there are two choice:

First, more encapsulation:

class A:
    def newMethod(self):
        self.b.newMethod()

class B:
    def newMethod(self):
        self.c.newMethod()

class C:
    def newMethod(self):
        #do something
        pass

a.newMethod()

Call service of c directly:

class A:
    pass

class B:
    pass

class C:
    def newMethod(self):
        #do something
        pass


b = a.b
c = a.c
c.newMethod()

Generally, what I learned from books told me that 1st choice is better.
But when C has many many methods to expose to outer user, 2nd choice seems to be more reasonable. And in the first design, A and B did nothing really useful.

What will you choose?

+3  A: 

Get your objects to do things for you, rather than asking them for their data and doing stuff with it.

If c in your example is exposing a lot of methods, I would suggest that you shouldn't be exposing these to a and your clients, but rather a and b should be working together to use these methods on behalf of the client.

A good indicator of a problem is a class that contains data, and provides getters for those data items, and the client code accessing that data and then performing work (DAOs excepted). In this (common) scenario the class most likely shouldn't be exposing that data (and perhaps breaking encapsulation), but rather doing the work for that client (either by having that functionality, or perhaps some injectable strategy object).

Check out the Law of Demeter (the linked document looks rather dry and academic, regrettably), which offers some good guidelines as to how objects and members should communicate.

Brian Agnew
Of course, generally, books will say that. But let me explain more. It's not only because C exposes many methods, it's because there are also C1, C2, C3, which are responsible to provide service for outter user code. Of course I could hide all B, C, C1 and add a lot of methods to A, so user code could not see the inner part of my library BUT, this really doesn't make sence. A didn't nothing but only pass parameters directly to B and other classes who IS responsible.According to SRP, A should have only one responsilbilty, A should not do B or C's job, it just give user a place to find B
lilyonwind
Another problem of hiding B/C/C1/C2 is that user code could not access event's of them. That means A has tranport every event in the library from inside to outside, a lot of useless jobs, I think.
lilyonwind