Preferisco il codice di auto-documentazione sulla complessità ciclomatica?

2

Sono interessato a quale approccio preferire. Prendi in considerazione un codice che recupera una traduzione per un testo. Deve rispettare questi vincoli:

  • Restituisce la traduzione solo se il testo verrà utilizzato su un'interfaccia utente. Se è usato in qualche altro posto (log di debug), restituisce la versione normalizzata del testo.
  • La normalizzazione del testo è costosa (risorse della cpu). Dovremmo farlo solo quando è richiesto.
  • Anche il caricamento della traduzione è costoso.
  • Se la traduzione per il testo è mancante o vuota, restituisci anche il testo originale normalizzato.

Primo approccio:

boolean useFallback = true;
if (textUsedForUi()) {
    final String translation = getNonEmptyTranslation(text);
    if (translation != null) {
        result.setText(translation);
        useFallback = false;
    }
}
if (useFallback) {
    result.setText(normalize(text));
}

String getNonEmptyTranslation(String text) {
    String translation = loadTranslation(text);
    if (StringUtils.isBlank(translation)) {
        return null;
    } else {
        return translation;
    }
}

Secondo approccio:

String translation = getTranslation(text);
if (translation != null) {
    result.setText(translation);
} else {
    result.setText(normalize(text));
}

String getTranslation(String text) {
    if (!textUsedForUi()) {return null;}
    String translation = loadTranslation(text);
    if (StringUtils.isBlank(translation)) {
        return null;
    } else {
        return translation;
    }
}

Il primo approccio indica chiaramente che la traduzione dipende da dove verrà utilizzato il testo e se è disponibile una traduzione. Ma devo introdurre una variabile helper per evitare la duplicazione del codice e assegnazioni non raccomandabili in condizioni:

String translation;
if (textUsedForUi() && (translation = getNonEmptyTranslation(text)) != null)

Non voglio fare affidamento sul valore precedente di result.getText() , quindi non posso utilizzarlo come flag se utilizzare o meno il fallback.

Il secondo approccio è chiaramente più semplice (riduzione della complessità ciclomatica). Ma nasconde la dipendenza da dove il testo è usato in una sub routine. Ciò riduce la natura di auto-documentazione del codice.

Quale approccio preferire?

    
posta Eduard Wirch 28.07.2016 - 10:13
fonte

3 risposte

4

Penso che la risposta dipenda dal fatto che getNonEmptyTranslation o getTranslation sarebbero più riutilizzabili, al di fuori di questo particolare pezzo di codice. Se nessuno dei due viene utilizzato al di fuori di questa routine, prenderei in considerazione l'idea di integrare la funzione. A parte questo, puoi sostituire la variabile useFallback con return :

if (textUsedForUi()) {
    final String translation = getNonEmptyTranslation(text);
    if (translation != null && StringUtils.isBlank(translation)) {
        result.setText(translation);
        return;
    }
}

result.setText(normalize(text));
    
risposta data 28.07.2016 - 19:42
fonte
7

La seconda versione è peggiore perché il metodo getTranslation() non fa necessariamente quello che indica il suo nome, ma cambia il suo comportamento a causa di un fattore totalmente non correlato. Il codice confuso e fuorviante è molto peggio di alcuni punti di CC.

    
risposta data 28.07.2016 - 21:34
fonte
1

La parte "nonEmpty" di getNonEmptyTranslation() è inutile. Si potrebbe verificare vuoto come facile come null. Né hai bisogno di una variabile di fallback. Quindi, sulla base di ciò, suggerirei

String translation = "";

if (textUsedForUi()) {
  translation = getTranslation(text);  // return empty if none

if (transation.length() > 0)
   result.setText(translation);
else
   result.setText(normalize(text));

Si potrebbe abbreviare il codice ancora di più con operatori terziari (? :) ma penso che sia più chiaro senza di essi.

    
risposta data 28.07.2016 - 21:25
fonte

Leggi altre domande sui tag