Cosa intendeva Rich Hickey quando disse: "Tutta quella specificità [di interfacce / classi / tipi] uccide il tuo riutilizzo!"


41

Nel keynote della stimolante conferenza di Rich Hickey " Il valore dei valori " a 29 minuti sta parlando dell'overhead di un linguaggio come Java e fa una dichiarazione del tipo: "Tutte quelle interfacce uccidono il tuo riutilizzo". Che cosa intende? È vero?

Nella mia ricerca di risposte, mi sono imbattuto in:

Chiaramente, qualsiasi cosa scritta abbastanza male sarà inutile. Ma come potrebbe l'interfaccia di un'API ben scritta impedire l'utilizzo di quel codice? Ci sono esempi nel corso della storia di qualcosa fatto per uno scopo e usato più per qualcos'altro . Ma nel mondo del software, se usi qualcosa per uno scopo a cui non era destinato, di solito si rompe.

Sto cercando un buon esempio di una buona interfaccia che impedisce un uso legittimo ma non intenzionale di un codice. Esiste? Non riesco a immaginarlo.


1
Non hai guardato / letto le cose (ho aggiunto "Stop Writing Classes" alla mia lista di osservatori :)), ma forse stanno discutendo da un angolo di battitura dinamico o statico? ...ancora?
Andres F.,

oO Interfacce dell'interfaccia di programmazione dell'applicazione
Thomas Eding

Grazie per i collegamenti! Non ho trovato il discorso di Jack Diederich particolarmente illuminante (guarda come non riesce a rispondere in modo convincente alle domande autentiche del pubblico .. "uh, sì, forse in quel caso ...". Mi è piaciuto che sembra discutere per la Programmazione Funzionale senza anche notandolo;)), ma la "crisi dell'abbigliamento imperiale" è molto buona e perspicace.
Andres F.

1
MPO è che le persone che non credono nel riutilizzo non suddividono le cose in unità abbastanza piccole. Una grande cosa costruita per uno scopo specifico non può essere riutilizzata. Tuttavia, le piccole cose di solito hanno uno scopo abbastanza piccolo da renderlo utile in più di un contesto.
Amy Blankenship,

1
@AmyBlankenship Ho trovato perspicace la "crisi dell'abbigliamento imperiale" collegata sopra. L'autore considera il "riutilizzo" un falso idolo (qualcosa che non è stato dimostrato utile nella pratica, e inoltre la maggior parte delle persone non lo capisce nemmeno se usa la parola). Inoltre non considera le biblioteche "riutilizzo"; si usa una libreria, non riutilizzare esso. Considera anche di progettare qualcosa per il riutilizzo "un'arma a doppio taglio"; qualcosa che le persone di solito considerano una situazione vantaggiosa per tutti ma che in realtà non lo è: quando progetti qualcosa per il riutilizzo, è sempre un compromesso (ad esempio potresti perdere in semplicità)
Andres F.

Risposte:


32

Non ho visto la presentazione completa di Rich Hickey, ma se lo capisco correttamente, e a giudicare da ciò che dice sul punteggio di 29 minuti, sembra che stia discutendo dei tipi che uccidono il riutilizzo. Sta usando il termine "interfaccia" liberamente come sinonimo di "tipo chiamato", il che ha senso.

Se hai due entità { "name":"John" }di tipo Persone { "name": "Rover" }di tipo Dog, in Java-land probabilmente non possono interagire a meno che non condividano un'interfaccia o un antenato comune (come Mammal, il che significa scrivere più codice). Quindi le interfacce / tipi qui stanno "uccidendo il tuo riutilizzo": anche se Persone Dogsembrano uguali, uno non può essere usato in modo intercambiabile con l'altro, a meno che non si scriva un codice aggiuntivo per supportarlo. Nota Hickey scherza anche sui progetti in Java che richiedono molte classi ("Chi ha scritto un'applicazione Java usando solo 20 classi?"), Che sembra una conseguenza di quanto sopra.

Nelle lingue "orientate al valore", tuttavia, non assegnerai tipi a tali strutture; sono solo valori che condividono la stessa struttura (nel mio esempio entrambi hanno un namecampo con un valore String) e quindi possono facilmente interagire, ad esempio possono essere aggiunti alla stessa raccolta, passati agli stessi metodi, ecc.

Per riassumere, tutto ciò sembra riguardare l' uguaglianza strutturale contro l' uguaglianza esplicita di tipo / interfaccia . A meno che non mi sia sfuggito qualcosa dalle parti del video che non ho ancora visto :)


2
A proposito, il discorso di Jack Diederich "Stop Writing Classes" sembra non avere alcuna relazione con questo argomento, ed è più su YAGNI e "non scrivere codice fino a quando non ne hai bisogno, e quindi scrivere solo codice semplice".
Andres F.

9
ERROR: Object doesn't have a property called "name"è spesso il risultato di value-orientedlingue e l'altro problema è quando non si desidera più chiamare quella proprietà name. Buona fortuna refactoring perché probabilmente ci sono centinaia di oggetti con una proprietà namema non tutti lo sono Persono Dog.
Reactgular,

2
@MathewFoscarini Sì, non sono necessariamente d'accordo, è solo la mia interpretazione di ciò che penso che Hickey stesse dicendo :) Mi piacciono i tipi e la tipizzazione statica; Sto appena iniziando a non gradire Java. E la mia antipatia non è correlata a interfaces ma al caos che è il tipico progetto Java.
Andres F.

1
Java è il linguaggio di programmazione per coloro che preferiscono pensare troppo. È una delle poche lingue che consente a uno sviluppatore di nascondere facilmente i suoi tentativi di progettare eccessivamente un progetto.
Reactgular,

"Nei linguaggi" orientati al valore "non assegnerai tipi a quelle strutture" - Penso che tu debba dire "Nel dinamico" orientamento al valore "..." Haskell e Scala sono orientati al valore, ma il loro sistema di tipi statici dà loro il problema esatto che stai descrivendo. Penso che la soluzione a questo problema non sia tanto quanto l'utilizzo delle mappe per passare parametri alle funzioni. L'uso di mappe (valori) immutabili è solo più sicuro.
GlenPeterson,

28

Probabilmente si riferisce al fatto fondamentale che un'interfaccia non può essere istanziata. Non è possibile reuseun'interfaccia. Puoi implementare solo il codice che lo supporta e quando scrivi il codice per un'interfaccia non c'è riutilizzo.

Java ha una storia di fornitura di framework di molte API che prendono un'interfaccia come argomenti, ma il team che ha sviluppato l'API non implementa mai una vasta gamma di classi per poterle riutilizzare con quelle interfacce.

È un po 'come un framework GUI che ha IWindowun'interfaccia per una finestra di dialogo e quindi puoi aggiungere IButtoninterfacce per i controlli. Tranne che non ti hanno mai dato una buona Buttonclasse che implementa IButton. Quindi sei rimasto a creare il tuo.

I framework astratti che dispongono di una vasta gamma di classi base che forniscono funzionalità di base sono più riutilizzabili e funzionano meglio quando tali classi astratte sono accessibili a coloro che utilizzano il framework.

Gli sviluppatori Java hanno iniziato a fare questa cosa in cui sono esposti solo i loro livelli API interfaces. È possibile implementare tali interfacce, ma non è mai possibile riutilizzare le classi dallo sviluppatore che ha implementato tali interfacce. È un po 'come uno stile di mantello e pugnale di sviluppo API.


4
Grazie per questa risposta Ora sento di capire la domanda e la risposta :)
MetaFight,

2
+1 Apprezzo molto la tua risposta e aggiunge un affascinante livello di informazioni interessanti a questa domanda. Ma penso che la risposta di Andreas F. sia probabilmente più vicina al cuore di ciò che intendeva Mr. Hickey, quindi ho accettato invece la sua.
GlenPeterson,

@GlenPeterson nessun problema, penso che potrebbe anche essere sul punto.
Reactgular,

1
Bene, questa e la risposta accettata evidenziano due interpretazioni leggermente diverse, ma ugualmente interessanti. Sono curioso di sapere quale Mr. Hickey avesse in mente quando parlava di questo ...
David Cowden,

Non è possibile riutilizzare un'interfaccia, ma è possibile estenderla (e fornire un prezioso numero di versione) senza modificare le vecchie classi. È inoltre possibile ereditare da molte interfacce per aggiungere un nuovo lavoro per nuove classi o aggiungere una nuova eredità nelle vecchie classi ricompilate. È inoltre possibile estendere la classe che implementa questa interfaccia per un nuovo lavoro.
cl-r,

14

Penso che la diapositiva 13 alla sua presentazione ( Il valore dei valori ) aiuti a capire questo:

http://i.stack.imgur.com/LVMne.png


Valori

  • Non ho bisogno di metodi
    • Posso inviarti valori senza codice
      e stai bene

La mia comprensione è che Hickey suggerisce che se devo, per esempio, raddoppiare il valore che mi hai inviato, scrivo semplicemente un codice simile a

    MyValue = Double(YourValue)

Vedi, il codice sopra è lo stesso, indipendentemente dal tipo di valore che hai inviato - una sorta di riutilizzo perfetto .

Ora, come apparirebbe nel linguaggio con oggetti e interfacce?

    Doublable MyValue = YourValue.Double()

oh aspetta! cosa succede YourValuese non implementare Doublable? non che non possa essere raddoppiato, potrebbe essere perfettamente ma ... e se non ci fosse un metodo Double ? (cosa succede se esiste un metodo chiamato dire TwiceAsMuch?)

Oh oh abbiamo un problema. YourValue.Doublenon funzionerà, non può più essere riutilizzato . Secondo la mia lettura della diapositiva sopra, si tratta di ciò che Hickey intendeva quando disse: "Tutte quelle interfacce uccidono il tuo riutilizzo!"

Vedete, le interfacce presuppongono che gli oggetti vengano passati "insieme ai loro metodi", insieme al codice che opera su questi. Per usare gli oggetti, è necessario capire come invocare quel codice, quale metodo chiamare.

Quando manca il metodo previsto , c'è un problema, anche se semanticamente , l'operazione desiderata ha perfettamente senso per un oggetto. Come indicato nella presentazione, i valori non hanno bisogno di metodi ("Posso inviarti valori senza codice e stai bene"), consentendo di scrivere codice trattandoli in modo generico.


Nota a margine: l'idea di passare in giro valori senza codice mi ricorda in qualche modo un modello Flyweight in OOP.

un oggetto che minimizza l'uso della memoria condividendo quanti più dati possibile con altri oggetti simili; è un modo per usare oggetti in grandi numeri quando una rappresentazione ripetuta semplice utilizza una quantità inaccettabile di memoria ... Gli oggetti flyweight sono per definizione oggetti valore . L'identità dell'istanza dell'oggetto non ha alcuna conseguenza, pertanto due istanze Flyweight dello stesso valore sono considerate uguali ...

Gli usi a peso mosca che ho visto in genere hanno seguito lo stesso approccio di togliere il codice (metodi, interfacce) dagli oggetti e far circolare oggetti come pure valori senza codice , aspettandosi che ricevere codice abbia i mezzi necessari per operare su questi.

Sembra quasi come nella diapositiva, "i valori non hanno bisogno di metodi. Posso inviarti valori senza codice e tu stai bene".


5
I generici si prenderanno praticamente cura di quel problema. Il raddoppio ha senso su alcuni oggetti, ma non su altri. Nel linguaggio Go, c'è un'implementazione implicita dell'interfaccia (una forma di duck typing), quindi non hai tutte quelle interfacce di cui preoccuparti. D'altra parte, devi sapere quale oggetto verrà colpito dalla firma del tuo metodo; in caso contrario, potresti ottenere risultati imprevisti. Ci sono sempre dei compromessi.
Robert Harvey,

1
Un'interessante interpretazione. Buona risposta!
maple_shaft

2
Il modello flyweight non è ciò di cui Rich sta parlando. Come afferma la seconda frase dell'articolo, lo scopo del modello flyweight è quello di conservare la memoria. L'approccio di Rich non cerca di farlo.

5
MyValue = Double(YourValue)non ha senso se YourValue è una stringa, un indirizzo, un utente, una funzione o un database. Altrimenti, l'argomento del metodo mancante è forte. OTOH, i metodi di accesso ti consentono di applicare vari vincoli in modo che i tuoi valori siano validi e che vengano utilizzate solo operazioni sensibili per produrre nuovi valori. Se in seguito decidi di separare l'indirizzo dal tuo utente e dalla tua azienda, i metodi di accesso significano che non rompi tutti i client del tuo codice. Quindi possono aiutare a riutilizzarli a lungo termine anche se a volte lo ostacolano a breve termine.
GlenPeterson,

4
(D'altro canto, concordo sul fatto che in Java-land, l'esplosione di classi, interfacce e framework è un incubo. La soluzione "enterprisey" più semplice in Java è un casino di codice. Quindi prendo una lezione preziosa da questo domanda e risposta, senza essere necessariamente d'accordo con la tipizzazione dinamica)
Andres F.

2

In un (cioè il mio) mondo ideale le classi e le interfacce descrivono sempre il comportamento, ma il fatto è che troppo spesso finiscono per descrivere i dati. Solo ieri ho visto il video di qualcuno costruire una cosiddetta BankAccountclasse che non era altro che un glorificato int(in effetti era molto meno utile di un int, quindi "uccidere" il riutilizzo che avrei avuto se fosse stato semplicemente lasciato come un int), tutto in nome del design "buono". La quantità di codice, sudore e lacrime sprecati per reinventare continuamente rappresentazioni contorte di dati è sconcertante; se non stai utilizzando i dati in modo significativo, ti preghiamo di lasciarli.

Ora, questo è il palcoscenico in cui Rich Hickey si accontenta di buttare il bambino con l'acqua del bagno e dire che dovremmo andare tutti a vivere nella terra dei valori (un vicino al regno dei nomi). Penso, d'altra parte, che OOP possa e riusci a promuovere il riutilizzo (e soprattutto la rilevabilità, che trovo carente nella programmazione funzionale) se impiegato con giudizio. Se stai cercando un principio OOP che catturi meglio questa tensione, penso che potrebbe essere http://c2.com/cgi/wiki?TellDontAsk (che ovviamente è un cugino stretto di Demetra)


Cosa intendi per rilevabilità? È simile a questo ?

1
Sì, penso che tocchi molti dei punti principali. È un punto sottile ma la rilevabilità è un atto di bilanciamento, anche rendere le cose troppo trasparenti è indesiderabile perché otterrai un cattivo rapporto segnale-rumore.
CurtainDog,
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.