È una cattiva pratica immagazzinare determinati valori come stringhe?

18

Questo è un titolo molto vago ma non riuscivo a pensare a un modo migliore di esprimerlo. Ma, ad esempio, pensiamo alla direzione in cui si muove un personaggio di un gioco. Sembra semplicemente sbagliato usare una stringa e poi fare cose come if(character.direction == "left") . Mi sembra che lasci troppo spazio per errori stupidi, come accidentalmente usando Left o l o qualsiasi cosa invece di left . I miei sospetti sono corretti? In tal caso, qual è il modo migliore per ottenere qualcosa di simile?

    
posta Cal7 16.12.2016 - 00:03
fonte

7 risposte

28

Se la lingua che stai utilizzando supporta l'uso di enumerazioni, le userei. Ti consente di limitare il numero di opzioni disponibili per un determinato tipo. per esempio. in Java:

public enum Direction {
    LEFT,
    RIGHT,
    UP,
    DOWN
}
    
risposta data 16.12.2016 - 07:08
fonte
12

È una pratica terribile usare stringhe letterali (o numeri magici) nel codice.

Le enumerazioni sono buone, o per lo meno usano costanti (le enumerate sono ovviamente solo un tipo di wrapper per una o più costanti correlate).

const string LEFT = "left"
if (someThing == LEFT) { doStuff(); }

Questo semplice switch ha così tanti vantaggi che non saprei neanche da dove cominciare a spiegarli (almeno non senza un po 'di caffè in più). Leggi i numeri magici, è lo stesso concetto esatto, applicato solo a un valore numerico anziché a un valore stringa.

Ecco un rapido ref, sono sicuro che ce ne sono altre centinaia: link

    
risposta data 16.12.2016 - 11:02
fonte
4

Risposta breve: Sì, le stringhe non sono l'ideale per qualsiasi attività diversa dall'archiviazione e dall'accesso a una sequenza di caratteri testuali e anche se i bit sottostanti di un'astrazione sono stringhe, ci sono dei vantaggi nel farli riferimento come variabili o costanti .

Risposta lunga: la maggior parte delle lingue offre tipi più vicini al dominio del tuo problema e, anche se non lo fanno, probabilmente hanno un metodo con cui puoi definire left come un'entità diversa da right (ecc. ecc.). Trasformarlo in una stringa utilizzando "left" è semplicemente la perdita del linguaggio e le funzionalità utili dell'IDE come il controllo degli errori. Anche se devi usare

left = "left";

o qualcosa di equivalente, ha dei vantaggi nell'usare la stringa quando ci si riferisce ad essa attraverso il codice. Ad esempio,

if (player.direction == Left)

verrebbe rilevato come errore in fase di compilazione (best case, java e così via) o essere contrassegnato da qualsiasi IDE che valga i suoi bit come errato (worst case, basic e così via).

Inoltre, avere la nozione di left come entità referenziabile ti aiuterà ad adattare qualsiasi direzione tu decida di seguire con il tipo di direzione. Utilizzando "left" , la direzione è impegnata a essere String . Se trovi o crei una migliore astrazione per il tipo, devi andare a caccia attraverso l'intero corpo del codice modificando ogni istanza di "left" . Una costante o variabile non richiede modifiche se il tipo è elaborato.

Il tipo che vuoi veramente è specifico per il tuo dominio. Qual è il tuo codice che pianifica di fare con il tuo left ? Forse vorrete specchiare l'asse x di una trama o di uno sprite rivolto verso sinistra o che avanza; in tal caso, potresti voler rendere left un oggetto con una proprietà o un metodo che rifletta tale comportamento, con il tuo oggetto right con il risultato opposto non speculare. Si può fare quella logica in un oggetto che rappresenta gli sprite o le trame, nel qual caso di nuovo si soffrirà per l'utilizzo di "left" invece di left per i motivi sopra indicati.

In Java (e probabilmente in altri linguaggi che ancora non conosco), enum è una buona alternativa perché in Java, enum è utile a final class con un insieme finito di istanze. Puoi definire i comportamenti se ne hai bisogno e puoi passare a una classe aperta senza problemi al di fuori del file che dichiara enum , ma molti linguaggi visualizzano un enum come tipo primitivo o richiedono una sintassi speciale da utilizzare. Che perde il enum hood per il codice che non ha nulla a che fare con esso e potrebbe dover essere corretto in seguito. Assicurati di aver compreso il concetto della tua lingua di enum prima di prendere in considerazione l'opzione.

    
risposta data 16.12.2016 - 18:45
fonte
2

Non hai specificato la tua lingua, ma per dare una risposta generica, dovresti usare le stringhe quando hai effettivamente bisogno del testo, non per rappresentare qualcosa. L'esempio che hai dato per esempio semplicemente non sarebbe accettabile nel software di produzione.

Ogni lingua ha vari tipi di dati di base e dovresti usare quello più appropriato per l'attività. Per usare il tuo esempio, potresti usare costanti numeriche per rappresentare stati diversi. Così a sinistra potrebbe avere un valore di zero e a destra sarebbe uno. Oltre al motivo che hai menzionato, i valori numerici occupano meno spazio (memoria) ed è sempre più veloce confrontare i numeri rispetto a confrontare più stringhe di caratteri.

Come è stato suggerito, usa le enumerazioni se la tua lingua lo consente. Nel tuo esempio specifico, è chiaramente la scelta migliore.

    
risposta data 16.12.2016 - 00:22
fonte
1

Usa semplicemente il tipo di dati che ha senso nella tua situazione.

L'uso del tipo string come una comunicazione inter / intra-applicazione sottostante non è intrinsecamente un problema. Infatti, a volte è preferibile utilizzare le stringhe: se si dispone di un'API pubblica, può essere desiderabile che i valori che entrano e escono dall'API siano leggibili. È più facile per le persone che usano la tua API imparare e fare il debug.

Il vero problema con il tuo codice sta nel ripetere il valore.

Non farlo:

if (direction == 'left') {
  goLeft();
}

Se hai fatto un errore di battitura in uno di questi condizionali o in altri usi di "sinistra" da qualche parte, potresti non essere in grado di eseguire efficacemente una ricerca in base al codice, perché hai sbagliato a digitarlo!

Invece, codifica contro un'enumerazione o una costante, a seconda di quale supporta il tipo di dati di cui hai bisogno nella lingua o nelle lingue che stai utilizzando.

Ciò significa che LEFT deve essere assegnato a una volta e una sola volta nella tua applicazione. E il resto del tuo codice dovrebbe sfruttare quegli enumerati o costanti:

const string LEFT = "left";

if (direction == LEFT) {
  goLeft();
}

Questo ti consente anche di cambiare più facilmente il tipo di dati che usi per le indicazioni stradali in seguito, se lo desideri.

    
risposta data 16.12.2016 - 20:37
fonte
1

È una cattiva pratica?

Probabilmente sì, ma dipende esattamente da quello che stai facendo, e anche dal linguaggio di programmazione che stai utilizzando.

Nel tuo esempio, possiamo dedurre che esiste una serie di valori piccoli e fissi per sempre che una direzione potrebbe prendere. In questo caso, non ci sono vantaggi nell'uso di una stringa e alcuni svantaggi definiti. Per questo esempio:

  • Un tipo di enum sarebbe preferibile, se il tuo linguaggio di programmazione lo supporta.
  • Altrimenti, le costanti integer denominate sono la strada da percorrere, con una singola definizione per le costanti.

Ma la risposta potrebbe essere diversa se l'insieme di valori è modificabile dinamicamente o deve evolversi nel tempo. Nella maggior parte delle lingue, la modifica di un tipo enum (ad es. Per aggiungere o rimuovere un valore) richiede una ricompilazione completa. Ad esempio, la rimozione di un valore enum in Java interrompe la compatibilità binaria. E lo stesso vale per le costanti integer denominate.

In scenari come questo potrebbe essere necessaria un'altra soluzione e usare le stringhe è una delle opzioni. (E potresti combinare stringhe letterali e costanti con nome ... se lo scenario comporta un nucleo fisso con estensioni dinamiche.)

Se stai implementando in Java, character.direction == "left" è una cattiva pratica per un altro motivo. Non dovresti usare == per confrontare le stringhe, perché sta testando le identità degli oggetti piuttosto che l'uguaglianza delle stringhe. (Funzionerebbe se potessi garantire che tutte le istanze della stringa "left" siano state internate, ma che richiede l'analisi di tutte le applicazioni.)

    
risposta data 17.12.2016 - 01:02
fonte
-3

Come suggerito, dovresti usare Enums. Tuttavia, usare semplicemente l'Enum come sostituto di Strigns non è sufficiente. Nel tuo particolare esempio, la velocità del giocatore dovrebbe essere effettivamente un vettore per mezzo della fisica:

class Vector {
  final double x;
  final double y;
}

Questo vettore dovrebbe quindi essere usato per aggiornare la posizione del giocatore ogni tick.

Puoi quindi combinarlo con un enum per una maggiore leggibilità:

enum Direction {
  UP(new Vector(0, 1)),
  RIGHT(new Vector(1, 0)),
  DOWN(new Vector(0, -1)),
  LEFT(new Vector(-1, 0));

  private Vector direction;

  Direction(Vector v) {
    this.direction = v;
  }

  public Vector getVector() { return this.direction; }
}
    
risposta data 16.12.2016 - 10:09
fonte

Leggi altre domande sui tag