Объектно-ориентированный дизайн Python с витыми оттенками - PullRequest
2 голосов
/ 10 августа 2010

Мой вопрос о том, как спроектировать код, который хорошо работает с объектно-ориентированным проектированием и асинхронными отложениями (вместо блокировки кода)

Ладно, два способа думать о разработке класса (любой из этих хороших проектов или я что-то забываю)

Первый путь

class Grooveshark(object):
def get_session(self):
    d = # implementation detail (gets page)
    d.addCallback(self.parse_session)# implmentation detail
    # all in all this goes through and sets self.session to the session value (it does not return it though; should I set it and return it?)
    self.session_time = time.time()
    return d
def get_country_id(self):
    # implmentation acts same as d just parses to diferrent id
    # also it grabs the same page; ANNOYING having to get the page twice ugh

def get_token(self):
    # relies on self.session being set
    d = # implmentation detail
    d.addCallback(self.parse_token)# implmentation detail
    # at the end of the day it sets self.token and then fires the deferred (same as session does not send it through the deferred, again should I seem repetitive?)
    return d
def construct_api_call(method, url, implmentation_arguments...)
    # checks if session is hour old
    if self.session_time - 3600 <= time.time() or self.session is None:

        # update
        d = get_session()
        # some how pass deferred or something
        d.addCallback(lambda ignored: self.get_country_id)
        d.addCallback(lambda ignored: self.get_token())
        d.addCallback(lambda ignored: self.construct_api_call(method, url, implmentation_arguments)
        # if error retry
        d.addErrback(lambda error: log.err(error))
        d.addErrback(lambda ignored: self.construct_api_call(method, url, implmentation_arguments)
        return d# would this work?  problem: with this how do I get it so I can do this whole update and do this again with the deferred I returned

    else:
        #implmentation details
        return d# fires when done with api call

Второй путь

class Grooveshark(object):
def get_session(self):

    d = # implmentation detail
    # differance this sends the session down the deferred callback and sets the instance var self.session (seems strange both modifying state and returning)

def get_token(self, session):
    d = # gets token but uses session argument NOT intance variable

def get_country_id # same as first class 

def construct_api_call(session, session_time, token, country_id, all the other args in above class):
    # problems it requires user of api to store session etc also how do I return if needs update right now I just error
    if self.session_time - 3600 <= time.time():
        raise RuntimeError("You need to update your session, ugh why does the user have to store the session ugh")

    else:
        # does what above class does as well

1 Ответ

1 голос
/ 04 февраля 2011

Краткий ответ: См. @defer.inlineCallbacks

Независимо от функционального или объектно-ориентированного программирования, суть и благословение использования Twisted заключается в том, что он использует управляемый событиями дизайн обратного вызова, позволяющийасинхронное выполнение программы.Распространенным наблюдением является то, что программирование, управляемое событиями, требует изменения стиля и компоновки кода - как показывает ваш вопрос.

Почти во всех случаях использование декоратора "@ defer.inlineCallbacks" в ваших методах или функциях поможет вамвитой код модульный и многоразового использования.Когда вы пишете исходный код, используя эту методологию, вы можете написать асинхронный код, который не «разделен» между многими функциями.Каждый раз, когда ваш кодовый блок должен переходить в следующий блок или «отложенный» сегмент, он использует команду yield.Это позволяет функции продолжать работу с того места, где она остановилась, когда отсроченное заканчивается.Это делает цепочку обратных вызовов похожей на обычный код блокировки.

Дополнительная справка

...