Come funziona il refactoring?

3

Diciamo che voglio avere una funzione per caricare i dati di un progetto sia da un json che da un percorso di file, la prima idea che mi viene in mente sarebbe avere un paio di funzioni come:

def load_project_from_json(json_data):
    ...

def load_project_from_path(path):
    with open(path) as f:
        load_project_from_json(f.read())

ma poi mi stavo chiedendo se forse sarebbe stato più conveniente realizzare entrambe le attività con una sola funzione, ad esempio:

def load_project(path_or_json)

Molti interroganti mi vengono in mente, ad esempio:

  • come fai a sapere quando è conveniente far esplodere una funzione in più o meno?

  • come posso giudicare se una funzione è una funzione "buona" o no?

  • è la funzione che segue SRP?

Domanda: quale metodo sistematico (insieme di passaggi o regole) potrebbe aiutarmi a estrarre tutte le responsabilità da qualsiasi funzione? La ragione principale è imparare come giudicare la qualità di qualsiasi funzione (non importa se stiamo parlando di funzioni libere o metodi di classe). In questo modo sarò in grado di dire se è necessario o meno il refactoring.

NS: quando dico che il metodo sistematico pensa in termini di semplificazione delle equazioni, se segui una serie di regole sarai in grado di raggiungere un punto in cui l'equazione non può essere ulteriormente semplificata, allo stesso modo mi piacerebbe sapere quali regole potrei applicare per sapere quando una funzione non può essere ulteriormente rielaborata. Spero che l'analogia abbia senso

    
posta BPL 13.03.2017 - 17:12
fonte

2 risposte

2

Avere una funzione carica da un file e un altro carico da JSON ha senso. Se la tua applicazione si trova in una situazione in cui questo è ambiguo - e in più punti - allora la terza funzione può essere aggiunta per rimuovere la replica della logica che determina quale formato è: File o JSON.

Fondamentalmente, avrai tutti e tre i casi in cui load_project(file_or_json) rileva se si tratta di un file e chiama il metodo appropriato:

def load_project(path_or_json)
  if os.path.exists(path_or_json):
     return load_project_from_path(path_or_json)
  else:
     return load_project_from_json(path_or_json)

I vantaggi:

  1. Posizione centralizzata del test indipendentemente dal fatto che qualcosa sia un percorso file o JSON

  2. È comodo da usare quando il chiamante non conosce la differenza

  3. Hai ancora funzioni esplicite quando fai conosci il formato

  4. È possibile ottimizzare il test. Invece di chiamare il file system, forse decidi di fare un rapido test Regex per vedere se è JSON (dopo tutto, quanti nomi di file inizieranno con { o [ caratteri?)

  5. Aderisci ancora al Principio di Responsabilità Unica, poiché la funzione load_project è responsabile della determinazione del formato. Le altre due funzioni sono responsabili del caricamento dai formati specifici.

risposta data 14.03.2017 - 13:17
fonte
1

In generale, una volta eliminati gli effetti collaterali dalle funzioni, idealmente non dovrebbe essercene mai stato prima , se le funzioni eseguono attività identiche, in lingue di digitazione dinamica o anatra , non c'è motivo per non refactoring in una singola funzione.

Allo stesso modo, se una grande porzione di ciò che due o più funzioni stanno facendo, ci può essere un ottimo caso per rimuovere quelle / quelle porzioni del codice a funzioni comuni, ad es. caricamento di diversi tipi di file in funzioni specifiche ma manipolazione dei contenuti in funzioni comuni.

Nelle lingue senza digitazione dinamica il tipo sicurezza spesso significa che hai bisogno di un codice duplicato, con tipi diversi ed è un'idea cattiva per indebolire la sicurezza del tipo per salvare del codice. Alcune lingue hanno i meccanismi di variante che consentono alle funzioni di operare su uno specifico sottoinsieme di tipi che possono essere utilizzati o, naturalmente, refactoring in classi in cui la classe base fornisce la funzionalità comune è spesso una buona idea ma può essere portata a eccesso - Ho visto un codice con 100s di classi ciascuna con circa 10 righe di codice in cui è quasi tanto male quanto avere una singola funzione di oltre 3000 righe duplicate in 3 file, (entrambi gli esempi erano degli stessi autori) .

Naturalmente in C ++, e in altri linguaggi, c'è l'idea di modelli che ti permettono, potenzialmente , di creare centinaia di classi / funzioni - ogni tipo di tecnologia sicuro - automaticamente.

    
risposta data 13.03.2017 - 20:27
fonte

Leggi altre domande sui tag