48

Sono appena iniziato a giocare con le architetture event-driven, proveniente da una mentalità orientata agli oggetti piuttosto standard.Scrittura mantenibile Event-Driven Codice

La prima cosa che ho notato è che la difficoltà di comprendere e tracciare i programmi sembra aumentare esponenzialmente con le dimensioni del programma. Mentre i piccoli progetti per animali domestici sono facili da seguire, sembra che il codice si trasformerà rapidamente in spaghetti.

Capisco che sono nuovo a questa mentalità di sviluppo e non tutte le preoccupazioni orientate agli oggetti portano avanti. Esistono risorse per scrivere codice gestibile basato sugli eventi gestibile e mantenibile? Che cosa fanno le persone che usano node.js o Twisted o Event Machine per questo?

risposta

4

userò Python come un esempio come quello è quello che sto usando per costruire enormi applicazioni distribuite al momento.

pitone intrecciato permette uno stile molto imperativo utilizzando sia inlinecallbacks o (un po 'più brutti) stili deferredGenerator. Questi metodi consentono di scrivere procedure che utilizzano codice di callback basato sugli eventi che è molto più facile da leggere e comprendere. L'implementazione trasforma la tua funzione in una sequenza pigra che produce una sequenza di differimenti.

In particolare, non è necessario costruire un insieme di nidificazione di callback funzioni/lambda/chiusura, e può invece cedere il controllo di una funzione di nuovo al ciclo di eventi in punti arbitrari. Puoi etichettarlo mentalmente come coroutine o multitasking cooperativo se vuoi. Ottiene il lavoro fatto. Un esempio potrebbe essere (utilizzando lo stile deferredGenerator più brutto) come questo:

@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... 

V'è un altro post qui che mostra il metodo inlineCallbacks, che è più pulita, ma richiede Python 2.5 o più recente (cioè non sotto CentOS/RHEL 5 serie, di cui sono tristemente attaccato per la mia app). Se puoi usarlo DO SO.

Come potete vedere, questo assomiglia alle cose imperative del vecchio pitone della scuola che conosci e ami, ma è SEMPRE più facile da mantenere senza un sacco di funzioni nidificate e lambda. Comunque desidero che Python abbia blocchi.

Come per il debug, è possibile attivare il debug del reattore a torsione utilizzando la chiamata defer.setDebugging (True) da qualche parte nel codice di inizializzazione. Questo allegherà il traceback originale che ha generato un'eccezione nel codice, in modo che sia possibile vedere banalmente dove si è verificato l'errore EFFETTIVAMENTE. Ricorda solo di ridimensionare la dichiarazione setDebugging prima di andare in produzione, perché si ottiene una quantità enorme di introspezione extra (guardala in silenzio se vuoi essere completamente inorridito).

1

Ovviamente ci sono già buone pratiche e modelli che continueranno a svilupparsi nel tempo.

Tuttavia, considerare anche la possibilità che la programmazione evento fornisca l'opportunità ai "piccoli progetti di animali domestici" di interagire tra loro. Immagina un mondo in cui migliaia di singoli progetti distribuiti interagiscono in tempo reale attraverso callback definiti dall'utente.

Gli utenti e gli sviluppatori saranno in grado di ricollegare il web e le applicazioni più di protocolli esistenti dall'alto verso il basso, invece di basarsi sulla progettazione di applicazioni esistente. I progettisti di applicazioni sarebbero quindi liberi di concentrarsi su casi d'uso individuali invece di fornire soluzioni di taglia unica o di preoccuparsi di ogni possibile contingenza.

Partenza Web Hooks e guardare come i servizi come Twilio sono già in funzione

4

Per Twisted, invece di utilizzare il vecchio deferredGenerator consiglio le inlineCallbacks; Ti consente di scrivere codice in stile blocco e continuare a giocare bene con il ciclo degli eventi.

@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 interamente su evitare gli spaghetti di richiamata.

Quello che mi è piaciuto molto del suo articolo è il processo di migliorare gli spaghetti in qualcosa di bello e pulito; all'inizio potrebbe sembrare un po 'formalizzato, ma quando vedi il risultato finale penso che sarai d'accordo sul fatto che mostra un vero talento artistico in un codice pulito, leggibile.

1

Il mio unico consiglio è pensare funzionale.

+2

cura di elaborare? – keyle