La duplicazione dei file evita di programmare la ramificazione di un pattern buono o anti?

7

per esempio, supponiamo di dover suonare suoni diversi in base al "grado":

elenco file:

fairSound.mp3
goodSound.mp3
excellentSound.mp3

codice:

showResult(grade){
  if(grade==0 || grade==1){
    SoundUtility.play(fairSound);
  }else if(grade==2 || grade==3){
    SoundUtility.play(goodSound);
  }else if(grade==4){
    SoundUtility.play(excellentSound);
  }
}

ma non voglio alcuna ramificazione in questo caso, quindi la mia domanda è, è un buono o un anti pattern per duplicare i suoni:

elenco file:

sound0.mp3 (copy from fairSound.mp3)
sound1.mp3 (copy from fairSound.mp3)
sound2.mp3 (copy from goodSound.mp3)
sound4.mp3 (copy from goodSound.mp3)
sound4.mp3 (excellentSound.mp3)

in modo che non abbia bisogno di scrivere alcun caso di diramazione nel programma in questo caso:

showResult(grade){
  SoundUtility.play(sound[grade]);
}

? Sta violando il principio DRY?

Nota: anche io non voglio qualcosa di simile:

var arr=[fairSound.mp3,fairSound.mp3,goodSound.mp3,goodSound.mp3,excellentSound.mp3];

nel mio codice perché quando voglio cambiare il grado 0 per giocare a fairSound.mp3, devo ancora modificare il codice

    
posta mmmaaa 02.11.2018 - 06:21
fonte

6 risposte

23

Se cambiando i file audio per ogni singolo grado senza modificare il codice è il requisito qui, vorrei esternalizzare la configurazione (mappatura).

Crea voci nel meccanismo di configurazione (file di configurazione o database) che contengono i nomi dei file audio per ogni grado.

Invece di duplicare i file audio, preferirei elencare più volte lo stesso nome del file.

Esempio per un file .ini:

[resultSounds]
0=fairSound.mp3
1=fairSound.mp3
2=goodSound.mp3
3=goodSound.mp3
4=excellentSound.mp3

Leggi il tuo file di configurazione in una struttura dati (come un array o una mappa hash) e utilizzalo nel tuo metodo per trovare il file da riprodurre.

    
risposta data 02.11.2018 - 10:45
fonte
11

Non è né buono né cattivo, e sicuramente né uno "schema" né un "anti-pattern". Questo è tutto su quali sono i tuoi requisiti (non funzionali).

Hai scritto che vuoi essere in grado "di cambiare il grado 0 per riprodurre fairSound.mp3" (o un altro suono), senza cambiare il codice. Questo mi sembra come se fosse più o meno "per caso" che alcuni gradi hanno lo stesso suono. Quindi potresti trattarli come se quei soundfile fossero tutti diversi, nel qual caso è chiaro che dovresti duplicare i file mp3. Questo assicura che ogni volta che cambi il suono di un grado, gli altri voti non siano influenzati.

Tuttavia, se si desidera poter scambiare il file mp3 di un suono in un secondo momento e assicurarsi che tutti gli usi di questo particolare file vengano aggiornati anche in seguito (per tutti i gradi in cui è stato utilizzato), è necessario evitare duplicazione. Puoi ottenerlo facilmente con il tipo di array che hai menzionato nella tua domanda. Se vuoi evitare di dover cambiare il codice in seguito, metti l'array in un file di configurazione esterno al di fuori del codice.

TLDR; pensa al tipo di "modificabilità" che vuoi raggiungere: o ottimizza la possibilità di variazione per "grado" o la possibilità di variazione per "categoria suono".

    
risposta data 02.11.2018 - 08:18
fonte
2

Sta usando il carattere { due volte nel tuo programma una violazione di DRY? Spero che dirai, naturalmente no.

Quando valuta se qualcosa è una violazione di DRY, non devi solo considerare la somiglianza tra i pezzi di codice (o i file nel tuo caso), ma anche il motivo per cui sembra così simile.

Se sembra simile perché è necessario che sia lo stesso (la stessa funzionalità è codificata due volte, oppure i gradi 0 e 1 devono sempre suonare lo stesso suono), allora hai individuato una violazione di DRY.
Se oggi sembra simile, ma è completamente soddisfacente e si aspetta che possa entrare un nuovo requisito che lo farà essere diverso, la somiglianza è incidentale e non una violazione di DRY. Ad esempio, se è ragionevole che ci possa essere una richiesta per riprodurre suoni diversi per i livelli di grado 0 e 1, allora il fatto che i file sound0.mp3 e sound1.mp3 siano attualmente gli stessi non è un problema.

    
risposta data 02.11.2018 - 08:14
fonte
0

Quello che stai facendo è mappare il file audio con un identificatore nel tuo programma (letteralmente un indice nell'array). Questo non è un antipattern se ogni singolo file non è correlato con un altro.

Tuttavia ora stai introducendo la qualità del grado nell'equazione, quindi ti ritrovi con gruppi di suoni correlati l'uno con l'altro. Per risolvere questo problema, devi mappare la mappatura . Questo non ha senso, dato che la mappatura è arbitraria e dipende interamente da te su come strutturare, quindi ha senso riorganizzare in modo tale da tenerne conto.

Raggruppamento dei suoni logici

Un modo possibile potrebbe essere creare sottogruppi di suoni. Piuttosto che avere una serie di suoni [A, B, C, D], con A, B, C che sono qualità diverse dello stesso suono, puoi raggrupparlo come [[A, B, C], [D]]. Il voto che viene passato ora corrisponde direttamente all'indice nel tuo sottoarray. Si noti che D sta da solo. Se è richiesto un suono di alta qualità D, è possibile afferrare l'elemento con l'indice min(gradeArr.length - 1, gradeParam) o, in altre parole, acquisire la qualità di livello appropriata o il massimo disponibile altrimenti.

Approccio alla denominazione dei file

Un secondo approccio potrebbe dare un raggruppamento logico a file appartenenti alla stessa classe sonora. Quindi, per il suono "birdChirping", per rappresentare più qualità del suono, i file birdChirping_01.mp3, birdChirping_02.mp3 e birdChirping_03.mp3 potrebbero essere presenti nella stessa cartella. Nel tuo programma, hai solo "birdChirping" come nome. Dare il nome e il voto sonoro, è possibile recuperare e riprodurre il file appropriato. Nel tuo programma, invece di mappare ogni singolo suono, mappi solo il suono tipo (o in questo caso "birdChirping").

Questo è più dinamico in quanto non è necessario attivare il programma per ogni nuovo file, tuttavia è possibile che si verifichino dei problemi quando il chiamante chiede un livello sonoro che non esiste. Potrebbe essere necessario elencare tutti i file chiamati birdChirping _ *. Mp3 per sapere quali qualità sonore sono disponibili fatte in questo modo. Quindi, anche se più dinamico, è anche meno robusto, quindi dovresti tenerne conto.

Conclusione

Fai lavorare i dati per te. Non aver paura di riorganizzare in configurazioni più utili, se necessario. Hai ragione di pensare che il programma non dovrebbe avere brutte altre sezioni per il voto. Questo è come lo aggiusti. Fai in modo che il programma elabori i dati forniti senza ulteriori controlli o mappature.

Spero di aiutarti!

    
risposta data 02.11.2018 - 09:22
fonte
0

Le altre risposte sono eccellenti e sono particolarmente d'accordo con @Neil riguardo alla perdita di robustezza se il tuo codice ora si basa su file che potrebbero non esserci. Volevo solo aggiungere che, supponendo che tu abbia l'installazione di test di configurazione per gestire questi problemi (ad esempio arresto anomalo all'avvio se mancano tutti i file richiesti), direi che gestire i file in base ai nomi dei file non è una cattiva idea tutti.

Questo è un approccio particolarmente valido in un caso in cui sono necessari file diversi in ambienti diversi. Quindi ogni ambiente avrebbe una diversa configurazione di questi file, e per risparmiare spazio e semplificare la configurazione, non è necessario copiarli, ma piuttosto si può fare affidamento sui collegamenti simbolici. Ad esempio, potresti avere la seguente struttura di file, ispirata a quella utilizzata in Apache per le configurazioni del sito:

├── sounds-available
│   ├── excellentSound.mp3
│   ├── fairSound.mp3
│   └── goodSound.mp3
└── sounds-enabled
    ├── excellentSound.mp3 -> ../sounds-available/excellentSound.mp3
    ├── fairSound.mp3 -> ../sounds-available/fairSound.mp3
    └── goodSound.mp3 -> ../sounds-available/fairSound.mp3

Per riassumere, questo modello sposta la flessibilità della configurazione fuori dal programma nell'ambiente stesso, che può quindi essere automatizzata e controllata da un sistema di gestione della configurazione come Chef / Puppet / Ansible. Ci sono pro e contro a questo approccio, ma direi che è una scelta molto valida per alcuni casi d'uso.

    
risposta data 07.11.2018 - 23:30
fonte
-2

Vuoi sostituire un codice perfettamente fine (beh, dovrebbe essere un interruttore che gestisce il valore predefinito) con qualcosa di molto più complicato per seguire alcuni principi. Nel codice corrente, tutto è in un posto, quindi tutte le modifiche saranno localizzate.

E sì, se le tue specifiche cambiano, cambi il codice.

È un buon pattern o un anti-pattern? Non è affatto un modello. Nessun altro pensa che sia una buona idea.

    
risposta data 02.11.2018 - 08:52
fonte

Leggi altre domande sui tag