Perché non esiste una definizione coerente di concetti essenziali per OOP?


12

Sono molto nuovo nella programmazione e un po 'confuso dalla lettura / ascolto di convenzioni diverse da fonti diverse:

La programmazione orientata agli oggetti ha 4 o 5 concetti?

Come nuovo arrivato, capisco che questi sono i 5 concetti:

  • Astrazione
  • Eredità
  • incapsulamento
  • Polimorfismo
  • modularità

Quindi come mai non trovo una definizione più "rigorosa" e sembrano esserci diverse disposizioni di questi concetti là fuori?


7
Forse perché non è come la matematica (alcuni concetti in CS sono, ma penso che OOP non appartenga a questa categoria), quindi non ci sono definizioni rigide per cominciare. Ad esempio, quanto è importante la "modularità"? È davvero così speciale per OOP che dobbiamo menzionarlo o sarebbe solo qualcosa che accade da solo se applichiamo correttamente gli altri quattro? Alcune liste aggiungono "gerarchia", ma è davvero qualcosa in più o segue solo l'eredità e il polimorfismo?
Thorsten Müller,

6
Parola di consiglio: come programmatore nuovissimo non dovresti essere così impiccato nella comprensione della terminologia e della teoria. Raccogli prima alcune esperienze pratiche di programmazione e diventerà molto più ovvio di cosa stanno parlando queste persone.
Philipp

9
Un'altra cosa è che OOP sta cambiando nel tempo. Molta attenzione nei primi giorni del C ++ (so che OOP è molto più indietro di così) era su Ereditarietà e polimorfismo. L'attenzione di oggi è molto più sull'astrazione e sull'incapsulamento.
Bent

3
Alcune interessanti discussioni sulla mancanza di precisione nella definizione di OO possono essere trovate qui: c2.com/cgi/wiki?NobodyAgreesOnWhatOoIs
MichelHenrich

Risposte:


26

Il motivo per cui si trovano diverse spiegazioni sul significato della programmazione orientata agli oggetti è perché non esiste una singola persona o organizzazione con l'autorità di formulare una definizione rigorosa universalmente applicabile.

La programmazione orientata agli oggetti non è uno standard ISO o una legge scientifica. È una filosofia. E come in tutte le filosofie, ci sono tutti i tipi di interpretazioni diverse e nessuna interpretazione è universalmente applicabile. Quando leggi un testo che ti dice quali concetti dovresti seguire durante la progettazione di un'architettura software, dovresti vederlo come una linea guida basata sulle opinioni formate dall'autore durante la loro esperienza professionale e non come una verità universale.


12

La programmazione orientata agli oggetti ha 5 o 4 componenti?

Come altri hanno già detto, "OO" non ha davvero alcun componente , perché è un modo di pensare alla modellazione di soluzioni ai problemi e non a un kit di strumenti né a una serie di processi chiaramente definiti.

Come nuovo arrivato, capisco che questi sono i 5 componenti:

Astrazione, ereditarietà, incapsulamento, polimorfismo e modularità?

Ereditarietà e polimorfismo sono funzioni del linguaggio di programmazione. È bene che tu li capisca, ma ricorda che sono strumenti (il che significa che, come con qualsiasi altro strumento, dovrebbero essere usati solo per risolvere problemi specifici e non trattati come un obiettivo o qualcosa a cui puntare). Puoi (e spesso dovresti) scrivere il codice "OO" senza usare nessuno dei due. Alcuni dei migliori codici "OO" che io abbia mai visto fanno ben poco uso dell'ereditarietà o del polimorfismo.

Astrazione, incapsulamento e modularità hanno meno a che fare con il codice e di più sul modo in cui si esamina un problema, sul modo in cui si tenta di comprenderlo e sul modo in cui si progetta e struttura la soluzione nel codice.

Inoltre, queste idee di design non sono esclusive di "OO". È probabile che tu li capisca ora a un livello di base, il che potrebbe includere la capacità di spiegare una definizione perfetta da manuale e applicarli a problemi in qualche modo non banali; sebbene un test più approfondito di comprensione stia ricevendo un problema molto grande e complesso e quanta complessità tu possa gestire.

Un altro test di comprensione è l'approccio che usi per abbattere un problema; e i nuovi arrivati ​​a "OO", a cui viene spesso insegnato a proposito di OO in termini di modellizzazione dei dati (perché è così che la maggior parte delle persone lo capiva negli anni '90), e spesso finiscono per concentrarsi sugli aspetti sbagliati di un problema - cioè si concentrano troppo sui dati e non si concentrano abbastanza sul comportamento.

Ad esempio, esempi classici fanno spesso riferimento a entità come Dog, Cat, Elephant, Seagull, Shark, ecc I nuovi arrivati "OO", spesso guardo esempi e subito penso "Oh, ho bisogno di un'entità di base chiamato Animal" , e possono anche finire con altri entità intermedie come Mammale Amphibianin un'ordinata eredità ereditaria, con attributi diversi in ciascuna.

Mentre quel modo di pensare dimostra una comprensione molto basilare di diversi concetti di OO, un programmatore di OO con esperienza non si avvicinerebbe mai così o non salterebbe a quella conclusione (e in realtà si lamenterebbe di non avere abbastanza informazioni), perché quell'approccio dimostra Entità modellazione piuttosto che modellazione OO, e perché l'esempio inventato non dice nulla sul comportamento di quegli animali (E molte persone sostengono in questi giorni che l' essenza di OO è tutta nel comportamento e nella funzionalità).

Il percorso per imparare a conoscere "OO" prevede tradizionalmente passare il tempo a costruire astrazioni sbagliate quando non si conosce nulla (o troppo poco) sul comportamento del problema che si sta modellando o quando si commette l'errore di focalizzare la propria attenzione sulle entità anziché funzionalità, anche se parte di ciò è dovuto al fatto che così tanti libri, corsi e tutorial online scritti nel corso degli anni hanno (erroneamente) guidato gli studenti lungo quel percorso (la marea sta cambiando però).

Complessivamente, molta della tua comprensione si riduce all'esperienza. Quei concetti che hai appreso finora sono un buon inizio, ci sono più concetti che dovrai imparare lungo il percorso (ad esempio, i principi "SOLID" e "DRY") e dovrai dedicare molto tempo a mettere la teoria in pratica con problemi reali molto complessi prima che sia probabile che tutti "scattino" in posizione.


2
Uno squalo e una rana nuotano entrambi, ma uno è un pesce, l'altro è un anfibio. Penso che questo esempio descriva bene il tuo punto.
RubberDuck,

10

Il termine "Orientamento agli oggetti" è stato coniato dal Dr. Alan Kay, quindi è la fonte autorevole su ciò che significa, e lo definisce così :

OOP per me significa solo messaggistica, conservazione locale, protezione e occultamento del processo statale ed estremo vincolo tardivo di tutte le cose.

Analizziamo questo:

  • messaggistica ("invio metodo virtuale", se non si ha familiarità con Smalltalk)
  • il processo statale dovrebbe essere
    • mantenuto localmente
    • protetta
    • nascosto
  • estremo legame tardivo di tutte le cose

Per quanto riguarda l'implementazione, la messaggistica è una chiamata di procedura in ritardo e, se le chiamate di procedura sono in ritardo, non è possibile sapere in fase di progettazione ciò che si intende chiamare, quindi non è possibile fare ipotesi sulla rappresentazione concreta dello stato. Quindi, in realtà si tratta di messaggistica, il late-binding è un'implementazione della messaggistica e l'incapsulamento ne è una conseguenza.

In seguito ha chiarito che " La grande idea è" messaggistica ", e si rammarica di averla definita" orientata agli oggetti "anziché" orientata ai messaggi ", poiché il termine" orientato agli oggetti "pone l'accento sulla cosa non importante (oggetti ) e distrae da ciò che è veramente importante (messaggistica):

Solo un gentile promemoria che ho fatto un po 'di fatica all'ultimo OOPSLA per cercare di ricordare a tutti che Smalltalk NON è solo la sua sintassi o la libreria di classi, non si tratta nemmeno di classi. Mi dispiace di aver coniato molto tempo fa il termine "oggetti" per questo argomento perché molte persone si concentrano sull'idea minore.

La grande idea è "messaggistica" - ecco di cosa si occupa il kernal di Smalltalk / Squeak (ed è qualcosa che non è mai stato del tutto completato nella nostra fase PARC Xerox). I giapponesi hanno una piccola parola - ma - per "ciò che sta in mezzo" - forse l'equivalente inglese più vicino è "interstiziale". La chiave per realizzare sistemi grandi e coltivabili è molto di più per progettare come comunicano i suoi moduli piuttosto che quali dovrebbero essere le loro proprietà e comportamenti interni. Pensa a Internet: per vivere, (a) deve consentire molti diversi tipi di idee e realizzazioni che vanno oltre ogni singolo standard e (b) per consentire vari gradi di interoperabilità sicura tra queste idee.

(Certo, oggi, la maggior parte delle persone non si concentra nemmeno sugli oggetti ma sulle classi, il che è ancora più sbagliato.)

La messaggistica è fondamentale per OO, sia come metafora che come meccanismo.

Se invii a qualcuno un messaggio, non sai cosa ci fanno. L' unica cosa che puoi osservare è la loro risposta. Non sai se hanno elaborato il messaggio da soli (cioè se l'oggetto ha un metodo), se hanno inoltrato il messaggio a qualcun altro (delega / proxy), se lo hanno persino capito. Ecco cos'è l'incapsulamento, questo è OO. Non puoi nemmeno distinguere un proxy dalla realtà, purché risponda a come ti aspetti.

Un termine più "moderno" per "messaggistica" è "invio di metodo dinamico" o "chiamata di metodo virtuale", ma che perde la metafora e si concentra sul meccanismo.

Quindi, ci sono due modi per guardare la definizione di Alan Kay: se la guardi da sola, potresti osservare che la messaggistica è fondamentalmente una chiamata di procedura in ritardo e l'associazione in ritardo implica l'incapsulamento, quindi possiamo concludere che # 1 e il n. 2 sono in realtà ridondanti e OO riguarda il late-binding.

Tuttavia, in seguito ha chiarito che la cosa importante è la messaggistica, e quindi possiamo guardarla da una prospettiva diversa: la messaggistica è in ritardo. Ora, se la messaggistica fosse l' unica cosa possibile, allora la # 3 sarebbe banalmente vera: se c'è solo una cosa, e quella cosa è in ritardo, allora tutte le cose sono in ritardo. E ancora una volta, l'incapsulamento segue dalla messaggistica.

Punti analoghi vengono anche menzionati in On Understanding Data Abstraction, rivisitato da William R. Cook e anche nella sua proposta di definizioni semplificate e moderne di "oggetto" e "oggetto orientato" .

L'invio dinamico delle operazioni è la caratteristica essenziale degli oggetti. Significa che l'operazione da invocare è una proprietà dinamica dell'oggetto stesso. Le operazioni non possono essere identificate staticamente e in generale non è possibile stabilire esattamente quale operazione verrà eseguita in risposta a una determinata richiesta, tranne eseguendola. Questo è esattamente lo stesso delle funzioni di prima classe, che vengono sempre inviate in modo dinamico.

In Smalltalk-72 non c'erano nemmeno oggetti! C'erano solo flussi di messaggi che venivano analizzati, riscritti e reindirizzati. Prima sono arrivati ​​i metodi (metodi standard per analizzare e reindirizzare i flussi di messaggi), successivamente sono arrivati ​​gli oggetti (raggruppamenti di metodi che condividono un certo stato privato). L'eredità è arrivata molto più tardi e le classi sono state introdotte solo come un modo per sostenere l'eredità. Se il gruppo di ricerca di Kay avesse già saputo dei prototipi, probabilmente non avrebbero mai introdotto le classi.

Benjamin Pierce in Tipi e linguaggi di programmazione sostiene che la caratteristica principale di Orientamento agli oggetti è Open Recursion .

Quindi: secondo Alan Kay, OO è tutto basato sulla messaggistica. Secondo William Cook, OO si basa sulla spedizione di metodi dinamici (che è davvero la stessa cosa). Secondo Benjamin Pierce, OO è tutto incentrato su Open Recursion, il che significa sostanzialmente che gli auto-riferimenti vengono risolti dinamicamente (o almeno questo è un modo di pensare), o, in altre parole, i messaggi.

Come puoi vedere, la persona che ha coniato il termine "OO" ha una visione piuttosto metafisica degli oggetti, Cook ha una visione piuttosto pragmatica e Pierce una visione matematica molto rigorosa. Ma la cosa importante è: il filosofo, il pragmatico e il teorico sono tutti d'accordo! La messaggistica è l'unico pilastro di OO. Periodo.

Nota che qui non si parla di eredità! L'ereditarietà non è essenziale per OO. In generale, la maggior parte dei linguaggi OO ha un modo per riutilizzare l'implementazione, ma ciò non deve necessariamente essere ereditarietà. Potrebbe anche essere una qualche forma di delega, per esempio. In effetti, il Trattato di Orlando tratta la delega come alternativa all'eredità e in che modo diverse forme di delega ed eredità portano a diversi punti di progettazione all'interno dello spazio di progettazione di linguaggi orientati agli oggetti. (Si noti che in realtà anche nelle lingue che supportano l'ereditarietà, come Java, alle persone viene effettivamente insegnato a evitarlo, indicando di nuovo che non è necessario per OO.)


1
@DavidArno Il tuo commento non è affatto costruttivo. Alan Kay stesso afferma di aver coniato il termine "oggetto" per questo concetto (sebbene, suppongo, non il concetto stesso). Se stai per contraddire un'autorità ben nota sull'argomento, almeno scrivi un commento più costruttivo.
Andres F.

1
@DavidArno Inoltre, il downvote è tuo? Quindi qualcuno si è preso il tempo di scrivere un elenco completo di diversi punti di vista, di noti esperti, su cosa significhi OOP e lo hai declassato perché non sei d'accordo con una sola frase? Oookay.
Andres F.

2
@AndresF. Questa risposta può essere riassunta come "ci sono due scuole, quella di Alan Kay e quella di tutti gli altri. Perché il primo ha coniato il termine ha automaticamente ragione e tutti quelli che non sono d'accordo con lui hanno torto". È un appello alla risposta fallace dell'autorità. Quindi il downvote.
David Arno,

2
In realtà, questa risposta può essere riassunta come "ci sono tre scuole di pensiero, che provengono da tre angolazioni completamente diverse e nessuno è in disaccordo con nessuno, infatti, sono tutti d'accordo". Il prescrittivista linguistico direbbe, Alan Kay ha inventato il termine, riesce a dire cosa significa e dice che significa messaggistica. Il descrittore linguistico direbbe, no, Alan Kay non riesce a dire nulla, dobbiamo vedere come viene effettivamente utilizzato il termine , ed è quello che Cook ha fatto: ha studiato quali lingue sono comunemente descritte come OO (Java, C ++ , C #, ecc.) Hanno in comune, e ha scoperto
Jörg W Mittag il

3
una cosa: la messaggistica.Ha studiato quali lingue comunemente descritte come non OO mancano di quelle comunemente descritte come OO e ha trovato una cosa: la messaggistica. Il teorico della torre d'avorio prende il calcolo λ e osserva quale sia la più piccola serie di funzionalità che si dovrebbe aggiungere per ottenere qualcosa che è comunemente descritto come OO, e arriva alla ricorsione aperta , che è fondamentalmente la base per la messaggistica .
Jörg W Mittag

3

Come afferma @Philipp, la radice del problema è che non esiste una definizione ufficiale di ciò che rende un linguaggio di programmazione orientato agli oggetti. Anzi, questa è probabilmente una buona cosa. Esistono molti modi per supportare la programmazione OO, ognuno con i propri vantaggi e svantaggi. La discussione su quali lingue sono più "pure OO" non raggiunge molto.

Tuttavia, guardando i 5 attributi che hai elencato, a mio avviso la modularità è sicuramente la strana fuori. La modularità è in realtà un attributo di un programma, non un linguaggio di programmazione. A livello linguistico, l'attributo è "supporto per la modularizzazione", che in genere assume la forma di un meccanismo "moduli" pr "pacchetti".

Ma la mia vera obiezione alla modularità è che non è la chiave della programmazione OO o dei linguaggi di programmazione OO, nella misura in cui il linguaggio di programmazione archetipico Smalltalk-80 non supporta affatto i moduli. E a pensarci bene, il supporto linguistico per i moduli in molti OOPL ampiamente utilizzati è "debole".

I moduli sono progettati per supportare la "programmazione in grande" ... dove la tua base di codice diventa troppo grande per essere compresa da una sola persona. E non hai bisogno di moduli in un linguaggio di programmazione per modulare il tuo codice.


Non sto entrando nel dibattito sull'altro attributo 4 e se (per esempio) quali modelli di "ereditarietà" siano OO puri. Inoltre, mentre Alan Kay è accreditato per aver inventato la programmazione OO, ciò non significa necessariamente che le sue definizioni di OO / e OOPL abbiano il primato. Chiaramente, non è così. È una fonte autorevole, ma ci sono altre fonti che danno altre definizioni per OO e OOPL che (in pratica) hanno un peso maggiore.


2
+1 La modularità è infatti ampiamente accettata come un attributo desiderabile della maggior parte dei sistemi software, indipendentemente dal linguaggio di programmazione e dal paradigma utilizzato. Molte lingue che non sono OO supportano la modularizzazione.
Andres F.

+1 @AndresF. commento. In effetti, la "programmazione strutturata" e la "raffinatezza graduale" (una tecnica per pensare alla struttura del codice) escono dal crogiolo di "complessità crescente che si traduce in software ancora peggiore". Se COBOL avesse preceduto che la lingua non avrebbe avuto una reputazione così negativa IMHO. E vedo OO pragmaticamente come una struttura di ordine superiore. E intendo dire che senza la struttura sottostante OO non è migliore del peggior COBOL.
radarbob
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.