Stringhe di hardcoding che non cambieranno mai

39

Quindi, nei miei sforzi di scrivere un programma per coniugare verbi (algoritmicamente, non attraverso un set di dati) per il francese, ho riscontrato un piccolo problema.

L'algoritmo per coniugare i verbi è in realtà abbastanza semplice per i casi di verbi 17-o-così, e gira su un modello particolare per ogni caso; quindi, i suffissi di coniugazione per queste 17 classi sono statici e (molto probabilmente) non cambieranno presto. Ad esempio:

// Verbs #1 : (model: "chanter")
    terminations = {
        ind_imp: ["ais", "ais", "ait", "ions", "iez", "aient"],
        ind_pre: ["e", "es", "e", "ons", "ez", "ent"],
        ind_fut: ["erai", "eras", "era", "erons", "erez", "eront"],
        participle: ["é", "ant"]
    };

Questi sono suffissi flessivi per la più comune classe di verbo in francese.

Ci sono altre classi di verbi (irregolari), le cui coniugazioni rimarranno molto probabilmente statiche per il prossimo secolo o due. Dal momento che sono irregolari, le loro coniugazioni complete devono essere incluse staticamente, perché non possono essere coniugate in modo affidabile da un modello (ci sono anche solo [dai miei conti] 32 irregolari). Ad esempio:

// "être":
    forms = {
        ind_imp: ["étais", "étais", "était", "étions", "étiez", "étaient"],
        ind_pre: ["suis", "es", "est", "sommes", "êtes", "sont"],
        ind_fut: ["serai", "seras", "sera", "serons", "serez", "seront"],
        participle: ["été", "étant"]
    };

Potrei mettere tutto questo in XML o anche JSON e deserializzare quando deve essere usato, ma c'è un punto? Queste stringhe fanno parte del linguaggio naturale, che cambia, ma a un ritmo lento.

La mia preoccupazione è che facendo le cose nel modo "giusto" e deserializzando qualche fonte di dati, non ho solo complicato il problema che non bisogno di essere complicato, ma ho anche completamente rintracciato sull'intero obiettivo dell'approccio algoritmico: per non utilizzare un'origine dati! In C #, potrei semplicemente creare una classe sotto namespace Verb.Conjugation (ad esempio class Irregular ) per ospitare queste stringhe in un tipo enumerato o qualcosa, invece di farle inglobare in XML e creare un class IrregularVerbDeserializer .

Quindi la domanda: è appropriato che le stringhe di hard-code siano molto improbabili che cambino durante la vita di un'applicazione? Naturalmente non posso garanzia 100% che non cambieranno, ma il rischio vs costo è quasi banale da soppesare ai miei occhi: l'hardcoding è l'idea migliore qui.

Modifica : proposto duplicato chiede a come memorizzare un gran numero di stringhe statiche , mentre la mia domanda è quando dovrei difficile- codice queste stringhe statiche .

    
posta Chris Cirefice 01.06.2015 - 21:44
fonte

6 risposte

56

is it appropriate to hard-code strings that are very unlikely to change during the lifetime of an application? Of course I can't guarantee 100% that they won't change, but the risk vs cost is almost trivial to weigh in my eyes - hardcoding is the better idea here

Mi sembra che tu abbia risposto alla tua stessa domanda.

Una delle maggiori sfide che dobbiamo affrontare è quella di separare le cose che probabilmente cambieranno da quelle che non cambieranno. Alcune persone impazziscono e scaricano assolutamente tutto ciò che possono in un file di configurazione. Altri vanno all'estremo opposto e richiedono una ricompilazione anche per i cambiamenti più evidenti.

Avrei scelto l'approccio più semplice da implementare fino a quando non ho trovato un motivo convincente per renderlo più complicato.

    
risposta data 01.06.2015 - 22:02
fonte
25

Stai ragionando nell'ambito sbagliato.

Non hai codificato solo i singoli verbi. Hai hardcoded la lingua e le sue regole . Questo, a sua volta, significa che l'applicazione non può essere utilizzata per altre lingue e non può essere esteso con altre regole.

Se questo è il tuo intento (cioè utilizzarlo solo per il francese), questo è l'approccio giusto, a causa di YAGNI. Ma ammetti che vuoi utilizzarlo anche in seguito per altre lingue, il che significa che molto presto dovrai spostare tutta la parte codificata sui file di configurazione. La domanda rimanente è:

  • In un prossimo futuro, con una certezza prossima al 100%, estendere l'app ad altre lingue? In questo caso, dovresti aver esportato elementi in file JSON o XML (per parole, parti di parole, ecc.) E lingue dinamiche (per regole) in questo momento di costringerti a riscrivere la maggior parte della tua app.

  • O c'è solo una piccola probabilità che l'app venga estesa da qualche parte in futuro, nel qual caso YAGNI impone che l'approccio più semplice (quello che stai usando in questo momento) è il migliore?

Come esempio, prendi il correttore ortografico di Microsoft Word. Quante cose pensi siano hardcoded?

Se stai sviluppando un elaboratore di testi, potresti iniziare con un semplice motore di controllo ortografico con regole hardcoded e persino parole codificate: if word == "musik": suggestSpelling("music"); . Rapidamente, inizierai a spostare le parole, quindi ti regole al di fuori del tuo codice. In caso contrario:

  • Ogni volta che devi aggiungere una parola, devi ricompilare.
  • Se hai imparato una nuova regola, devi cambiare il codice sorgente ancora una volta.
  • E, soprattutto, non è possibile adattare il motore a tedesco o giapponese senza scrivere enormi quantità di codice.

Come ti sei evidenziato:

Very few rules from French could be applied to Japanese.

Non appena esegui l'hardcode delle regole per una lingua, ogni altra richiederà sempre più codice, soprattutto data la complessità dei linguaggi naturali.

Un altro argomento è come si esprimono queste diverse regole, se non attraverso il codice. In definitiva, potresti trovare che un linguaggio di programmazione è lo strumento migliore per questo. In tal caso, se hai bisogno di estendere il motore senza ricompilarlo, lingue dinamiche potrebbe essere una buona alternativa.

    
risposta data 01.06.2015 - 22:08
fonte
15

Le stringhe devono essere estratte in un file o database di configurazione quando i valori potrebbero cambiare in modo indipendente dalla logica del programma.

Ad esempio:

  • Estrazione di testi dell'interfaccia utente in file di risorse. Ciò consente a un non programmatore di modificare e rileggere i testi e consente di aggiungere nuove lingue aggiungendo nuovi file di risorse localizzati.

  • Estrazione di stringhe di connessione, URL di servizi esterni, ecc. nei file di configurazione. Ciò consente di utilizzare diverse configurazioni in ambienti diversi e di cambiare le configurazioni al volo perché potrebbero dover essere modificate per motivi esterni all'applicazione.

  • Un correttore ortografico che contiene un dizionario di parole da controllare. Puoi aggiungere nuove parole e lingue senza modificare la logica del programma.

Ma c'è anche un sovraccarico di complessità con l'estrazione nella configurazione, e non sempre ha senso.

Le stringhe potrebbero essere hardcoded quando la stringa effettiva non può cambiare senza modificare la logica del programma.

Esempi:

  • Un compilatore per un linguaggio di programmazione. Le parole chiave non vengono estratte in una configurazione, poiché ogni parola chiave ha una semantica specifica che deve essere supportata dal codice nel compilatore. L'aggiunta di una nuova parola chiave richiederà sempre modifiche al codice, quindi nessun valore nell'estrazione delle stringhe in un file di configurazione.
  • Implementazione di un protocollo: es. un client HTTP avrà stringhe hardcoded come "GET", "content-type" ecc. Qui le stringhe fanno parte delle specifiche del protocollo, quindi sono le parti del codice meno probabile a cambiare .

Nel tuo caso penso che sia chiaro che le parole sono parte integrante della logica del programma (dato che stai costruendo un coniugatore con regole specifiche per parole specifiche), e l'estrazione di queste parole in un file esterno non ha valore.

Se aggiungi una nuova lingua, dovrai comunque aggiungere un nuovo codice, poiché ogni lingua ha una logica di coniugazione specifica.

Alcuni hanno suggerito di aggiungere una sorta di motore di regole che consente di specificare le regole di coniugazione per le lingue arbitrarie, in modo che le nuove lingue possano essere aggiunte esclusivamente per configurazione. Pensa molto attentamente prima di intraprendere questa strada, perché le lingue umane sono meravigliosamente strane quindi hai bisogno di un motore di regole molto espressivo. Sarebbe fondamentalmente inventare un nuovo linguaggio di programmazione (una coniugazione DSL) per un dubbio beneficio. Ma hai già un linguaggio di programmazione a tua disposizione che può fare tutto il necessario. In ogni caso, YAGNI.

    
risposta data 02.06.2015 - 09:11
fonte
5

Sono d'accordo al 100% con la risposta di Dan Pichelman, ma vorrei aggiungere una cosa. La domanda che dovresti porci qui è "chi manterrà / estenderà / correggerà l'elenco delle parole?". Se è sempre la persona che mantiene anche le regole di una lingua specifica (il particolare sviluppatore, immagino tu), allora non ha senso usare un file di configurazione esterno se questo rende le cose più complesse - non otterrai alcun beneficio da Questo. Da questo punto di vista, avrà senso inserire un hardcode di tali elenchi di parole anche se hanno per cambiarli di volta in volta, purché sia sufficiente consegnare un nuovo elenco come parte di un nuova versione.

(D'altra parte, se c'è una leggera possibilità che qualcun altro debba essere in grado di mantenere l'elenco in futuro, o se è necessario cambiare gli elenchi di parole senza distribuire una nuova versione della propria applicazione, quindi utilizzare un altro file).

    
risposta data 01.06.2015 - 23:28
fonte
2

Anche se l'hardcoding sembra andare bene qui, e meglio che caricare dinamicamente i file di configurazione, ti consiglio comunque di fare rigorosamente separare i tuoi dati (il dizionario dei verbi) da l'algoritmo . Puoi compilarli direttamente nella tua applicazione nel processo di compilazione.

In questo modo risparmierai moltissimo con la manutenzione della lista. Nel tuo VCS puoi facilmente identificare se un commit ha cambiato l'algoritmo, o semplicemente correggere un bug di coniugazione. Inoltre, potrebbe essere necessario aggiungere l'elenco in futuro per i casi che non hai preso in considerazione. Soprattutto, il numero dei 32 verbi irregolari che hai contato non sembra essere esatto. Mentre quelli sembrano coprire quelli comunemente usati, ho trovato riferimenti a 133 o anche 350 di loro.

    
risposta data 01.06.2015 - 23:00
fonte
0

La parte importante è la separazione delle preoccupazioni. Il modo in cui lo raggiungi è meno rilevante. Ad esempio, Java va bene.

Indipendentemente dal modo in cui le regole sono espresse, dovresti aggiungere una lingua di modifica a una regola: quanti codici e file devi modificare?

Idealmente, aggiungere una nuova lingua dovrebbe essere possibile aggiungendo un file "english.xml" o un nuovo oggetto "EnglishRules implementa ILanguageRules". Un file di testo (JSON / XML) offre un vantaggio se si desidera modificarlo al di fuori del ciclo di vita della build, ma richiede una grammatica complessa, l'analisi e sarà più difficile eseguire il debug. Un file di codice (Java) consente di esprimere regole complesse in un modo più semplice, ma richiede una ricostruzione.

Vorrei iniziare con una semplice API Java dietro un'interfaccia agnostica pulita, in quanto è necessario in entrambi i casi. È sempre possibile aggiungere un'implementazione di tale interfaccia supportata da un file XML in un secondo momento, se lo desideri, ma non vedo la necessità di affrontare il problema immediatamente (o mai).

    
risposta data 01.06.2015 - 22:42
fonte

Leggi altre domande sui tag