... ed è probabilmente uno di quegli articoli su cui si basava OOP.
Non proprio, ma si è aggiunto alla discussione, specialmente per i professionisti che, all'epoca, erano addestrati a scomporre i sistemi usando i primi criteri che descrive nel documento.
Innanzitutto voglio sapere se la mia valutazione è corretta. Il paradigma FP e questo articolo sono filosoficamente in disaccordo?
No. Inoltre, ai miei occhi, la tua descrizione di come appare un programma FP non è diversa da qualsiasi altra che usi procedure o funzioni:
I dati vengono passati da una funzione all'altra, ogni funzione essendo intimamente consapevole dei dati e "cambiandoli" lungo il percorso.
... ad eccezione della parte "intimità", poiché è possibile (e spesso lo fanno) avere funzioni che operano su dati astratti, proprio per evitare l'intimità. Quindi, hai un certo controllo su quella "intimità" e puoi regolarla come preferisci, impostando interfacce (cioè funzioni) per ciò che vuoi nascondere.
Quindi, non vedo alcun motivo per cui non saremmo in grado di seguire i criteri di Parnas per nascondere le informazioni utilizzando la programmazione funzionale e finire con l'implementazione di un indice KWIC con vantaggi simili simili alla sua seconda implementazione.
Supponendo che siano d'accordo, mi piacerebbe sapere quale sia l'attuazione del programma quadro per nascondere i dati. È ovvio vederlo in OOP. Puoi avere un campo privato a cui nessuno al di fuori della classe può accedere. Non esiste un'analogia ovvia per me in FP.
Per quanto riguarda i dati, è possibile elaborare astrazioni di dati e astrazioni di tipi di dati utilizzando FP. Ognuna di queste nasconde strutture concrete e manipolazioni di queste strutture concrete usando funzioni come astrazioni.
MODIFICARE
C'è un numero crescente di affermazioni qui che affermano che "nascondere i dati" nel contesto di FP non è così utile (o OOP-ish (?)). Quindi, lasciatemi timbrare qui un esempio molto semplice e chiaro di SICP:
Supponiamo che il tuo sistema debba lavorare con numeri razionali. Un modo in cui potresti volerli rappresentare è come una coppia o un elenco di due numeri interi: il numeratore e il denominatore. Così:
(define my-rat (cons 1 2)) ; here is my 1/2
Se ignori l'astrazione dei dati, molto probabilmente otterrai il numeratore e il denominatore utilizzando car
e cdr
:
(... (car my-rat)) ; do something with the numerator
Seguendo questo approccio, tutte le parti del sistema che manipolano i numeri razionali sapranno che un numero razionale è un cons
- saranno cons
numeri per creare razionali ed estrarli usando operatori di lista.
Un problema che potresti dover affrontare è quando devi avere una forma ridotta dei numeri razionali: saranno necessari cambiamenti nell'intero sistema. Inoltre, se decidi di ridurre al momento della creazione, potresti scoprire in seguito che è meglio ridurre quando si accede a uno dei termini razionali, producendo un altro cambiamento su vasta scala.
Un altro problema è se, ipoteticamente, si preferisce una rappresentazione alternativa per loro e si decide di abbandonare la cons
rappresentazione - di nuovo il cambiamento di fondo scala.
Qualsiasi sforzo sensato nel gestire queste situazioni probabilmente inizierà a nascondere la rappresentazione di razionali dietro le interfacce. Alla fine, potresti finire con qualcosa del genere:
(make-rat <n> <d>)
restituisce il numero razionale il cui numeratore è il numero intero <n>
e il cui denominatore è il numero intero <d>
.
(numer <x>)
restituisce il numeratore del numero razionale <x>
.
(denom <x>)
restituisce il denominatore del numero razionale <x>
.
e il sistema non saprà più (e non dovrebbe più) sapere di cosa sono fatte le razionali. Questo perché cons
, car
e cdr
non sono intrinseci ai razionali, ma make-rat
, numer
e lo denom
sono . Naturalmente, questo potrebbe facilmente essere un sistema FP. Quindi, "nascondere i dati" (in questo caso, meglio noto come astrazione dei dati, o lo sforzo di incapsulare rappresentazioni e strutture concrete) viene come un concetto pertinente e una tecnica ampiamente usata ed esplorata, sia nel contesto di OO, programmazione funzionale o qualunque cosa.
E il punto è ... sebbene si possa provare a fare distinzioni tra quale "tipo di nascondersi" o incapsulamento stanno facendo (se nascondono una decisione di progettazione, o strutture di dati o algoritmi - nel caso di astrazioni procedurali), tutti hanno lo stesso tema: sono motivati da uno o più punti resi espliciti da Parnas. Questo è:
- Modificabilità: se le modifiche richieste possono essere apportate localmente o se vengono diffuse nel sistema.
- Sviluppo indipendente: fino a che punto due parti del sistema possono essere sviluppate in parallelo.
- Comprensibilità: quanto del sistema è necessario per essere conosciuto per comprendere una delle sue parti.
L'esempio sopra è stato preso dal libro SICP, quindi, per la discussione completa e la presentazione di questi concetti nel libro, consiglio vivamente di dare un'occhiata al capitolo 2 . Raccomando anche di acquisire familiarità con i tipi di dati astratti nel contesto di FP, il che mette in discussione altri problemi.