sasker
sasker

Reputation: 2321

Connect class, static or instance?

I am trying to write a class that encapsulates the logic to:

Should the connection class be a bunch of staticmethods/classmethods that return the data I'm looking for?

    class Bar(object):
        def build_url(self, Foo):
            # get host/port from config
            # build url based on Foo's properties
            return url

        def connect(self, url):
            # connects to the url that was built
            return Bar.parse_response(the_response)

        def parse_response(self, response):
            # parses response

or

Should I build an object that holds the data that I need so that I can extract the data from it after the connection?

    class Bar(object):
        def __init__(self, foo):
            self.url = 

        def _build_url(self):
            # build url based on Foo's properties            
            self.url = # do something with Foo

        def _parse_response(self, response):
            # parses response

        def connect(self, url):
            # connects to the url that was built
            self.raw_response = urllib.urlopen(self.url).read()
            self.parsed_response = self._parse_response(self.raw_response)

or even a hybrid?

    class Bar(object):
        def __init__(self, foo):
            self.foo = foo
            self.url = self._build_url()

        def _build_url(self):
            # build url based on Foo's properties            
            self.url = # do something with Foo

        def _parse_response(self, response):
            # parses response

        @classmethod
        def connect(cls, Foo):
            # connects to the url that was built
            bar = Bar(Foo)
            self._build_url()
            self.raw_response = urllib.urlopen(self.url).read()
            self.parsed_response = self._parse_response(self.raw_response)
            return bar

Upvotes: 1

Views: 1115

Answers (2)

shaunc
shaunc

Reputation: 5611

Hmm... well why not break it down into two classes; one for extracting info from config, and the other for combining that info with info from class to do the tasks you need to do. Depending on what goes into these tasks it might make sense to break things down even further.

Also, as Wilduck notes, the interface of Foo from which the info is retrieved bears thinking about... make sure that the "Combiner" doesn't need to know more than is healthy about Foo instances.

class Config( object ):
    '''
    read configuration from file
    '''

    configurations = {}
    def __new__( cls, config_file ):
        try:
            return cls.configurations[ config_file ]
        except KeyError:
            return super( Config, cls ).__new__( cls, config_file )

    def __init__( self, config_file ):
        if getattr( self, 'config_read', False ): 
            return
        self.read_config( config_file )
        self.config_read = True

    def read_config( self ):
        ...

class Combiner( object ):
    '''
    build url based on config and other object
    '''

    def __init__( self, config_file, foo ):
        self.config = Config( config_file )
        self.foo = foo

    def build_url( self ):
        ...

    def connect( self ):
        ...

    def parse_response( self ):
        ...

Upvotes: 0

Mark Gemmill
Mark Gemmill

Reputation: 5949

A single class should ideally represent a clear and cohesive set of behaviour. Sometimes it isn't always clear what the best fit is, but in your case, I would code each of your steps as a distinct class or function something like this:

def build_url(foo):
    # build the url from foo
    return the_url

def get_response(url):
    # do the connection, read the response
    return the_response

def parse_response(response):
    # parse the response
    return parsed_response

response = get_response(build_url(foo_object))
stuff_you_want = parse_response(response)

You can do the same thing with class' instead of functions if any of those steps require more internal logic that would be better served in a class construct. e.g. it might make sense for the url and response parsing logic to be in classes:

class Url(object):
    def __init__(self, foo):
        self._url = self._build_url_from_foo(foo)

    def _build_url_from_foo(self, foo):
        # do the url stuff
        return the_url

    def url_string(self):
       return self._url

class ResponseWrapper(object):
    def __init__(self, response):
        self._response = response

    def parse(self):
        # parsing logic here
        return parsed_response

response = ResponseWrapper(get_response(Url(foo)))
response.parse()

Upvotes: 1

Related Questions