Reputation: 2321
I am trying to write a class that encapsulates the logic to:
parses the response
class Foo(object):
def __init__(self, a, b):
self.a = a
self.b = b
self.connect_id = None
self.response = None
def something_that_requires_bar(self):
# call bar
pass
# ...other methods
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
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
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