object1.action (oggetto2) vs object2.action (oggetto1)

1

Mi scuso per il titolo potenzialmente fuorviante e ambiguo; Ho cercato di generalizzarlo nel miglior modo possibile.

Attualmente sto lavorando a un progetto OpenGL in C ++. Volevo avvolgere un paio di funzioni OpenGL in oggetti di livello superiore. Mi sono imbattuto in (quello che pensavo fosse un unico) problema. Non potevo decidere se avere un oggetto Renderer essere responsabile del disegno di un oggetto Drawable , o che un oggetto Drawable si occupasse di disegnare se stesso con Renderer come target.

renderer.render(Drawable) vs Drawable.draw(Renderer)

Più ho pensato a questo problema più ho trovato gli scenari in cui questo problema si pone.

Altri esempi:

writer.write(File) vs file.write(Writer)
video.play(Screen) vs screen.play(Video)
object.toString()  vs toString(Object)

Ovviamente, per l'ultimo, Java usa object.toString() Mi ha fatto pensare però. Non tutti gli oggetti sostituiscono il metodo toString , quindi non violare il principio di segregazione dell'interfaccia?

Ho capito che questo è un problema onnipresente. Ho provato a fare qualche ricerca, ma non ho trovato le parole giuste per fare effettivamente search per questo problema. Ecco perché lo sto chiedendo qui.

La soluzione è puramente soggettiva, in base alle preferenze di progettazione? La soluzione è diversa a seconda del contesto come i problemi file e video ? Per favore aiutami a capire di più.

    
posta Greg M 09.04.2018 - 04:12
fonte

3 risposte

10

Billy colpisce la palla

La palla colpisce Billy

Einstein potrebbe dirti che è tutto relativo ma le immagini create nella tua testa da queste sono molto diverse.

Alcuni programmatori si concentrano solo su meccanica e struttura. Visto con quegli occhi, sì non c'è differenza qui.

I programmatori migliori rendono meccanici e strutturano gli schiavi alla semantica. Si sono impegnati a esprimersi in modo fluente. Rendono il loro intento qualcosa che capisci a colpo d'occhio.

Se il modo di pensare in questo modo ancora non lo rende chiaro, allora forse il metodo non appartiene a nessuno dei due oggetti.

    
risposta data 09.04.2018 - 05:55
fonte
5

Se il messaggio chiede di cambiare un oggetto, quello deve essere il destinatario. L'unico modo per cambiare un oggetto dovrebbe essere inviandogli un messaggio.

view.draw(drawable);

Se un oggetto è responsabile dell'azione richiesta, quello dovrebbe essere il destinatario.

Se è probabile che sia uno di una cascata di messaggi verso un oggetto, questa è un'altra buona ragione per renderlo il ricevitore. [Sto usando la sintassi Dart qui. Smalltalk ha anche la sintassi per i messaggi in cascata. Altre lingue affrontano scrivendo messaggio concatenato per restituire il destinatario.]

renderer..draw(circle2)
    ..draw(rectangle1)
    ..setColor(blue)
    ..draw(rectangle2);

iostream..print(summary)
    ..setPrecision(2)
    ..print(total);

notificationBuilder..style(styleObject)
    ..sound(alertTone)
    ..priority(Priority.high)
    ..icon(appIcon)
    ..title(localizedTitle)
    ..body(richTextBody);

Quando la decisione sul design non è ovvia, non preoccuparti. Scegline uno e vai avanti. Rivedi più tardi se ti sembra imbarazzante. A volte non esiste una risposta migliore e a volte un oggetto implementa semplicemente il messaggio delegando l'altro comunque.

Ma consiglio di fare la scelta per motivi di progettazione O-O, non ragionando sulla tassonomia di classe, sulla linguistica o sulla fisica.

    
risposta data 09.04.2018 - 08:24
fonte
1

Pensare in termini di passaggio di messaggi ti darà spesso una risposta qui. Non necessariamente la risposta migliore , ma probabilmente una buona risposta, una soluzione sensata.

L'idea è che l'oggetto prima del punto è il destinatario di un messaggio e la parte dopo il punto è il messaggio che viene inviato.

renderer.render (drawable) vs drawable.draw (renderer)

Con la prima opzione, stai dicendo a un oggetto Renderer, "Disegna il dato oggetto Drawable". Con il secondo, stai dicendo a un oggetto Drawable, "Disegnati da un oggetto Renderer". Il verbo "disegnare" è più diretto del verbo "hai disegnato te stesso", quindi la prima opzione ha più senso.

writer.write (file) vs file.write (writer)

Praticamente uguale a sopra. Con la prima opzione, stai dicendo a un oggetto Writer, "Scrivi sull'oggetto File specificato". Con il secondo, stai dicendo a un oggetto File, "Ti sei scritto con l'oggetto Writer dato". Il verbo "scrivere" è più diretto del verbo "scrivi te stesso", quindi la prima opzione ha più senso.

video.play (schermo) vs screen.play (video)

Penso che questo sembri simile a quanto sopra, ma ora sembra un po 'più discutibile. Con la prima opzione, stai dicendo a un oggetto Video, "Giocati sull'oggetto Screen specificato." Con il secondo, stai dicendo a un oggetto Screen, "Riproduci l'oggetto Video dato". Mi piace il secondo, meglio.

... sebbene uno schermo (il dispositivo fisico) sia semplicemente una destinazione passiva per i dati video, quindi se l'oggetto "Schermo" rappresenta semplicemente uno schermo, allora non dovrebbe sapere come per visualizzare un video. Se un oggetto "Screen" è un qualche tipo di oggetto manager , allora , avrebbe senso sapere come visualizzare un video.

    
risposta data 09.04.2018 - 06:44
fonte

Leggi altre domande sui tag