Soluzione semplice o complessa (ma efficiente dal punto di vista delle prestazioni) - quale scegliere e quando?

28

Ho programmato per un paio d'anni e mi sono trovato spesso in un dilemma.

Ci sono due soluzioni -

  • uno è semplice, ovvero approccio semplice, più facile da capire e mantenere. Implica una certa ridondanza, un po 'di lavoro extra (extra IO, elaborazione extra) e quindi non è la soluzione ottimale.
  • ma altri utilizza un approccio complesso, difficile da implementare, che spesso implica l'interazione tra molti moduli ed è una soluzione efficiente dal punto di vista delle prestazioni.

A quale soluzione dovrei mirare quando non ho uno SLA a prestazioni elevate da soddisfare e anche la soluzione semplice può soddisfare lo SLA delle prestazioni? Ho sentito sdegno tra i miei colleghi sviluppatori per una soluzione semplice.

È buona norma proporre la soluzione più ottimale ottimale se il tuo SLA delle prestazioni può essere soddisfatto con una soluzione semplice?

    
posta MoveFast 14.09.2012 - 15:55
fonte

10 risposte

58

Which solution should I strive for when I do not have hard performance SLA to meet and even the simple solution can meet the performance SLA?

Quello semplice. Soddisfa le specifiche, è più facile da capire, è più facile da mantenere ed è probabilmente molto meno bacato.

Quello che stai facendo nel sostenere la soluzione efficiente dal punto di vista delle prestazioni è l'introduzione di generalità speculativa e ottimizzazione prematura nel codice. Non farlo! Le prestazioni vanno contro ogni altra ingegneria del software (affidabilità, manutenibilità, leggibilità, testabilità, comprensibilità, ...). Le prestazioni di Chase durante i test indicano che c'è davvero bisogno di rincorrere le prestazioni.

Non inseguire le prestazioni quando le prestazioni non contano. Anche se fosse importante, dovresti solo inseguire le prestazioni in quelle aree in cui il test indica che esiste un collo di bottiglia nelle prestazioni. Non lasciare che i problemi di prestazioni siano una scusa per sostituire simple_but_slow_method_to_do_X() con una versione più veloce se quella semplice versione non viene visualizzata come collo di bottiglia.

Le prestazioni potenziate sono quasi inevitabilmente ingombrate da una miriade di problemi di odore di codice. Ne hai menzionati diversi nella domanda: un approccio complesso, difficile da implementare, un accoppiamento più elevato. Quelli che vale davvero la pena di trascinare?

    
risposta data 14.09.2012 - 16:11
fonte
12

Risposta breve: preferisci le soluzioni semplici rispetto a quelle complesse e ricorda KISS e YAGNI principi

Poiché i requisiti del progetto iniziale e il software non sono mai perfetti, richiedono modifiche man mano che l'applicazione viene sviluppata / utilizzata. L'approccio iterativo nelle fasi di sviluppo è un ottimo abbinamento per iniziare le cose in modo semplice ed estenderlo secondo necessità. Le soluzioni più semplici hanno spazio per flessibilità e facilità di manutenzione.

Inoltre, il tentativo di essere intelligenti e l'aggiunta di un'ottimizzazione aggiuntiva durante la creazione della tua applicazione non è una buona pratica e potrebbe complicare eccessivamente la tua soluzione. Come è noto, "premature optimization is the root of all evil" - dal libro di Knuth

    
risposta data 14.09.2012 - 16:36
fonte
8

Fai una lezione da Knuth qui: "Dovremmo dimenticare le piccole efficienze, diciamo circa il 97% delle volte: l'ottimizzazione prematura è la radice di tutti i mali".

Pensa alle tue soluzioni in questo ordine: in primo luogo, sempre, correttezza. In secondo luogo, migliorare la chiarezza e la semplicità. Terzo, e solo quando puoi dimostrare la necessità, l'efficienza.

L'aggiunta di efficienza ti costa quasi sempre qualcosa di importante, e quindi dovrebbe essere perseguita solo quando sai che è necessario.

    
risposta data 14.09.2012 - 16:19
fonte
7

La semplicità è un prerequisito di affidabilità . Se si dispone di una soluzione semplice che funziona, con tutti i mezzi per farlo! È molto più facile ottimizzare un programma di lavoro piuttosto che far funzionare un programma ottimizzato. Inoltre, non dimenticare la legge di Moore : se la tua soluzione semplice soddisfa gli obiettivi di prestazione oggi, probabilmente li schiaccerà < sup> 1 tra un anno o due.

1 Non c'è alcuna garanzia lì, perché come Jimmy Hoffa annotato nel suo commento qui sotto , La legge di Moore ha i suoi limiti.     
risposta data 14.09.2012 - 16:07
fonte
3

Is it good practice to come up with most optimal complex solution if your performance SLA can be met by a simple solution?

Optimal è una parola ambigua!

In definitiva, se c'è molto rischio nel dover mantenere quello complesso, e se quello semplice è "abbastanza buono", sbaglierei sempre dalla parte di quello semplice.

Aggiungi il rischio che il complesso non sia abbastanza buono, quindi KISS è probabilmente la risposta giusta.

    
risposta data 14.09.2012 - 15:57
fonte
2

Preferirei quello semplice. A mio avviso, le ottimizzazioni premature causano tanti problemi quanti ne risolvono. In molti casi un buon design consente di cambiare le implementazioni date in futuro, se diventano colli di bottiglia.

Quindi, nel complesso, lo progetterò il più flessibile possibile, ma non sacrificherò troppo la semplicità per la flessibilità.

    
risposta data 14.09.2012 - 16:32
fonte
2

Quale costa meno?

La maggior parte delle volte, una soluzione semplice che è leggermente più lenta sarà perfettamente accettabile in termini di prestazioni, e la semplicità lo renderà più economico da sviluppare, mantenere ed eventualmente sostituire.

D'altra parte, a volte la velocità è davvero importante, e il guadagno finanziario derivante anche da piccoli miglioramenti di velocità può essere di gran lunga maggiore del costo maggiore di una soluzione più complicata. Ad esempio, la rasatura di 0,01 secondi per completare una transazione può rendere molto più redditizio un sistema di negoziazione di titoli. Un miglioramento del 10% nell'efficienza di un sistema che supporta diversi milioni di utenti potrebbe significare una significativa riduzione dei costi del server.

Quindi, la domanda che devi porci è: L'utilizzo della soluzione complessa ha un impatto sufficiente sulla redditività per pagare il suo costo aggiuntivo? In realtà, dovresti probabilmente chiedere al tuo cliente decidere perché stanno pagando le bollette e raccogliendo i potenziali benefici. Una buona opzione è quella di adottare prima la soluzione semplice e offrire la soluzione più complessa come possibile miglioramento. Ciò ti consente di far funzionare il tuo sistema e dà al tuo cliente qualcosa da cui iniziare a testare, e quell'esperienza potrebbe informare la decisione di implementare (o non implementare) la soluzione più complicata.

    
risposta data 14.09.2012 - 16:37
fonte
2

Nel valutare due approcci, uno più semplice ma meno efficiente mentre altri sono più complessi e più efficienti, è necessario considerare il problema e il dominio del progetto.

Considera un progetto multimiliardario per l'industria sanitaria che ha una durata prevista di oltre 15 anni di manutenzione e 20 anni di utilizzo. In tale progetto, le prestazioni non saranno sicuramente un problema, ma la complessità e la struttura del progetto possono causare grossi problemi per il mantenimento del progetto, che dura almeno 15 anni. Manutenibilità e semplicità vengono prima di tutto.

Quindi, considera un altro esempio. Un motore di gioco per console che dovrebbe alimentare i prossimi giochi della compagnia per i prossimi 5 anni. Poiché i giochi sono programmi estremamente limitati dalle risorse, in molti casi l'efficienza va prima della manutenibilità. Scrivere le proprie strutture dati e algoritmi molto specifici per alcune attività può essere molto importante anche se va contro qualsiasi tipo di "best practice" di sviluppo del software. Un buon esempio di questo potrebbe essere Data Oriented Design in cui memorizzi i tuoi dati in matrici di dati simili, piuttosto che in oggetti reali . Questo per aumentare il riferimento della località e aumentare l'efficienza della cache della CPU. Non pratico, ma molto cruciale nel dominio specificato.

    
risposta data 14.09.2012 - 16:16
fonte
1

Questa è sempre una domanda difficile e vedo le risposte oscillare in un modo, quindi giocherò il gioco per l'altro lato, anche se non pretendo che nessuna delle risposte sia corretta, è molto morbida e caso per caso argomento.

Una cosa su una soluzione complessa ma ad alte prestazioni è che puoi sempre documentare il resto della vita. In genere sono un fan del codice di auto-documentazione, ma sono anche un fan del software che risponde in un tempo che mi fa sentire come se non mi rallentasse. Se vai con la soluzione complessa ma ad alte prestazioni, considera ciò che puoi fare per renderlo non così male:

Avvolgilo in un'interfaccia, inseriscilo in un assembly da solo, possibilmente anche in un processo tutto suo. Rendilo il più libero possibile il più possibile con un muro di astrazione attorno ad esso per evitare perdite . Scrivi molti test unitari per salvare le regressioni in futuro.

Documentalo nel codice, anche considerando di scrivere della vera documentazione. Pensa a strutture di dati complesse e al modo in cui sono documentate, immagina di provare a comprendere l'implementazione di uno di essi dal codice senza un articolo di bookwork / wikipedia per spiegarlo. Eppure accettiamo tutti che queste complesse strutture di dati sono in effetti buone cose ed è vantaggioso che qualcuno le abbia implementate nelle nostre lingue.

Ricorda che tutti noi stiamo inviando messaggi su uno stack TCP / IP che è probabilmente tanto difficile quanto il codice può ottenere se qualcuno di noi dovesse guardarlo, espressamente, in modo che esegua anche il modo in cui tutti noi lo richiediamo. Forse il tuo problema non richiede questo livello di ottimizzazione, forse lo fa, ma fai attenzione quando affronti questa domanda come tutti noi di volta in volta: ci sono draghi lì.

    
risposta data 14.09.2012 - 16:22
fonte
0

Sto arrivando a questo lavoro in aree in cui non ci sono SLA sulle prestazioni. Quando si tratta di renderer offline in computer grafica, non c'è "prestazione soddisfacente" per gli utenti, perché stanno già distribuendo enormi somme di denaro per distribuire il computing attraverso i cloud e renderizzare le farm anche con i renderizzatori allo stato dell'arte per produrre immagini e fotogrammi di qualità di produzione per film, ad esempio

Tuttavia, devo dire che quando lavoriamo in questo settore da molti anni, qualsiasi soluzione che degrada in modo significativo la mantenibilità a favore dell'efficienza sta effettivamente lavorando contro i sempre mutevoli requisiti di prestazioni. Perché se non riesci a mantenere efficacemente la tua soluzione per anni a venire mentre le cose stanno cambiando sotto i piedi (sia in termini di codice circostante che di aspettative degli utenti in quanto concorrenti si sovraperformano l'un l'altro), la soluzione sta già lavorando verso l'obsolescenza e in necessità di sostituzione all'ingrosso.

Non vedo lo scopo ultimo dei profiler come VTune come un modo per far funzionare il mio codice più velocemente. Il loro valore finale è quello di assicurarsi che non sto degradando la mia produttività per soddisfare richieste di prestazioni sempre più elevate. Se devo assolutamente applicare una micro-ottimizzazione dall'aspetto grossolano, allora il profiler, combinato con l'esecuzione contro casi reali dell'utente (e non alcuni casi di test che immagino potrebbe essere importante), assicura Applico tali ottimizzazioni, inevitabilmente grossolane, molto, molto giudiziosamente solo ai migliori hotspot che appaiono e con molta attenzione a documentarle perché inevitabilmente dovrò rivisitarle e mantenerle e modificarle per gli anni successivi a venire, se questa soluzione rimane praticabile.

E soprattutto se la tua soluzione ottimizzata richiede più accoppiamento, allora sarei davvero riluttante a usarla. Tra le metriche più preziose che ho imparato ad apprezzare nella maggior parte delle aree critiche per le prestazioni del codebase è il disaccoppiamento (come nel minimizzare la quantità di informazioni che qualcosa deve funzionare, che minimizza anche la probabilità che richieda cambiamenti a meno che non abbia bisogno di modifiche ), perché quelle aree critiche moltiplicano in modo significativo le ragioni per cui le cose cambiano. Il che significa che meno informazioni richiede qualcosa per lavorare, meno ragioni hanno per il cambiamento e minimizzare le ragioni del cambiamento è davvero una parte enorme del miglioramento della produttività nelle mie particolari aree di attenzione perché le cose dovranno cambiare costantemente comunque (noi diventerà obsoleto in un anno altrimenti) e aiuta a ridurlo al minimo e a ridurre il costo di tali cambiamenti.

Per me le soluzioni migliori e più efficaci che ho trovato sono quelle in cui efficienza, manutenibilità e produttività non sono diametralmente opposte l'una all'altra. La ricerca per me è cercare di rendere questi concetti armoniosi come si può eventualmente fare.

    
risposta data 15.12.2018 - 13:13
fonte