User or UserManager ? Problems of Observer Pattern

Discussion in 'Python' started by Ò»Ê×Ê«, Apr 3, 2009.

  1. Ò»Ê×Ê«

    Ò»Ê×Ê« Guest

    #This is a real world problem I met.
    #
    #We have a database containing serveral tables, like : user, role,
    organization. Each 2 of them has m:n relationships. These relations
    are stored in association tables.
    #
    #Not we have to load all these data in memory to gain higher
    performances. We create 3 classes , User, Role, Organization, to hold
    these data.
    #
    #The question is : should I implement "add/delete/update" as methods
    of User, or should I add another class UserManager?


    #----------------
    # Choice 1
    #----------------

    user_dict = {}
    role_dict = {}

    class User:
    on_del_funcs = []
    roles = []

    def del(self):
    user_dict.pop(self.name)

    for f in self.on_del_funcs:
    f(self)

    # Using Observer Pattern to notify this user is deleted.
    def addUserDelListener(self, on_del_func):
    on_del_funcs.append(on_del_funcs)

    def delUserDelListener(self, on_del_func):
    on_del_funcs.remove(on_del_func)

    class Role:

    users = []

    def addUsser(self, user):
    self.users.append(user)
    user.roles.append(self)
    users.addUserDelListener(self.onUserDel)

    def onUserDel(self, user):
    self.users.remove(user)
    user.delUserDelListener(self.onUserDel)

    #----------------
    # Choice 2
    #----------------

    class UserManager:

    users = []

    @classmethod
    def delUser(cls, user):
    cls.users.remove(user)

    RoleManager.onUserDel(user)

    class RoleManager:

    roles = []

    @classmethod
    def onUserDel(cls, user):
    for r in cls.roles.items():
    r.users.remove(user)


    # These codes are not complete, but that's enough to show my question.
    # The first choice, which use Observer Pattern, has a very big
    problem.
    # When calling addUserDelListener, user got not only a callback
    function, it
    # also add reference count of role. So when we want to delete a
    role. We have
    # to carefully remove all *listener* hold by other objects, otherwise
    this role
    # will never be garbage collected.

    # Not a big problem for only 2 classes. But when there are 10
    *subject* classes which
    # Role want to *observe*, 10 listeners has to be removed when delete a
    role.
    # And if these *subject* have 5 different types of events, then 50
    listeners has
    # to be removed.

    # Actually I tried this approach once, and it is still a big headache
    for 10
    # programmers. ( The company I worked at that time hate any change to
    so-called
    # working code )



    # The second choice, which I am using right now, actually has nothing
    to do with
    # Object Oriented Designing. The manager classes are not real
    classes, just
    # container of methods. These User/Role classes are only container
    of data,
    # not behavior.
    #
    # For many times, I asked my self, "Is it too hard for me to see the
    power of
    # OO, or I have just never met a problem suitable for a OO resolution?"
    Ò»Ê×Ê«, Apr 3, 2009
    #1
    1. Advertising

  2. Re: User or UserManager ? Problems of Observer Pattern

    On Apr 3, 7:34 pm, Ò»Ê×Ê« <> wrote:
    > #----------------
    > # Choice 2
    > #----------------
    >
    > class UserManager:
    >
    > users = []
    >
    > @classmethod
    > def delUser(cls, user):
    > cls.users.remove(user)
    >
    > RoleManager.onUserDel(user)
    >
    > class RoleManager:
    >
    > roles = []
    >
    > @classmethod
    > def onUserDel(cls, user):
    > for r in cls.roles.items():
    > r.users.remove(user)


    Choice #2 is better, but it should not be implemented
    this way. Using a class as a pure container of methods,
    a big singleton, makes little sense, since you would
    be better off with a module and old fashioned procedural
    programming. You recognize this and are worried about this.
    You do not need to be worried to much,
    since there is nothing wrong with procedural design
    (but you should use modules not classes). If you want
    to be more object oriented, the first thing is to understand
    is that you define objects in order to pass them to
    other objects. For instance, you are using a global
    list of users as a class attribute, but I would
    just pass the list in the __init__ method, and
    make it an instance attribute. I also would make
    a RoleManager instance and pass it to the UserManager,
    so that it can be used directly. Or perhaps I would
    define a single UserRoleManager doing all the job.
    It depends.
    But all the point of OOP is to pass objects to other objects.
    It is not bad to think of a data object as of a record
    on steroids. Objects which are purely data and not
    behavior are the simplest and the best objects, start
    from them.
    There are also objects which are mostly behavior
    and nearly no data (the Manager objects here, which
    just act over collections of other objects). Those
    are more difficult to write. OTOH, nobody forces you
    to write the managers as objects. You may find easier
    to write a set of manager functions. This set of
    functions can later become methods of a Manager object,
    if it seems fit, but that must be done a posteriori,
    not a priori.
    Perhaps you should read some book like "Programming Python"
    by Ludz which has many examples of how to write OO applications
    in Python (I mean no offense, but indeed from you examples
    is seems to me that you are missing the point of OOP,
    as you are the first to recognize).
    HTH,

    Michele Simionato
    Michele Simionato, Apr 4, 2009
    #2
    1. Advertising

  3. Ò»Ê×Ê«

    Ò»Ê×Ê« Guest

    Re: User or UserManager ? Problems of Observer Pattern

    Thanks for your advice.

    I studied python from the tutorial and the library manual, and I think
    I am familiar enough with Python's grammar and API. That's why I
    never thought I need to read a book of Python.

    But if "Programming Python" also explains OO, I would be happy to read
    it.
    In fact, I am also planning to read again "Head First Object-Oriented
    Design and Analysis".
    I thought it's time for me to try again to find what is the *point* of
    Obejct.

    Anyway, this time I will be patient enough. I won't touch my code
    until I am sure find some way to improve it.

    On Apr 4, 1:14 pm, Michele Simionato <>
    wrote:
    > On Apr 3, 7:34 pm, Ò»Ê×Ê« <> wrote:
    >
    >
    >
    > > #----------------
    > > # Choice 2
    > > #----------------

    >
    > > class UserManager:

    >
    > > users = []

    >
    > > @classmethod
    > > def delUser(cls, user):
    > > cls.users.remove(user)

    >
    > > RoleManager.onUserDel(user)

    >
    > > class RoleManager:

    >
    > > roles = []

    >
    > > @classmethod
    > > def onUserDel(cls, user):
    > > for r in cls.roles.items():
    > > r.users.remove(user)

    >
    > Choice #2 is better, but it should not be implemented
    > this way. Using a class as a pure container of methods,
    > a big singleton, makes little sense, since you would
    > be better off with a module and old fashioned procedural
    > programming. You recognize this and are worried about this.
    > You do not need to be worried to much,
    > since there is nothing wrong with procedural design
    > (but you should use modules not classes). If you want
    > to be more object oriented, the first thing is to understand
    > is that you define objects in order to pass them to
    > other objects. For instance, you are using a global
    > list of users as a class attribute, but I would
    > just pass the list in the __init__ method, and
    > make it an instance attribute. I also would make
    > a RoleManager instance and pass it to the UserManager,
    > so that it can be used directly. Or perhaps I would
    > define a single UserRoleManager doing all the job.
    > It depends.
    > But all the point of OOP is to pass objects to other objects.
    > It is not bad to think of a data object as of a record
    > on steroids. Objects which are purely data and not
    > behavior are the simplest and the best objects, start
    > from them.
    > There are also objects which are mostly behavior
    > and nearly no data (the Manager objects here, which
    > just act over collections of other objects). Those
    > are more difficult to write. OTOH, nobody forces you
    > to write the managers as objects. You may find easier
    > to write a set of manager functions. This set of
    > functions can later become methods of a Manager object,
    > if it seems fit, but that must be done a posteriori,
    > not a priori.
    > Perhaps you should read some book like "Programming Python"
    > by Ludz which has many examples of how to write OO applications
    > in Python (I mean no offense, but indeed from you examples
    > is seems to me that you are missing the point of OOP,
    > as you are the first to recognize).
    > HTH,
    >
    > Michele Simionato
    Ò»Ê×Ê«, Apr 4, 2009
    #3
    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. Beatrice Rutger
    Replies:
    0
    Views:
    716
    Beatrice Rutger
    Jun 5, 2005
  2. Replies:
    6
    Views:
    740
    Chris Uppal
    Feb 13, 2006
  3. mem

    Observer pattern

    mem, May 18, 2004, in forum: C++
    Replies:
    2
    Views:
    533
    adiian
    Jun 4, 2007
  4. Paolino

    An observer pattern application.

    Paolino, Aug 18, 2005, in forum: Python
    Replies:
    0
    Views:
    339
    Paolino
    Aug 18, 2005
  5. Michael Schneider

    weakrefs to functions for observer pattern

    Michael Schneider, Nov 3, 2005, in forum: Python
    Replies:
    3
    Views:
    372
    Alex Martelli
    Nov 3, 2005
Loading...

Share This Page