È accettabile copiare e incollare codice lungo ma semplice invece di includerli in una classe o funzione?

29

Supponiamo che abbia un segmento di codice per connettersi a Internet e mostri risultati di connessione come:

HttpRequest* httpRequest=new HttpRequest();
httpRequest->setUrl("(some domain .com)");
httpRequest->setRequestType(HttpRequest::Type::POST);
httpRequest->setRequestData("(something like name=?&age=30&...)");
httpRequest->setResponseCallback([=](HttpClient* client, HttpResponse* response){
    string responseString=response->getResponseDataString();
        if(response->getErrorCode()!=200){
            if(response->getErrorCode()==404){
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setFontColor(255,255,255);
                alert->setPosition(Screen.MIDDLE);
                alert->show("Connection Error","Not Found");
            }else if((some other different cases)){
                (some other alert)
            }else
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setPosition(Screen.MIDDLE);
                alert->setFontColor(255,255,255);
                alert->show("Connection Error","unknown error");
            }
        }else{
            (other handle methods depend on different URL)
        }
}

il codice è lungo, ed è comunemente usato, ma il codice sopra non richiede cose extra come la funzione e la classe personalizzate (HttpRequest e Alert sono entrambi forniti dal framework per impostazione predefinita) e sebbene il segmento di codice sia lungo , è semplice e non complesso (è lungo solo perché ci sono pacchetti di impostazioni come url, dimensione del carattere ...), e il segmento di codice ha poche variazioni tra le classi (es .: url, dati di richiesta, casi di handle del codice di errore , casi normali di handle ...)

La mia domanda è: è accettabile copiare e incollare codice lungo ma semplice anziché avvolgerli in una funzione per ridurre la dipendenza del codice?

    
posta ggrr 25.01.2016 - 05:07
fonte

8 risposte

87

Devi considerare il costo del cambiamento. E se volessi cambiare il modo in cui vengono fatte le connessioni? Quanto sarebbe facile? Se disponi di un sacco di codice duplicato, la ricerca di tutti i luoghi che devono essere modificati potrebbe richiedere molto tempo e essere soggetta a errori.

Devi anche considerare la chiarezza. Molto probabilmente, dover guardare 30 righe di codice non sarà facile da capire come una singola chiamata a una funzione "connectToInternet". Quanto tempo andrà perso cercando di capire il codice quando è necessario aggiungere nuove funzionalità?

Ci sono alcuni rari casi in cui la duplicazione non è un problema. Ad esempio, se stai facendo un esperimento e il codice verrà gettato via alla fine della giornata. Ma in generale, il costo della duplicazione supera il piccolo risparmio di tempo di non dover estrarre il codice in una funzione separata .

Vedi anche link

    
risposta data 25.01.2016 - 05:15
fonte
54

No.

In effetti, anche il tuo codice "semplice" dovrebbe essere suddiviso in parti più piccole. Almeno due.

Uno per effettuare la connessione e gestire la normale risposta 200. Ad esempio, cosa succede se si passa da un POST a un PUT in alcuni casi? Cosa succede se stai facendo miliardi di queste connessioni e hai bisogno di un multi-threading o di un pool di connessioni? Avere il codice in un unico posto, con un argomento per il metodo, renderà questo molto più semplice

Allo stesso modo, un altro per gestire gli errori. Ad esempio, se si modifica il colore o la dimensione del carattere dell'avviso. Oppure hai problemi con le connessioni intermittenti e vuoi registrare gli errori.

    
risposta data 25.01.2016 - 06:44
fonte
18

is it acceptable to copy and paste ...

No.

Per me, l'argomento decisivo è questo:

... it is commonly used ...

Se usi una parte di codice in più di una posizione, quando cambia, devi cambiarla in più di un posto o si inizia a ottenere incongruenze - iniziano a verificarsi "cose strane" (cioè si introducono bug).

it is straightforward and not complex ...

E così dovrebbe essere tutto più facile da refactoring in una funzione.

... there are bundles of settings such as url, font size ...

E cosa cambiano gli amanti degli utenti? Caratteri, dimensioni, colori, ecc. Ecc.

Ora; in quanti posti dovrai cambiare lo stesso pezzo di codice per ottenere di nuovo tutti lo stesso colore / carattere / dimensione? (Risposta consigliata: solo uno ).

... the code segment has little variations among class (e.g.: url,request data, error code handle cases, normal handle cases...)

Variation = > parametro (i) di funzione.

    
risposta data 25.01.2016 - 13:39
fonte
8

Questo in realtà non ha nulla a che fare con il copia e incolla. Se prendi il codice da un'altra parte, al secondo prendi il codice è il tuo codice e la tua responsabilità, quindi non importa se è copiato o scritto da solo da solo .

Nei tuoi avvisi prendi qualche decisione sul design. Molto probabilmente le decisioni di progettazione simili dovrebbero essere prese per tutti gli avvisi. Quindi è probabile che tu debba avere un metodo da qualche parte "ShowAlertInAStyleSuitableForMyApplication" o forse un po 'più breve, e che dovrebbe essere chiamato.

Avrai molte richieste http con simile gestione degli errori. Probabilmente non dovresti duplicare la gestione degli errori ancora e ancora e ancora ma estrai la gestione degli errori più comuni. Soprattutto se la gestione degli errori diventa un po 'più elaborata (per quanto riguarda gli errori di timeout, 401 e così via).

    
risposta data 25.01.2016 - 10:13
fonte
6

La duplicazione è OK in alcune circostanze. Ma non in questo. Questo metodo è troppo complesso. C'è un limite inferiore, quando la duplicazione è più semplice del "factoring out" di un metodo.

Ad esempio:

def add(a, b)
    return a + b
end

è stupido, fai solo un + b.

Ma quando diventi solo un po ', un po' più complesso, di solito sei in linea.

foo.a + foo.b

dovrebbe diventare

foo.total
def foo
    ...
    def total
        return self.a + self.b
    end
end

Nel tuo caso, vedo quattro "metodi". Probabilmente in diverse classi. Uno per effettuare la richiesta, uno per ottenere la risposta, uno per visualizzare gli errori e una sorta di richiamo per essere chiamato dopo che la risposta ritorna per elaborare la risposta. Personalmente, probabilmente aggiungerei anche un "wrapper" di questo tipo per rendere più facili le chiamate.

Alla fine, per fare una richiesta web vorrei che una chiamata assomigliasse a qualcosa del tipo:

Web.Post(URI, Params, ResponseHandler);

Quella linea è ciò che avrei in tutto il mio codice. Poi, quando ho avuto bisogno di apportare modifiche a "come ottengo le cose", potrei farlo rapidamente, con molto meno sforzo.

Questo mantiene anche il codice DRY e aiuta con SRP .

    
risposta data 25.01.2016 - 18:51
fonte
0

In un progetto di qualsiasi dimensione / complessità, voglio essere in grado di trovare il codice quando ne ho bisogno per i seguenti scopi:

  1. Risolvi quando è rotto
  2. Modifica la funzionalità
  3. Riutilizzalo.

Non sarebbe bello, o partecipare a un progetto in corso o continuare a lavorare su un progetto per diversi anni e quando una nuova richiesta di "connettersi a internet e mostrare i risultati della connessione" era in una posizione facile da trovare a causa avere un buon design invece di fare una ricerca attraverso il codice per un httprequest? Probabilmente è più facile da trovare con Google comunque.

Non preoccuparti, sono il nuovo ragazzo e mi rifatterò su questo blocco di codice perché sono così sconvolto per essermi unito a questa squadra clueless con l'orribile base di codice o ora sono sotto pressione come il resto di voi e lo copierà e incollerà. Almeno manterrà il capo dalle mie spalle. Poi, quando il progetto sarà veramente identificato come un disastro, sarò il primo a raccomandare che lo riscriviamo copiando e incollando la versione nel quadro più recente e più grande che nessuno di noi capisce.

    
risposta data 25.01.2016 - 17:18
fonte
0

Una classe e / o una funzione è migliore, almeno secondo me. Per una volta, rende il file più piccolo che è un guadagno molto pesante se gestisci applicazioni web o applicazioni per dispositivi con poca memoria (IoT, vecchi telefoni, ecc.)

E ovviamente il punto migliore è che se hai qualcosa da cambiare a causa di nuovi protocolli, ecc. basta cambiare il contenuto della funzione e non molte volte hai messo questa funzione da qualche parte che potrebbe essere anche in file diversi che li rendono ancora più difficile da trovare e modificare.

Ho scritto un intero interprete SQL in modo da passare meglio da MySQL a MySQLi in PHP, perché devo solo cambia il mio interprete e tutto funziona, anche se questo è un esempio estremo.

    
risposta data 25.01.2016 - 11:56
fonte
-1

Per decidere se un codice deve essere duplicato o spostato su una funzione chiamata due volte, prova a determinare quale è più probabile:

  1. Sarà necessario modificare entrambi gli usi del codice nello stesso modo.

  2. Sarà necessario modificare almeno un uso del codice in modo che differiscano.

Nel primo caso, sarà probabilmente meglio avere una funzione che gestisca entrambi gli usi; in quest'ultimo caso, sarà probabilmente meglio avere un codice separato per i due usi.

Nel decidere se un pezzo di codice che verrà usato una volta dovrebbe essere scritto in linea o estratto in un'altra funzione, capire come descriverebbe il comportamento richiesto dalla funzione. Se una descrizione completa e accurata del comportamento richiesto dalla funzione sarebbe lunga o più lunga del codice stesso, spostare il codice in una funzione separata potrebbe rendere le cose più difficili da comprendere piuttosto che più semplici. Potrebbe ancora valere la pena farlo se c'è un'alta probabilità che un secondo chiamante debba utilizzare la stessa funzione, e che eventuali modifiche future alla funzione avranno bisogno di influenzare entrambi i chiamanti, ma in assenza di tale considerazione, la leggibilità favorirebbe la suddivisione delle cose al livello in cui il codice e una descrizione del suo comportamento richiesto sarebbero ugualmente lunghi.

    
risposta data 25.01.2016 - 20:48
fonte

Leggi altre domande sui tag