0

In the code below the User class needs to access a function get_user inside an instance of WebService class, as that contains other functions required for authentication with the web server (last.fm). Actual code is here.

class WebService:

    def __init__(self, key):
        self.apikey = key

    def get_user(self, name):
        pass # Omitted

class User:

    def __init__(self, name, webservice):
        self.name = name
        self.ws = webservice

    def fill_profile(self):
        data = self.ws.GetUser(self.name)
        # Omitted

The problem is that a reference needs to be held inside every ´User´. Is there another way of doing this? Or is it just me overcomplicating things, and this is how it actually works in the real world?

  • Why is `fill_profile` in User? Seems like it would make more sense to have a UserFactory that calls the service (or just processes a service response) and returns a User. – Silas Ray May 31 '12 at 20:14
  • Get user can return an object too I just put the actual logic of populating the attributes inside it because it seemed to me that `User` would need to process data anyway since there're other functions (like `get_top_albums` and `get_friends`) Should every function like this get it's own individual class too? –  May 31 '12 at 20:26
  • 1
    I second @gilesc in having GetUser return a User. As to handling things like get_top_albums and get_friends, that depends on how you want to model the system. If you don't want to cache the data locally, I'd say just call the service each time with a user ID. If you do want to cache the data locally, you could pass a User object to the method in WebService, then have the method populate the members of the User. You do have to make a design decision though to either have a WebService and a User (what would probably be best), or just a UserWebService. – Silas Ray May 31 '12 at 20:33
  • 1
    (Oops --accidental early submit before!) The other way of doing this is to use User as purely a data object and let WebService do any work that requires the WebService. I.e., User.get_friends() becomes WebService.get_friends(User). Likewise User.fill_profile is just merged into WebService.get_user (no need for a UserFactory; WebService IS the UserFactory). – gilesc May 31 '12 at 20:35
  • @sr2222 It seems like offloading every data generation to `WebService` is the best call here. Could you add your comment as an answer so I can accept it? –  May 31 '12 at 20:55

2 Answers2

2

You can certainly make the reference a static variable, if the web service object is the same for all users.

The syntax is:

class User:
    webservice = ...
...

You will then even be able to access it from User instances, but not to assign to it that way, that would require User.webservice syntax.

You are also getting good design alternatives suggested in the comments.

Community
  • 1
  • 1
Jirka Hanika
  • 13,301
  • 3
  • 46
  • 75
2

As requested: As to handling things like get_top_albums and get_friends, that depends on how you want to model the system. If you don't want to cache the data locally, I'd say just call the service each time with a user ID. If you do want to cache the data locally, you could pass a User object to the method in WebService, then have the method populate the members of the User. You do have to make a design decision though to either have a WebService and a User (what would probably be best), or just a UserWebService.

Silas Ray
  • 25,682
  • 5
  • 48
  • 63