48

Я только недавно начал играть с архитектурой, управляемой событиями, исходя из довольно стандартного объектно-ориентированного мышления.Написание поддерживаемого кода, управляемого событиями

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

Я понимаю, что я новичок в этом мышлении развития, и не все мои объектно-ориентированные заботы переносятся. Существуют ли какие-либо ресурсы для написания поддерживаемого, понятного кода, управляемого событиями? Что делают люди, которые используют node.js или Twisted или Event Machine, об этом?

ответ

4

Я буду использовать Python в качестве примера, как это то, что я использую для создания огромных распределенных приложений прямо сейчас.

Twisted python допускает очень императивный стиль, используя либо inlinecallbacks, либо (слегка уродливые) отложенные стили генератора. Эти методы позволяют вам писать процедуры, которые используют код обратного вызова, управляемый событиями, который намного легче читать и понимать. Реализация превращает вашу функцию в ленивую последовательность, которая дает последовательность отсрочек.

В частности, вам не нужно создавать глубоко вложенный набор функций обратного вызова/lambdas/closures и вместо этого вместо этого управлять контролем функции в цикле событий в произвольных точках. Вы можете мысленно перемаркировать это как сопрограммы или совместную многозадачность, если хотите. Он выполняет свою работу. Пример может быть (с использованием нелицеприятного стиля deferredGenerator), как это:

@defer.deferredGenerator 
def foo(arg): 
    bar = nonBlockingFunction(foo) 
    baz = waitForDeferred(aFunctionThatReturnsADeferredToo(bar)) 
    yield baz #Returns control to the event loop 
    output = baz.getResult() #This gets the output of aFunctionThat...Too above 
    yield output #This is how we return a result instead of using return 

@defer.deferredGenerator 
def aFunctionThatReturnsADeferredToo(put_bar_here): 
    """Stuff happens here....""" 
    ...etc... 

Существует еще один пост здесь, что показывает метод inlineCallbacks, который чист, но требует Python 2.5 или более поздней версию (что означает не под Centos/RHEL 5 серии, которые я, к сожалению, застрял для своего приложения). Если вы можете использовать его, DO SO.

Как вы можете видеть, это похоже на старый учебный материал для питона, который вы знаете и любите, но его легко поддерживать без тонны вложенных функций и лямбда. Я все еще хочу, чтобы у python были блоки.

Что касается отладки, вы можете включить отладку открученного реактора, используя вызов defer.setDebugging (True) где-то в вашем коде инициализации. Это приложит исходную трассировку, которая вызвала бы исключение в вашем коде, чтобы вы могли тривиально увидеть, где произошла ошибка ACTUALLY. Просто не забудьте отредактировать оператор setDebugging перед тем, как начать производство, потому что это приводит к ОГРОМНОЙ сумме дополнительной интроспекции (смотрите ее в strace, если хотите, чтобы вы были в ужасе).

1

Очевидно, что существуют уже лучшие практики и модели, которые будут продолжать развиваться с течением времени.

Однако рассмотрите также возможность того, что запланированное программирование дает возможность «маленьким животным проектам» взаимодействовать друг с другом. Представьте себе мир, в котором тысячи распределенных отдельных проектов взаимодействовали в реальном времени через пользовательские обратные вызовы.

Пользователи и разработчики смогут перенастраивать веб-приложения и приложения поверх существующих протоколов сверху вниз, а не полагаться на существующий дизайн приложения. Тогда разработчики приложений могли бы сосредоточиться на отдельных случаях использования вместо того, чтобы предоставлять решения одного размера для всех или беспокоиться о любых возможных непредвиденных обстоятельствах.

Заканчивать Web Hooks и посмотреть, как услуги, такие как Twilio уже работают

4

Для Twisted, вместо использования старого отложенного генератора, я рекомендую inlineCallbacks; Он позволяет полностью писать код стиля блокировки и по-прежнему хорошо воспроизводить цикл событий.

@defer.inlineCallbacks 
def foo(arg): 
    bar = nonBlockingFunction(foo) 
    output = yield FunctionThatReturnsADeferredToo(bar) 
    defer.returnValue(output) #This is how we return a result instead of using return 
6

Martyn Loughran wrote an excellent short article полностью о предотвращении обратного вызова спагетти.

Что мне действительно понравилось в его статье - процесс улучшения спагетти во что-то приятное и чистое; сначала это может показаться немного формализованным, но когда вы видите конечный результат, я думаю, вы согласитесь, что он показывает реальную артистичность в чистом, разборчивом коде.

1

Мой единственный совет: think functional.

+2

заботиться о разработке? – keyle