Cosa si intende per "OOP nasconde lo stato"? [chiuso]


11

In uno dei tanti rant anti-OOP su cat-v.org ho trovato un passaggio di Joe Armstrong che sollevava diverse obiezioni contro il modello OOP, uno dei quali era il seguente:

Obiezione 4 - Gli oggetti hanno uno stato privato

Lo stato è la radice di tutti i mali. In particolare, le funzioni con effetti collaterali dovrebbero essere evitate.

Mentre lo stato nei linguaggi di programmazione è indesiderabile, nel mondo reale abbonda. Sono molto interessato allo stato del mio conto bancario e quando deposito o prelevo denaro dalla mia banca mi aspetto che lo stato del mio conto bancario venga aggiornato correttamente.

Dato che lo stato esiste nel mondo reale quali servizi dovrebbe fornire il linguaggio di programmazione per gestire lo stato?

Gli OOPL dicono "nascondi lo stato al programmatore". Gli stati sono nascosti e visibili solo attraverso le funzioni di accesso. I linguaggi di programmazione convenzionali (C, Pascal) affermano che la visibilità delle variabili di stato è controllata dalle regole di ambito del linguaggio. Le lingue dichiarative pure dicono che non c'è stato. Lo stato globale del sistema viene portato in tutte le funzioni ed esce da tutte le funzioni. Meccanismi come monadi (per FPL) e DCG (linguaggi logici) vengono utilizzati per nascondere lo stato al programmatore in modo che possano programmare "come se lo stato non avesse importanza" ma avere pieno accesso allo stato del sistema qualora ciò fosse necessario.

L'opzione "nascondi lo stato al programmatore" scelta da OOPL è la scelta peggiore possibile. Invece di rivelare lo stato e cercare di trovare il modo di minimizzare il fastidio dello stato, lo nascondono.

Cosa si intende esattamente con questo? Ho poca esperienza procedurale o di basso livello, principalmente OOP, quindi ciò spiega probabilmente quanto non mi sia familiare. E da un punto di vista più moderno, ora che la maggior parte dell'isteria orientata agli oggetti è passata (almeno per quanto ne so), quanto pensate sia accurato / pertinente quel passaggio?

Grazie per l'aiuto.


3
lettura consigliata: Discuti questo $ {blog}
moscerino il

1
Se me lo chiedi, l'articolo a cui ti sei collegato fa alcuni argomenti piuttosto scadenti (per non parlare della qualità della scrittura). Non metterei troppa scorta in quello che ha da dire.
Benjamin Hodgson,

1
Bah. Sempre più sto pensando che tutta questa cosa "immutabile" sia una buona idea che sta iniziando a puzzare di religione.
Rob,

3
Joe Armstrong ha riconosciuto pubblicamente che le sue obiezioni contro OO erano basate su gravi incomprensioni su cosa sia esattamente OO. Si è ora reso conto che Erlang è in realtà un linguaggio profondamente orientato agli oggetti (in effetti, potrebbe essere il linguaggio più orientato agli oggetti nell'uso tradizionale).
Jörg W Mittag,

9
Per approfondire questo: la prima cattura di archive.org del rant di Joe Armstrong è dell'aprile 2001. Joe ha scritto la sua tesi nel 2003. Durante la stesura della sua tesi, ha imparato molto su OO e si è reso conto di essere caduto in preda al malinteso comune che OO fosse in qualche modo correlato allo stato mutabile (non lo è, lo stato mutabile è completamente ortogonale). Da allora, ha riconosciuto che la sua critica a OO era sbagliata e che ironicamente Erlang è in realtà un linguaggio orientato agli oggetti (ha messaggi, ha oggetti che chiama processi, ha incapsulamento).
Jörg W Mittag,

Risposte:


32

Cosa si intende esattamente con questo?

In questo contesto, significa che OOP oscura lo stato di un programma nascondendolo al programmatore ma rendendolo comunque visibile tramite metodi di accesso (che perdono). L'argomento è che oscurando lo stato, rende più difficile lavorare con, e per estensione porta a più bug.

quanto accurato / pertinente pensate sia quel passaggio?

Sento che è pertinente, ma mal indirizzato. C'è assolutamente un problema se la tua classe perde il concetto del suo stato nel mondo esterno. C'è assolutamente un problema se la tua classe cerca di oscurare lo stato quando dovrebbe essere manipolato dal mondo esterno. Questo però non è un fallimento di OOP nel suo insieme, ma con il design individuale della classe. Non direi che nascondere lo stato stesso sia un problema: le monadi lo fanno continuamente nella programmazione funzionale.

Nel migliore dei casi, OOP funziona come il miglior mix di programmazione funzionale e procedurale: le persone possono usare la classe "come se lo stato non avesse importanza" perché lo stato privato usato per proteggere gli invarianti della classe è nascosto, ma hanno la libertà usare uno stato pubblico ben definito della classe che toglie i dettagli.

OOP rende più difficile per le persone ottenere questo migliore dei casi? Possibilmente. Le "scuole Java" e l'intera scuola di insegnamento OO di Shape / Circle / Rectangle o Car probabilmente hanno più da incolpare dell'approccio stesso. La moderna OOP prende un po 'dalla programmazione funzionale, incoraggiando oggetti immutabili e funzioni pure scoraggiando l'eredità per aiutare a semplificare la progettazione di classi che funzionano bene.


3
Concordo con tutto il cuore sull'intera "scuola di java", non mi piace affatto eh. Grazie mille, voterei se potessi.
Jake,

2
Per essere precisi: le monadi in generale non nascondono lo stato, alcune monadi lo fanno (es. IO). Vedi tra gli altri stackoverflow.com/questions/2488646/...
thSoft

2
+1. Questa è un'analisi molto più equilibrata e sfumata rispetto all'articolo che il Quester ha collegato
Benjamin Hodgson,

2
Joe Armstrong ha riconosciuto pubblicamente che le sue obiezioni contro OO erano basate su gravi incomprensioni su cosa sia esattamente OO. Si è ora reso conto che Erlang è in realtà un linguaggio profondamente orientato agli oggetti (in effetti, potrebbe essere il linguaggio più orientato agli oggetti nell'uso tradizionale).
Jörg W Mittag,

2
Jorg - potresti pubblicare un link al follow-up di Joe? Sarei davvero interessato a leggerlo. E @radarbob, subito!
user949300,

2

Ragionare su un sistema sarà difficile se ci sono parti di stato mutevole che non hanno un chiaro "proprietario". Ciò non significa che gli oggetti non dovrebbero mai avere uno stato mutabile, ma piuttosto che gli oggetti che hanno uno stato mutabile non dovrebbero essere usati in modi in cui la proprietà potrebbe non essere chiara e, al contrario, gli oggetti che dovranno essere liberamente passati senza tenere traccia della proprietà dovrebbero essere immutabile.

In pratica, una programmazione efficiente richiede spesso che alcuni oggetti abbiano uno stato mutabile; tale stato, tuttavia, dovrebbe essere limitato, tuttavia, agli oggetti worker non condivisi . Considera le interfacce IEnumerable/ IEnumeratorin .NET: se una raccolta implementa IEnumerable, consentirà di leggere gli elementi uno alla volta. Il processo effettivo di lettura di una raccolta richiederà spesso di tenere traccia di quali elementi sono stati letti (un pezzo di stato mutevole), ma tale stato non è contenuto in un'implementazione di IEnumerable. Invece, IEnumerablefornisce un metodo chiamato GetEnumeratorche restituirà un oggetto che implementa IEnumeratore contiene abbastanza stato per consentire gli elementi per essere letti dalla raccolta. Il fatto che l'oggetto contenga tale stato non pone alcun problema, tuttavia,se l'implementazione dell'oggetto IEnumeratornon è condivisa .

Il modello migliore nella maggior parte dei casi è utilizzare una combinazione di oggetti che sono liberamente condivisi ma che non saranno mai modificati (almeno non dopo che sono stati condivisi) e oggetti che hanno un chiaro proprietario e possono essere liberamente modificati da quel proprietario , ma non vengono mai condivisi con nessuno.


Eccellente distinzione tra ciò che dovrebbe essere immutabile e ciò che può avere uno stato mutevole. Leggendo questo, mi sono reso conto che i miei grafici a oggetti più recenti (più immutabili di prima) seguono sostanzialmente questa linea guida senza che sia stata dichiarata chiaramente come hai fatto tu. Questo è un buon antidoto moderato allo "hogwash sempre cattivo" che a volte senti.
Mike supporta Monica il

@Mike: penso che il vero problema sia che tutti i riferimenti agli oggetti in Java e .NET sono completamente promiscui; qualsiasi codice che acquisisce o riceve un riferimento a un oggetto può condividerlo con qualsiasi altro codice, senza restrizioni. Nessuno dei due framework ha alcun concetto di campo di riferimento non condivisibile; strutture e byref in .NET si avvicinano, ma sono piuttosto limitati in termini di cosa possono fare o cosa possono impedire al codice esterno di fare. In ogni caso, vorrei offrire un detto fondamentale riguardo allo stato mutevole: alle 12:57, un oggetto può rappresentare contemporaneamente ...
supercat

... lo stato attuale di un oggetto del mondo reale e lo stato dell'oggetto alle 12:57. Se lo stato reale dell'oggetto cambia, non sarà più possibile per un oggetto rappresentare entrambi. A volte sarà necessario che l'oggetto continui a rappresentare lo stato delle 12:57, e talvolta lo stato attuale. La relazione tra lo stato 12:57 e lo stato attuale non può rimanere, tuttavia, se lo stato attuale cambia.
supercat

0

A rischio di andare oltre la risposta alla domanda, è facile vedere difetti nell'idea di OOP, ma sono propenso a pensare che il potere di un'idea si rifletta nella sua capacità di essere abusato.

Dopotutto, ognuno ha la sua lingua preferita, che descrivono in termini di "molto molto potente", il che significa che a loro piace molto . Ma la meraviglia dell'universalità computazionale è che non importa quanto sia gloriosa una lingua, se è veramente potente può simulare il linguaggio assembly. E se può, qualcuno vedrà che lo fa. (Non che ci sia qualcosa di sbagliato nel linguaggio assembly.)

La mia personale sensazione riguardo al carrozzone OOP è che rappresenta un arresto della formazione delle persone nell'ingegneria del software / informatica. Sono stentati a un livello in cui pensano che tutto riguardi la struttura dei dati. Classi, ereditarietà, contenitori, iteratori, mappe hash, proprietà, nascondere lo stato , ecc. - tutto sulla struttura dei dati - tanto più è bello.

Personalmente vorrei vedere un livello successivo in cui le persone imparerebbero a risolvere i problemi osservandoli linguisticamente. Dove comprenderanno il concetto di linguaggi specifici del dominio, come renderli facilmente e lasciare che la loro creazione sia parte integrante della risoluzione dei problemi. Non è errato affermare che una struttura di dati sia una lingua. Le persone dovrebbero avere quell'abilità nel design del linguaggio, quindi non si limitano a confonderlo.

Quindi come livello successivo, vorrei vedere l'intelligenza artificiale rinvigorita. Mi piacerebbe vedere i programmatori andare oltre byte e thread, tabelle di funzioni virtuali e CUDA e passare a come far ragionare, apprendere e creare le macchine. So che questo è progredito molto lontano in piccoli angoli del campo, ma da nessuna parte abbastanza ampiamente.


1
"Se è veramente potente, può simulare il linguaggio assembly" - si cambia la definizione di powerfullì. Quando altri dicono powerful, parlano di quanto bene permetta ai programmatori di astrarre , che è una storia diversa rispetto al potere computazionale .
Phil

@Phil: abstract è un'altra di quelle parole :)
Mike Dunlavey,

Nah. Stavi parlando di parole. Stavo parlando di idee. Il tuo secondo e terzo uso della parola powersignificano cose diverse. Per favore, non indurre in errore.
Phil

A proposito, se sei interessato, dai un'occhiata a Racket , che è in qualche modo vicino all'approccio che stai dicendo nel tuo quarto paragrafo (consentendo ai programmatori di portare la lingua al livello del loro problema invece di farli portare il loro problema al insieme fisso di costrutti del linguaggio). Va ben oltre il classico Lisp / Scheme, nel caso in cui qualcuno abbia quell'impressione quando lo guarda per la prima volta.
Phil

0

L'accessibilità non è una funzionalità di OOP, è specifica per implementazioni come Java e Microsoft dotNET. La caratteristica principale che definisce OOP è il polimorfismo.

In ogni caso, nascondendo lo stato dell'oggetto, non è possibile creare un'API significativa. La presentazione è una componente vitale della OOP del mondo reale. Coloro che non sono d'accordo probabilmente hanno un'ostilità irrazionale nei confronti dell'industria del software, il che rende la loro opinione irrilevante dal mio punto di vista.

I siti web come quello che hai collegato sono noti per pensieri e critiche estremamente rigide sulle nuove tecnologie. Alcune persone semplicemente non capiscono.


Dovrebbe esistere un oggetto per proteggere gli invarianti del concetto che modella. La presentazione è una preoccupazione completamente separata e non può essere gestita in modo efficiente e sostenibile dallo stesso oggetto, poiché un oggetto non può comprendere tutti i vari modi in cui potrebbe essere presentato nel tempo e nello spazio. La presentazione deve essere gestita attraverso altri meccanismi come lo streaming di eventi e le viste materializzate se il tuo obiettivo è oggetti versatili e gestibili. L'unica volta in cui un oggetto dovrebbe cambiare è se il suo concetto viene rivisto o i suoi invarianti cambiano.
Andrew Larsson,
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.