Configurazione in fase di compilazione e in fase di esecuzione

1

Sto iniziando un nuovo progetto e devo decidere come gestire la configurazione. Recentemente mi sono imbattuto in un progetto senza successo. Anche se ha i suoi problemi, mi è piaciuto molto il suo approccio alla configurazione - solo un file di intestazione con variabili statiche.

Quali sono i pro e i contro dell'uso delle opzioni di compilazione rispetto alle opzioni di runtime (== file di configurazione)? Sarebbe accettabile che il prodotto mirasse a utenti più esperti di tecnologia a utilizzare la configurazione in fase di compilazione? Ha ancora vantaggi sui sistemi moderni?

Mi sto concentrando sui desktop / laptop moderni, solo l'architettura supportata probabilmente sarà amd64. Il progetto è un'applicazione GUI focalizzata sull'accesso di varie informazioni.

    
posta graywolf 29.04.2015 - 16:26
fonte

3 risposte

3

Questa risposta è specifica per C ++ (come indicato dal tag su questa domanda).

La maggior parte degli altri linguaggi compilati (al di fuori di C e C ++) non hanno questa considerazione, perché in quei linguaggi non c'è alcun vantaggio nello spostare le configurazioni in fase di compilazione. Al di fuori di C e C ++, la compilazione condizionale è strongmente scoraggiata o semplicemente non supportata. Inoltre, i compilatori C e C ++ applicano un'eliminazione aggressiva del codice morto e altre ottimizzazioni in fase di compilazione, in modo che il codice che è dimostrato escludibile dalla configurazione in fase di compilazione non esista nel binario.

Questa domanda può anche diventare un non-problema quando viene presa in considerazione la compilazione just-in-time (JIT). È ampiamente ipotizzato che JIT sarà disponibile per C ++ un giorno.

Da una prospettiva di molti chilometri, ci sono tre considerazioni principali per la configurazione di compilazione vs runtime (o programma di avvio).

Necessità.

La necessità si riferisce a requisiti software, utente o legali che sono rigidi e non possono essere elaborati, e quindi influisce sulla necessità o meno di una configurazione di essere in fase di compilazione o di runtime.

Ad esempio, se è necessario che una configurazione possa essere modificata senza riavviare un'applicazione già in esecuzione, ovviamente tale configurazione deve essere modificabile in fase di esecuzione.

Se il progetto ha una dipendenza opzionale da un componente di terze parti e se quel componente ha termini di licenza che lo rendono inapplicabile a qualche sottoinsieme di clienti, allora dovrai fornire una configurazione di build per includere o escludere il collegamento e utilizzo di quel componente di terze parti dal tuo progetto. Ovviamente quella configurazione deve essere in fase di compilazione.

Burden / Overhead.

Ciò include il costo in termini di tempo e il costo di inconveniente di tutto - la ricompilazione del tempo dell'utente, l'overhead dell'esecuzione del codice (controllo condizionale, configurazioni di lettura, ecc.) e molte altre cose.

Come sottolinea Dan Pichelman nel commento, il tempo speso per la ricompilazione in genere supererà di gran lunga il tempo trascorso su qualsiasi altra cosa.

L'unica eccezione a questa osservazione è che, se per altri motivi, il codice è già stato ricompilato frequentemente, ad esempio, ogni giorno o anche ogni ora. Questo può accadere quando è già presente un sistema di integrazione continua (builds e deployments automatizzati). In tali ambienti, mettere la configurazione in tempo di compilazione può essere efficace perché non ci sono costi aggiuntivi e solo una minore latenza dal cambiamento all'effetto.

gonfiare.

Bloat fa riferimento all'aumento di dimensioni, numero di artefatti di build o altre quantità quando è necessario supportare più configurazioni (sia in fase di compilazione che in fase di esecuzione), rispetto alla stessa quantità quando è necessaria una sola configurazione.

Ad esempio, se si ha la possibilità di utilizzare Algoritmo A contro Algoritmo B per un determinato compito:

  • Opzione 1: compila entrambi gli algoritmi nel binario, consentendo così la scelta di essere eseguito in fase di runtime. La dimensione binaria è la somma della dimensione binaria di entrambi gli algoritmi, meno la dimensione delle parti binarie condivise.
  • Opzione 2: compila solo uno dei due algoritmi nel binario. La scelta è fissa in fase di compilazione; l'applicazione / utente non sarà in grado di scegliere in fase di runtime.
  • Opzione 3: crea una build (binaria) contenente solo Algoritmo A e un'altra build (binaria) contenente solo Algoritmo B. Fornisci entrambi all'utente. Un cambio di scelta richiederà il riavvio dell'applicazione utilizzando il file binario di scelta.
  • Opzione 4: refactoring di entrambi gli algoritmi in un modello di algoritmo generalizzato e massimizzazione del riutilizzo della logica, nella speranza di ridurre le dimensioni binarie.

È ovvio che l'Opzione 3 avrà il massimo gonfio, perché molta logica binaria comune a entrambi dovrà essere duplicata. Il rigonfiamento risultante dall'opzione 1 sembra essere ragionevole rispetto all'opzione 3.

L'opzione 2 non ha la scelta runtime, quindi è soggetta ai primi criteri - necessità - a seconda delle esigenze del software e dell'utente.

L'opzione 4 richiede uno sforzo di programmazione extra, ma avrà l'impatto minore sul carico e sull'abbondanza rispetto a tutte le altre opzioni.

    
risposta data 29.04.2015 - 19:28
fonte
1

La decisione di disporre di una configurazione basata su codice o di una configurazione basata su file dipenderà interamente dal fatto che sia necessaria o meno la flessibilità di configurazione in fase di esecuzione rispetto al tempo di compilazione. Le prestazioni sono quasi certamente un problema, dal momento che è possibile memorizzare i valori una volta letti dal file di configurazione.

    
risposta data 29.04.2015 - 17:42
fonte
1

Il titolo suggerisce che l'argomento sia in qualche modo basato sull'opinione pubblica.

Tuttavia, ignoriamo questo problema e affrontiamo la domanda. Penso che i pro ei contro siano abbastanza ovvi, dal momento che entrambi i metodi sono solo compromessi.

Ad esempio, supponiamo che tu abbia implementato un sistema di configurazione runtime. Contro:

  • Che cosa fai se alcuni valori mancano nella configurazione / la configurazione stessa non è presente? Devi comunque definire alcuni "valori di tempo di compilazione".

  • Dovrai caricare e analizzare il file. Al giorno d'oggi questo non è più un problema, visto che lavoriamo con processori gigahertz e gigabyte di RAM. Ma immagina se tu avessi un dispositivo che offre meno.

Pro:

  • Flessibilità. L'utente può adattare i valori corrispondenti alle sue esigenze. Per essere onesti, a mio parere questo supera tutti gli svantaggi per questo che puoi immaginare.

Bene, diamo un'occhiata all'opzione di configurazione del tempo di compilazione: Pro:

  • Il programma si avvia più velocemente e così via. Ma questo non è un problema in questi giorni poiché abbiamo, come già detto, computer molto potenti rispetto a quello che avevamo un paio di anni fa.

Contro:

  • Valori hard codificati. I valori sono hard coded e difficilmente puoi cambiarli per il debug, per la tua gioia personale o per quello che mai.

Come accennato all'inizio, questo è principalmente basato sull'opinione pubblica, dal momento che i pro ei contro non hanno molto peso. Se hai già implementato un parser che puoi nutrire con i file di configurazione, allora mi attenerei ad esso.

EDIT: Qualcosa che ho dimenticato di dire: Esporre solo quei valori di configurazione, che si desidera modificare. Non ha senso dare all'utente la possibilità di abilitare una funzione che non è supportata sul suo sistema.

    
risposta data 29.04.2015 - 17:48
fonte

Leggi altre domande sui tag