Penso che potresti trovare un post di blog del mio su perdente astrazioni utili. Ecco lo sfondo pertinente:
Abstraction è un meccanismo per aiutare a prendere ciò che è comune tra un gruppo di frammenti di programma correlati, rimuovere le loro differenze e consentire ai programmatori di lavorare direttamente con un costrutto che rappresenta quel concetto astratto. Questo nuovo costrutto (virtualmente) ha sempre parametrizzazioni : un mezzo per personalizzare l'uso del costrutto in base alle tue esigenze specifiche.
Ad esempio, una classe List
può astrarre i dettagli di un'implementazione di liste collegate-- dove invece di pensare in termini di manipolazione di next
e previous
puntatori, puoi pensare al livello di aggiunta o rimuovendo valori in una sequenza. L'astrazione è uno strumento essenziale per creare utili, ricche e talvolta complesse funzionalità da un insieme molto più piccolo di concetti più primitivi.
L'astrazione è legata all'incapsulamento e alla modularità e questi concetti sono spesso fraintesi.
Nell'esempio List
, incapsulamento può essere utilizzato per nascondere i dettagli di implementazione di una lista concatenata; in un linguaggio orientato agli oggetti, ad esempio, puoi rendere privati i puntatori next
e previous
, in cui solo l'implementazione Elenco può accedere a questi campi.
L'incapsulamento non è sufficiente per l'astrazione, perché non implica necessariamente una concezione nuova o diversa dei costrutti. Se tutta la classe List
ha dato i metodi di accesso allo stile ' getNext
' / ' setNext
', verrebbe incapsulata dai dettagli dell'implementazione (ad esempio, hai nominato il campo ' prev
' o ' previous
'? qual era il suo tipo statico?), ma avrebbe un grado di astrazione molto basso.
Modularità si occupa di nascondere le informazioni : le proprietà stabili sono specificate in un'interfaccia e un modulo implementa tale interfaccia, mantenendo tutti i dettagli di implementazione all'interno del modulo. La modularità aiuta i programmatori ad affrontare le modifiche, perché gli altri moduli dipendono solo dall'interfaccia stabile.
L'occultamento delle informazioni è facilitato dall'incapsulazione (in modo che il codice non dipenda da dettagli di implementazione instabili), ma l'incapsulamento non è necessario per la modularità. Ad esempio, puoi implementare una struttura List
in C, esponendo i puntatori ' next
' e ' prev
' al mondo, ma fornisci anche un'interfaccia, contenente initList()
, addToList()
e removeFromList()
funzioni. A condizione che le regole dell'interfaccia vengano seguite, è possibile garantire che determinate proprietà rimarranno sempre valide, ad esempio garantendo che la struttura dei dati sia sempre in uno stato valido. [La carta classica di Parna sulla modularità, per esempio, è stata scritta con un esempio in assemblea. L'interfaccia è un contratto e una forma di comunicazione sul design, non deve necessariamente essere controllata meccanicamente, anche se è quello su cui ci basiamo oggi.]
Sebbene termini come astratti, modulari e incapsulati siano usati come descrizioni positive del design, è importante rendersi conto che la presenza di una di queste qualità non ti dà automaticamente un buon design:
-
Se un algoritmo n ^ 3 è "ben incapsulato", funzionerà ancora peggio di un algoritmo n log n migliorato.
-
Se un'interfaccia si impegna su uno specifico sistema operativo, nessuno dei vantaggi di un design modulare sarà realizzato quando, per esempio, un videogioco deve essere trasferito da Windows all'iPad.
-
Se l'astrazione creata espone troppi dettagli inessenziali, non riuscirà a creare un nuovo costrutto con le proprie operazioni: sarà semplicemente un altro nome per la stessa cosa.