OOP mantiene la promessa di riutilizzo del codice? Quali alternative ci sono per ottenere il riutilizzo del codice?


56

Forse la più grande promessa di usare il paradigma orientato agli oggetti è il riutilizzo del codice. Alcuni contestano che ciò sia stato raggiunto. Perché è stato (non) raggiunto?

Il riutilizzo del codice come OOP lo definisce, rende i progetti più produttivi?

O più gestibile? O più facile da mantenere? O con più qualità?

Probabilmente siamo tutti d'accordo sul fatto che il riutilizzo del codice sia una buona cosa, ma ci sono diversi modi per raggiungere questo obiettivo. La domanda riguarda il metodo di riutilizzo del codice offerto da OOP. È stata una buona cosa? Esistono metodi migliori per ottenere il riutilizzo del codice rispetto all'orientamento agli oggetti, alla sottoclasse, al polimorfismo, ecc.? Quali sono i modi migliori? Perché ?

Raccontaci la tua esperienza con il riutilizzo OOP o il riutilizzo di altri paradigmi.



7
È complementare, non esattamente duplicato. Ho riformulato per capire meglio la differenza.
Maniero,

Se puoi votare e pensare che questa sia una domanda utile o abbia delle risposte utili di seguito, vota per favore. I siti StackExchange hanno bisogno di voti per costruire una buona comunità. Puoi dare 30 voti al giorno, non sprecarli. Specialmente gli utenti con alta reputazione e basso numero di voti assegnati, per favore leggi questo: meta.programmers.stackexchange.com/questions/393/…
Maniero


2
@j_random_hacker: leggi i commenti.
Maniero,

Risposte:


34

Il riutilizzo del codice è una buona idea. Non eccezionale .

Ho una prospettiva tratta da circa 30 anni di ingegneria del software, cercando di "riutilizzare".

Ho iniziato a studiare il "riutilizzo del codice" come argomento di ricerca negli anni '80, dopo aver scoperto di aver riutilizzato la progettazione di un sistema operativo che ho creato nei primi anni '70, per un altro sistema operativo che ho costruito alla fine degli anni '70.

La buona parte del riutilizzo del codice è la possibilità di riutilizzare a volte il codice preesistente da onesto a dio. Ma il mondo è pieno di codice; come puoi trovare quello che vuoi? Ecco cosa chiamo la maledizione del riutilizzo :

Sono Babbo Natale (ok Open Source) e ho un sacco di 1 miliardo di componenti software. Puoi averne uno qualsiasi.

Buona fortuna a scegliere.

Per risolvere bene il problema del riutilizzo:

  • il riutilizzatore deve in qualche modo specificare ciò di cui ha bisogno (funzionalità, prestazioni, lingua di destinazione, ipotesi ambientali, ...)
  • ci deve essere una libreria di codice "riutilizzabile" che è stata indicizzata in vari modi da questi criteri potenziali
  • deve esistere un meccanismo per selezionare gli elementi candidati (con un miliardo di elementi, non è possibile esaminarli tutti personalmente)
  • deve esserci un modo per caratterizzare quanto siano lontani dalle specifiche i candidati scelti
  • dovrebbe esistere un processo regolare per consentire al reutente di modificare il codice riutilizzabile scelto (ecco il maggior contributo di OOP: è possibile modificare un componente / oggetto esistente sovrascrivendo i suoi slot. OOP non fornisce alcun altro aiuto).
  • tutto ciò deve chiaramente essere più economico della semplice ricodifica

Principalmente ciò che è stato scoperto nel corso degli anni è che per essere riutilizzabile, il codice deve essere progettato a tale scopo o contiene troppe ipotesi implicite. Le librerie di riutilizzo del codice di maggior successo sono state in realtà piuttosto piccole. Probabilmente librerie e framework sono codici "riutilizzabili" e hanno un enorme successo; Java e C # non riescono perché sono linguaggi per computer piuttosto buoni, ma piuttosto perché dispongono di enormi librerie ben progettate, implementate e documentate. Ma le persone non guardano il codice sorgente nelle librerie; chiamano semplicemente un'API ben documentata (progettata per essere generalmente utilizzabile).

Ciò che il riutilizzo del codice non ha fatto (nemmeno OOP) è fornire ordini di miglioramento della grandezza nella nostra capacità di codificare i sistemi.

Penso che il difetto chiave sia che qualsiasi tipo di riutilizzo del codice è fondamentalmente limitato perché il codice ha troppe ipotesi integrate . Se rendi il codice minuscolo, riduci al minimo le ipotesi, ma poi il costo per creare da zero non è molto grande e i guadagni di riutilizzo non sono efficaci. Se rendi enormi i blocchi di codice, sono praticamente inutili in un nuovo contesto. Come Gulliver, sono legati alla spiaggia da un milione di piccole stringhe e semplicemente non puoi permetterti di tagliarle tutte.

Ciò su cui dovremmo lavorare è il riutilizzo della conoscenza per costruire il codice . Se riusciamo a farlo, allora possiamo applicare quella conoscenza per costruire il codice di cui abbiamo bisogno, gestendo l'attuale insieme di ipotesi.

Per fare ciò, è ancora necessaria la stessa capacità di specifica per caratterizzare i componenti software (devi ancora dire quello che vuoi!). Ma poi si applica questa conoscenza di "costruzione" alle specifiche per generare il codice desiderato.

Come comunità, non siamo ancora molto bravi in ​​questo. Ma la gente lo fa sempre; perché non possiamo automatizzarlo? C'è molta ricerca, e questo dimostra che può essere fatto in molte circostanze.

Un elemento chiave del macchinario necessario per questo sono strumenti meccanici per accettare "descrizioni dei componenti" (questi sono solo documenti formali e possono essere analizzati come linguaggi di programmazione) e applicare loro trasformazioni di programma .

I compilatori lo fanno già: -} E sono davvero bravi nella classe di problemi che affrontano.

I modelli UML con generazione di codice sono un tentativo per farlo. Non è un ottimo tentativo; praticamente quello che si dice nella maggior parte dei modelli UML è "Ho dati che assomigliano a questo". Abbastanza difficile generare un vero programma se la funzionalità viene lasciata fuori.

Sto cercando di costruire sistemi di trasformazione del programma pratico, uno strumento chiamato DMS . Sono stato abbastanza ben distratto dall'applicazione delle trasformazioni del programma non tanto alle specifiche astratte per generare il codice, ma piuttosto al codice legacy per ripulirlo. (Questi sono gli stessi problemi in astratto!). (Per costruire tali strumenti richiede molto tempo; lo faccio da 15 anni e nel frattempo devi mangiare).

Ma DMS ha le due proprietà chiave che ho descritto sopra: la capacità di elaborare specifiche formali arbitrarie e la capacità di acquisire "conoscenze sulla generazione di codice" come trasformazioni e applicarle su richiesta. E sorprendentemente, generiamo in alcuni casi speciali, un codice piuttosto interessante dalle specifiche; DMS è in gran parte costruito usando se stesso per generare la sua implementazione. Ciò ha raggiunto per noi almeno alcune delle promesse di riutilizzo (della conoscenza): incrementi di produttività estremamente significativi. Ho un team di circa 7 persone tecniche; abbiamo probabilmente scritto 1-2 MSLOC di "specifiche" per DMS, ma abbiamo circa 10 MSLOC di codice generato.

Riepilogo: il riutilizzo della conoscenza della generazione è la vittoria, non il riutilizzo del codice .


4
IMHO, la migliore risposta. L'importante è il riutilizzo di idea / idea, non il codice.
kravemir,

4
Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions.Ho raggiunto una conclusione simile, ma non potevo esprimerlo in modo così conciso.
biziclop,

36

Il riutilizzo del codice è ottenuto in OOP ma anche nella programmazione funzionale. Ogni volta che prendi un blocco di codice e lo rendi richiamabile dal resto del codice in modo che tu possa usare questa funzionalità altrove è il riutilizzo del codice.

Questo tipo di riutilizzo del codice rende anche il codice più gestibile perché la modifica di questo blocco richiamabile modifica tutte le posizioni in cui viene chiamato. Direi che anche questo risultato ha migliorato la qualità e la leggibilità.

Non sono sicuro che OOP sia semplicemente lì per fornire il riutilizzo del codice. Considero OOP più un modo per interagire con gli oggetti e sottrarre i dettagli della struttura dei dati.

Da Wikpedia:

La programmazione orientata agli oggetti ha radici che possono essere fatte risalire agli anni '60. Poiché l'hardware e il software sono diventati sempre più complessi, la gestibilità è diventata spesso una preoccupazione. I ricercatori hanno studiato i modi per mantenere la qualità del software e hanno sviluppato una programmazione orientata agli oggetti in parte per affrontare i problemi comuni enfatizzando fortemente le unità discrete e riutilizzabili della logica di programmazione [citazione necessaria]. La tecnologia si concentra sui dati piuttosto che sui processi, con programmi composti da moduli autosufficienti ("classi"), ciascuna delle quali ("oggetti") contiene tutte le informazioni necessarie per manipolare la propria struttura di dati ("membri"). Ciò è in contrasto con la programmazione modulare esistente che era stata dominante per molti anni incentrata sulla funzione di un modulo, piuttosto che specificamente sui dati, ma che prevedeva ugualmente il riutilizzo del codice, e unità riutilizzabili autosufficienti della logica di programmazione, consentendo la collaborazione attraverso l'uso di moduli collegati (subroutine). Questo approccio più convenzionale, che persiste ancora, tende a considerare i dati e il comportamento separatamente.


9
La programmazione funzionale +1 può essere la strada da percorrere per il riutilizzo del codice.
Jonas,

1
@Matthieu M .: Beh, quanto è riutilizzabile double sqrt (double x)? Le funzioni pure sono l'archetipo della riusabilità.
Joonas Pulakka,

3
@Joonas: double sqrt(double x), float sqrt(float x), int sqrt(int x)è possibile definire un sacco di loro, mentre con un linguaggio di programmazione generico si dovrebbe Number sqrt(Number x)e da fare con esso.
Matthieu M.

1
@Matthieu M .: In effetti, i generici riducono la replica del codice, quindi è "più riutilizzabile", sì. Tuttavia, penso che la vera chiave della riusabilità sia definire funzioni semplici, piccole, sane, pure (questa è la direzione della "programmazione funzionale") e passarle in giro, cosa possibile in C. Si tratta più dello stile di programmazione generale che di sulle capacità della lingua stessa.
Joonas Pulakka,

1
@Joonas: Ah, mi era sfuggita la parola pura , hai ragione, comporre piccole funzioni pure è semplicemente fantastico, e persino C presenta dei puntatori a funzioni per quello.
Matthieu M.,

15

Sì e no

Il riutilizzo del codice è un termine generico per molte attività diverse.

  1. Riutilizzo del codice all'interno di un singolo progetto. OO è perfettamente adatto a questo, un'applicazione ben progettata avrà mappato da vicino le relazioni del mondo modellato, eliminando il codice duplicato il più possibile e consigliabile. Tuttavia, puoi sostenere che le tecnologie pre-OO potrebbero ottenere la stessa cosa, il che è vero, ma OO è per molti aspetti più conveniente.
  2. Librerie di terze parti Questo sembra funzionare ugualmente bene con o senza OO.
  3. Riutilizzo del codice multiuso La più grande promessa di riutilizzo del codice di OO era che il codice, una volta scritto per un'applicazione, potesse essere successivamente riutilizzato per un'altra, per cui non era stato progettato specificamente. Questo fu di gran moda quando il concetto di OO filtrò attraverso le porte degli uffici di gestione superiore e OO non riuscì completamente a raggiungerlo. Si è scoperto che lo scopo era un aspetto cruciale della progettazione di OO (e forse tutto il codice procedurale, ma questa è solo la mia teoria) e i tentativi di riproporre il codice si sono conclusi in catastrofi di manutenzione. (I famosi modelli di un vecchio framework nessuno osa modificare e il suo amico, i framework leggermente diversi per ogni app di solito derivano da qui.)

13

Vorrei pubblicare una risposta lunga ma perché? Udi Dahan lo spiega molto meglio di me.

http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/

Ecco l'inizio del post:

Questo settore è pre-occupato con il riutilizzo.

C'è questa convinzione che se riutilizzassimo più codice, tutto sarebbe meglio.

Alcuni arrivano addirittura a dire che l'intero punto dell'orientamento agli oggetti è stato riutilizzato - non lo era, l'incapsulamento era la cosa più importante. Dopo che l'orientamento ai componenti era la cosa che doveva far accadere il riutilizzo. A quanto pare non è andato così bene anche perché ora stiamo riponendo le nostre speranze riutilizzabili sull'orientamento al servizio.

Sono stati scritti interi libri di schemi su come ottenere il riutilizzo con l'orientamento della giornata. I servizi sono stati classificati in tutti i modi nel tentativo di raggiungere questo obiettivo, dai servizi alle entità e ai servizi di attività, attraverso i servizi di processo e i servizi di orchestrazione. I servizi di composizione sono stati pubblicizzati come la chiave per il riutilizzo e la creazione di servizi riutilizzabili.

Potrei anche farti conoscere il piccolo segreto sporco:

Il riutilizzo è un errore


4
-1. Il signor Dahan è preoccupato per gli uomini di paglia; nessuno riutilizza seriamente il codice non generico come suggerisce, e se rimuovi quell'argomento dal suo articolo, è in effetti a favore o al riutilizzo del codice in modo appropriato .
Steven A. Lowe,

3
@Steven A. Lowe Beh, vorrei che fosse vero. Vorrei avere la tua fortuna perché ho visto il riutilizzo del codice in forma non generica. Non è stato carino.
Tony,

1
sono sicuro che non lo era - ma erano seri ? dilbert.com/strips/comic/1996-01-31
Steven A. Lowe il

1
D'accordo, il costo per rendere riutilizzabile il codice è davvero alto, quindi non paga se non si parla della scala delle classi base Java o .NET. Vedi youtube.com/watch?v=aAb7hSCtvGw
Andomar

13

Sono d'accordo con Chris, la programmazione funzionale è un buon modo per riutilizzare il codice.

Molti programmi hanno strutture di codice ricorrenti. Per questo alcuni modelli di progettazione sono utilizzati nel mondo OOP, ma ciò può essere ottenuto mediante funzioni ricorsive e corrispondenza dei modelli in linguaggi di programmazione funzionale. Per ulteriori informazioni, consultare il primo capitolo nella Programmazione funzionale del mondo reale .

Penso che l'eredità profonda in OOP possa essere fuorviante in molti casi. Hai una classe e molti dei metodi strettamente correlati sono implementati in diversi file. Come ha detto Joe Armstrong su OOP:

Il problema con i linguaggi orientati agli oggetti è che hanno tutto questo ambiente implicito che portano con sé. Volevi una banana ma quello che hai ottenuto è stato un gorilla con in mano la banana e l'intera giungla.

Le funzioni di ordine elevato sono anche molto utili quando si tratta di riutilizzo del codice, ad esempio, mape foldrquesto è il fondamento di MapReduce di Google .

Il passaggio di messaggi asincroni è anche un buon modo per organizzare software complessi e alcuni informatici affermano che si presume che gli oggetti comunichino tra loro asincroni come nel Tell, non chiedere il principio OOP. Maggiori informazioni in merito alla programmazione orientata agli oggetti: il percorso sbagliato? dove Joe Armstrong è citato:

Ho iniziato a chiedermi cosa fosse la programmazione orientata agli oggetti e pensavo che Erlang non fosse orientato agli oggetti, era un linguaggio di programmazione funzionale. Quindi, il mio supervisore della tesi ha detto "Ma ti sbagli, Erlang è estremamente orientato agli oggetti". Ha detto che i linguaggi orientati agli oggetti non sono orientati agli oggetti. Potrei pensare, anche se non sono del tutto sicuro di crederci o no, ma Erlang potrebbe essere l'unico linguaggio orientato agli oggetti perché i 3 principi della programmazione orientata agli oggetti sono che si basa sul passaggio di messaggi , che hai l' isolamento tra gli oggetti e avere polimorfismo .

Il passaggio di messaggi asincroni come nei sistemi basati sugli eventi e in Erlang è anche un ottimo modo per disaccoppiare i sistemi e l' accoppiamento lento è importante nei sistemi complessi. Con un sistema sufficientemente disaccoppiato è possibile far evolvere il sistema mentre è in esecuzione, magari su nodi diversi. Unibet ha fatto un'ottima presentazione al riguardo: Domain Event Driven Architecture

Tuttavia, penso che la maggior parte del riutilizzo del codice venga eseguita utilizzando librerie e framework.


2
Adoro quella citazione di Gorilla. ^^
gablin

Pensavo che la domanda riguardasse il riutilizzo del codice, non una bella semantica ...?
Daniel Lubarov,

6

L'umile pipe unix ha fatto di più per il riutilizzo del codice di qualsiasi altra cosa sia andata e venuta. Gli oggetti sono semplicemente diventati un modo intuitivo di strutturare il codice quando sono arrivati ​​e in seguito le persone hanno iniziato ad attaccare qualsiasi cosa su di esso. In generale gli oggetti sono per l'incapsulamento e non per il riutilizzo del codice, il riutilizzo del codice richiede qualcosa di più e la gerarchia dell'ereditarietà delle classi è un cattivo sostituto di ciò che dovrebbe essere un meccanismo di riutilizzo del codice.


4

OOP non è speciale; puoi creare codice riutilizzabile con o senza OOP. Le funzioni pure sono particolarmente riutilizzabili : ad esempio, java.lang.math.sqrt(double)accetta un numero e ne fornisce un numero. No OOP, ma sicuramente più riutilizzabile rispetto alla maggior parte dei codici disponibili.


4

Dal punto di vista della programmazione funzionale, OOP riguarda principalmente la gestione dello stato.

Nella programmazione funzionale puoi facilmente avere centinaia di utili funzioni per gli elenchi: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html .

Avresti centinaia di metodi in una classe List? I metodi pubblici sono considerati un'interfaccia allo stato interno che si desidera mantenere di dimensioni ridotte.

Purtroppo, invece di (ri) utilizzare molte piccole funzioni, alcune persone duplicano la funzionalità. Per me è perché OOP non incoraggia il riutilizzo del codice tanto quanto la programmazione funzionale.


1
Le tue conclusioni sono tutte sbagliate, @ Lenny222. Non c'è nulla in OOP che richiede alle classi di mantenere lo stato. Questa è una domanda della sua architettura se memorizza lo stato internamente o, come le classi Integer di Smalltalk, crea un'istanza di nuovi oggetti con un nuovo stato.
Huperniketes,

1
Mi dispiace di non essermi espresso in un modo che ha impedito questo fraintendimento: ciò che intendevo dire è che la differenza tra OOP e FP non è che il codice EOP di EOPage riutilizzi più di quanto faccia FP (cosa implica il titolo). Ho sperimentato un riutilizzo del codice molto migliore con FP. Se hai solo classi immutabili, stai emulando FP, perché OOP in primo luogo? Nel mio POV si tratta della gestione imperativa dello stato.
LennyProgrammers,

3

Per me sì, ma non sempre, e avrebbe potuto essere fatto in altri modi.

Il più delle volte creando una classe base astratta e creando implementazioni concrete di quella classe.

Inoltre, molti framework utilizzano l'ereditarietà per fornire il riutilizzo del codice (Delphi, Java, .Net sono solo alcuni di quelli che vengono subito in mente).

Questo non vuol dire che molte librerie di utilità e frammenti di codice non avrebbero potuto fare altrettanto, ma c'è qualcosa di gradito in una gerarchia di oggetti ben progettata.


3

Nella mia esperienza, ho avuto più successo sfruttando il codice "riutilizzabile" attraverso strutture di programmazione generiche (come i modelli C ++) di quanto abbia avuto usando i principi OOP come le gerarchie di ereditarietà.


2

OOP è troppo aperto per un riutilizzo efficace.

Ci sono troppi modi per riutilizzarli. Ogni classe pubblica chiede: "creami una nuova istanza!" , ogni metodo pubblico dice: "chiamami!" , ogni metodo protetto produce: "scavalcami!" - e tutti questi modi di riutilizzo sono diversi , hanno parametri diversi, appaiono in contesti diversi, tutti hanno le loro regole diverse, come chiamarlo / estenderlo / sovrascriverlo.

L'API è migliore, è un sottoinsieme rigoroso di punti OOP (o non-oop), ma nella vita reale le API sono troppo funzionanti e in continua crescita, ci sono ancora troppi punti di connessione. Inoltre, una buona API può semplificare la vita, è il modo migliore per fornire l'interfaccia per OOP.


Il paradigma di Datadlow fornisce un'interfaccia rigorosa per i componenti, hanno porte dei seguenti tipi:

  • consumatori (input) e
  • produttori (risultati).

Dipende dal dominio, ci sono alcuni tipi di pacchetti, quindi consumatori e produttori possono essere collegati in quanto hanno porte uguali (o compatibili). La parte più bella di ciò, che può essere eseguita visivamente, poiché non ci sono parametri o altre modifiche sulle connessioni, collegano davvero solo un consumatore e un produttore.

Ero un po 'poco chiaro, potresti dare un'occhiata al tag "flusso di dati" su StackOverflow , o alla "programmazione datafow" di Wikipedia o alla "programmazione basata sul flusso" di Wikipedia .

(Inoltre, ho scritto un sistema di flusso di dati, in C ++. Quindi OOP e DF non sono nemici, DF è un modo di organizzazione di livello superiore.)


2

In CommonLisp ci sono molti modi per ottenere il riutilizzo:

  • digitazione dinamica, il cui codice è generico per impostazione predefinita

  • astrazioni imperative, cioè subroutine

  • orientamento agli oggetti, con ereditarietà multipla e invio multiplo

  • sintassi-astrazione, la capacità di definire nuovi costrutti sintattici o abbreviare il codice della piastra della caldaia

  • astrazioni funzionali, chiusure e funzioni di alto ordine

Se si tenta di confrontare l'esperienza Common Lisp ad altre lingue vedrai che la caratteristica principale che facilita il riutilizzo del codice è la presenza di entrambe le astrazioni orientate agli oggetti e funzionali. Sono più complementari che alternativi: senza uno di essi sei costretto a reimplementare le funzionalità mancanti in modo goffo. Vedere, ad esempio, le classi di funzioni utilizzate come chiusure e corrispondenza dei modelli per ottenere l'invio di metodi non estensibile.


1

In realtà non esiste un "riutilizzo" nel modo in cui le persone lo descrivono. Il riutilizzo è una proprietà accidentale di qualsiasi cosa. È difficile pianificarlo. Ciò che la maggior parte delle persone intende quando parlano di "riutilizzo" è "uso". È un termine molto meno attraente ed eccitante. Quando usi una libreria, la usi per quello a cui era destinata, normalmente. Stai Non riutilizzando a meno che non si sta facendo qualcosa di veramente pazzesco con esso.

In tal senso, il riutilizzo nel mondo reale riguarda il ri-scopo delle cose. Posso riutilizzare questi posti qui e riordinarli per formare ... un letto! Non è un letto molto comodo, ma posso farlo. Questo non è il loro uso principale. Li sto riutilizzando al di fuori del loro dominio originale di applicabilità. [...] Domani tornerò in aereo nel Regno Unito. Io non riutilizzare il piano. Lo userò solo per lo scopo a cui era destinato, non c'è niente di speciale o eccitante in questo.

- Kevlin Henney


3
Le persone crederanno a tutto ciò che vedono nella stampa. Kevlin Henney non è corretto e ha basato il suo ragionamento su una mancanza di contesto storico e una scarsa interpretazione semantica. Il riutilizzo del codice era un principio di programmazione fondamentale dai tempi dei computer a tubi sottovuoto UNIVAC e IBM. Riutilizzare il codice non significava riutilizzarlo per alcune funzionalità diverse da quella per cui era stato pianificato . Hai scritto e assemblato (in seguito è stato compilato) le tue routine secondarie per produrre codice oggetto che è stato quindi collegato al tuo programma. Riutilizzare significa davvero cosa significhi comunemente nel settore oggi.
Huperniketes,

Se scrivi due funzioni che fanno esattamente la stessa cosa, NON hai riutilizzato il codice indipendentemente da quante volte le hai usate.
JeffO,

L'analogia della sedia è buona e tutto questo, ma solo una parola: Lego.
biziclop,

1

Rischio di ridicolizzare e confessare, ho usato OOP solo di recente. Non viene da me automaticamente. La maggior parte della mia esperienza riguarda database relazionali, quindi penso a tabelle e join. Ci sono affermazioni che è meglio impararlo dall'inizio, il che evita di dover ricollegare il tuo pensiero quando si tratta di programmazione. Non ho quel lusso e mi rifiuto di abbandonare la mia carriera su una teoria della torre d'avorio. Come tutto il resto, lo capirò.

All'inizio pensavo che l'intero concetto non avesse senso. Sembrava inutile e troppi problemi. Lo so, questo è un discorso folle. Ovviamente ci vuole un certo livello di comprensione prima che tu possa apprezzare i benefici di qualsiasi cosa o respingerlo per metodi migliori.

Il riutilizzo del codice richiede la volontà di non ripetere il codice, una comprensione di come realizzarlo, una pianificazione anticipata. Dovresti evitare di riutilizzare il codice quando hai deciso di avere un caso in cui non ne vale la pena? E nessun linguaggio è così rigorosamente OO che genererà un errore quando pensa che dovresti aver ereditato il codice da un'altra classe. Nella migliore delle ipotesi forniscono un ambiente favorevole alla sua attuazione.

Penso che il più grande vantaggio di OOP sia l'accettazione generale di come dovrebbe essere organizzato il codice. Tutto il resto è sugo. Un team di programmatori potrebbe non essere completamente d'accordo su come tutte le classi dovrebbero essere strutturate, ma dovrebbero essere in grado di trovare il codice.

Ho visto abbastanza codice procedurale per sapere che potrebbe essere ovunque, e talvolta è ovunque.


"E nessun linguaggio è così rigorosamente OO che genererà un errore quando pensa che dovresti aver ereditato il codice da un'altra classe" - non ancora, comunque!
Steven A. Lowe,

1

OOP ti offre più modi per riutilizzare il codice. Questo è tutto.


OOP promuove anche il riutilizzo dell'interfaccia e il riutilizzo del design.
rwong

Mi dà molti meno modi di scrivere un codice generico, riutilizzabile, altamente astratto rispetto agli altri paradigmi, come la programmazione funzionale (curriculum mentale, librerie combinatorie, ecc.) E la metaprogrammazione. In realtà, OOP sembra avere un livello di coppa di astrazione, quando le alternative non sono affatto limitate.
Logica SK

@ SK-logic: ortogonale.
Steven A. Lowe,

1

Riutilizzo orizzontale: aspetti, tratti, innesti

OO classico a volte non riesce a riutilizzare il codice, specialmente quando impazzisci per l'eredità per mancanza di un modo migliore per condividere la funzionalità effettiva tra le classi. Per questo problema, sono stati creati meccanismi di riutilizzo orizzontale, come AOP, tratti e innesti.

Programmazione orientata agli aspetti

Considero AOP come la mezza arancia mancante di OOP. AOP non è poi così noto, ma è arrivato al codice di produzione.

Lo proverò a spiegare in termini semplici: immagina di poter iniettare e filtrare la funzionalità con una struttura speciale chiamata aspetto, questi aspetti hanno "metodi" che definiscono cosa e come verranno influenzati dalla riflessione , ma al momento della compilazione , questo processo si chiama tessitura .

Un esempio potrebbe essere un aspetto che dice "per tutti i metodi di determinate classi che iniziano con get, il programma scriverà in un file di registro i dati che sono stati ottenuti e l'ora in cui sono stati".

Guarda questi due discorsi se vuoi capire meglio AOP:

Tratti e innesti

I tratti sono un altro costrutto per definire il codice riutilizzabile che integra OOP, sono simili ai mixin , ma più puliti.

Invece di spiegarli, c'è un ottimo RFC PHP che spiega entrambi . I tratti stanno arrivando a PHP tra l'altro, sono già impegnati nel trunk.

In sintesi

OOP è la chiave della modularità, secondo me, e come la conosciamo oggi, OOP è ancora incompleta .


0

OOP Fornisce una serie di strumenti utili che ti consentono di scrivere codice che può essere utilizzato in più punti di quanti ne potresti avere senza quegli strumenti. Se scrivi una PrintItfunzione che accetta qualsiasi vecchio oggetto e lo chiama .toString(), avrai riutilizzato quel codice non appena lo chiamerai con più di un tipo di oggetto. Con questi strumenti, ogni riga di codice fa di più.

La programmazione funzionale è molto calda in questo momento tra gli hipster. Ti fornisce un set di strumenti completamente separato per fare di più ogni riga di codice. Probabilmente non è meglio o funziona, ma fornisce un altro strumento nella casella degli strumenti.

(C'era un'idea folle per un ulteriore livello di riutilizzo orientato agli oggetti: l'idea era che potremmo definire una singola Customerclasse e usarla in ogni applicazione che abbiamo scritto. Quindi le applicazioni sarebbero solo un po 'di colla qua e là. non ha funzionato, ma ciò non significa che OO sia fallito, o anche che il Riutilizzo sia fallito. I tipi di base di riutilizzo del codice all'interno delle applicazioni hanno permesso di scrivere applicazioni che hanno fatto di più e di scriverle più velocemente.)


0

Leggendo i post precedenti, alcune osservazioni:

  • Molti pensano che il riutilizzo del codice in OOP implichi l'ereditarietà. Non sono d'accordo. Interfacce e contratti sono il nucleo per riutilizzare il codice nei sistemi OOP. OOP è un tentativo in scatola grigia nella creazione di una tecnologia componente.
  • La differenza tra "quadri" specifici di dominio e generici come soggetto di riutilizzo mi sembra troppo astratta. A mio avviso, un componente (un contratto di interfaccia conciso, minimale e riutilizzabile e l'implementazione dietro) può essere fatto solo se il problema che affronta è ben compreso. Un componente specifico del dominio, che consente agli esperti non di dominio di svolgere il proprio lavoro con meno conoscenze sul dominio, è un componente (ri) utile. Gli utenti devono comprendere l'interfaccia, tanto meno le complessità del dominio problematico.
  • Livelli di riutilizzo spesso dimenticati: riutilizzo di idee, riutilizzo di specifiche, riutilizzo di architettura / design, riutilizzo di interfacce, riutilizzo di test case. Il riutilizzo del codice non è sempre favorevole. Ma è spesso un grande risparmio di tempo attenersi a un'architettura specifica per affrontare un nuovo prodotto simile.
  • I modelli di OOP Design (Gamma et. Al) ai miei occhi hanno elaborato tecniche di implementazione tattica anziché essere significativi nel contesto del riutilizzo del codice su scala più ampia. Aiutano a scrivere un'applicazione con elementi OOP, ma non li vedrei come una soluzione alla domanda "riutilizzo del codice" oltre a una singola applicazione.
  • Forse non è giusto: 20 anni di esperienza in C / C ++ / C # e 6 mesi di programmazione funzionale (F #). Un elemento importante per consentire il riutilizzo è: le persone devono trovare facilmente "l'interfaccia", studiarla, comprenderla, quindi usarla. La pura programmazione funzionale non mi rende facile vedere la struttura, i candidati per il riutilizzo o dove tutto inizia e dove tutto finisce. Lo "zucchero sintattico" tanto apprezzato è spesso il sale nei miei occhi, che mi impedisce di vedere facilmente cosa succede. Pertanto, avrei meno probabilità di provare a riutilizzare un funzionale (che cos'è - un gruppo di funzioni?), Che potrebbe avere effetti collaterali nascosti che non riesco nemmeno a vedere (valutazione pigra, monadi, ...). Non fraintendetemi, la programmazione funzionale ha lati molto interessanti, ma tutti i punti di forza proclamati vedo con una buona dose di dubbi.
  • Specifica, progettazione, implementazione sono viste accoppiate, ma non facilmente percorribili sulla "stessa cosa". Molto più vitale per una maggiore produttività futura rispetto a un nuovo paradigma di programmazione è, per colmare il divario, per aumentare (ragionamento automatizzato, tracciabilità) i vantaggi reciproci tra tali punti di vista. Linguaggi di specifica formalizzati, notazioni di prova standardizzate (ad es. Ttcn3) e linguaggi di programmazione che supportano la verifica di interfacce e contratti rispetto a specifiche senza sporcare commenti possono essere ciò di cui abbiamo più urgente bisogno.

0

Il problema è imho più sottile:

  1. OOP è un ottimo metodo per strutturare il codice con stato mutabile . Incapsulando lo stato in oggetti, il codice stateful imperativo diventa più comprensibile perché, ad esempio, se un pezzo di stato viene espresso come campi privati ​​di una classe, sai che almeno questo particolare pezzo di stato può essere modificato solo con metodi di questo classe. (E puoi facilmente rompere questo beneficio abusando dell'eredità, tra l'altro.) Ora questo è abbastanza, ma è meglio che non avere nemmeno questo.
  2. il codice con stato modificabile è intrinsecamente difficile da riutilizzare . Molto più difficile del codice utilizzando strutture di dati immutabili.

Quindi OOP in sé non è male dal punto di vista della creazione di codice riutilizzabile , ma i tipi di codice che vengono scritti usando OOP sono intrinsecamente difficili da riutilizzare .

Inoltre, la programmazione funzionale può comportare un codice più riutilizzabile . Ma ottenere le astrazioni giuste per scrivere un codice funzionale sano nel rispetto di una scadenza potrebbe non essere fattibile. E le astrazioni "a metà destra" saranno più facili da esprimere in stile OOP. E non tenderà a facilitare il riutilizzo del codice : un livello più elevato di astrazioni significa che la comprensione del codice richiederà un investimento iniziale più elevato a causa della limitata capacità cognitiva dei programmatori.

Come esempio pratico: il codice di gioco comporta un sacco di stato mutevole, perché questo è il modo naturale di pensare alla codifica di un gioco, a meno che non sia un puzzle / algoritmico, quindi finisce per essere strutturato usando OO. E ovviamente è difficile riutilizzarlo. Ma lo stesso codice, contenente la stessa conoscenza, sarebbe ancora più difficile da riutilizzare senza OOP . E riscriverlo come stile funzionale potrebbe aver bisogno di cambiare totalmente il modo in cui pensi a quel codice, la conoscenza dietro di esso. Sì, la conoscenza risultante dietro il codice sarebbe molto più chiara dopo la riscrittura da OO a FP forse ... ma il costo potrebbe essere enorme e potrebbe essereil tipo di costo che dovrebbe anche essere pagato dalle persone che desiderano riutilizzare il codice incredibilmente intelligente e ben astratto che si finisce con , quindi paradossalmente, le persone finirebbero per non riutilizzare il codice, anche se tecnicamente è più riutilizzabile.

... che porta all'ultima sottigliezza: il riutilizzo del codice riguarda l' interfaccia People | Code , non solo il codice. OOP fa un buon lavoro nel servire questa interfaccia perché si associa bene a quante persone pensano a molti tipi di codice scritti al giorno d'oggi. FP potrebbe essere migliore per il riutilizzo del codice, ma non per riutilizzare facilmente il tipo di codice che le persone devono effettivamente scrivere al giorno d'oggi. Questo cambierà come cambia il tipo di codice di cui abbiamo bisogno per scrivere.

PS E se qualcuno vuole dire che "OO non riguarda lo stato mutabile, puoi anche avere OO con stato immutabile" ... Io chiamo quel "FP che usa le classi come spazi dei nomi". È fantastico quando funziona per te ed evita alcune carenze dei sistemi dei moduli di alcune lingue e può comportare un codice più riutilizzabile. Ma questo non è OO;)

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.