Domanda

Spesso i programmatori scrivono codice che genera altro codice.

(Il termine tecnico è metaprogramming , ma esso è più comune dei semplici compilatori incrociati; pensa a ogni pagina Web PHP che genera HTML o ogni file XSLT.)

Un'area che trovo difficile è trovare tecniche per garantire che entrambi il file sorgente scritto a mano e il file oggetto generato dal computer siano chiaramente rientrati per facilitare il debug. I due obiettivi sembrano spesso essere in competizione.

Lo trovo particolarmente impegnativo nella combinazione PHP / HTML. Penso che sia perché:

  • a volte c'è più codice HTML nel file sorgente rispetto al PHP di generazione
  • I file HTML tendono ad essere più lunghi, per esempio, delle istruzioni SQL e hanno bisogno di un rientro migliore
  • HTML ha funzionalità sensibili allo spazio (ad es. tra tag)
  • il risultato è HTML più pubblicamente visibile delle istruzioni SQL, quindi c'è una maggiore pressione per fare un lavoro ragionevole.

Quali tecniche usi per affrontare questo?


Modifica: accetto che ci siano almeno tre argomenti per non preoccuparsi di generare un bel codice HTML:

  • La complessità della generazione del codice è aumentata.
  • Non fa differenza nel rendering tramite browser; gli sviluppatori possono usare Firebug o simili per visualizzarlo bene.
  • Minor hit delle prestazioni: maggiore tempo di download per i caratteri degli spazi bianchi.

A volte ho sicuramente generato codice senza pensare al rientro (specialmente SQL).

Tuttavia, ci sono alcuni argomenti che spingono dall'altra parte:

  • Trovo, in pratica, che faccio leggo spesso il codice generato - avere ulteriori passaggi per accedervi è scomodo.
  • HTML presenta alcuni problemi di sensibilità allo spazio che mordono di tanto in tanto.

Ad esempio, considera il codice:

<div class="foo">
    <?php
        $fooHeader();
        $fooBody();
        $fooFooter();
    ?>
</div>

È più chiaro del seguente codice:

<div class="foo"><?php
        $fooHeader();
        $fooBody();
        $fooFooter();
?></div>

Tuttavia, ha anche un rendering diverso a causa dello spazio bianco incluso nell'HTML.

È stato utile?

Soluzione

Nel caso più generale, ho scritto il codice XSLT che genera il codice dell'interfaccia del database C ++. Anche se all'inizio ho cercato di generare correttamente il codice rientrato dall'XSLT, questo è diventato rapidamente insostenibile. La mia soluzione era ignorare completamente la formattazione nell'output XSLT e quindi eseguire la riga di codice molto lunga risultante tramite Rientro GNU . Ciò ha prodotto un file sorgente C ++ ragionevolmente formattato adatto per il debug.

Posso immaginare che il problema diventi molto più pungente quando si ha a che fare con fonti combinate come HTML e PHP.

Altri suggerimenti

Genera un AST, poi attraversalo in ordine ed emette il codice sorgente che è formattato correttamente.

Una tecnica che uso quando il codice di generazione domina sul codice generato è di passare un parametro di rientro.

ad esempio, in Python, generando più Python.

def generateWhileLoop(condition, block, indentPrefix = ""):
    print indentPrefix + "while " + condition + ":"
    generateBlock(block, indentPrefix + "    ")

In alternativa, a seconda del mio umore:

def generateWhileLoop(condition, block, indentLevel = 0):
    print " " * (indentLevel * spacesPerIndent) + "while " + condition + ":"
    generateBlock(block, indentLevel + 1)

Nota che condition è un breve testo che si adatta alla stessa riga, mentre block si trova su una riga rientrata separata. Se questo codice non può essere sicuro che gli elementi secondari debbano essere rientrati, questo metodo inizia a cadere.

Inoltre, questa tecnica non è altrettanto utile per spargere quantità relativamente piccole di PHP in HTML.

[Modifica per chiarire: ho scritto la domanda e anche questa risposta. Volevo seminare le risposte con una tecnica che uso e che a volte è utile, ma questa tecnica mi manca per la tipica codifica PHP, quindi sto cercando altre idee simili.]

Ho scoperto che è meglio ignorare il rientro durante la generazione. Ho scritto un motore generico di "formattazione del codice" che pubblica elaborato tutto il codice prodotto. In questo modo, posso definire le regole di rientro e le regole di sintassi del codice separatamente dal generatore. Ci sono chiari vantaggi in questa separazione.

Sono d'accordo con la risposta di oddthinking.

A volte è meglio risolvere il problema invertendolo. Se ti ritrovi a generare molto testo, considera se è più semplice scrivere il testo come modello con piccoli frammenti di codice di generazione intelligente. O se riesci a scomporre il problema in una serie di piccoli modelli che assembli e quindi indentare ogni modello nel suo complesso.

Rendere problematici i siti Web in PHP, trovare problematiche nella miscelazione di HTML e funzioni PHP specifiche, limita la panoramica e rende più difficile il debug. Una soluzione per evitare il missaggio in questo caso è l'utilizzo di contenuti basati su modelli, ad esempio vedi Smarty . Tranne una migliore intenzione, la modellazione del contenuto è utile per altre cose come, ad esempio, patch più veloci. Se un cliente richiede una modifica del layout, quel particolare problema di layout può essere rapidamente individuato e risolto, senza preoccuparsi del codice PHP funzionale che genera i dati (e viceversa).

In particolare sulla generazione di HTML: perché è importante?

Stai passando un sacco di tempo a passare attraverso i parametri di rientro e stai cercando di capire quanto sei profondamente annidato, ecc. Oltre ad essere una perdita di tempo generale (poiché non c'è differenza nel rendering finale output), come si mantengono tutte queste cose quando si aggiungono altri markup HTML e si avvolgono le pagine in un div ecc?

In ogni caso, installa Firebug (e barra degli strumenti dello sviluppatore IE per testare IE in seguito) ed entrambi mostrano l'HTML nel formato nidificato E puoi semplicemente fare clic sull'elemento della pagina per visualizzare direttamente il markup - MODO più efficiente rispetto a guardare l'output HTML di origine non elaborata.

I la situazione PHP / HTML provo a mantenere ogni frammento di codice costantemente rientrato nel suo codice sorgente. Ciò mantiene il codice leggibile dove conta davvero e di solito ha l'effetto collaterale di produrre output HTML che è leggibile. Come altri hanno già detto, firebug si prende cura di tutto il resto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top