È una cattiva pratica che un'istanza composta possa fare riferimento al suo genitore? Se sì, perché?

-1

Sto costruendo una classe Selection che contiene e consente di manipolare Items selezionato su un'area di lavoro.

  • Il Selection fa parte di Document , il contenitore di app di primo livello, se lo desideri.

  • Mi piacerebbe essere in grado di cancellare la selezione dalla classe Selection .

  • Il problema è che la creazione / eliminazione della selezione viene eseguita su Document .

È un odore di codice iniettare il genitore Document nel child Selection così posso richiamare i suoi metodi da Selection ?

Se sì, perché e quali sono le alternative a questo?

class Document {
  constructor() {
    this.currentSelection = null
  }

  createSelection(items) { 
    // here I'm creating a Selection and injecting
    // this 'Document' within it.
    this.currentSelection = new Selection(items, this)
  }

  clearSelection() {
    this.currentSelection = null
  }
}


class Selection extends HTMLElement {
  // this class also renders the flyout buttons that follow around
  // the selection on the canvas. The buttons can call methods on
  // this class.
  constructor(items, document) {
    this.items = items
    this.document = document
  }

  updateFillColor(fillColor) {
    // updates all this.items fill color, just a placeholder for now
  }

  clear() {
    this.document.clearSelection()
  }
}

Nota : quanto sopra è solo un esempio. Il mio problema reale è significativamente più complicato (implica chiamare più metodi sul genitore), ma è concettualmente lo stesso.

    
posta Nik Kyriakides 14.06.2018 - 18:14
fonte

1 risposta

1

Chiedi "È un odore di codice iniettare il genitore Document nel child Selection in modo da poter invocare i suoi metodi da Selection ?"

Questo potrebbe sentire l'inutile accoppiamento delle due classi, ma sicuramente ci sono relazioni genitore-figlio in cui è ragionevole passare il genitore all'oggetto figlio.

Una domanda che dovresti porci è: perché Selection deve sapere o dipendere da Document ? Se Document è complessa e contiene metodi che non hanno alcuna rilevanza per Selection , questo inizia a puzzare.

Se Selection ha solo bisogno di lasciare che Document sappia che è stato cancellato, tutta la selezione avrebbe bisogno di un riferimento a SelectionClearedListener con il metodo clearSelection , che la classe Document implementerebbe e questo viene chiamato dal metodo clear su Selection . In questo modo, puoi passare il documento alla selezione senza sapere che è un Document . Il punto è quale ruolo il documento gioca alla selezione; in questo caso, qualcuno che agisce sulla cancellazione della selezione.

Tu scrivi che il tuo problema reale è molto più complicato e che Selection deve chiamare più metodi su% genDocument. Puoi seguire il ragionamento: quali altri oggetti il Selection deve interagire con quello può effettivamente essere un Document , ma a cui Selection non interessa sapere è un Document ? Questi potrebbero essere noti al Selection come altri tipi di oggetto e essere passati a Selection come oggetti separati. (In realtà, quegli altri oggetti potrebbero essere implementati da classi diverse da Document . Dividere le responsabilità di Document in oggetti separati può ridurre la complessità.)

Un principio pertinente che cattura quanto sopra è il principio di segregazione dell'interfaccia , che può essere applicato al tuo esempio: " Selection non dovrebbe essere forzato a dipendere dai metodi di Document che non usa ".

Nel tuo scenario reale, Document contiene metodi di cui Selection non deve dipendere? Se è così, questa dipendenza tra i due oggetti inizia a puzzare.

Un'altra considerazione è che la selezione può essere riutilizzata per altre raccolte di articoli. Ancora una volta potremmo chiederci quale ruolo ha l'oggetto per il bambino.

    
risposta data 16.06.2018 - 17:22
fonte

Leggi altre domande sui tag