Quali modelli di progettazione potrebbero essere utilizzati qui?

2

Sto cercando di creare un bel design (preferibilmente pythonic) per il seguente caso d'uso.

Diciamo che ci sono tre servizi: A, B, C in più posizioni L1, L2, L3, ecc. Ogni servizio fornisce valori diversi, ad es. A restituisce a1, B restituisce b1, C restituisce c1.

L'attività consiste nell'eseguire periodicamente una funzione che recupera questi parametri da tutte le posizioni disponibili, esegue alcuni calcoli matematici (ad esempio, riassume) sui valori dei servizi corrispondenti e scrive i valori calcolati sui servizi in ogni posizione. Cioè.

for l in locations:
    as.append(getAfrom(l).get_a())
    bs.append(getBfrom(l).get_b())
    cs.append(getCfrom(l).get_c())

new_a = calculate(as)
new_b = calculate(bs)
new_c = calculate(cs)

for l in locations:
    getAfrom(l).write(new_a)
    getBfrom(l).write(new_b)
    getCfrom(l).write(new_c)

Il codice precedente lo fa in modo molto diretto (probabilmente non è così male), ma non riesce a ridimensionare se il numero di servizi o parametri aumenta.

Quali modelli di progettazione renderebbero questa soluzione più flessibile, estendibile (più parametri, più servizi)?

    
posta Sorantis 06.07.2015 - 23:23
fonte

1 risposta

1

Probabilmente vuoi usare qualcosa come il schema dei visitatori , o schema di strategia .

qualcosa di simile (assumendo alcuni refactoring):

services = [a,b,c] # add more as needed

accum_strat = lambda l,s: s.Find_Service(l).GetVal()
accum_list = [[] for x in range(len(services))]

for l in locations:
    for srv, lst in zip(services, accum_list):
        lst.append(accum_strat(l, srv)

calcd = [calculate(lst) for lst in accum_list]
write_strat = lambda l,s,v: s.Find_Service(l).write(v)

for l in locations:
    for s,v in zip(services, calcd):
        write_strat(l,s,v)

potresti persino rifattorizzare ulteriormente:

def visit_locations(func, args):
    for l in locations:
        for a in args:
            func(l,*a)

services = [a,b,c] # add more as needed

accum_strat = lambda l,s: s.Find_Service(l).GetVal()
accum_list = [[] for x in range(len(services))]
write_strat = lambda l,s,v: s.Find_Service(l).write(v)

visit_locations(lambda l,s,t: t.append(accum_strat(l,s)), zip(services, accum_list))

calcd = [calculate(lst) for lst in accum_list]

visit_locations(write_strat, zip(services, calcd))

Aggiungendo un nuovo servizio, è sufficiente estendere l'elenco dei servizi. Una nuova operazione aggiunge un'altra chiamata a visit_locations o qualsiasi altra informazione intermedia da calcolare.

questo potrebbe essere ulteriormente astratto:

... 
operations = [lamdba : visit_locations(...),
              lamdba : calcd=...,
              ...
             ]

for op in operations:
    op()

A seconda dei requisiti effettivi del tuo sistema, questo potrebbe essere un passo troppo lungo, o solo ciò che è necessario per il tuo sistema. Si potrebbe fare qualcosa di equivalente ma con le classi; questo esercizio sarà lasciato al lettore.

NB. Ho confuso il visitatore e i modelli di strategia, IIRC la differenza tra loro è principalmente il modo in cui vengono utilizzati.

    
risposta data 09.07.2015 - 02:35
fonte

Leggi altre domande sui tag