Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > User or UserManager ? Problems of Observer Pattern

Reply
Thread Tools

User or UserManager ? Problems of Observer Pattern

 
 
一首诗
Guest
Posts: n/a
 
      04-03-2009
#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?"
 
Reply With Quote
 
 
 
 
Michele Simionato
Guest
Posts: n/a
 
      04-04-2009
On Apr 3, 7:34 pm, 一首诗 <(E-Mail Removed)> 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
 
Reply With Quote
 
 
 
 
一首诗
Guest
Posts: n/a
 
      04-04-2009
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 <(E-Mail Removed)>
wrote:
> On Apr 3, 7:34 pm, 一首诗 <(E-Mail Removed)> 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


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Observer pattern mem C++ 2 06-04-2007 10:32 PM
Observer pattern issue cstratelos@gmail.com Java 6 02-13-2006 12:43 PM
weakrefs to functions for observer pattern Michael Schneider Python 3 11-03-2005 03:24 PM
An observer pattern application. Paolino Python 0 08-18-2005 08:24 AM
JMS or MVC (Observer pattern) in lightweight front end? Beatrice Rutger Java 0 06-05-2005 04:27 PM



Advertisments