OOP è difficile perché non è naturale?


86

Spesso si sente che OOP corrisponde naturalmente al modo in cui le persone pensano al mondo. Ma sarei fortemente in disaccordo con questa affermazione: noi (o almeno io) concettualizziamo il mondo in termini di relazioni tra le cose che incontriamo, ma l'obiettivo di OOP è progettare le singole classi e le loro gerarchie.

Si noti che, nella vita di tutti i giorni, le relazioni e le azioni esistono principalmente tra oggetti che sarebbero stati casi di classi non correlate in OOP. Esempi di tali relazioni sono: "il mio schermo è in cima al tavolo"; "Io (un essere umano) sono seduto su una sedia"; "un'auto è sulla strada"; "Sto scrivendo sulla tastiera"; "la macchina da caffè bolle acqua", "il testo è mostrato nella finestra del terminale".

Pensiamo in termini di verbi bivalenti (a volte trivalenti, come, ad esempio, in "Ti ho dato dei fiori") in cui il verbo è l'azione (relazione) che opera su due oggetti per produrre un risultato / azione. L' attenzione si concentra sull'azione e i due (o tre) oggetti [grammaticali] hanno uguale importanza.

In contrasto con OOP, dove devi prima trovare un oggetto (sostantivo) e dirgli di eseguire un'azione su un altro oggetto. Il modo di pensare viene spostato dalle azioni / dai verbi che operano sui sostantivi ai sostantivi che operano sui sostantivi - è come se tutto fosse detto con voce passiva o riflessiva, ad esempio "il testo viene mostrato dalla finestra del terminale". O forse "il testo si disegna sulla finestra del terminale".

Non solo il focus è spostato sui nomi, ma uno dei nomi (chiamiamolo soggetto grammaticale) ha una "importanza" maggiore dell'altro (oggetto grammaticale). Quindi si deve decidere se dirà terminalWindow.show (someText) o someText.show (terminalWindow). Ma perché caricare le persone con decisioni così banali senza conseguenze operative quando si intende davvero show (terminalWindow, someText)? [Le conseguenze sono operativamente insignificanti - in entrambi i casi il testo è mostrato nella finestra del terminale - ma può essere molto serio nella progettazione delle gerarchie di classi e una scelta "sbagliata" può portare a un codice contorto e difficile da mantenere.]

Direi quindi che il modo tradizionale di fare OOP (basato sulla classe, single-dispatch) è difficile perché NON È NATURALE e non corrisponde a come gli umani pensano del mondo. I metodi generici di CLOS sono più vicini al mio modo di pensare, ma purtroppo questo non è un approccio diffuso.

Dati questi problemi, come / perché è accaduto che l'attuale modo tradizionale di fare OOP è diventato così popolare? E cosa si può fare per detronizzarlo?


OOP è per la "programmazione", è fatto per i compilatori. non è un modo per modellare il mondo reale in alcun modo. È comune usare esempi del mondo reale come la classe animale e la classe rettangolo, durante l'insegnamento di OOP, ma questi sono solo esempi per semplificare i concetti. Sfortunatamente, il linguaggio di programmazione e i paradigmi 'accadono' in modo non evolutivo e non scientifico. Con poche eccezioni, il processo di progettazione del linguaggio è in genere figlio della migliore ipotesi di poche persone!
NoChance,

3
Non sarei d'accordo con l'affermazione "l'obiettivo di OOP è la progettazione di singole classi e delle loro gerarchie". da maybie è al centro di alcune implementazioni di OOP, ma ad esempio ho scoperto che i linguaggi OOP dinamici di solito non hanno gerarchie di grandi dimensioni, o addirittura classi. Bene, la definizione di OOP potrebbe cambiare in futuro, c'è un tentativo di cambiare anche l'Oggetto wcook.blogspot.com/2012/07/proposal-for-simplified-modern.html
Azder

1
OOP identifica gli oggetti nel sistema e costruisce classi basate su tali oggetti. Non il contrario. Questo è il motivo per cui non sono d'accordo con "l'obiettivo di OOP è la progettazione di singole classi e le loro gerarchie".
Radu Murzea,


1
Penso che questa sia una domanda altamente soggettiva ed è piena di strane ipotesi su OOP e su cosa sia il "mondo reale" e come la gente pensi ai problemi. E infine chiede persino "E cosa si può fare per detronizzarlo? il che dimostra che l'OP ha un'opinione molto forte al riguardo. Se sei così "religioso" riguardo ai paradigmi di programmazione, immagino che non ti servano risposte ... sai già cosa vuoi sentire. Se avessi saputo di questa domanda quando è stata posta per la prima volta, probabilmente avrei votato per chiuderla ...
Simon Lehmann

Risposte:


97

OOP è innaturale per alcuni problemi. Quindi è procedurale. Quindi è funzionale. Penso che OOP abbia due problemi che lo rendono davvero difficile.

  1. Alcune persone si comportano come se fosse l'unico vero modo di programmare e tutti gli altri paradigmi sono sbagliati. IMHO tutti dovrebbero usare un linguaggio multiparadigm e scegliere il miglior paradigma per il sottoproblema su cui stanno attualmente lavorando. Alcune parti del codice avranno uno stile OO. Alcuni saranno funzionali. Alcuni avranno uno stile procedurale diretto. Con l'esperienza diventa ovvio quale paradigma è meglio per cosa:

    un. OO è generalmente migliore quando si hanno comportamenti fortemente accoppiati allo stato su cui operano, e la natura esatta dello stato è un dettaglio di implementazione, ma l'esistenza di esso non può essere facilmente sottratta. Esempio: classi di raccolte.

    b. La procedura è la migliore per quando hai un sacco di comportamenti che non sono fortemente associati a nessun dato particolare. Ad esempio, forse funzionano su tipi di dati primitivi. È più facile pensare al comportamento e ai dati come entità separate qui. Esempio: codice numerico.

    c. Funzionale è la cosa migliore quando hai qualcosa che è abbastanza facile da scrivere in modo dichiarativo in modo tale che l'esistenza di qualsiasi stato sia un dettaglio di implementazione che può essere facilmente sottratto. Esempio: Mappa / Riduci parallelismo.

  2. OOP generalmente mostra la sua utilità su grandi progetti dove è davvero necessario disporre di pezzi di codice ben incapsulati. Questo non succede troppo nei progetti per principianti.


4
Penso che un punto importante della domanda non sia se la OOP sia naturale, ma se l'approccio tradizionale alla OOP sia l'approccio OOP più naturale. (Buona risposta comunque.)
Giorgio,

11
"OOP generalmente mostra la sua utilità su grandi progetti in cui è davvero necessario disporre di pezzi di codice ben incapsulati": ma questa non è una proprietà specifica di OOP, poiché esistono buoni concetti di modulo anche per linguaggi di programmazione imperativi, funzionali, ... .
Giorgio,

2
OOP è davvero su un asse diverso da procedurale / funzionale; affronta come organizzare e incapsulare il codice, non come descrivere le operazioni. (Collabora sempre OOP con un paradigma di esecuzione. Sì, ci sono OOP + linguaggi funzionali.)
Donal Fellows

1
Non si potrebbe dire che OOP sono solo le scatole in cui mettiamo le cose procedurali?
Erik Reppen,

In OOP, puoi ancora scrivere metodi. Cosa rende l'OPP più debole della programmazione procedurale?
Mert Akcakaya,

48

IMHO è una questione di gusti personali e modi di pensare. Non ho molti problemi con OO.

Noi (o almeno io) concettualizziamo il mondo in termini di relazioni tra le cose che incontriamo, ma l'obiettivo di OOP è progettare singole classi e le loro gerarchie.

IMHO questo non è del tutto vero, sebbene possa essere una percezione comune. Alan Kay, l'inventore del termine OO, ha sempre sottolineato i messaggi inviati tra gli oggetti, piuttosto che gli oggetti stessi. E i messaggi, almeno per me, denotano relazioni.

Si noti che, nella vita di tutti i giorni, le relazioni e le azioni esistono principalmente tra oggetti che sarebbero stati casi di classi non correlate in OOP.

Se esiste una relazione tra oggetti, allora sono correlati, per definizione. In OO potresti esprimerlo con un'associazione / aggregazione / dipendenza d'uso tra due classi.

Pensiamo in termini di verbi bivalenti (a volte trivalenti, come, ad esempio, in "Ti ho dato dei fiori") in cui il verbo è l'azione (relazione) che opera su due oggetti per produrre un risultato / azione. L'attenzione si concentra sull'azione e i due (o tre) oggetti [grammaticali] hanno uguale importanza.

Ma hanno ancora ruoli ben definiti nel contesto: soggetto, oggetto, azione, ecc. "Ti ho dato dei fiori" o "Mi hai dato i fiori" non sono gli stessi (per non parlare di "Il fiore ti ha dato a me": -)

In contrasto con OOP, dove devi prima trovare un oggetto (sostantivo) e dirgli di eseguire un'azione su un altro oggetto. Il modo di pensare viene spostato dalle azioni / dai verbi che operano sui sostantivi ai sostantivi che operano sui sostantivi - è come se tutto fosse detto con voce passiva o riflessiva, ad esempio "il testo viene mostrato dalla finestra del terminale". O forse "il testo si disegna sulla finestra del terminale".

Non sono d'accordo con questo. IMHO la frase inglese "Bill, go to hell" si legge più naturalmente nel codice del programma bill.moveTo(hell)piuttosto che move(bill, hell). E il primo è in effetti più analogo alla voce attiva originale.

Quindi si deve decidere se dirà terminalWindow.show (someText) o someText.show (terminalWindow)

Ancora una volta, non è lo stesso chiedere al terminale di mostrare del testo o chiedere al testo di mostrare il terminale. IMHO è abbastanza ovvio quale sia più naturale.

Dati questi problemi, come / perché è accaduto che l'attuale modo tradizionale di fare OOP è diventato così popolare?

Forse perché la maggior parte degli sviluppatori OO vede OO in modo diverso da te?


15
+1 per aver menzionato direttamente i messaggi tra gli oggetti e la loro importanza da Alan Kay
bunglestink,

3
@zvrba, in effetti, c'erano anche altri pionieri di OO, ma questo non è il punto di questa discussione. "La cosa più naturale è chiedere che il testo venga mostrato." - ora stai usando la stessa voce passiva che secondo te è così "innaturale" in OOP.
Péter Török,

5
@zvrba, dici "c'è sempre un" agente "[...] che fa qualcosa", ma protesta contro l'approccio OO di identificare e nominare quegli agenti (oggetti) e gestirli come cittadini di prima classe nella lingua . Per me questo fa parte della modellizzazione del dominio problematico - devi comunque farlo, basta mappare il modello di dominio risultante per codificare in modo diverso, a seconda che la tua lingua sia OO o meno.
Péter Török,

6
@zvrba, non è OO in sé, ma uno sviluppatore / designer che decide i ruoli e le responsabilità di diversi oggetti. L'uso dell'approccio OO può produrre modelli e design di domini buoni o cattivi, così come l'uso di un coltello può darti una fetta di pane fine o un dito sanguinante - tuttavia non diamo la colpa al coltello, perché è solo uno strumento. Si noti inoltre che i concetti / oggetti / agenti nel modello sono astrazioni di cose nel mondo reale, e come tali sono sempre limitati e distorti, concentrandosi solo su specifici aspetti "interessanti".
Péter Török,

6
@zvrba, un'auto in effetti non parte di sua spontanea volontà - proprio come Carfarebbe un oggetto start()solo quando il suo metodo viene esplicitamente chiamato da qualcuno.
Péter Török,

10

Alcuni programmatori trovano OOD difficile perché a quei programmatori piace pensare a come risolvere il problema per il computer, non a come risolvere il problema.

... ma l'obiettivo di OOP è la progettazione di singole classi e delle loro gerarchie.

OOD NON riguarda questo. OOD consiste nel capire come le cose si comportano e interagiscono.

Pensiamo in termini di verbi bivalenti (a volte trivalenti, come, ad esempio, in "Ti ho dato dei fiori") in cui il verbo è l'azione (relazione) che opera su due oggetti per produrre un risultato / azione. L'attenzione si concentra sull'azione e i due (o tre) oggetti [grammaticali] hanno uguale importanza.

Il focus su OOD è sempre sull'azione, dove le azioni sono i comportamenti degli oggetti. Gli oggetti non sono nulla senza i loro comportamenti. L'unico vincolo di oggetto di OOD è che tutto deve essere fatto da qualcosa.

Non vedo l'agente come più importante della cosa che ha fatto qualcosa.

Ma perché caricare le persone con decisioni così banali senza conseguenze operative quando si intende davvero show (terminalWindow, someText)?

Per me è la stessa cosa con una notazione diversa. Devi ancora decidere chi è lo show-er e chi è lo show-ee. Una volta che lo sai, allora non c'è alcuna decisione in OOD. Windows mostra il testo -> Window.Show (testo).

Un sacco di roba là fuori (specialmente nell'area legacy) dice che è OO quando non lo è. Ad esempio, esiste un'enorme quantità di codice C ++ che non implementa un fico di OOD.

OOD è facile quando si esce dalla mentalità che si sta risolvendo un problema per i computer. Stai risolvendo problemi per cose che fanno cose.


10
Non mi piace OOD esattamente perché preferisco pensare a come risolvere il problema, punto. Non voglio pensare a come tradurre il linguaggio naturale di un dominio problematico in un mondo alieno di oggetti, messaggi, eredità e così via. Non voglio inventare tassonomie gerarchiche dove non esistono naturalmente. Voglio descrivere il problema nel suo linguaggio naturale e risolverlo nel modo più semplice possibile. E, a proposito, il mondo non è fatto solo di "cose ​​che fanno cose". La tua visione della realtà è estremamente ristretta.
SK-logic

7
@Matt Ellen, scrivo programmi che modellano il comportamento di entità che non sono "cose" e che non "fanno" alcuna "roba". Qualsiasi entità immutabile non fa nulla. Qualsiasi funzione matematica pura non fa nulla - è solo una mappatura da un insieme all'altro, e questo mondo è principalmente descritto da tali funzioni. Qualsiasi formalismo logico non "fa" nulla. Sì, OOD non mi aiuterà, perché sono in grado di utilizzare astrazioni e modelli molto, molto più potenti. Tornare a un OOD primitivo, limitato e limitante mi ostacolerà gravemente.
SK-logic

2
@Matt Ellen, sì, mi piacerebbe vedere riferimenti a sostegno di affermazioni così strane che il mondo è meglio visto come una raccolta di "cose ​​che fanno cose", o "oggetti che interagiscono tramite messaggi". È completamente innaturale. Prendi qualsiasi teoria scientifica (poiché sono tutti vicini alla modellazione del mondo reale come è possibile in questa fase) e prova a riscriverlo usando la tua terminologia. Il risultato sarà goffo e imbarazzante.
SK-logic

4
@ Antonio2011a, non esiste un unico paradigma di programmazione o modellizzazione in grado di coprire in modo efficiente tutti i possibili domini problematici. OOP, funzionale, flusso di dati, logica del primo ordine, qualsiasi altra cosa: sono tutti paradigmi specifici del dominio del problema e nient'altro. Sto solo sostenendo la diversità e l'approccio aperto alla risoluzione dei problemi. Restringere il tuo pensiero ad un unico paradigma è semplicemente stupido. La cosa più vicina a un approccio universale, che non ti limita a un singolo framework semantico, è en.wikipedia.org/wiki/Language-oriented_programming
SK-logic

3
@Calmarius perché dovresti semplificare la programmazione per i computer? È solo stupido. Sono gli umani che devono fare il lavoro più duro.
Matt Ellen,

7

Forse non sono in grado di capire il punto, ma:

Leggendo il primo libro su OOP (primi anni '90, il sottile manuale di Borland a Pascal) sono rimasto semplicemente stupito dalla sua semplicità e potenzialità. (Prima avevo usato Cobol, Fortran, linguaggio Assembly e altre cose preistoriche.)

Per me, è abbastanza chiaro: un cane è un animale, un animale deve mangiare, il mio cane è un cane, quindi deve mangiare ...

D'altra parte, la programmazione stessa è intrinsecamente innaturale (cioè artificiale). Il linguaggio umano è artificiale (non incolpare me, tutti abbiamo imparato le nostre lingue dagli altri, nessuno conosce la persona che ha inventato l'inglese). Secondo alcuni scienziati, la mente umana è formata dal linguaggio che ha imparato per primo.

Lo ammetto, alcuni costrutti nei moderni linguaggi OO sono un po 'imbarazzanti, ma è l'evoluzione.


1
Qual è stato esattamente il tuo compito per te passare da cobol a fortran, quindi all'assemblaggio (e al resto)?
Rook

1
Ordine sbagliato. In effetti, ho iniziato con Basic, poi mi sono trasferito a Fortran e poi a Assembly e Cobol (sì, è l'ordine corretto: prima Assembly). Il primo computer della mia vita è stato un "gigantesco" mainframe, 256kB di memoria, macchina da scrivere la sua console, alimentandolo con schede perforate, perché ero il suo operatore. Quando mi ero alzato abbastanza da diventare un programmatore di sistemi, un oggetto sospetto chiamato PC-AT era atterrato sulla mia scrivania. Quindi mi ero tuffato in GW-Basic, Turbo-Pascal, ... e così via.
Nerevar,

1
Non mi riferivo a questo. Più per il tuo dominio di lavoro; perché non conosco molte persone (nessuno in realtà) che hanno avuto a che fare con COBOL (orientato al business), fortran (dominio scientifico), assemblatore (più orientato ai cs) e poi con quelli. Tuttavia sono programmatori professionisti o meno.
Arriva il

1
Nessun mistero: entrare a far parte di team e progetti in cui era già stata presa una decisione sull'approccio al linguaggio. E un livello non banale di curiosità sugli strumenti che stavano usando.
Nerevar,

6

Una cosa che mi ha reso difficile pensare che OOP riguardasse la modellazione del mondo. Pensavo che se non avessi capito bene, sarebbe potuto succedere qualcosa che mi avrebbe morso nel culo (una cosa è vera o no). Ero molto consapevole dei problemi che pretendere che tutto fosse un oggetto o un'entità. Questo mi ha reso molto incerto e poco sicuro della programmazione in OOP.

Poi ho letto SICP e ho capito che si trattava davvero di tipi di dati e controllo dell'accesso a essi. Tutti i problemi che avevo risolto perché erano basati su una premessa errata, che in OOP stai modellando il mondo.

Mi meraviglio ancora dell'immensa difficoltà che mi ha dato questa falsa premessa (e di come mi sono lasciata vedere).


Grazie per aver sottolineato il pericolo di provare a modellare il mondo.
Sean McMillan,

4

Sì, la stessa OOP è molto innaturale - il mondo reale non è interamente fatto di tassonomie gerarchiche. Alcune piccole parti sono fatte di quella roba e quelle parti sono le uniche cose che potrebbero essere adeguatamente espresse in termini di OO. Tutto il resto non può essere naturalmente inserito in un modo di pensare così banale e limitato. Vedi le scienze naturali, vedi quanti diversi linguaggi matematici sono stati inventati per esprimere nel modo più semplice o almeno comprensibile la complessità del mondo reale. E quasi nessuno di loro può essere facilmente tradotto in una lingua di oggetti e messaggi.


5
Bene, questo è altrettanto vero per qualsiasi tipo di notazione formale che cerca di descrivere con precisione il mondo reale.
Péter Török,

1
@Péter Török, proprio il mio punto. Non esiste un singolo formalismo che copra tutto. Devi usarli tutti, in tutta la loro moltitudine spaventosa. Ed è questo il motivo per cui credo in una programmazione orientata al linguaggio: permette di adottare vari formalismi, spesso incompatibili, in una solida entità di codice.
SK-logic

1
Tutto può essere classificato in tassonomie gerarchiche. Il trucco sta venendo fuori con schemi che hanno senso. L'eredità multipla è spesso coinvolta. Una grande differenza tra software e mondo reale è che nel mondo reale, spesso dobbiamo dedurre o scoprire gli schemi di categorizzazione; nel software, li inventiamo.
Caleb,

1
Usando un termine come "tassonomia gerarchica", penso che tu stia pensando, beh, all'eredità. L'ereditarietà è davvero difficile da ragionare. Ecco perché le persone suggeriscono di usare la composizione piuttosto che l'eredità.
Frank Shearar,

1
@Frank: ci sono molti tipi di tassonomie gerarchiche nel mondo reale, di cui l'eredità è solo una. Fare tutto ciò in modo appropriato richiede strumenti migliori di OOP (ad es. Ragionamento ontologico) e ha causato problemi ai filosofi per millenni ...
Donal Fellows

4

Noi (o almeno io) concettualizziamo il mondo in termini di relazioni tra le cose che incontriamo, ma l'obiettivo di OOP è progettare singole classi e le loro gerarchie.

Stai partendo da (IMO) una premessa errata. Le relazioni tra oggetti sono probabilmente più importanti degli oggetti stessi. Sono le relazioni che danno una struttura di programma orientata agli oggetti. L'ereditarietà, la relazione tra le classi, è ovviamente importante perché la classe di un oggetto determina cosa può fare quell'oggetto . Ma sono le relazioni tra i singoli oggetti che determinano cosa fa effettivamente un oggetto entro i limiti definiti dalla classe e quindi come si comporta il programma.

Il paradigma orientato agli oggetti può essere difficile all'inizio non perché è difficile pensare a nuove categorie di oggetti, ma perché è difficile immaginare un grafico di oggetti e capire quali dovrebbero essere le relazioni tra loro, in particolare quando non si ha un modo di descrivere quelle relazioni. Ecco perché i modelli di progettazione sono così utili. I modelli di progettazione riguardano quasi interamente le relazioni tra oggetti. I pattern ci danno sia i mattoni che possiamo usare per progettare relazioni di oggetti a un livello superiore sia un linguaggio che possiamo usare per descrivere tali relazioni.

Lo stesso vale per i campi creativi che funzionano nel mondo fisico. Chiunque potrebbe mettere insieme un mucchio di stanze e chiamarlo un edificio. Le camere potrebbero anche essere completamente arredate con tutti gli accessori più recenti, ma ciò non fa funzionare l'edificio. Il lavoro di un architetto è di ottimizzare le relazioni tra quelle stanze rispetto ai requisiti delle persone che usano quelle stanze e l'ambiente dell'edificio. Rendere giuste queste relazioni è ciò che fa funzionare un edificio dal punto di vista sia funzionale che estetico.

Se hai difficoltà ad abituarti a OOP, ti incoraggio a riflettere di più su come i tuoi oggetti si incastrano e come sono organizzate le loro responsabilità. Se non lo hai già fatto, leggi gli schemi di progettazione: probabilmente ti renderai conto di aver già visto gli schemi di cui leggi, ma dare loro i nomi ti consentirà di vedere non solo gli alberi, ma anche stand, poliziotti, boschetti, boschi, boschi, aree boschive e infine boschi.


3

Questa è solo una parte di ciò che non va in OOP.

In sostanza, le funzioni diventano cittadini di seconda classe e questo è negativo.

I linguaggi moderni (ruby / python) non presentano questo problema e forniscono funzioni come oggetti di prima classe, oltre a consentire di creare programmi senza creare alcuna gerarchia di classi.


OOP mi sembra molto naturale, in effetti è difficile per me pensare alle attività di programmazione in qualsiasi altro modo. Tuttavia, nel corso degli anni ho capito che OOP tende a dare troppa enfasi ai nomi rispetto ai verbi. Questo sfogo del 2006 mi ha aiutato a capire questa distinzione: steve-yegge.blogspot.com/2006/03/…
Jim In Texas,

3

OOP non è difficile. Ciò che rende difficile usare bene è una comprensione superficiale di ciò per cui è buono, in cui i programmatori ascoltano massime casuali e le ripetono a se stesse sottovoce per ricevere le benedizioni della divina Banda dei Quattro, il beato Martin Fowler, o chiunque altro stiano leggendo.


3

MODIFICATO

Innanzi tutto, vorrei dire che non ho mai trovato OOP difficile o più difficile di altri paradigmi di programmazione. La programmazione è intrinsecamente difficile perché cerca di risolvere i problemi del mondo reale e il mondo reale è estremamente complesso. D'altra parte, quando ho letto questa domanda mi sono posto la domanda: OOP è "più naturale" degli altri paradigmi? E quindi più efficace?

Una volta ho trovato un articolo (vorrei poterlo trovare di nuovo in modo da poterlo pubblicare come riferimento) su uno studio comparativo tra programmazione imperativa (IP) e programmazione orientata agli oggetti (OOP). Fondamentalmente avevano misurato la produttività dei programmatori professionisti che utilizzano IP e OOP in diversi progetti, e il risultato è stato che non avevano riscontrato grandi differenze. Quindi, l'affermazione era che non vi era alcuna grande differenza nella produttività tra i due gruppi e che ciò che conta davvero è l'esperienza.

D'altra parte, i fautori dell'orientamento agli oggetti affermano che, mentre durante lo sviluppo iniziale di un sistema OOP può richiedere anche più tempo che imperativo, a lungo termine il codice è più facile da mantenere ed estendere a causa della stretta integrazione tra dati e operazioni.

Ho lavorato principalmente con i linguaggi OOP (C ++, Java) ma ho spesso la sensazione di poter essere altrettanto produttivo usando Pascal o Ada anche se non li ho mai provati per progetti di grandi dimensioni.

Contrastalo con OOP, dove devi prima trovare un oggetto (sostantivo) e dirgli di eseguire un'azione su un altro oggetto.

[tagliare]

Direi quindi che il modo tradizionale di fare OOP (basato sulla classe, single-dispatch) è difficile perché NON È NATURALE e non corrisponde a come gli umani pensano del mondo. I metodi generici di CLOS sono più vicini al mio modo di pensare, ma purtroppo questo non è un approccio diffuso.

Quando ho letto più attentamente questo ultimo paragrafo, ho finalmente capito il punto principale della tua domanda e ho dovuto riscrivere la mia risposta da zero. :-)

Conosco altre proposte OO in cui più oggetti ricevono un messaggio anziché solo uno, vale a dire che diversi oggetti svolgono un ruolo simmetrico quando ricevono un messaggio. SÌ, questo mi sembra un approccio OOP più generale e forse più naturale (meno restrittivo).

D'altra parte, "invio multiplo" può essere facilmente simulato utilizzando "invio singolo" e "invio singolo" è più facile da implementare. Forse questo è uno dei motivi per cui la "spedizione multipla" non è diventata mainstream.


3

Smetti di cercare un paradigma esclusivamente OOP e prova alcuni JavaScript.

Al momento ho elaborato una sorta di schema in cui i miei oggetti dell'interfaccia utente funzionano sotto un'interfaccia basata sugli eventi. Vale a dire, avrò quello che sembra un tipico metodo pubblico che, quando sparato, si traduce in un'azione definita internamente. Ma quando viene attivato, ciò che accade realmente è che innesco un evento sull'oggetto stesso e un gestore predefinito all'interno di quell'oggetto risponde. Questo evento e l'oggetto evento a cui puoi associare le proprietà che passano a qualsiasi altro ascoltatore possono essere ascoltati da tutto ciò che interessa ascoltare. Puoi ascoltare direttamente l'oggetto, oppure puoi generalmente ascoltare quel tipo di evento (gli eventi vengono anche attivati ​​su un oggetto generico che possono ascoltare tutti gli oggetti creati dalla fabbrica). Quindi, ad esempio, ho una casella combinata in cui selezioni un nuovo elemento dall'elenco a discesa.

Se vuoi, (e sono stato sorpreso di scoprire che di solito non voglio - è un problema di leggibilità quando non riesci a vedere da dove proviene l'evento) puoi avere il disaccoppiamento completo degli oggetti e stabilire il contesto tramite un oggetto evento passato. Indipendentemente da ciò, stai ancora schivando l'invio singolo essendo in grado di registrare più responder.

Ma non lo sto facendo con OOP da solo e JS non è nemmeno 'propriamente' OOP secondo alcune definizioni, che trovo esilaranti. Corretto, per i più alti livelli di sviluppo di app secondo me, è avere il potere di piegare il paradigma a tutto ciò che funziona per la tua situazione e possiamo emulare le lezioni bene se ci teniamo. Ma in questo caso, sto mescolando aspetti di funzionale (passando i gestori in giro) con OOP.

Ancora più importante, quello che ho sembra abbastanza potente. Non sto pensando in termini di un oggetto che agisce su un altro. Fondamentalmente sto decidendo che cosa gli oggetti tengono, dandogli gli strumenti di cui hanno bisogno per sistemare le cose e semplicemente lasciarle cadere in un mixer e farle reagire l'una con l'altra.

Quindi immagino che ciò che sto dicendo sia questo: non è un tipo di istruzione switch come un problema. È un mix and match. Il problema sono le lingue e le mode che vogliono farti credere che sia una cosa assolutamente superflua. Come può uno sviluppatore java junior, ad esempio, apprezzare veramente OOP quando pensa di farlo sempre correttamente per impostazione predefinita?


2

Il modo in cui mi è stato spiegato è stato con un tostapane e un'auto. Entrambi hanno molle, quindi avresti un oggetto "a molla" e avrebbero dimensioni, punti di forza e quant'altro diversi, ma sarebbero entrambi "molle" e poi estenderebbero quella metafora sull'auto, se avessi un sacco di ruote (Le ruote, ovviamente, più il volante, ecc.) E questo aveva molto senso.

Quindi puoi pensare al programma come a un elenco di oggetti, ed è molto più semplice visualizzare quindi "È un elenco di cose che fanno cose, quindi non è come quell'elenco di istruzioni che hai visto prima"

Penso che il vero problema con OOP sia il modo in cui viene spiegato alle persone. Spesso (nelle mie classi uni) vedo che viene spiegato dicendo "si tratta di molte classi che fanno piccole cose, e puoi creare oggetti da quello" e tutto confonde molte persone, perché sta usando ciò che è essenzialmente astratto termini per spiegare questi concetti, piuttosto che idee concrete che le persone hanno compreso quando avevano 5 anni giocando con lego.


2
Springs sono disponibili in milioni di forme, i quali svolgono analoghe funzioni . Direi che questo è un esempio perfetto per la programmazione funzionale.
10

2

È il modo naturale di pensare al mondo attraverso la categorizzazione. Questo è più o meno ciò che riguarda OO. OOP è difficile perché la programmazione è difficile.


Ma classifichi in base al fatto che alcuni oggetti abbiano attributi o comportamenti comuni? Tutto ciò che ha nome e cognome è una persona? Tutto ciò che cammina è un animale?
zvrba,

Quando si tratta di categorizzazione, essere in grado di eseguire un determinato comportamento è un attributo. Zebre e cavalli possono riprodursi, ma la prole è un ibrido. Molto difficile prevedere questo risultato in base al possesso della funzione di accoppiamento a meno che non si sappia che non sono la stessa specie.
JeffO

1
@zvrba: La mia risposta alla domanda posta nel commento è quella it doesn't matter. Tutto ciò che ha un nome e un cognome è una persona per ogni programma che si preoccupa solo delle persone. Per qualsiasi programma che non ha conoscenza di persone o non persone, è un IHasNameAndSurname. Gli oggetti devono solo risolvere il problema a portata di mano.
Tom W,

@Jeff O Anche all'interno della stessa specie / razza / popolazione esistono variazioni e nessun esempio ideale (essenziale). Quindi, sì, OO non è come la natura è in realtà, ma si adatta bene a come gli umani pensano naturalmente.
Tom Hawtin - affronta il

2

Penso che alcune delle difficoltà si presentino quando le persone cercano di usare OOP per rappresentare la realtà. Tutti sanno che un'auto ha quattro ruote e un motore. Tutti sanno che le macchine possono Start(), Move()e SoundHorn().

Una luce scattò nella mia testa quando mi resi conto che avrei dovuto smettere di provare a farlo tutto il tempo. Un oggetto non è la cosa con cui condivide un nome. Un oggetto è (cioè dovrebbe essere) una partizione di dati sufficientemente dettagliata pertinente all'ambito del problema. Per oughtavere esattamente ciò di cui ha bisogno la soluzione al problema, né più né meno. Se rendere un oggetto responsabile di un certo comportamento si traduce in più righe di codice rispetto allo stesso comportamento che è il lavoro di qualche nebulosa terza parte (qualcuno potrebbe chiamarlo "poltergeist"), allora il poltergeist guadagna i suoi chip.


1

Per gestire la complessità, dobbiamo raggruppare la funzionalità in moduli, e questo è un problema difficile in generale. È come il vecchio detto sul capitalismo, OOP è il peggior sistema per organizzare il software là fuori, tranne per tutto il resto che abbiamo provato.

Il motivo per cui raggruppiamo le interazioni all'interno dei sostantivi, anche se spesso c'è un'ambiguità su quale dei due sostantivi raggrupparli, è che la quantità di sostantivi si risolve in classi di dimensioni gestibili, mentre il raggruppamento per verbi tende a produrre gruppi molto piccoli come singoli, o gruppi molto grandi per una funzione come lo spettacolo . Anche il riutilizzo di concetti come l'ereditarietà si risolve molto più facilmente quando si raggruppano i nomi.

Inoltre, la questione di decidere se mettere in mostra con la finestra o il testo è quasi sempre molto più chiara in pratica che in teoria. Ad esempio, quasi tutti i gruppi di strumenti della GUI vengono aggiunti con il contenitore, ma vengono visualizzati con il widget. Se provi a scrivere codice nell'altro modo, la ragione diventa evidente abbastanza rapidamente, anche se pensandoci in modo astratto i due metodi sembrano intercambiabili.


2
Hai mai visto un sistema di moduli adeguato ? Come puoi dire che OOP è la cosa migliore disponibile? I moduli SML sono molto, molto più potenti. Ma anche i pacchetti Ada sono sufficienti per la maggior parte dei casi, anche senza un piccolo accenno di OOP.
SK-logic

@ SK-logic, penso che ti stai impiccando su definizioni troppo precise. Per OOP, non intendo le classi , intendo raggruppare logicamente i "verbi" in base ai "sostantivi" su cui operano, ed essere in grado di riutilizzare e specializzare quei verbi in base ai nomi particolari su cui capita di operare. Le classi sono l'implementazione più nota di ciò, ma non sono l' unica implementazione. Ammetto l'ignoranza dei moduli SML, ma il primo esempio che ho visto quando l'ho cercato è stato l'implementazione di una coda che potrebbe provenire da qualsiasi libro di progettazione OO con modifiche alla sintassi per renderlo funzionale.
Karl Bielefeldt,

semplicemente non sarebbe giusto dare a uno sfortunato OOP troppo credito per qualcosa che non gli appartiene. I moduli sono una grande invenzione. I moduli di prima classe sono fantastici. Ma OOP non ha nulla a che fare con loro. Alcuni linguaggi OOP hanno adottato alcune delle funzionalità del modulo (in particolare gli spazi dei nomi), ma i moduli sono un concetto molto più generale e potente rispetto alle classi. Hai detto che le lezioni sono "le migliori", il che è lontano dalla verità. I moduli di prima classe sono molto migliori. E, naturalmente, i sistemi di tipi sono molto più ampi e profondi di un semplice OO con il suo sottotitolo.
SK-logic

1
"È come il vecchio detto sul capitalismo, OOP è il peggior sistema per organizzare il software là fuori, tranne per tutto il resto che abbiamo provato.": Forse non ci stiamo provando da abbastanza tempo. :-)
Giorgio,

1
Penso che intendi "democrazia": quotationspage.com/quote/364.html
nicodemus13

1

No . Esistono diversi modi per risolvere un problema utilizzando la programmazione: funzionale, procedurale, logico, OOP, altro.

Nel mondo reale, a volte, le persone usano il paradigma funzionale e, a volte, usiamo il paradigma procedurale e così via. E a volte ci siamo confusi. E alla fine li rappresentiamo come un particolare stile o paradigma di programmazione.

Esiste anche il paradigma "tutto è un elenco o un elemento", utilizzato in LISP. Mi piace menzionare una cosa diversa dalla programmazione funzionale . PHP lo usa negli array associativi.

I paradigmi OOP e "Tutto è un elenco o un elemento" sono considerati 2 degli stili di programmazione PIÙ NATURALI , come ricordo in alcune classi di Intelligenza Artificiale.

Mi sembra strano, "OOP non è naturale", forse il modo in cui impari o il modo in cui ti è stato insegnato su OOP è sbagliato, ma non lo stesso OOP stesso.


1

Dati questi problemi, come / perché è accaduto che l'attuale modo tradizionale di fare OOP è diventato così popolare? E cosa si può fare per detronizzarlo?

OOP è diventato popolare perché offre strumenti per organizzare il tuo programma a un livello di astrazione più elevato rispetto ai linguaggi procedurali popolari che lo hanno preceduto. Era anche relativamente facile creare un linguaggio che avesse una struttura procedurale all'interno dei metodi e una struttura orientata agli oggetti che li circondava. Ciò ha permesso ai programmatori che già sapevano programmare di raccogliere proceduralmente i principi OO uno alla volta. Ciò ha portato anche a molti programmi OO solo in nome che erano programmi procedurali racchiusi in una o due classi.

Per detronizzare OO, crea un linguaggio che semplifichi la transizione in modo incrementale da ciò che la maggior parte dei programmatori conosce oggi (principalmente procedurale, con un po 'di OO) al tuo paradigma preferito. Assicurati che fornisca utili API per svolgere attività comuni e promuoverlo bene. Le persone realizzeranno presto programmi X-in-name nella tua lingua. Quindi puoi aspettarti che ci vorranno anni e anni perché le persone diventino brave a fare davvero X.


Il PO non sostiene che l'OO sia in generale cattivo e debba essere detronizzato, ma che il "modo corrente principale di fare OOP" non è il più naturale (rispetto al "dispacciamento multiplo").
Giorgio,

L'OP sembra anche troppo focalizzato sulla definizione della gerarchia dei tipi, in cui i migliori programmi OO tendono a fare maggiormente affidamento su interfacce e composizione. Se la spedizione multipla è X, creare una lingua che consenta alle persone di apprendere gradualmente le competenze associate alla spedizione multipla è ancora la chiave per cambiare l'ambiente.
Sean McMillan,

1

Penso che anche le lingue OOP e OOP abbiano dei problemi.

Se lo capisci correttamente, OOP riguarda le scatole nere (oggetti) che hanno pulsanti che possono essere spinti (metodi). Le lezioni sono lì solo per aiutare a organizzare queste scatole nere.

Un problema è quando il programmatore mette i pulsanti sull'oggetto sbagliato. Il terminale non può mostrare il testo su se stesso, il testo non può mostrarsi sul terminale. Il componente del gestore delle finestre del sistema operativo che può farlo. La finestra e il testo del terminale sono solo un'entità passiva. Ma se pensiamo in questo modo realizziamo che la maggior parte delle entità sono cose passive e avremmo solo pochissimi oggetti che effettivamente fanno qualsiasi cosa (o semplicemente uno: il computer ). Infatti quando usi C lo organizzi in moduli, questi moduli rappresentano quei pochi oggetti.

Un altro punto è che il computer esegue semplicemente le istruzioni in sequenza. Supponiamo che tu abbia un VCRe un Televisionoggetto, come faresti a riprodurre video? Probabilmente scrivi qualcosa del genere:

connect(television, vcr);
vcr.turnOn();
television.turnOn();
insert(vcr, yourFavoriteCasette);
vcr.play();
while (vcr.isPlaying()) {} // Wait while the VCR is playing the casette.
vcr.eject();
vcr.turnOff();
television.turnOff();

Questo sarebbe così semplice, ma per questo avresti bisogno di almeno 3 processori ( o processi ): uno gioca il ruolo di te, il secondo è il videoregistratore, il terzo è la TV. Ma normalmente hai un solo core (almeno non abbastanza per tutti i tuoi oggetti). Al college, molti dei miei compagni di classe non capivano perché la GUI si blocca quando un pulsante fa un'operazione costosa.

Quindi penso che un design orientato agli oggetti possa descrivere abbastanza bene il mondo, ma non è la migliore astrazione per il computer.


0

Dai un'occhiata al DCI (dati, contesto e interazione) inventato dall'inventore del modello MVC.

L'obiettivo di DCI è (citato da Wikipedia):

  • Assegna lo stato di prima classe al comportamento del sistema , sopra gli oggetti (nomi).
  • Separare in modo chiaro il codice per il rapido cambiamento del comportamento del sistema (cosa fa il sistema) dal codice per cambiare lentamente la conoscenza del dominio (che cos'è il sistema), invece di combinare entrambi in un'interfaccia di una classe.
  • Supportare uno stile di pensiero oggettivo vicino ai modelli mentali delle persone, piuttosto che allo stile di pensiero di classe.

Ecco un buon articolo degli autori ed ecco una piccola implementazione di esempio (.NET) se vuoi vedere del codice. È molto più semplice di quanto possa sembrare e sembra molto naturale.


0

Spesso si sente che OOP corrisponde naturalmente al modo in cui le persone pensano al mondo. Ma sarei fortemente in disaccordo con questa affermazione (...)

Essendo evangelizzato nei libri e altrove per decenni, anche io non sono d'accordo. Ciononostante, penso che Nygaard e Dahl siano stati quelli che lo hanno messo in questo modo, e penso che si stessero concentrando su quanto fosse più facile pensare a progettare simulazioni rispetto alle alternative del tempo.

(...) ma l'obiettivo di OOP è la progettazione di singole classi e le loro gerarchie.

Questa affermazione entra in un territorio sensibile alla luce di quanto siano sbagliate le idee sbagliate di OOP e quanto OO sia sensibile alla definizione. Ho più di dieci anni nel settore, svolgendo sia lavori di settore che ricerche accademiche sul prog. lingue, e posso dirti che ho passato molti anni a disimparare il "mainstream OO" perché ho iniziato a notare quanto sia diverso (e inferiore) da ciò a cui i creatori precedenti miravano. Per un trattamento moderno e aggiornato dell'argomento, vorrei fare riferimento al recente sforzo di W. Cook:

"Una proposta di definizioni moderne e semplificate di" oggetto "e" orientato agli oggetti " http://wcook.blogspot.com.br/2012/07/proposal-for-simplified-modern.html

Dati questi problemi, come / perché è accaduto che l'attuale modo tradizionale di fare OOP è diventato così popolare?

Forse lo stesso motivo per cui le tastiere QWERTY sono diventate popolari o lo stesso motivo per cui il sistema operativo DOS è diventato popolare. Le cose fanno semplicemente un giro su veicoli popolari, nonostante le loro proprietà, e diventano popolari da soli. E a volte, versioni simili ma peggiori di qualcosa sono considerate la cosa reale.

E cosa si può fare per detronizzarlo?

Scrivi un programma usando un approccio superiore. Scrivi lo stesso programma usando un approccio OO. Mostra che il primo ha proprietà migliori del secondo in ogni aspetto significativo (sia le proprietà del sistema stesso che le proprietà ingegneristiche). Mostrare che il programma scelto è pertinente e l'approccio proposto sostiene l'alta qualità delle proprietà se applicato ad altri tipi di programmi. Siate rigorosi nelle vostre analisi e usate definizioni precise e accettate quando necessario.

Infine, condividi i tuoi risultati con noi.


-1

Prendi Java: gli oggetti sono una specie di collo di bottiglia di astrazione, la maggior parte delle "cose" sono o rigorosamente sotto-componenti di oggetti o usano gli oggetti come loro sotto-componenti. Gli oggetti devono essere abbastanza polivalenti per un intero strato di astrazione tra questi due tipi di cose - muti-purpose significa che non esiste una metafora che essi incarnino. In particolare, Java rende gli oggetti (e le classi) l'unico livello attraverso il quale si chiama / si invia il codice. Questa quantità di cose incarnate dagli oggetti le rende, francamente, troppo complesse. Qualsiasi descrizione utile di essi deve essere limitata a qualche forma specializzata o riservata.

Le gerarchie di ereditarietà e interfaccia sono "cose" che usano oggetti come sottocomponenti. Questo è un modo specializzato di descrivere gli oggetti, non un modo per ricavare una comprensione generale degli oggetti.

Si può dire che gli "oggetti" abbiano o siano molte cose perché sono un'astrazione multiuso che è più o meno universale in un "OO Langauge". Se sono usati per contenere uno stato locale mutabile o per accedere ad uno stato mondiale esterno, allora assomigliano molto a un "sostantivo".

Al contrario, un oggetto che rappresenta un processo, ad esempio "crittografa" o "comprimi" o "ordina", sembra un "verbo".

Alcuni oggetti vengono utilizzati per il loro ruolo di spazio dei nomi, ad esempio un luogo in cui inserire la funzione "statica" in Java.

Sono propenso a concordare con l'argomento secondo cui Java è troppo pesante per le chiamate al metodo degli oggetti, con invio sull'oggetto. Questo probabilmente perché preferisco le classi di tipi di Haskell per il controllo della spedizione. Questa è una limitazione di spedizione ed è una caratteristica di Java ma non della maggior parte delle lingue, o anche della maggior parte dei linguaggi OO.


-3

Ho assistito e partecipato a numerosi dibattiti online su OOP. I sostenitori di OOP di solito non sanno come scrivere un codice procedurale adeguato. È possibile scrivere un codice procedurale altamente modulare. È possibile separare codice e dati e garantire che le funzioni possano scrivere solo nel proprio archivio dati. È possibile implementare il concetto di eredità utilizzando il codice procedurale. Ancora più importante, il codice procedurale è più snello, più veloce e più facile da eseguire il debug.

Se si creano moduli a file singolo con rigide convenzioni di denominazione, il codice procedurale è più facile da scrivere e mantenere rispetto a OO e farà lo stesso o più e più velocemente. E non dimenticare che quando l'applicazione viene eseguita, è sempre procedurale, indipendentemente dal numero di classi presenti nello script.

Quindi hai il problema di linguaggi come PHP, che non sono veramente orientati agli oggetti e si basano su hack per falsificare cose come l'eredità multipla. I grandi colpi che influenzano la direzione della lingua hanno trasformato PHP in un patchwork di regole incoerenti che sono diventate troppo grandi per quello che inizialmente intendevano. Quando vedo gli sviluppatori scrivere enormi classi di template per quello che era inteso come linguaggio di template procedurale, non posso fare a meno di sorridere.

Se confronti il ​​codice OO correttamente scritto con il codice procedurale scritto male, allora giungerai sempre a una conclusione errata. Pochissimi progetti garantiscono un design orientato agli oggetti. Se sei IBM e gestisci un grande progetto che deve essere mantenuto per anni da più sviluppatori, scegli Object Oriented. Se stai scrivendo un piccolo blog o un sito Web di shopping per un cliente, pensaci due volte.

Per rispondere alla domanda originale, OOP è difficile perché non risolve i dilemmi di programmazione della vita reale senza ricorrere a soluzioni 100 volte più complicate di quanto dovrebbero essere. Una delle soluzioni più potenti a molti problemi di programmazione è l'uso giudizioso dei dati globali. Eppure i neolaureati della nuova ondata ti diranno che è un grande no-no. I dati disponibili a livello globale sono pericolosi solo se sei un goffo programmatore. Se disponi di un rigido set di regole e convenzioni di denominazione adeguate, puoi farcela con tutti i tuoi dati globali.

Dovrebbe essere un requisito obbligatorio per qualsiasi programmatore orientato agli oggetti sapere come scrivere un'applicazione che gioca a scacchi nell'assemblatore per una memoria massima disponibile di 16 KB. Avrebbero quindi imparato a tagliare il grasso, ridurre la pigrizia e generare soluzioni ingegnose.

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.