jeudi 25 mai 2017

Suggestion for design pattern or implementation

I am stuck at finding correct pattern or solving the following problem.

class Proxy:
    db_name = ''

    @property
    def cursor(self):
        return db_cursor(self.db_name)


class Profile:
    db_proxy = Proxy()

    def __init__(self, user_name, gender, **kwargs):
        self.user_name = user_name
        self.gender = gender
        # etc...

    @classmethod
    def create(cls, data):
        # create profile in database, and assing properties to object
        cls.db_proxy.cursor.execute('create user profile query')
        profile = cls(**data)
        return profile

    @property
    def is_male(self):
        return self.gender == 'male'

    @property
    def is_female(self):
        return self.gender == 'female'


class User:
    db_proxy = Proxy()

    def __init__(self, user_id, profile):
        self.user_id = user_id
        self.profile = profile

    @classmethod
    def create(cls, user_id, user_profile):
        cls.db_proxy.cursor.execute('create user query')
        profile = Profile.create(user_profile)
        user = cls(user_id, profile)
        return user

    @property
    def is_male(self):
        return self.profile.is_male

    @property
    def is_female(self):
        return self.profile.is_female


class Server1:
    def __init__(self):
        # database proxy should connect to 'server1_db'
        pass

    def create_user(self, user_id, user_profile):
        user = User.create(user_id, user_profile)

        return {
            'id': user.user_id,
            'name': user.profile.user_name,
            'gender': user.profile.gender,
            'success': True
        }


class Server2:
    def __init__(self):
        # database proxy should connect to 'server2_db'
        pass

    def create_user(self, user_id, user_profile):
        user = User.create(user_id, user_profile)

        return {
            'UserId': user.user_id,
            'UserName': user.profile.user_name,
            'Gender': user.profile.gender,
            'Status': 'OK'
        }

1) I want to have User/Profile one implementation, so they would be like core logic to process users and their profiles. Also it has access to database "proxy".

2) Different Server's are connected to separate databases with separate settings on each, however the way User/Profile are stored and queried should remain the same.

3) After Server instantiated, i need to connect to required database, that is set in __init__ method of the server.

4) After request received on server, i want to be able to user User/Profile instances as described in create_user() method of Server's, and so processing users will use correct databases

5) User/Profile, Proxy, Server1, Server2 are implemented in different modules.

6) The main thing is to be able to use User/Profile instances without providing it db connection to methods, like this create_user(db, *args), and it would itself handle db connection set in Proxy or kind of.

I came up with idea to set db connection in Server's __init__ method, like this:

...
def __init__(self):
    User.db = db_connection()
    Profile.db = db_connection()

However it wont work, because db would be overrided after another Server initialized.

Also i tried to create UserProxy/ProfileProxy for every server and use them:

class UserProxy(User):
    db = None

class ProfileProxy(Profile):
    db = None

class Server:

    def __init__(self):
        UserProxy.db = db_connection()
        ProfileProxy.db = db_connection() 
    ...

    def create_user(self, **kwargs):
        user = UserProxy.create_user(**kwargs)

It would work for User, but obviously not for Profile, because inside users module, where User and Profile classes are, User are using Profile class and doesnt know anything about which db to connect to.

7) I am not sure if i described it understandable enough, not an english native speaker.

8) Maybe it looks too complicated, but maybe there's some kind of desing pattern available to accomplish this.

Aucun commentaire:

Enregistrer un commentaire