Come scegliere la soluzione più adatta per un problema date alcune scelte?

-1

Per illustrare la mia preoccupazione principale, iniziamo considerando un tipico problema "banale", il filtraggio dei dati e l'amp; parsing proveniente da un processo e scaricando le informazioni su qualcosa {gui console, file, stdout, ...}. Ora, diciamo che abbiamo un "codebase" comune (esempio minimo e molto semplificato):

class Listener:

    def on_process(self, line):
        print(line)


class CommandExecutor:

    def __init__(self, on_process=None):
        self.on_process = on_process

    def run(self):
        lines = [
            ".\a.py:9:9: F841 local variable 'foo' gives error1",
            ".\b.py:9:9: F842 local variable 'bar' gives error2",
            ".\c.py:9:9: F843 local variable 'foo' gives error3"
        ]

        for l in lines:
            if self.on_process:
                self.on_process(line=l)

Quindi, dopo un po 'di riflessione, diciamo che ho raccolto dalla dozzina di possibili soluzioni solo 3, cioè:

solution1

if __name__ == "__main__":
    l = Listener()

    def process_line(line):
        if "F842" in line:
            return False, None
        else:
            return True, f"{line} <---PARSED SUCCESFULLY"

    def on_process(**kwargs):
        line = kwargs["line"]
        valid_line, new_line = process_line(line)
        if valid_line:
            l.on_process(new_line)

    c = CommandExecutor(on_process)
    c.run()

Solution2

if __name__ == "__main__":
    l = Listener()

    def process_line(line):
        if "F842" in line:
            raise Exception("Invalid line")
        else:
            return f"{line} <---PARSED SUCCESFULLY"

    def on_process(**kwargs):
        try:
            line = kwargs["line"]
            new_line = process_line(line)
            l.on_process(new_line)
        except Exception as e:
            pass

    c = CommandExecutor(on_process)
    c.run()

SOLUTION3

if __name__ == "__main__":
    l = Listener()

    def check_line(line):
        if "F842" in line:
            return False
        else:
            return True

    def parse_line(line):
        return f"{line} <---PARSED SUCCESFULLY"

    def on_process(**kwargs):
        line = kwargs["line"]
        if check_line(line):
            l.on_process(parse_line(line))

    c = CommandExecutor(on_process)
    c.run()

E dopo che alcuni pensieri hanno concluso che:

  • Soluzione1: è quella meno pitone, la più pericolosa di tutto il set ma probabilmente la "più veloce" (microottimizzazione)
  • Soluzione2: è "più pulito" di solution1 ma probabilmente sta facendo troppo, non ha una corretta separazione delle preoccupazioni
  • Soluzione3: probabilmente è il codice più pulito ma sarà piuttosto prolisso e forse non offre troppi vantaggi

Sono abbastanza interessato a sapere se c'è un evidente "miglior candidato" dal gruppo di soluzioni di cui sopra ... o se c'è una soluzione migliore di quelle proposte.

Il fatto è che io tendo a perdere tempo quando scelgo una soluzione per risolvere un problema specifico specifico perché di solito trovo molte soluzioni ... In effetti, ho appena postato 3 possibili modi, ma nella mia testa ne ho poche dozzine ... E questo è davvero brutto perché ovviamente è una grande perdita di tempo e una grande indicazione che non conosco il modo migliore per affrontare un particolare problema. Mi piace quando posso scegliere una soluzione di codifica il più presto possibile

Quindi la domanda qui sarebbe, come decidere con quale soluzione astratta rimanere fedele prima di iniziare a usarla ampiamente nelle app? Vuoi veramente evitare di refactoring il meno possibile quando il numero di app che utilizzano una particolare soluzione è cresciuto così nel mio libro sembra che valga la pena di dare una giusta quantità di pensiero nelle fasi iniziali prima di aumentare di livello (voglio dire, estendere la tua app usando eredità, composizione, plugin, ...).

    
posta BPL 07.07.2018 - 16:48
fonte

2 risposte

3

Lo stai pensando troppo. Nessuna delle soluzioni che ci hai fornito è migliore delle altre date le informazioni che abbiamo. Questo codice è abbastanza piccolo per non meritare il tempo a cui pensare. Se questo codice si trovava nel ciclo più interno di un'operazione di elaborazione complessa e hai riscontrato un collo di bottiglia nelle prestazioni o una fonte di bug, allora, e solo allora, dovresti preoccuparti se è il modo ottimale di scriverlo per la tua situazione. Se hai trovato che hai bisogno di un codice molto simile con piccole differenze in dozzine di punti del tuo codice, varrebbe la pena dedicare del tempo a vedere se il refactoring avrebbe reso il tuo codice migliore. Ma finché non sai che questo codice non è ottimale, misurandolo, non dovresti preoccuparti troppo di queste decisioni minori.

    
risposta data 07.07.2018 - 18:24
fonte
0

Perché e quando smettere

Chiedi perché hai trovato una soluzione. Corollario, cosa ti ha spinto a cercare un'altra soluzione?

Off hand ho due ragioni per cercare alternative. Innanzitutto per trasmettere meglio significato e intenzione. Secondo per conformarsi al design generale. No? Potrebbe essere un cambiamento fine a se stesso ed è ora di smettere.

Dov'è l'architettura?

La differenza tra un booleano e un'eccezione ha profonde implicazioni e l'una o l'altra deve lavorare contro il progetto più grande. Ecco allora, c'è un altro cartello che è ora di smettere.

Rilevare un'eccezione a monte solo per "passare" mi dice che non esiste un vero punto di riferimento. Le eccezioni non sono la struttura di controllo di base. Inoltre, in questo caso, ha perso l'opportunità di aggiungere contesto all'eccezione: dove viene attivato e nei livelli intermedi mentre bolle. Questi strati hanno un qualche significato - contesto - no? Sia booleano che eccezionale, deve essere eseguito in modo coerente ovunque. Proprio come "costantemente ovunque" è ridondante, così come la dicotomia eccezione / booleana. Per riflettere tra un'eccezione e un booleano questo profondo nei dettagli mi dice che c'è un buco nel design.

    
risposta data 08.07.2018 - 06:59
fonte