Domanda

Quali fattori determinano quale approccio è più appropriato?

È stato utile?

Soluzione

Penso che entrambi abbiano il loro posto.

Non dovresti semplicemente usare DoSomethingToThing(Thing n) solo perché pensi che "la programmazione funzionale sia buona".Allo stesso modo non dovresti semplicemente usare Thing.DoSomething() perché "La programmazione orientata agli oggetti è buona".

Penso che dipenda da ciò che stai cercando di trasmettere.Smetti di pensare al tuo codice come a una serie di istruzioni e inizia a pensarlo come un paragrafo o una frase di una storia.Pensa a quali parti sono le più importanti dal punto di vista del compito da svolgere.

Ad esempio, se la parte della "frase" che desideri sottolineare è l'oggetto, dovresti utilizzare lo stile OO.

Esempio:

fileHandle.close();

Nella maggior parte dei casi, quando si passano gli handle di file, la cosa principale a cui si pensa è tenere traccia del file che rappresenta.

Controesempio:

string x = "Hello World";
submitHttpRequest( x );

In questo caso l'invio della richiesta HTTP è molto più importante della stringa che ne costituisce il corpo, quindi submitHttpRequst(x) è preferibile a x.submitViaHttp()

Inutile dire che questi non si escludono a vicenda.Probabilmente l'avrai davvero

networkConnection.submitHttpRequest(x)

in cui li mescoli entrambi.La cosa importante è pensare a quali parti vengono enfatizzate e cosa trasmetterai al futuro lettore del codice.

Altri suggerimenti

Per essere orientato agli oggetti, racconta, non chiedere: http://www.pragmaticprogrammer.com/articles/tell-dont-ask.

Quindi, Thing.DoSomething() anziché DoSomethingToThing(Thing n).

Se hai a che fare con lo stato interno di una cosa, Thing.DoSomething() ha più senso, perché anche se cambi la rappresentazione interna di Thing, o come funziona, il codice che parla con esso non deve cambiare.Se hai a che fare con una raccolta di cose o scrivi alcuni metodi di utilità, DoSomethingToThing() in stile procedurale potrebbe avere più senso o essere più semplice;ma tuttavia, di solito può essere rappresentato come un metodo sull'oggetto che rappresenta quella raccolta:ad esempio

GetTotalPriceofThings();

contro

Cart.getTotal();

Dipende davvero da quanto è orientato agli oggetti il ​​tuo codice.

  1. Cosa. Fai qualcosa è appropriato se Thing è l'oggetto della tua frase.
    • FaiQualcosaPerCosa(Cosa n) è appropriato se Thing è l'oggetto della tua frase.
    • CosaA.FaiQualcosa AllaCosaB(CosaB m) è una combinazione inevitabile, poiché in tutti i linguaggi a cui riesco a pensare, le funzioni appartengono a una classe e non sono di proprietà reciproca.Ma questo ha senso perché puoi avere un soggetto e un oggetto.

La voce attiva è più semplice di quella passiva, quindi assicurati che la frase abbia un soggetto che non sia semplicemente "il computer".Ciò significa utilizzare frequentemente il modulo 1 e il modulo 3 e utilizzare raramente il modulo 2.

Per chiarezza:

// Form 1:  "File handle, close."
fileHandle.close(); 

// Form 2:  "(Computer,) close the file handle."
close(fileHandle);

// Form 3:  "File handle, write the contents of another file handle."
fileHandle.writeContentsOf(anotherFileHandle);

Sono d'accordo con Orion, ma riformulerò il processo decisionale.

Hai un sostantivo e un verbo / un oggetto e un'azione.

  • Se molti oggetti di questo tipo utilizzeranno questa azione, prova a rendere l'azione parte dell'oggetto.
  • Altrimenti, prova a raggruppare l'azione separatamente, ma con azioni correlate.

Mi piacciono gli esempi di file/stringhe.Esistono molte operazioni sulle stringhe, come "SendAsHTTPReply", che non si verificano per la stringa media, ma si verificano spesso in una determinata impostazione.Tuttavia, in pratica chiuderai sempre un file (si spera), quindi ha perfettamente senso inserire l'azione Chiudi nell'interfaccia della classe.

Un altro modo di pensare a questo è come acquistare parte di un sistema di intrattenimento.Ha senso abbinare un telecomando TV con una TV, perché li usi sempre insieme.Ma sarebbe strano collegare insieme al televisore un cavo di alimentazione per uno specifico videoregistratore, poiché molti clienti non lo utilizzeranno mai.L'idea chiave è quanto spesso verrà utilizzata questa azione su questo oggetto?

Non ci sono abbastanza informazioni qui.Dipende se la tua lingua supporta anche il costrutto "Thing.something" o equivalente (es.è un linguaggio OO).Se è così, è molto più appropriato perché questo è il paradigma OO (i membri dovrebbero essere associati all'oggetto su cui agiscono).In uno stile procedurale, ovviamente, DoSomethingtoThing() è la tua unica scelta...o CosaFaiQualcosa()

DoSomethingToThing(Thing n) sarebbe più un approccio funzionale mentre Thing.DoSomething() sarebbe più un approccio orientato agli oggetti.

Questa è la scelta tra programmazione orientata agli oggetti e programmazione procedurale :)

Penso che i vantaggi OO ben documentati si applichino a Thing.DoSomething()

Ecco un paio di fattori da considerare:

  • Puoi modificare o estendere il file Thing classe.In caso contrario, utilizzare il primo
  • Potere Thing essere istanziato.In caso contrario, utilizzare il successivo come metodo statico
  • Se Thing vengono effettivamente modificati (ad es.ha proprietà che cambiano), preferiscono la seconda.Se Thing non viene modificato, quest'ultimo è altrettanto accettabile.
  • Altrimenti, poiché gli oggetti devono essere mappati su oggetti del mondo reale, scegli il metodo che sembra più radicato nella realtà.

Anche se non lavori in un linguaggio OO, dove avresti Thing.DoSomething(), per la leggibilità complessiva del tuo codice, con una serie di funzioni come:

ThingDosomething () ThingDoAnotherTask () ThingWedosomethingelse ()

Poi

Un'altra cosa fai qualcosa()

e così via è molto meglio.

Tutto il codice che funziona su "Thing" si trova in un'unica posizione.Naturalmente, "DoSomething" e altre attività dovrebbero essere denominate in modo coerente, quindi hai un ThingOneRead(), un ThingTwoRead()...a questo punto dovresti avere punti.Quando tornerai a lavorare sul codice tra dodici mesi, apprezzerai il tempo dedicato a rendere le cose logiche.

In generale, se "qualcosa" è un'azione che "cosa" sa naturalmente fare, allora dovresti usare thing.doSomething().Questo è un buon incapsulamento OO, perché altrimenti DoSomethingToThing(thing) dovrebbe accedere a potenziali informazioni interne di "thing".

Ad esempio fattura.getTotal()

Se "qualcosa" non fa naturalmente parte del modello di dominio della "cosa", allora un'opzione è utilizzare un metodo di supporto.

Per esempio:Logger.log(fattura)

Se è probabile che DoingSomething to a object produca un risultato diverso in un altro scenario, allora ti suggerirei oneThing.DoSomethingToThing(anotherThing).

Ad esempio potresti avere due modi per salvare qualcosa nel tuo programma, quindi potresti adottare un DatabaseObject.Save(thing) SessionObject.Save(thing) sarebbe più vantaggioso di thing.Save() o thing.SaveToDatabase o thing.SaveToSession() .

Raramente non passo parametri a una classe, a meno che non stia recuperando proprietà pubbliche.

Per aggiungere alla risposta di Aeon, dipende dalla cosa e da cosa vuoi farci.Quindi, se stai scrivendo Thing e DoSomething altera lo stato interno di Thing, l'approccio migliore è Thing.DoSomething.Tuttavia, se l'azione non si limita a modificare lo stato interno, allora DoSomething(Thing) ha più senso.Per esempio:

Collection.Add(Thing)

è meglio di

Thing.AddSelfToCollection(Collection)

E se non hai scritto Thing e non puoi creare una classe derivata, allora non hai altra scelta che fare DoSomething(Thing)

Anche nella programmazione orientata agli oggetti potrebbe essere utile usare una chiamata di funzione invece di un metodo (o per questo motivo chiamare un metodo di un oggetto diverso da quello su cui lo chiamiamo).Immagina un semplice framework di persistenza del database in cui desideri semplicemente chiamare save() su un oggetto.Invece di includere un'istruzione SQL in ogni classe che desideri salvare, complicando così il codice, diffondendo SQL in tutto il codice e rendendo la modifica del motore di archiviazione un PITA, potresti creare un'interfaccia che definisca save(Class1), save(Class2 ) eccetera.e la sua implementazione.Quindi chiameresti effettivamente databaseSaver.save(class1) e avrai tutto in un unico posto.

Devo essere d'accordo Kevin Conner

Tieni presente anche il chiamante di uno dei 2 moduli.Il chiamante è probabilmente un metodo di qualche altro oggetto che sicuramente fa qualcosa alla tua Cosa :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top