Подключить класс, статический или экземпляр? - PullRequest
1 голос
/ 18 октября 2011

Я пытаюсь написать класс, который инкапсулирует логику в:

  • создание определенного URL-адреса на основе свойств другого класса и информации о хосте / порте из файла конфигурации
  • установить соединение
  • разбирает ответ

    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
    

Должен ли класс соединения быть набором статических методов / методов класса, которые возвращают данные, которые я ищу?

    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

или

Должен ли я построить объект, который содержит данные, которые мне нужны, чтобы я мог извлечь данные из него после подключения?

    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)

или даже гибрид?

    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

Ответы [ 2 ]

1 голос
/ 18 октября 2011

В идеале отдельный класс должен представлять собой четкий и сплоченный набор поведения. Иногда не всегда понятно, что лучше всего подходит, но в вашем случае я бы закодировал каждый ваш шаг как отдельный класс или функцию примерно так:

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)

Вы можете сделать то же самое с классом 'вместо функций, если любой из этих шагов требует больше внутренней логики, которая была бы лучше подана в конструкции класса. например логика разбора URL и ответа может иметь смысл в классах:

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()
0 голосов
/ 18 октября 2011

Хм ... ну почему бы не разбить его на два класса;один для извлечения информации из конфигурации, а другой для объединения этой информации с информацией из класса для выполнения задач, которые вам нужно сделать.В зависимости от того, что входит в эти задачи, возможно, имеет смысл разбить вещи еще дальше.

Кроме того, как отмечает Уилдак, интерфейс Foo, из которого извлекается информация, заставляет задуматься ... убедитесь, что"Combiner" не нужно знать больше, чем полезно для экземпляров Foo.

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 ):
        ...
...