Qual è il valore nel nascondere i dettagli attraverso le astrazioni? Non c'è valore nella trasparenza?

30

Sfondo

Non sono un grande fan dell'astrazione. Devo ammettere che si può beneficiare dell'adattabilità, della portabilità e della riutilizzabilità delle interfacce, ecc. C'è un vantaggio reale in questo caso, e non voglio metterlo in dubbio, quindi ignoriamolo.

Esiste l'altro "vantaggio" principale dell'astrazione, che è quello di nascondere la logica di implementazione ei dettagli dagli utenti di questa astrazione. L'argomento è che non è necessario conoscere i dettagli e che a questo punto si dovrebbe concentrarsi sulla propria logica. In teoria ha senso.

Tuttavia, ogni volta che mantengo grandi applicazioni aziendali, ho sempre bisogno di conoscere maggiori dettagli. Diventa un'enorme seccatura che scava sempre più in profondità nell'astrazione ad ogni svolta solo per scoprire esattamente cosa fa qualcosa; vale a dire fare "dichiarazione aperta" circa 12 volte prima di trovare la stored procedure utilizzata.

Questa mentalità "nascondi i dettagli" sembra essere d'intralcio. Desidero sempre interfacce più trasparenti e meno astrazione. Posso leggere il codice sorgente di alto livello e sapere cosa fa, ma non saprò mai come lo fa, quando come lo fa, è ciò che ho davvero bisogno di sapere.

Cosa sta succedendo qui? Ogni sistema su cui ho mai lavorato è stato mal progettato (almeno da questa prospettiva)?

La mia filosofia

Quando sviluppo software, sento di provare a seguire una filosofia che ritengo sia strettamente correlata alla filosofia di ArchLinux :

Arch Linux retains the inherent complexities of a GNU/Linux system, while keeping them well organized and transparent. Arch Linux developers and users believe that trying to hide the complexities of a system actually results in an even more complex system, and is therefore to be avoided.

E quindi, non cerco mai di nascondere la complessità del mio software dietro i livelli di astrazione. Cerco di abusare dell'astrazione, non diventare schiavo di esso.

Domanda di cuore

  1. Esiste un valore reale nel nascondere i dettagli?
  2. Non stiamo sacrificando la trasparenza?
  3. Questa trasparenza non è preziosa?
posta user606723 26.01.2012 - 20:22
fonte

17 risposte

47

Il motivo per nascondere i dettagli non è quello di mantenere nascosti i dettagli; è per rendere possibile modificare l'implementazione senza rompere il codice dipendente.

Immagina di avere una lista di oggetti, e ogni oggetto ha una proprietà Name e altri dati. E un sacco di volte, devi trovare un elemento nell'elenco la cui Name corrisponde a una determinata stringa.

Il modo più ovvio consiste nel ricorrere ad ogni elemento uno alla volta e verificare se Name corrisponde alla stringa. Ma se trovi che ci vuole troppo tempo, (come sarebbe se tu avessi diverse migliaia di elementi nella lista), potresti voler sostituirlo con una ricerca nel dizionario oggetto-stringa.

Ora, se tutte le tue ricerche sono state eseguite recuperando l'elenco e scorrendo su di esso, hai una quantità enorme di lavoro da fare per risolvere questo problema. È ancora più difficile se sei in una biblioteca e gli utenti di terze parti lo utilizzano; non puoi uscire e correggere il loro codice!

Ma se disponi di un metodo FindByName per incapsulare il processo della ricerca del nome, puoi semplicemente cambiare il modo in cui è implementato e tutto il codice che lo chiama continuerà a funzionare e diventerà molto più veloce gratuitamente. Questo è il vero valore dell'astrazione e dell'incapsulamento.

    
risposta data 26.01.2012 - 20:28
fonte
15

Ho appena finito di leggere la sezione in Code Complete sull'astrazione, quindi è qui che si trova la maggior parte di queste fonti.

Il punto di astrazione è rimuovere la necessità di chiedere "come viene implementato?". Quando chiami user.get_id() , sai che un id è ciò che stai per recuperare. Se devi chiedere "come ottiene l'ID utente?" quindi probabilmente non hai bisogno di un id , o get_id() restituisce qualcosa che è inaspettato e mal progettato.

Usi l'astrazione per permetterti di progettare:

a house with doors and windows

non progettare

a box with four walls,
    with 3 holes,
        two of which fit panes of glass surrounded by wood frames,
        one that fits a large plank of wood with hinges and a metal knob,
etc.
    
risposta data 26.01.2012 - 20:32
fonte
8

Is there real value in hiding the details?

Sì. Presentando astrazioni possiamo pensare e programmare a un livello superiore.

Immagina di modellare sistemi fisici senza calcolo o algebra di matrice. È completamente poco pratico. Allo stesso modo, se possiamo programmare solo a livello scalare, non saremo in grado di risolvere problemi interessanti. Anche le applicazioni web relativamente semplici possono trarre grandi vantaggi dalle astrazioni come le librerie di tag. È molto più facile inserire un tag che significa "campi di inserimento indirizzo" piuttosto che creare ripetutamente quattro campi di testo e una casella di selezione. E se decidi di espandersi oltreoceano, puoi semplicemente modificare la definizione del tag, piuttosto che correggere ogni modulo per gestire gli indirizzi internazionali. L'uso efficace dell'astrazione è ciò che rende alcuni programmatori dieci volte più efficaci di altri.

Gli umani hanno una memoria di lavoro limitata. L'astrazione ci consente di ragionare su grandi sistemi.

Aren't we sacrificing transparency?

No. Se le astrazioni non vengono utilizzate, lo scopo di un componente software è nascosto in dettagli ripetuti. Gli sviluppatori passano i loro giorni ad attraversare il codice in questo modo:

for (i = 0; i < pilgrim.wives.size(); ++i) {
  wife = pilgrim.wives[i];
  for (j = 0; j < wife.sacks.size(); ++j) {
     sack = wife.sacks[i];
     for (k = 0; j < sack.cats.size(); ++j) {
        cat = sack.cats[k];
        for (m = 0; m < cat.kits.size(); ++m) {
           ++count;
        }
     }
  }
}

e pensando "oh sì un altro loop a quattro livelli sui kit", invece di vedere

pilgrim.kits.each { ++count; }

Isn't this transparency valuable?

Come hai sottolineato, c'è un costo per l'indirezione. Non ha senso creare strati "nel caso". Usa l'astrazione per ridurre la duplicazione e chiarire il codice.

    
risposta data 26.01.2012 - 22:28
fonte
7

Quando le persone dicono che le astrazioni nascondono i dettagli di implementazione, in realtà non significano "nascondere" nel senso di renderlo difficile da trovare. Ciò che intendono sono dettagli di implementazione separati dall'interfaccia pubblica, per mantenere l'interfaccia semplice, concisa e gestibile. Proprio come una macchina "nasconde" la maggior parte delle sue parti vitali e offre solo un insieme abbastanza rudimentale di controlli per gestirle, un modulo software "nasconde" la maggior parte delle sue funzionalità nelle sue viscere e espone solo un numero limitato di metodi di accesso a guidarla. Immagina un'auto in cui dovevi azionare manualmente tutti i componenti interni del motore (e ce ne sono molti di questi), faresti davvero fatica a tenere d'occhio il traffico e trovare la strada.

Ma mantenere l'interfaccia semplice non è solo una cosa estetica; può fare la differenza tra un progetto di successo e una Marcia della morte. Giochiamo al difensore del diavolo per un minuto; immagina un progetto software senza astrazioni. Se è necessario mantenere un valore intorno, si utilizza una variabile globale. Se è necessario utilizzare la funzionalità più di una volta, si copia e incolla. Se hai bisogno di due versioni diverse di una certa sezione di codice, fai copia-incolla, racchiudila in un'istruzione if e modifica entrambi i rami. Tecnicamente parlando, funziona, ma a pochi mesi lungo la strada, dovrai combattere alcuni problemi davvero sgradevoli:

  • Quando trovi e correggi un bug, è probabile che esista anche in altre istanze copiate di codice simile, quindi oltre a trovare e correggere il bug, devi anche andare a cercare altre occorrenze e correggerle, anche.
  • Per trovare un bug o implementare una modifica, un programmatore di manutenzione deve essere in grado di comprendere il codice pertinente. La difficoltà nel fare ciò aumenta con la dimensione della sezione di codice rilevante, ma ancora di più con la sua portata. Mantenere una mezza dozzina di variabili nella tua testa mentre passi mentalmente attraverso il codice è fattibile; ma se ne hai poche centinaia, la tua produttività è gravemente compromessa (mi piace confrontare il processo di pensiero con un programma che esaurisce la RAM fisica e devi immergerti nel file di scambio: invece di leggere il codice fluentemente in una volta sola , il programmatore deve saltare avanti e indietro per cercare le cose).
  • Lo scopo di un pezzo di codice influisce anche sulla dimensione del codebase da scavare per trovare il bug. Se si dispone di una funzione a dieci righe con due parametri e nessuna globalità, e si conoscono i valori dell'input e la linea a cui si blocca, trovare il bug di solito è banale e spesso non richiede altro che guardare il codice. Se si tratta di poche centinaia di righe, venti parametri, quindici numeri globali e chiamate alcune altre funzioni di natura simile, ci si trova di fronte a qualche problema serio.
  • Senza un'astrazione appropriata, qualsiasi modifica può potenzialmente influire su ampie parti della base di codice, poiché praticamente qualsiasi cosa può dipendere dal codice da modificare. Un tipico sintomo di tali basi di codice è che si esegue un piccolo, apparentemente innocente cambiamento, e una caratteristica completamente indipendente si rompe improvvisamente. Con l'astrazione, puoi limitare la quantità di danni che un cambiamento può fare e rendere l'impatto più prevedibile. Se cambi il nome di un campo privato, hai solo un file sorgente da controllare; se cambi il nome di una variabile globale, devi eseguire l'intera base di codice.

In un codebase male astratto, l'impatto cresce in modo esponenziale con le dimensioni del codebase, ovvero l'aggiunta di una quantità costante di codice aumenta lo sforzo di manutenzione di un fattore costante. A peggiorare le cose, aggiungere più programmatori a un progetto non aumenta la produttività in modo lineare, ma logaritmicamente nella migliore delle ipotesi (perché più grande è il tuo team, maggiore è il sovraccarico per la comunicazione).

    
risposta data 26.01.2012 - 20:52
fonte
2

Penso che dovresti capire come funziona se necessario. Una volta stabilito che fa ciò che pensavi avrebbe fatto, allora hai la pace della mente. Non ho mai pensato che l'obiettivo fosse nasconderlo per sempre.

Una volta impostato un allarme su un orologio che si è sicuri funzionerà, è possibile dormire un po 'sapendo che si spegnerà al momento giusto. Svegliarsi un'ora prima, così da poter guardare i secondi che spuntano è uno spreco.

    
risposta data 26.01.2012 - 20:14
fonte
2

Per rispondere in modo specifico alle tue domande:

Is there real value in hiding the details?

Sì. Come confermi nella prima riga della tua domanda.

Aren't we sacrificing transparency?

Non proprio. Un'astrazione ben scritta faciliterà la comprensione dei dettagli, se necessario.

Isn't this transparency valuable?

Sì. Le astrazioni dovrebbero essere progettate e implementate per rendere la comprensione dei dettagli semplice quando necessario / desiderato.

    
risposta data 26.01.2012 - 21:14
fonte
1

Direi che nascondere i dettagli è fantastico quando le cose nascoste funzionano.

Ad esempio, diciamo che sviluppiamo un'interfaccia che definisce i comportamenti (es. GetListItems, SendListItem), che sono due caratteristiche che vengono avviate dall'utente tramite un clic del pulsante o qualcosa del genere .. ORA, ogni utente può avere il proprio "ListItemStore" .. diciamo uno su Facebook, uno su myspace .. (per esempio) .. e diciamo che è salvato come proprietà utente / impostazione da qualche parte nell'app tramite prefrenze dell'utente .. e che è possibile per gli sviluppatori di app aggiungere ulteriori ListItemStore su il corso del tempo (mybook, facespace, ecc.)

ora ci sono molti dettagli nella connessione a Facebook e nel recupero degli oggetti .. e ci sono altrettanti dettagli quando ci si connette a myspace .. e così via ...

ora, dopo che il codice iniziale di "accesso al negozio" è stato scritto, potrebbe non essere necessario modificarlo (beh, nel caso di facebook probabilmente abbiamo bisogno di uno sviluppatore a tempo pieno per tenere il passo con le modifiche, zing ..),

quindi quando usi il codice è qualcosa del tipo:

    new ItemManager(user) //passes in user, allowing class to get all user properties
    ItemManager.GetListItems()

e ora hai i dati dell'Utente da qualunque luogo siano stati archiviati, e dal momento che tutto ciò di cui sono preoccupato è ottenere l'elenco di elementi e fare qualcosa con esso, e poiché sono necessarie solo 2 linee che funzioneranno non importa quanti altri negozi vengono aggiunti posso tornare a rispondere / pubblicare domande sullo stack ... lol ..

Quindi, tutti gli impianti idraulici per farlo accadere sono "nascosti" e chi se ne frega davvero come fa finchè ottengo la lista corretta degli articoli .. se hai dei test unitari, puoi anche riposarti più facilmente perché i risultati avrebbero dovuto essere già quantificati ..

    
risposta data 26.01.2012 - 20:28
fonte
1

Ciò a cui ti riferisci come "Nascondersi", molti vedono come una separazione di preoccupazioni (ad esempio Implementazione rispetto all'interfaccia).

A mio parere, uno dei principali vantaggi dell'astrazione è di ridurre il disordine dei dettagli non necessari dal limitato spazio del cervello dello sviluppatore.

Se il codice di implementazione fosse stato offuscato, ho potuto vedere che la trasparenza, ma l'astrazione come la vedo io, è solo una buona organizzazione.

    
risposta data 26.01.2012 - 20:59
fonte
1

Prima di tutto, qualsiasi cosa oltre una singola istruzione di codice macchina è essenzialmente un'astrazione - un ciclo while...do è un modo simbolico coerente di rappresentare i confronti e le chiamate di indirizzo richieste per ripetere un insieme di istruzioni finché non viene soddisfatta una condizione. Allo stesso modo il tipo int è un'astrazione per il numero X di bit (a seconda del sistema). La programmazione è interamente basata sull'astrazione.

Probabilmente sarai d'accordo sul fatto che quelle astrazioni primitive siano di grande utilità. Bene, così è in grado di costruire il tuo. OOAD e OOP sono tutti circa.

Supponiamo di avere un requisito in base al quale gli utenti vogliono essere in grado di esportare i dati da uno schermo in una varietà di formati: testo delimitato, Excel e pdf. Non è pratico che tu possa creare un'interfaccia chiamata "Exporter" con un metodo di esportazione (dati), basato sul quale puoi costruire un DelimitedTextExporter, un ExcelExporter e un PDFExporter, ognuno dei quali sa come creare un suo particolare output? Tutto quello che il programma chiamante deve sapere è che può chiamare il metodo di esportazione (dati) e qualsiasi implementazione verrà utilizzata. Inoltre, se le regole delimitate del testo cambiano, è possibile modificare DelimitedTextExporter senza dover fare confusione con ExcelExporter, interrompendolo eventualmente.

Praticamente tutti i modelli di progettazione ben noti utilizzati nella programmazione OO dipendono dall'astrazione. Consiglierei di leggere i Head First Design Patterns di Freeman e Freeman per avere un'idea migliore del motivo per cui l'astrazione è una buona cosa

    
risposta data 26.01.2012 - 21:05
fonte
1

Penso di capire la tua opinione su questo, e penso di avere un'opinione simile.

Ho lavorato con sviluppatori Java che trasformano 50 code line class in 3 classi e 3 interfacce perché è facile da capire. E non potrei sopportarlo.

La cosa era terribilmente difficile da capire, quasi impossibile eseguire il debug e mai e poi mai aver bisogno di "cambiare l'implementazione".

D'altra parte, ho visto anche il codice in cui più oggetti condividono comportamenti simili e sono usati in un unico posto, e potrebbero davvero utilizzare ordinamenti comuni / loop di elaborazione se i metodi sarebbero stati esposti attraverso l'interfaccia comune.

Quindi, IMHO, gli oggetti principali che potrebbero essere utilizzati in scenari simili di solito traggono vantaggio da un comportamento comune che dovrebbe essere accessibile tramite l'interfaccia. Ma questo è praticamente tutto, l'astrazione di cose semplici perché è giusto, o rende possibile il passaggio di implementazioni è solo un modo per rendere il codice disordinato.

Quindi, di nuovo, preferisco le lezioni più intelligenti più lunghe rispetto a una quantità esplosiva di classi piccole con tutti i problemi di gestione della durata, e le relazioni difficili da vedere e i grafici delle chiamate sugli spaghetti. Quindi alcune persone non saranno d'accordo con me.

    
risposta data 26.01.2012 - 22:22
fonte
1

Lo scopo guida del nascondimento e dell'astrazione dovrebbe essere disaccoppiare l'utente dall'implementazione in modo che possano essere modificati indipendentemente se il consumatore è accoppiato con i dettagli di implementazione, a causa di giocherellare con i loro interni entrambi sono scolpiti nella pietra e diventa più difficile introdurre nuove funzionalità o algoritmi migliori in futuro.

Durante la scrittura di un modulo, parti nascoste dell'implementazione ti danno il vantaggio di essere in grado di cambiarle senza rischiare di rompere altri codici a cui non riesci a pensare.

Un altro vantaggio di fornire interfacce opache è che riducono in modo significativo la superficie tra i sottosistemi. Riducendo la quantità di modi in cui possono interagire possono diventare più prevedibili, più facili da testare e avere meno bug. Le interazioni tra i moduli aumentano anche quadraticamente con il numero di moduli, quindi c'è un valore nel tentativo di controllare questa crescita della complessità.

Detto questo, è ovviamente possibile nascondere troppo e nidificare le interfacce troppo in profondità. È compito del programmatore, in quanto uomo intelligente, progettare il sistema in modo che sia massimamente utile, riducendo al minimo la complessità e massimizzando la manutenibilità.

    
risposta data 27.01.2012 - 13:00
fonte
0

In così tanti casi, semplicemente non è necessario per sapere come sono implementate le cose. Posso quasi garantire che scriverò codice come people.Where(p => p.Surname == "Smith") così tante volte al giorno, ma difficilmente penserai mai "come funziona effettivamente questo metodo Where() ?" Semplicemente non ti interessa - sai che questo metodo è lì e che ti ottiene i risultati che desideri. Perché ti interessa come funziona?

Questo è esattamente lo stesso per qualsiasi software interno; solo perché non è scritto da Oracle, Microsoft, ecc. non significa che dovresti andare a caccia di come è implementato. Puoi ragionevolmente aspettarti che un metodo chiamato GetAllPeopleWithSurname(string name) ti restituisca un elenco di persone che hanno quel cognome. Potrebbe scorrere su un elenco, potrebbe utilizzare un dizionario, potrebbe fare qualcosa di completamente pazzo ma non dovresti interessarti .

Ovviamente c'è una eccezione a questa regola (non sarebbe una regola senza una!) e cioè se c'è un bug nel metodo. Quindi nell'esempio sopra, se hai una lista con 3 persone e sai che uno di loro ha il cognome Smith e non vengono restituiti nella lista allora ti interessa l'implementazione di quel metodo perché è chiaramente rotto.

L'astrazione, se eseguita correttamente, è meravigliosa perché ti consente di filtrare tutto ciò che non è utile quando devi leggerlo in un secondo momento. Non dimenticare che si impiega molto più tempo per leggere il codice di quanto si è speso a scriverlo, quindi l'accento deve essere posto sulla semplificazione del compito. Potresti anche pensare che l'astrazione significhi una gerarchia di oggetti purché il tuo braccio, ma può essere semplice come refactoring di un metodo a 100 linee in 10 metodi, ciascuno lungo 10 righe. Quindi, quello che una volta erano 10 passi raggruppati insieme ora sono 10 passaggi separati che ti permettono di andare direttamente nel punto in cui questo fastidioso bug si nasconde.

    
risposta data 26.01.2012 - 22:37
fonte
0

Le astrazioni determinano l'occultamento delle informazioni. Questo dovrebbe finire in un accoppiamento inferiore. Ciò dovrebbe portare a minori rischi nei cambiamenti. Ciò dovrebbe portare a programmatori felici, non innervosirsi quando si tocca il codice.

Queste idee sono espresse attraverso tre leggi fondamentali nell'architettura del software:

La legge di Simon: "Le gerarchie riducono la complessità". (Le gerarchie introducono l'astrazione)

Legge di Parna: "Solo ciò che è nascosto può essere modificato senza rischi."

La legge di Constantin: I programmi robusti richiedono un accoppiamento basso e un'elevata coesione

    
risposta data 26.01.2012 - 23:41
fonte
0

Anch'io sono nel business delle applicazioni aziendali e questa domanda mi ha attirato perché anch'io ho la stessa domanda. Finora ho avuto alcune informazioni sul problema dell'astrazione nel corso della mia carriera, ma la mia intuizione non è affatto la risposta universale. Sto continuando a imparare / ascoltare nuove idee e pensieri, quindi quello che credo ora potrebbe cambiare.

Quando stavo mantenendo una domanda sanitaria complessa e complessa, mi piaceva, odiavo tutte le astrazioni lì. Capire dove è andato tutto il codice è stato il dolore al collo. Saltare in diverse classi mi ha fatto girare la testa. Quindi mi sono detto "l'astrazione fa schifo, ridurrò al minimo l'astrazione quando disegno cose".

Poi, è arrivato il momento in cui ho dovuto progettare un'applicazione (il relativo piccolo componente del servizio Web) da zero. Ricordando tutto il dolore, avevo un design piuttosto piatto del componente. Il problema era che, quando i requisiti cambiarono, dovevo cambiare in molti posti diversi (i requisiti erano piuttosto fluidi e non potevo fare nulla al riguardo). E 'stato così brutto, fondamentalmente ho buttato via il mio progetto iniziale e riprogettato con l'astrazione, e le cose sono migliorate - non ho dovuto apportare modifiche in molti posti quando i requisiti sono cambiati di più.

Ho consegnato l'applicazione, sono rimasto in giro per alcune settimane, quindi mi è stato detto di iniziare a mantenere l'applicazione. Ero stato per un po ', non ricordavo tutto, quindi ho faticato un po' per capire il mio codice e l'astrazione non mi ha aiutato.

Sono stato messo su molti altri progetti in seguito e ho avuto la possibilità di giocare un po 'di più con i livelli di astrazione. Quello che trovo è, e questa è solo la mia personale opinione, l'astrazione aiuta molto nello sviluppo ma ha un impatto negativo quando non scrivi il codice e stai cercando di capire tutto al livello più profondo di un'applicazione; trascorrerai più tempo saltando attorno a classi diverse e cercando di stabilire le connessioni.

La mia sensazione è che l'astrazione sia così preziosa durante il tempo di sviluppo che il problema che affrontiamo come manutentore nel cercare di capire il codice valga la pena. Il software esiste per risolvere i problemi aziendali, i problemi aziendali si evolvono nel tempo; quindi, il software deve evolversi nel tempo. Senza astrazione, l'evoluzione del software è molto difficile. Si può progettare l'astrazione in modo che il manutentore possa navigare facilmente attorno al codice base una volta che vedono il modello della struttura del codice, in modo che solo la curva di apprendimento iniziale sia frustrante.

    
risposta data 27.01.2012 - 16:12
fonte
0

Come altri hanno già detto, "nascondere i dettagli" dietro un'astrazione consente di modificarli senza influire sugli utenti. Questa idea proviene da Parnas ' sui criteri da utilizzare per decomporre i sistemi nei moduli (1972), ed è correlato all'idea di tipi di dati astratti (ADT) e programmazione orientata agli oggetti.

Allo stesso tempo, il di Codd è un modello relazionale di dati per grandi condivisioni Data Banks (1970) è stato motivato (vedere l'abstract e l'intro) volendo modificare la rappresentazione interna dello storage dei database, senza influenzare gli utenti del database. Aveva visto i programmatori prendere regolarmente giorni, modificando le pagine di codice, per far fronte a piccoli cambiamenti di archiviazione.

Detto questo, un'astrazione non è molto utile se devi vedere cosa c'è dentro per poterla usare. Può essere molto difficile progettarlo bene. Un esempio di buona astrazione è l'aggiunta - quando è stata l'ultima volta che hai dovuto pensare a cosa succede dentro? (ma a volte lo fai, ad esempio per overflow).

Il problema essenziale (IMHO) è che per progettare bene i moduli (secondo il senso di Parnas), è necessario prevedere cosa cambierà e cosa no. Predire il futuro è difficile - ma se hai molta esperienza con qualcosa e comprendi chiaramente, allora puoi fare un buon lavoro di previsione. E quindi, puoi progettare un modulo (astrazione) che funzioni bene.

Tuttavia, sembra il destino di tutte le astrazioni - anche le migliori - che alla fine ci saranno cambiamenti imprevisti (e probabilmente imprevedibili) che richiedono la rottura dell'astrazione. Per risolvere questo problema, alcune astrazioni hanno una via di fuga, dove puoi accedere ad un livello più profondo se ne hai davvero bisogno.

Questo sembra tutto molto negativo. Ma penso che la verità sia che siamo circondati da astrazioni che funzionano così bene che non le notiamo o non realizziamo ciò che nascondono. Notiamo solo le scarse astrazioni, quindi abbiamo una visione itterica di esse.

    
risposta data 31.01.2012 - 00:56
fonte
0

Le astrazioni sono per lo più a beneficio dei loro consumatori (ad es. programmatori di applicazioni). I programmatori del sistema (designer) hanno più lavoro da fare per renderli belli e utili, ed è per questo che un buon design non viene solitamente svolto dai principianti.

Forse non ti piacciono le astrazioni perché aggiungono sempre complessità? Forse i sistemi su cui hai lavorato avevano un'astrazione (uso eccessivo di astrazioni)? Non sono una panacea.

Il lavoro extra e la complessità di un'astrazione utile dovrebbero ripagare, ma è difficile saperlo con certezza. Se si pensa a un'astrazione come a un punto cardine, il design del software può flettere su entrambi i lati: le implementazioni dell'astrazione possono essere modificate senza violare il codice cliente e / o i nuovi client possono facilmente riutilizzare l'astrazione per fare nuove cose.

Potresti quasi misurare il ritorno sull'investimento delle astrazioni mostrando che sono state "flesse" nel tempo in una o entrambe le direzioni: cambiamenti di implementazione relativamente indolore e nuovi clienti aggiuntivi.

Ad esempio: utilizzando l'astrazione della classe Socket in Java, sono sicuro che il mio codice applicazione da Java 1.2 funziona ancora bene con Java 7 (anche se potrebbero esserci delle modifiche alle prestazioni). Dal momento che Java 1.2, ci sono stati sicuramente molti nuovi client che hanno utilizzato questa astrazione.

Per quanto riguarda l'infelicità con le astrazioni, se avessi parlato con gli sviluppatori che hanno mantenuto il codice dietro della classe Socket, allora forse le loro vite non sono così pesche e rosei come i clienti che hanno usato Socket per scrivere divertimento applicazioni. Lavorare all'implementazione di un'astrazione sicuramente è più lavoro che usarlo. Ma questo non lo rende cattivo.

Per quanto riguarda la trasparenza, in una strategia di progettazione top-down, la trasparenza totale crea cattivi design. I programmatori intelligenti tendono a sfruttare al massimo le informazioni a loro disposizione e il sistema diventa quindi strettamente accoppiato. Il più piccolo cambiamento di dettaglio (ad esempio, la modifica dell'ordine dei byte in una struttura dati) in un modulo potrebbe interrompere qualche codice da qualche altra parte, perché un programmatore intelligente ha usato quell'informazione per fare qualcosa di utile. David Parnas ha indicato questo problema in articoli del 1971 dove ha proposto nascondere le informazioni nei disegni.

Il tuo riferimento ad ArchLinux ha senso per me se consideri il "dentro" del sistema operativo come la complessa implementazione dell'astrazione che è il sistema operativo per le applicazioni che vengono eseguite su di esso. Mantienilo semplice nelle viscere dell'astrazione.

    
risposta data 28.08.2012 - 20:37
fonte
0

Risponderò alla tua domanda con una domanda; stamattina quando andavi al lavoro (presumo che in effetti lo facessi), ti è importato esattamente come il motore ha aperto le valvole per far entrare le miscele di carburante-aria e poi le ha accese? No. Non ti interessa come il motore della tua auto funziona quando stai guidando lungo la strada. Ti interessa che faccia funzioni.

Supponiamo che un giorno la tua macchina non funzioni. Non inizia, lancia una canna, rompe una cintura, inspiegabilmente solca quella barriera di cemento senza colpa tua mentre eri impegnato a mandare sms. Ora, hai bisogno di una nuova macchina (almeno temporaneamente). Ti importa esattamente come funziona questa nuova macchina? No. Quello che ti interessa è innanzitutto che funzioni, e in secondo luogo che puoi usare le stesse conoscenze e abilità che hai usato per guidare la tua vecchia auto per guidare quella nuova. Idealmente, dovrebbe sembrarti che non ci siano stati cambiamenti nell'auto che stai guidando. Realisticamente, il modo in cui funziona questa nuova macchina dovrebbe darti il minor numero possibile di "sorprese".

Questi principi fondamentali sono il principio cardine dietro l'incapsulamento e l'astrazione. La conoscenza di come un oggetto fa quello che fa non dovrebbe essere un requisito per usarlo per fare ciò che fa. Anche nella programmazione dei computer, i dettagli dei percorsi elettrici all'interno della CPU che esegue il programma sono estratti da almeno una mezza dozzina di livelli di istruzioni di I / O, driver, software del sistema operativo e runtime. Molti ingegneri del software di grande successo scrivono un codice perfettamente buono senza preoccuparsi dell'architettura hardware esatta o della build del sistema operativo che lo eseguirà. Compreso me.

L'incapsulamento / nascondimento delle informazioni consente alla mentalità "non importa come funziona, basta preoccuparsi che faccia". Il tuo oggetto dovrebbe esporre ciò che è utile al consumatore, in un modo che il consumatore può facilmente consumare. Ora, nel mondo reale, questo non significa che una macchina non dovrebbe fornire all'utente alcuna informazione sul funzionamento interno, o che l'auto dovrebbe consentire all'utente solo le funzionalità più elementari come l'accensione, il volante, e pedali. Tutte le auto hanno tachimetri e indicatori di livello carburante, tachimetri, luci idiota e altri feedback. Praticamente tutte le vetture dispongono anche di interruttori per vari sottosistemi indipendenti, come fari, indicatori di direzione, radio, regolazione del sedile, ecc. Alcune macchine consentono alcuni input utente piuttosto esoterici, come la sensibilità del differenziale centrale a slittamento limitato. In tutti i casi, se ne conosci abbastanza, puoi aprirlo e cambiare le cose per farlo funzionare in un modo leggermente diverso. Ma, nella maggior parte dei casi, forse, solo forse, l'utente non dovrebbe essere in grado di controllare direttamente e in modo indipendente le pompe del carburante dall'interno della cabina? Forse, solo forse, l'utente non dovrebbe essere in grado di attivare le luci dei freni senza effettivamente premere il pedale del freno?

L'astrazione permette che "questo non è lo stesso, ma perché sono entrambi X posso usarli come vorrei ogni mentalità X". Se il tuo oggetto eredita o implementa un'astrazione, i tuoi consumatori dovrebbero aspettarsi che la tua implementazione produca lo stesso risultato o lo stesso risultato di altre implementazioni conosciute dell'astrazione. Una Toyota Camry e una Ford Fusion sono entrambe "macchine". Come tali, hanno una serie comune di funzionalità previste, come un volante. Giralo in senso antiorario, la macchina va a sinistra. Giralo in senso orario, la macchina va bene. Puoi salire su qualsiasi auto negli Stati Uniti e aspettarti che l'auto abbia un volante e almeno due pedali, quello a destra è il pedale "la macchina va" e quello al centro è il pedale "ferma auto" .

Un corollario di astrazione è la "teoria del minimo stupore". Se ti mettessi al volante di una nuova auto per un giro di prova, ruotasse il volante in senso orario e la macchina girasse a sinistra, saresti piuttosto stupito a dir poco. Dovresti accusare il rivenditore di spacciare un POS e difficilmente ascolterai una delle sue ragioni per cui il nuovo comportamento è "migliore" di quello a cui sei abituato, o quanto bene questo comportamento è "documentato" o come " trasparente "il sistema di controllo è. Nonostante questa nuova auto e tutte le altre che hai guidato ancora come "auto", quando guidi questa vettura devi cambiare alcuni concetti fondamentali su come si suppone che una macchina debba essere guidata per guidare con successo la nuova vettura. Tipicamente è una cosa brutta, e succede solo quando c'è un vantaggio intuitivo nel nuovo paradigma. Forse l'aggiunta delle cinture di sicurezza è un buon esempio; 50 anni fa sei appena entrato e sei andato, ma ora devi allacciare le cinture, il vantaggio intuitivo è che non si passa attraverso il parabrezza o sul sedile del passeggero in caso di incidente. Anche allora, i piloti hanno resistito; molti proprietari di auto hanno tagliato le cinture di sicurezza fuori dall'auto fino a quando non sono state approvate delle leggi che ne autorizzano l'uso.

    
risposta data 28.08.2012 - 21:37
fonte

Leggi altre domande sui tag