Gli oggetti in OOP devono rappresentare un'entità?


82

Un oggetto deve rappresentare un'entità?

Da un'entità intendo qualcosa come Product, Motorun ParkingLotecc, un fisico, o anche un oggetto concettuale non fisico netta - qualcosa che è ben definita, con alcuni dati fondamentali chiaramente appartenenti all'oggetto, e alcune funzioni / metodi che operano chiaramente sui dati di base.

Ad esempio, posso avere un oggetto di un Demon, un'entità in sé, un immaginario forse e non fisico ma un'entità comunque

Un oggetto può essere solo un insieme di metodi , un insieme comune di procedure collegate a un obiettivo comune?

Esempio: può essere chiamata una classe MotorOperationso MotorActions, dove non c'è entità, ma i metodi all'interno della classe fanno cose del genere

  • getMotorDataFromHTMLForm ()
  • getMotorManufacturers ()
  • selectMotorFromUserRequirements ($ requisiti)
  • canMotorCanHandleOperatingConditions ($ condizioni)
  • computePowerConsumptionForMotor ($ id)

Una classe viene in genere definita come centrale per l'oggetto + operazioni sui dati. Quindi per un Motorci possono essere alcune variabili del motore relative alle specifiche del motore e ci possono essere operazioni che combinano quei dati per produrre qualcosa.

Nel mio caso è più come se avessi una classe con operazioni su dati + dati passati attraverso la classe, non ci sono dati incentrati su "Motor Operations", oltre ai dati temporanei pass-through-the-class.

Domanda

Le classi possono rappresentare oggetti senza entità? In caso contrario, perché sono cattivi / incompleti / non-OOP-centrici? Ci sono modi in cui devono essere cambiati / migliorati concettualmente per essere in linea con OOP?


2
+1. Ma "sì" significherebbe che deve rappresentare un'entità o significherebbe che possono rappresentare oggetti senza entità?
Panzercrisis,

1
Prima cosa che mi viene in mente: java.awt e le sue classi "Op" (es. Docs.oracle.com/javase/7/docs/api/java/awt/image/… ), se è questo che intendi. Rappresenta un'operazione. Ora, non sono sicuro che sia una buona pratica (sembra strano e brutto), ma è incluso nella libreria standard Java e Java è OOP. Per la maggior parte.
Luca

1
No non lo è, ma ciò non significa MotorActionso MotorOperationssono buone idee o no.
user253751

1
Questa domanda potrebbe beneficiare di un'ulteriore specifica di can .
reinierpost,

3
@Dennis Mi sento davvero come se stessi facendo tutte le domande sbagliate. Primo perché non esiste una definizione definitiva di OOP, secondo perché i paradigmi sono solo un mezzo per raggiungere un fine. Le uniche domande che contano sono "scrivere codice in questo modo rende più facile ragionare sulla sua correttezza?" e "scrivere codice in questo modo facilita il riutilizzo?"
Doval,

Risposte:


109

No , un oggetto non deve rappresentare un'entità.

In effetti, direi che quando smetti di pensare agli oggetti come entità fisiche è quando finalmente ottieni i benefici che OOP promette.

Questo non è il miglior esempio, ma il design della caffettiera è probabilmente il punto in cui la luce ha iniziato ad accendersi per me.

Gli oggetti riguardano i messaggi. Riguardano le responsabilità. Non si tratta di automobili, utenti o ordini.

So che insegniamo OO in questo modo, ma dopo alcuni tentativi diventa evidente quanto sia fondamentalmente frustrante capire dove vanno le cose quando provi a fare MVC, MVVM o MVWhatever. O i tuoi modelli diventano ridicolmente gonfi o lo fanno i tuoi controller. Per la navigabilità, è bello sapere che tutto ciò che tocca i veicoli è nel file Vehicle.ext, ma quando la tua applicazione riguarda i veicoli, inevitabilmente finisci con 3000 linee di spaghetti in quel file.

Quando hai un nuovo messaggio da inviare, hai almeno un nuovo oggetto e forse un paio di essi. Quindi, nella tua domanda su un insieme di metodi, direi che potenzialmente stai parlando di un insieme di messaggi. E ognuno potrebbe essere il proprio oggetto, con il proprio lavoro da svolgere. E va bene. Diventerà evidente quando dividerai le cose che le cose davvero, davvero hanno bisogno di stare insieme. E li metti insieme. Ma non lasci immediatamente cadere tutti i metodi in un cassetto vagamente appropriato per comodità, se vuoi goderti OO.

Parliamo di sacchi di funzioni

Un oggetto può essere solo una raccolta di metodi ed essere ancora OO, ma le mie "regole" sono piuttosto rigide.

  1. La raccolta dovrebbe avere una sola responsabilità e quella responsabilità non può essere generica come "Fa roba ai motori". Potrei fare qualcosa come una facciata del livello di servizio, ma sono profondamente consapevole di essere pigro per motivi di navigabilità / scoperta, non perché sto cercando di scrivere il codice OO.

  2. Tutti i metodi dovrebbero essere a un livello coerente di astrazione. Se un metodo recupera oggetti motore e un altro restituisce potenza, probabilmente è troppo distante.

  3. L'oggetto dovrebbe funzionare sullo stesso "tipo" di dati. Questo oggetto fa cose ai motori (start / stop), questo fa cose con lunghezze di manovella, questo gestisce il sequenziamento dell'accensione, questo assume una forma html. Questi dati potrebbero essere campi sull'oggetto e sembrerebbero coesivi.

Generalmente costruisco oggetti di questo tipo quando faccio trasformazioni, composizione o semplicemente non voglio preoccuparmi della mutabilità.

Trovo che concentrarmi sulle responsabilità oggettive mi porti alla coesione. Deve esserci un po 'di coesione per essere un oggetto, ma non c'è bisogno di campi o comportamenti per essere un oggetto. Se stavo costruendo un sistema che richiedesse quei 5 metodi motori, inizierei con 5 diversi oggetti che fanno quelle cose. Quando ho trovato la comunanza, avrei iniziato a fondere le cose insieme o avrei usato oggetti comuni "aiutanti". Questo mi porta a preoccupazioni aperte / chiuse: come posso estrarre questo bit di funzionalità in modo da non dover più modificare quel particolare file ma utilizzarlo ancora dove necessario?

Gli oggetti riguardano i messaggi

I campi contano a malapena un oggetto: ottenere e impostare i registri non cambia il mondo al di fuori del programma. Collaborare con altri oggetti porta a termine il lavoro. Tuttavia, il punto di forza di OO è che possiamo creare astrazioni in modo da non dover pensare a tutti i singoli dettagli contemporaneamente. Le astrazioni che perdono o non hanno senso sono problematiche, quindi pensiamo profondamente (troppo, forse) alla creazione di oggetti che corrispondono ai nostri modelli mentali.

Domanda chiave: perché questi due oggetti devono dialogare?

Pensa all'oggetto come a un organo di una persona: ha uno scopo predefinito e cambia comportamento solo quando riceve un messaggio specifico a cui tiene.

Immagina uno scenario in cui sei nel passaggio pedonale e un'auto sta arrivando velocemente. Come oggetto del cervello, rilevo un fattore di stress. Dico all'ipotalamo di inviare l'ormone che rilascia corticotrofina. La ghiandola pituitaria riceve quel messaggio e rilascia l'ormone corticotrofico surrenale. Le ghiandole surrenali ricevono quel messaggio e creano adrenalina. Quando l'oggetto muscolare riceve quel messaggio di adrenalina, si contrae. Quando il cuore riceve lo stesso messaggio, batte più velocemente. C'è un'intera catena di giocatori coinvolti nell'iniziare il comportamento complesso di correre attraverso la strada ed è i messaggi che contano. L'oggetto cerebrale sa come far sì che l'ipotalamo invii l'allerta, ma non conosce la catena di oggetti che alla fine farà accadere il comportamento. Allo stesso modo il cuore non ha idea da dove provenga l'adrenalina,

Quindi, in questo esempio ( semplificato ), l'oggetto ghiandola surrenale deve solo sapere come prendere ACTH e produrre adrenalina. Non ha bisogno di alcun campo per farlo, eppure mi sembra ancora un oggetto.

Ora, se la nostra applicazione è progettata solo per correre attraverso la strada, potrei non aver bisogno della ghiandola pituitaria e degli oggetti della ghiandola surrenale. Oppure ho solo bisogno di un oggetto ghiandola pituitaria che fa solo una piccola parte di quello che potremmo vedere concettualmente come il "modello di ghiandola pituitaria". Tutti questi concetti esistono come entità concettuali, ma è un software e possiamo creare AdrenalineSender o MuscleContractor o qualsiasi altra cosa e non preoccuparci molto della "incompletezza" del nostro modello.


4
Sono d'accordo con il contenuto effettivo di questa risposta, ma mi sembra che fraintenda la domanda. Nello specifico, la domanda include nell'entità "o un concetto, qualcosa che è ben definito". I contro-esempi a questo sono " MotorOperationso MotorActions". Da questo, sono abbastanza fiducioso che sia il progetto di classe originale che quello finale dell'esempio CoffeeMaker rientrano nella definizione dell'OP di "rappresentare un'entità"
Ben Aaronson,

1
L'architettura di sistema postmoderna DCI gestisce questo senza le astrazioni estreme create da ingegneri amanti della struttura. Il computer dovrebbe pensare a cosa sta pensando l'utente, non viceversa. fulloo.info/doku.php?id=what_is_dci
ciscoheat

@BenAaronson Sento che puoi evolvere in quell'oggetto come concetto coesivo con uno sforzo abbastanza concertato, ma ho trovato la tendenza a focalizzare l'entità per forzare insieme le cose che dovrebbero essere separate. Le entità incoraggiano i confini nei nostri nomi, il che è buono, ma portano anche questa nozione di correttezza / completezza, che tende a ferire. Nei termini più ridicoli, sono per un oggetto FirstNameValidator e contro un oggetto Name che esegue anche la convalida per nome e cognome.
Steve Jackson,


2
Gli oggetti riguardano i messaggi - la risposta di Steve Jackson - questo è assolutamente giusto. MOP non è ciò che si intende per "messaggistica" come concepito da The Father of OO Alan Kay, che ha affermato che la grande idea è la messaggistica . E inoltre, mi dispiace di aver coniato molto tempo fa il termine "oggetti" per questo argomento perché induce molte persone a concentrarsi sull'idea minore.
radarbob,

21

Le classi possono rappresentare oggetti senza entità? In caso contrario, perché sono cattivi / incompleti / non-OOP-centrici? Ci sono modi in cui devono essere cambiati / migliorati?

In breve, puoi fare qualsiasi cosa, ma questo scenario specifico sarebbe contrario ai principi OOP :)

Quello che stai descrivendo è talvolta chiamato una classe di "utilità" - di solito un segno di odore di codice. Si desidera evitare di creare classi per mantenere alcuni metodi insieme.

Non tutti gli oggetti nella tua applicazione devono essere collegati a un'entità reale come un motore o un'auto; quelli sono oggetti business. Nella tua applicazione, è probabile che tu utilizzi molti dei tuoi oggetti business, ma avrai anche bisogno di un po 'più di segregazione per altre operazioni che non fanno parte di entità aziendali, come quelle che hai elencato.

Dovresti dare un'occhiata ai modelli architettonici comuni: uno di questi è MVC (Model-View-Controller) .

Se dovessi distribuire i metodi che hai elencato usando MVC, ecco cosa farei:

Visualizza classe:

  • GetMotorDataFromHTMLForm ()

Classe di modello (motore essenzialmente):

  • GetMotorManufacturer ()
  • CanMotorHandleOperationConditions ()
  • CalculatePowerConsumption ()

Classe controller (MotorsController):

  • GetAllMotors ()
  • GetMotorById ()
  • GetMotorByUserRequirements ()

Sembra che tu stia usando PHP; un buon framework MVC da dare un'occhiata è Laravel . Nei loro esempi illustrano bene a quali metodi appartengono.

Un'altra fonte di informazioni più generica su come decidere a quale metodo appartengono sono i principi GRASP e SOLID .


Grazie. In sostanza, mi sembra che ciò che ho sia una classe Controller con alcune impurità mescolate in (Modello, Vista, ecc.). Questo significa che se cambio titolo MotorOperationsper MotorsControllere pulire un po ', la mia collezione di funzioni sarà in linea con la programmazione orientata agli oggetti?
Dennis,

@Dennis, non necessariamente, dai un'occhiata alla mia raccolta di metodi in ogni classe. Il controller non è una classe che contiene tutto :) È la classe che ha operazioni sui tuoi modelli e niente di più. Le uniche dipendenze di un controller sarebbero generalmente DAL (Data Access Layer) direttamente o servizi che ti forniscono l'accesso a DAL. Non si vuole mai accedere a View dal controller (esempio: getMotorDataFromHTMLForm), invece, View dovrebbe essere quello dipendente dal controller.
Alexus,

2
Potresti approfondire il motivo per cui una Utilsclasse sarebbe un esempio di odore di codice? Solo curioso, dato che mi sono divertito ad avere funzioni util casuali racchiuse in una Utilsclasse invece di essere solo funzioni autonome ... nella mia esperienza rende il codice un po 'più leggibile, ma la mia esperienza è limitata.
HC_

3
@HC_ Avere una classe Utils è come avere una cartella "Misc" nella tua raccolta di immagini. Indica che eri pigro nell'assegnare responsabilità ai tuoi oggetti correttamente / oggetti potenzialmente mancanti e usa Utils per compensare ciò. C'è spazio per le classi Util, specialmente con le funzioni statiche e le estensioni ad altre classi, ma prima di creare una raccolta del genere, controlla se puoi incorporarle nelle tue classi OOP appropriate :) Un altro motivo è che a volte una classe può avere solo un metodo. Ma andando avanti, devi aggiungere altro e la classe Utils diventa un casino più grande.
Alexus,

Finisco spesso con una LIBRERIA Utils, ma di solito cerco di raggruppare e nominare le mie classi utils in modo un po 'più descrittivo. In questi giorni, ci sono molte librerie di "utilità comuni" open source là fuori che hanno già utilità di uso generale di cui la maggior parte delle persone ha bisogno, quindi mi guarderei un po 'prima di scrivere la tua.
Guy Schalnat,

15

Le classi possono rappresentare oggetti senza entità?

Può? Sì. Dovrebbero? Probabilmente no - o almeno, non come stai esprimendo le cose.

Gli oggetti in realtà sono i migliori quando non rappresentano direttamente un oggetto fisico poiché la realtà si associa così raramente al codice. Ma devono rappresentare un concetto coerente o un oggetto codice. Devono rappresentare un'unica responsabilità coesa.

Il solo raggruppamento di un insieme di funzioni tangenzialmente correlate è uno spazio dei nomi o un modulo, non un oggetto nel linguaggio OOP. Questi possono essere utili, ma non sono gli stessi e richiedono un diverso tipo di utilizzo / pensiero per funzionare efficacemente.


3
bundling a bunch of tangentially related functions together is a namespace: sembra più un paradigma procedurale piuttosto che orientato agli oggetti.
Dennis,

@dennis: esattamente (o funzionale se lo chiami Modulo). Il mix di paradigmi può essere potente. Oppure può essere terribilmente disordinato.
Telastyn,

O entrambi :) - - - - -
Alexus

@Dennis: O nessuno dei due - raggruppare insieme solo funzioni tangenzialmente correlate è una pratica dubbia in qualsiasi paradigma.
sdenham,

Ho a che fare con il codice iniziato come base di codice procedurale. Ad un certo punto è stato fatto uno sforzo per convertirlo in OOD ma, soprattutto le classi sono state create per "contenere funzioni e metodi", senza alcun reale progetto OO. Ho scoperto alcune cose come questa che cercano di colmare il divario tra i paradigmi ma non sono né l'uno né l'altro
Dennis

11

Una classe dovrebbe modellare qualcosa - altrimenti è inutile. Tuttavia, ciò che viene modellato potrebbe non essere una "cosa" fisica; invece, potrebbe essere una rappresentazione di qualcosa che non è "reale", ma che è necessario per controllare il sistema da modellare. Ad esempio, in un sistema di controllo del semaforo potresti benissimo avere una sorta di classe ControlSignal, che rappresenta un segnale inviato da una parte del sistema a un'altra per indicare che è necessario eseguire alcune azioni. Nel "mondo reale" questi segnali potrebbero consistere in impulsi elettrici trasmessi attraverso fili da una scatola all'altra. Il processo di modellazione di qualcosa che non è "reale" come un oggetto concreto viene definito "reificazione".

Buona fortuna.


Sì, è quasi esattamente quello che avrei detto. Una classe non è altro che un modello per un sostantivo . Questo è tutto. Niente di più, niente di meno. Una classe è un sostantivo e i metodi sono verbi (o messaggi se preferisci). Un ingegnere junior che pensa in questi semplici termini può fare molto prima che queste analogie si rompano (diversamente dal cercare di fingere che le classi siano descrizioni di oggetti fisici - un'analogia che inizia a rompersi su quasi il tuo primo progetto).
Calphool,

7

No. (Titolo modificato per porre la domanda opposta!)

per esempio:

Public class MyRepository
{
    public MyObject GetObject(string id)
    {
        //get data from the DB and build an object
    }
}

o

Public class MyService
{
    public MyObject3 ProcessData(MyObject1 obj1, MyObject2 obj2)
    {
         //perform a process which is not a sole responsiblity of obj1 or obj2
    }
}

Tuttavia, in generale l'ideale dietro OOP è allontanarsi da

public struct Car
{
    public Wheel[] Wheels;
}

public int CountWheelsOnCar(MyCarStruct car)
{
   return car.Wheels.Length;
}

per

public class Car
{
    private Wheel[] wheels;
    Public int CountWheels()
    {
        return this.wheels.Length;
    }
}

Vuoi dire che possono rappresentare oggetti senza entità? (Vedi il commento che ho lasciato sulla domanda.)
Panzercrisis,

3
Sto programmando OO da troppo tempo immagino - quando ho guardato MyRepository ho immediatamente immaginato una ciotola di vetro sul mio cassettone con un mucchio di monete e cazzate. Raggiungi e prendi un penny o un pulsante ....
Bill K

@pan sì, come il servizio e il repository nel mio esempio
Ewan

@bill, vecchio pazzo !!! Questa è la classe MyButtonAndOrPennyBowl! codice pulito ftw
Ewan

1
Il tuo secondo esempio mi sembra una funzione vestita come un oggetto, che (a mio avviso) non è giustificato per se stessa, anche se potrebbe esserci qualche altra giustificazione (ad esempio se le funzioni non sono entità di prima classe nella lingua. )
sdenham,

5

Penso che visualizzare qualcosa nel mondo reale sia utile quando si codificano le classi ma non è necessario.

In effetti, a seconda di quanto letteralmente vuoi essere, molti oggetti con cui lavoriamo non hanno affatto rappresentazioni fisiche. Ad esempio, considera l'architettura MVC. Nel mondo reale non esiste un modello o controller anche se sono generalmente rappresentati da classi. I tre insieme spesso rappresentano qualcosa, ma non sempre - ma come ho detto probabilmente potresti forzare un adattamento a qualcosa se davvero lo desideri (ed essere in grado di immaginare QUALCOSA aiuta! Visualizzo la maggior parte degli oggetti in qualche modo - proprio niente avresti mai visto nel mondo reale).

Per lo più queste "Regole" che imparerai su OO sono solo linee guida pensate per orientarti a pensare in OO, non necessariamente cose di cui ti preoccupi una volta che lo usi per programmare quotidianamente.

A proposito OO stesso non è un po 'di panacea e non ti aiuta molto durante il tuo primo passaggio nel codificare una soluzione, ma penso che se fatto bene è un modo davvero fantastico di organizzare il codice in modo che possa essere più prontamente capito più tardi. La scrittura di codice gestibile è probabilmente una delle attività più difficili nello sviluppo del software e in molti casi (tutto ciò che richiede un debug / manutenzione in corso) è di gran lunga la più importante.


5

Un oggetto deve rappresentare un'entità?

Domanda: quale entità Loggerrappresenta?

Non metaforicamente - letteralmente.

Quando si spiega OOP agli studenti, è utile spiegare oggetti con analogie con il mondo fisico.

Alan Kay - uno dei padri di OOP - scrisse quanto segue:

[...]

La sua concezione originale aveva le seguenti parti.

  • Ho pensato che gli oggetti fossero come cellule biologiche e / o singoli computer in una rete, in grado di comunicare solo con i messaggi
  • Volevo sbarazzarmi dei dati.

[...]

OOP per me significa solo messaggistica, conservazione e protezione locali e

nascondendo il processo statale ed estremo vincolo tardivo di tutte le cose.

architettura HW quasi incredibile. Mi sono reso conto che il

la metafora cellula / intero computer eliminerebbe i dati

fonte

Da questo, gli oggetti sono meglio compresi come

  • oggetti autarchici che incapsulano / nascondono dati

  • comunicare con altri oggetti tramite messaggi

Le classi possono rappresentare oggetti senza entità?

Sicuramente: pensa a Math


Per quanto riguarda il tuo esempio:

Esempio: una classe può essere chiamata MotorOperations o MotorActions, dove non esiste un'entità, ma i metodi all'interno della classe fanno cose come

  • getMotorDataFromHTMLForm ()

  • getMotorManufacturers ()

  • selectMotorFromUserRequirements ($ requisiti)

  • canMotorCanHandleOperatingConditions ($ condizioni)

  • computePowerConsumptionForMotor ($ id)

Per decidere, dove mettere questi metodi, devi dare un'occhiata a responsibilities: chi è responsabile per cosa .

getMotorDataFromHTMLForm ()

Il contesto di tale metodo sarebbe la costruzione di un oggetto motore . Non è responsabilità del motore creare se stesso dai dati recuperati tramite un modulo . Ci sono almeno due oggetti coinvolti; uno è il motore e l'altro è il creatore del motore .

getMotorManufacturers ()

Il contesto tipico in cui si scriverà un tale metodo è a service.

selectMotorFromUserRequirements ($ requisiti)

Questo sarebbe anche usato in un service-contesto

canMotorCanHandleOperatingConditions ($ condizioni)

Questa è una domanda a un motor-oggetto

computePowerConsumptionForMotor ($ id)

Anche questa è una domanda che è meglio porre al motore stesso.


tl; dr

La metafora di objectscome oggetti fisici è più irritante che utile.


wow la tua risposta respira un po 'di vita in OOP! Devo dire che non intendevo fisico come fine di tutto. lo scopo della mia domanda era più "un oggetto deve essere un thingdato con i dati in cui i dati appartengono chiaramente alla cosa e le funzioni che operano chiaramente sui dati che appartengono alla cosa". Quindi Logger in questo caso, sebbene non sia una cosa fisica, è un concetto simile a quello di un "diario di bordo fisico". Se ha dati che sono fondamentali per il suo stato e che non sono solo transitori ad esso, ciò può dipendere dall'implementazione e dall'interpretazione .. ed è più che altro dove andava la mia domanda ..
Dennis

ma sì, le risposte hanno dovuto affrontare il mio pregiudizio fisico
Dennis

3

Si, puoi fare questo. Ma essenzialmente stai creando una classe per fornire le stesse funzionalità di una libreria procedurale. L'unico motivo per farlo è se la tua lingua manca di moduli procedurali (ad es. Java o Ruby).

In un linguaggio con moduli procedurali (penso che PHP abbia moduli procedurali), potresti prendere in considerazione solo l'uso di un modulo procedurale.

Potresti anche considerare di riprogettare la tua classe in modo che un'istanza della classe rappresenti un oggetto coerente.

Ma usa la notazione OO solo quando ti dà potenza extra, non solo per essere OO!


3

Nelle parole di laici

  • Quello che descrivi si chiama una classe di utilità.
  • Non ha uno stato, il che significa che non avrai mai davvero bisogno di avere diversi casi
  • Tutti i metodi sono statici, il che significa che devi passare tutto come parametro

Esistono tali classi, ad esempio Java SDK ha la classe Collections che consiste esclusivamente di metodi statici che operano su o restituiscono raccolte.

Quindi la risposta sarebbe no, non tutte le classi devono essere modellate da un'entità di dominio.

D'altra parte, tali classi sono solo alcune o dovrebbero essere solo alcune in un programma realizzato in un linguaggio OOP, poiché il vero potere di OOP risiede nel polimorfismo e nell'incapsulamento.

Sarebbe come usare un aereo per spostarsi da un posto all'altro non volando ma guidandolo in autostrada. Gli aerei hanno le ruote come fanno le macchine, ma sono destinati a volare.


2

No, una classe rappresenta semplicemente qualcosa che può essere istanziato, ha membri e da cui può essere ereditato.

In effetti, la tua lingua potrebbe avere classi statiche, che non sono nemmeno istanziate più di una volta.

.NETMath è un ottimo esempio di una classe "professionale" che non rappresenta alcuna entità (a meno che tu non voglia essere filosofico su cosa sia la matematica ...), e capita anche di illustrare un caso d'uso legittimo di tale classe. Ha solo metodi e 2 campi (entrambi che rappresentano singole costanti).

La gerarchia di classi di una libreria simile Math.Netraggruppa i metodi matematici / numerici in classi per tipo. Qui le classi non rappresentano un'entità, ma una categoria logica.

Io stesso finisco spesso per creare classi (statiche) che non sono altro che un insieme di funzioni correlate (statiche) o un gruppo di costanti comodamente raggruppate in un posto centrale. Non direi che questo è un buon design, ma a volte è la soluzione più semplice.


1
Il fatto che i metodi relativi alla matematica siano collocati in .NET / BCL in una classe separata come metodi statici non è una necessità o una considerazione progettuale ma una conseguenza del fatto che non ci sono metodi indipendenti in C #. In C ++ tali funzioni potrebbero essere semplicemente raggruppate in uno spazio dei nomi.
Vlad,

1

Le risposte alle tue domande alla fine dipendono da come si definiscono esattamente termini come "classe" ed "entità". Hai fatto un buon lavoro nel definire quest'ultimo, permettendo sia entità fisiche che concettuali. Ma il termine "classe" per i puristi sarà sempre "una fabbrica per istanziare oggetti con una particolare rappresentazione interna" e per i pragmatici il termine comprenderà quelle cose Java o C ++ disprezzate dai puristi. Idem per il termine "OOP", che i pragmatici potrebbero dire che fanno Java e C ++, ma quali puristi avrebbero significato il significato di Alan Kay quando ha osservato ["Ho inventato il termine orientato agli oggetti e posso dirti che non l'ho fatto avere in mente C ++ "] ( Allora, cosa * Alan Kay * intendeva veramente con il termine" orientato agli oggetti "? ).

Se si considera la vista pragmatica, è possibile accettare le classi di utilità senza istanza. Ma la visione purista è più interessante. OOP, secondo Kay, riguardava sempre più i messaggi che le classi. Quindi alle tue domande:

Le classi possono rappresentare oggetti senza entità?

No. Le classi classificano gli oggetti. Le classi sono per definizione quelle entità a cui si invia un messaggio tale da newprodurre un oggetto. Un oggetto è un'entità composta da una classe. Esistono classi per fabbricare, e anzi classificare, oggetti. Ecco cosa fanno le lezioni. Le classi creano oggetti. Usiamo le classi per classificare gli oggetti. Quindi se C è solo un insieme di metodi che non consente l'istanza o la sottoclasse, non ci possono essere oggetti classificati da C, quindi C non è una classe.

In caso contrario, perché sono cattivi / incompleti / non-OOP-centrici?

Non sono cattivi. Basta non chiamarli classi. Un pacchetto di metodi è OOPable: qualcosa a cui potresti inviare un messaggio per invocare un metodo, ma non è una classe a meno che non possa creare un'istanza di un oggetto. Conosci Ruby? In Ruby un modulo è un insieme di metodi. Una classe è un modulo che può istanziare oggetti. Non c'è niente di male in un modulo . Ma la cosa che rende una classe diversa da un modulo (in termini puramente OOP) è che una classe può avere istanze. Un modulo è solo alcuni metodi. La confusione è che C ++ e Java e altri linguaggi usano il termine "classe" sia per classe che per modulo .

Ora, per guardare uno dei tuoi esempi specifici, chiedi di una MotorOperationsclasse a cui potresti inviare il messaggio computePowerConsumptionForMotorcon argomento id. È male? Almeno non viola il principio Tell Don't Ask . Facciamo dobbiamo fare una classe di motore e inviarlo il powerConsumptionmessaggio? Forse non il 100% delle volte, ma forse provare a fare queste cose porterà ad alcune belle intuizioni sul tuo codice. Oppure, può portare a un'esplosione di piccole classi che sarebbe male.

Ci sono modi in cui devono essere cambiati / migliorati concettualmente per essere in linea con OOP?

Se "fare OOP" è importante per te, allora vorrai cercare modi per progettare un sistema in componenti che comunicano inviando messaggi l'un l'altro. Questo è esattamente ciò che è OOP , o almeno quello che aveva in mente il conio del termine. Le classi di utilità non sono OOP in questa vista. Ma per alcune persone, potrebbero essere.

Cercare di realizzare un intero sistema di grandi dimensioni con milioni di persone viventi, respiranti, oggetti, tutti istanziati dalle classi, potrebbe funzionare per alcuni progetti. Ma se ti ritrovi a creare classi artificiali e dal suono sbagliato, allora i moduli dovrebbero essere introdotti. Cerca di enfatizzare le classi e usa i moduli quando le classi istantanee sarebbero ridicole.

TL; i bundle del metodo DR non sono sempre male. Prova a usare prima le classi istanziabili. Torna ai "moduli" solo quando necessario.


0

Prendendo gli esempi forniti:

getMotorDataFromHTMLForm()
selectMotorFromUserRequirements($requirements)

Sembrano metodi "di fabbrica", che restituirebbero un Motoroggetto. Il secondo implica che o stai creando un nuovo oggetto per soddisfare i requisiti oppure hai un database o una raccolta di motori in memoria che stai esaminando. Nel qual caso dovrebbe essere un metodo su questo. Oppure potrebbe essere un metodo sull'oggetto requisiti.

getMotorManufacturers()

Da dove li stai prendendo? Ecco di cosa dovrebbe essere un metodo.

canMotorCanHandleOperatingConditions($conditions)
computePowerConsumptionForMotor($id)

Sembra che dovrebbero essere metodi Motor.


Sì. è un "insieme di metodi probabilmente non correlati" (abbreviato in BOPUM). Sono d'accordo con i commenti di fabbrica e motore. getMotorManufacturersè di restituire tutti i produttori di motori dal database. Non sono sicuro di dove vada. Mi ci vorrà del tempo per svelare questo BOPUM per mettere le cose dove devono andare ..
Dennis

Ricevo getMotorManufacturersdal database. Il database non può avere un metodo ... Attualmente ho un modello DataMapper che interroga il database, inizializza un array e lo popola con Motor Objects (contenente anche informazioni sul produttore), quindi restituisce tale array al chiamante. Il chiamante è la mia MotorOperationsclasse, che a sua volta viene chiamata da una ProductSelectionclasse (che contiene un algoritmo che viene utilizzato per selezionare i motori, e le informazioni sui motori caricate sono i dati per tale algoritmo)
Dennis

0

Un oggetto è una raccolta di metodi e dati con elevata coesione. Appartengono a una classe perché sono altamente correlati e lo stato viene mantenuto.

Questo è vero sia che utilizzi un design frontale di grandi dimensioni e provi a modellare tutto, sia che si tratti di un design emergente in cui si itera e si evolve l'oggetto in qualsiasi cosa si adatti alle esigenze del sistema in quel momento.

Se non hai motivo di mantenere lo stato, probabilmente non hai alcun motivo per creare un'istanza di un oggetto, il che significa che probabilmente non c'è motivo di avere una classe. A meno che, la lingua utilizzata non abbia la capacità di definire uno spazio dei nomi diverso dall'uso della classe. In quale classe usare dovrebbe andare bene perché sarebbe idiomatica.

Non riesco a pensare a nessun aspetto negativo dell'uso delle classi in questo modo diverso dal tipico. Il tuo invitante costo e complessità inutili dovendo istanziare uno "spazio dei nomi". Chiunque supporti questo codice si chiederà dove i dati costano un carico cognitivo aggiuntivo (molto probabilmente un costo una tantum per persona). È un uso insolito senza alcun valore aggiuntivo.

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.