L'eleganza non è controproducente? [chiuso]

-1

Sono state poste molte domande sulla natura dell'elegante codice e design, ma l'ipotesi sottostante sembra essere che l'eleganza è una buona cosa . Pertanto è accettabile o addirittura desiderabile fare uno sforzo in più per creare soluzioni eleganti.

Ma ne vale davvero la pena?

Non sto chiedendo cosa sia elegante; né sto chiedendo del buon codice. Presumo che "lo sai quando lo vedi", e può anche essere vagamente caratterizzato dalla verifica che non è rimasto nulla da togliere, nel senso che il modello mentale che hai nella tua mente è espresso direttamente e non oscurato nel lingua di tua scelta (linguaggio di programmazione, progettazione orientata agli oggetti, schema relazionale, ecc.), senza distrazioni.

Tuttavia, un corollario ad esso è che l'eleganza è sempre relativa (e in un certo senso soggettiva); dipende da cosa pensi che sia il problema e come dovrebbe essere la soluzione. Il problema, naturalmente, è che il dominio del problema e la sua comprensione di esso cambiano costantemente (in aggiunta, la tua conoscenza del linguaggio / dei modelli / degli strumenti di programmazione si sviluppa, ma non è ciò di cui sono principalmente preoccupato).

Questo implica che per mantenere il tuo design elegante, devi ripensarlo costantemente man mano che il problema / il suo sviluppo si evolve. In pratica, fare ciò comporterebbe un refactoring quasi infinito.

Inoltre, sostengo anche che, sforzandosi di sviluppare soluzioni eleganti, la manutenibilità necessariamente soffre. Le soluzioni più eleganti sono le più strettamente collegate al dominio del problema, perché se non lo fossero, allora ci sarebbe qualcosa da togliere, quindi non sarebbero più eleganti. Se c'è qualcosa di abbondante nella tua soluzione, allora puoi semplificarlo e renderlo più elegante rimuovendo quella parte abbondante, vero?

Ma poi, a volte, quando hai un design davvero elegante e devi implementare un cambiamento, devi prima "svitare" la tua soluzione, solo per essere in grado di fare un imprevisto (come la maggior parte di loro) cambiare affatto. Tuttavia, il principio aperto / chiuso afferma che ciò non dovrebbe essere necessario. Quindi, un'altra formulazione più concreta della domanda è:

In una certa misura, non sono l'eleganza e il principio di apertura / chiusura in contrasto tra loro?

Che ne pensi?

    
posta proskor 18.07.2014 - 15:49
fonte

5 risposte

3

Isn't striving for elegance counter-productive?

Passato un certo punto, sì.

But is it really worth it? I am not asking what is elegant; neither am I asking about good code. I assume that "you know it when you see it"

Beh ... probabilmente dovresti [chiedere "cosa è elegante"]. "Lo sai quando lo vedi" sottintende che non lo sai, finché non lo vedi anche tu, e quindi, il tuo sforzo di scrivere codice elegante è uno sforzo speso con una direzione carente (o, sforzo speso nella direzione sbagliata ).

This implies that in order to keep your design elegant, you have to constantly rethink it as the problem / your undestanding of it evolves. Practically, doing so would result in almost endless refactoring.

No, non implica che tu debba costantemente rething il problema. Dovresti pensare bene il problema all'inizio. Più penserai all'inizio, meno dovrai cambiare dopo. Se non hai una chiara idea di dove sei / dovresti essere (all'inizio) allora avrà bisogno di cambiare il codice. Per evitare un refactoring senza fine, dovresti (prima) decidere come dovrebbe essere la soluzione, come dovrebbe essere una soluzione elegante, quindi implementarla.

Saprai che lo stai facendo nel modo giusto, quando finisci per spendere fino a 10 volte * per la progettazione dell'interfaccia (e i test), quindi spendi per l'implementazione.

Furthermore, I even maintain that by striving to develop elegant solutions maintainability necessarily suffers.

Se una soluzione non è gestibile, come puoi chiamarla elegante? Una soluzione elegante dovrebbe essere (con la mia definizione) una soluzione che risponda bene al problema, alla progettazione, alla manutenibilità e ai requisiti prestazionali. Altrimenti, potrebbe non essere affatto una soluzione al tuo problema (per non parlare di uno elegante). Questo rende anche il mio punto sopra (sulla necessità di chiedere "cosa è elegante" prima di andare alla ricerca di soluzioni eleganti).

The most elegant solutions are the most tightly coupled to the problem domain, for if they weren't, then there would be something to take away from it, hence they would not be most elegant anymore.

Nel mio libro, quelle non sono soluzioni eleganti, sono soluzioni inflessibili (e per definizione, al contrario dell'eleganza che si può ottenere).

If there is something abundant in your solution, then you can simplify it and make it more elegant by removing that abundant part, right?

Uhh ... no. Fare ciò dipenderebbe da ciò che guadagneresti con un tale cambiamento, e se il guadagno ne vale la pena.

you first have to "untighten" your solution

AFAIK, questo si chiama implementare un design liberamente accoppiato ed è considerato un caposaldo per scrivere codice elegante. Non è qualcosa che va contro il design elegante, ne fa parte.

To some degree, aren't elegance and open/closed-principle at odds with each other?

No. Una soluzione elegante sarebbe quella che tenesse conto del principio aperto / chiuso sin dall'inizio.

  • questa idea è stata presa da Alexander Stepanov, il designer del C ++ STL (ed è un'idea che posso confermare attraverso l'esperienza).
risposta data 18.07.2014 - 16:55
fonte
3

Non vedo giustizia in questa affermazione:

... by striving to develop elegant solutions maintainability necessarily suffers. The most elegant solutions are the most tightly coupled to the problem domain, for if they weren't, then there would be something to take away from it, hence they would not be most elegant anymore.

Un esempio di una soluzione elegante che non è strettamente accoppiata al dominio è algoritmi di ordinamento generici. Hai sei elementi in una lista (vettore / array / qualunque) che devono essere ordinati; costruisci manualmente le 12 righe di codice che sfruttano l'ordinamento parziale intrinseco della lista o invochi una funzione di ordinamento in una riga?

Allo stesso modo, fai un algoritmo in modo esplicito e lo ri-implementa in diversi punti oppure estrai un metodo e lo rendi generico?

In entrambi i casi, la soluzione elegante è molto più breve e più comprensibile. Le soluzioni fornite sono anche più manutenibili.

Questo è un argomento straw man:

in order to keep your design elegant, you have to constantly rethink it as the problem / your undestanding of it evolves. Practically, doing so would result in almost endless refactoring.

La ricerca dell'eleganza è sempre bilanciata rispetto a tutte le altre esigenze del progetto.

    
risposta data 18.07.2014 - 16:26
fonte
3

However, the open/closed-principle states that this should not be necessary. Questa non è un'interpretazione utile del principio aperto / chiuso.

C'è sempre un requisito che il tuo design non può soddisfare. Pensaci in questo modo: un programma può essere pensato come una libreria specifica del dominio i cui componenti sono combinati in un modo particolare dalla funzione main per risolvere qualche problema. Se quella libreria è abbastanza flessibile da fare qualsiasi cosa senza modifiche al suo codice sorgente, è completa e hai creato un linguaggio di programmazione oltre al tuo linguaggio di programmazione e non è meglio di quando hai iniziato. Affinché la libreria sia utile, deve essere adattata a un'attività particolare e ben definita e quando l'ambito di tale attività cambia, così deve essere la libreria.

(L'alternativa sarebbe scrivere ogni possibile programma, in modo che quando qualcuno viene da te con un nuovo problema, hai già un programma per questo problema. I problemi con questo approccio sono ovvi.)

Inoltre, il Principio Aperto / Chiuso fu originariamente coniato nel 1988, quando la nostra comprensione dell'OOP era ancora giovane. Bertrand Meyer probabilmente ha avuto in mente un'estensione attraverso l'eredità quando ha coniato, ma risulta che non è possibile sovrascrivere i metodi arbitrari da una classe senza che le sottoclassi scendano ulteriormente lungo la linea quando la classe genitrice viene aggiornata. In altre parole, la classe base deve essere progettata in primo piano con l'ereditarietà in mente e puoi tranquillamente ignorare qualsiasi cosa la classe base dica che potresti scavalcare. La promessa di essere in grado di gestire attività impreviste attraverso l'ereditarietà ad-hoc era falsa. Questo è noto come problema della classe base fragile .

Direi che un'interpretazione più utile del principio di apertura / chiusura è che quando la portata delle tue esigenze si espande per includere una nuova attività, il tuo codice non dovrebbe essere hard-coded a quella particolare istanza dell'attività. Per esempio. Se ora hai bisogno di ordinare un elenco di date, è molto probabile che dovrai anche ordinare altri tipi di cose. Piuttosto che scrivere una funzione che ordina solo elenchi di date, potresti anche scrivere una funzione che può ordinare elenchi di tutto ciò che può essere confrontato.

Una volta riconosciuto che è folle anticipare ogni possibile cambiamento, "eleganza" sta semplicemente trovando il modo più chiaro, semplice o "bello" di esprimere la soluzione al tuo particolare problema.

    
risposta data 18.07.2014 - 16:23
fonte
3

it can also be vaguely characterized by verifying that there is nothing left to take away, in a sense that the mental model you have in your mind is expressed directly and unobscrured in the language of your choice (programming language, object oriented design, relational schema etc.), without distractions.

Non sono sicuro di essere d'accordo con questo. Conosco molte barebone o soluzioni concise per un problema che sono direttamente e chiaramente implementate senza essere elegante . Voglio dire, se faccio la forza bruta alla tua password, il codice sarà una chiara descrizione di ciò che sto cercando di realizzare - ma la soluzione in sé non è minimamente elegante.

Per me, una soluzione elegante è quella in cui le cose "svaniscono". Considera il modello composito. Molte volte, l'uso giudizioso di questo modello produce questo tipo di effetto. Senza il modello, il problema "è una cosa sola, o è molte cose" deve essere diffuso ovunque che usi l'interfaccia. Utilizzando il pattern composito, nascondi questa complessità in modo che i consumatori non abbiano bisogno di cure.

Le soluzioni eleganti sono quelle che non risolvono solo un problema, ma impediscono che i problemi si verifichino. Quindi no, lottare per l'eleganza non è controproducente.

    
risposta data 18.07.2014 - 16:46
fonte
2

Quando si prende tempo per studiare l'eleganza al di fuori dei costrutti del codice, si ottiene un apprezzamento per ciò che è veramente elegante. Secondo i grandi maestri dell'arte (come Da Vinci) e alcune delle più grandi menti matematiche (come Einstein), un attributo molto comune di eleganza è semplicità .

Che cos'è l'eleganza

Leggendo la tua domanda, mi sembra che tu stia equipaggiando l'eleganza con soluzioni fantasiose che usano scatole nere complesse che nascondono i dettagli di implementazione da te. Questa è la cosa più lontana dall'eleganza, per i seguenti motivi:

  • I dettagli nascosti e le eccezioni ingerite possono nascondere quale sia il vero problema.
  • Riflessione come caratteristica principale di un framework / ecc. rende molto difficile rintracciare cosa sta succedendo in un'applicazione.
  • Confonde la comprensione del codice e del dominio del problema.
  • Ti richiede di imparare una nuova lingua e un nuovo processo di pensiero oltre alla lingua che stai utilizzando.

Questi sono attributi degli ingombranti problemi che probabilmente sono iniziati come una buona idea, e poi portati troppo lontano. Questi problemi complicano il mantenimento del codice, hanno difficoltà a comprendere concetti e, in generale, non migliorano la linea di fondo. Anche se alcune persone hanno una soluzione semplice e le soluzioni come questa sono "eleganti", se non rimangono eleganti in una soluzione più complessa, allora non è davvero elegante.

Definizione di eleganza

Il codice elegante semplifica la soluzione in modo comprensibile a tutti i membri del team. Se stai lavorando con un linguaggio orientato agli oggetti, una soluzione elegante non ti obbliga a cambiare il modo in cui pensi in termini di un linguaggio funzionale. Vale anche il contrario. Di seguito sono riportati gli attributi di soluzioni eleganti:

  • Il debugging e il successivo flusso di codice sono molto semplici
  • Riduce notevolmente il codice di clutter che nasconde l'intento di un metodo
  • I concetti e il metodo di pensiero si adattano bene al linguaggio utilizzato, e veramente elegante rende anche il dominio del problema più facile da comprendere nel codice.
  • Migliora l'efficienza degli sviluppatori che lavorano con il codice

Possiamo imparare nuovi modi di affrontare un problema che sono più eleganti di quelli che stiamo usando? Assolutamente. Vale la pena riadattare il codice esistente con la soluzione più nuova, più semplice e più elegante? Non sempre. Questa è una decisione di gestione del progetto che richiede di bilanciare il costo del cambiamento con quello che otterrà quella soluzione.

Dovremmo perseguire l'eleganza?

La ricerca dell'eleganza è sinonimo di semplificazione del codice e renderlo più comprensibile. Tutto ciò che puoi fare per alleggerire il carico cognitivo già pesante che uno sviluppatore ha nel mantenere il codice, meglio è. A volte tutto ciò che puoi permetterti di fare sono piccoli miglioramenti (refactoring leggero) qua e là mentre entri e lavori sul codice. A volte c'è così tanto codice in decomposizione a causa dei mutevoli requisiti che è necessario riscrivere una sezione del codice per soddisfare meglio le attuali esigenze e abilitare nuove funzionalità. Non cambia il fatto che perseguire l'eleganza è sinonimo di semplificarti la vita e migliorare la manutenibilità del codice.

    
risposta data 18.07.2014 - 17:24
fonte

Leggi altre domande sui tag