Interfaccia Principio di segregazione - digitare suggerimenti su più interfacce

1

La domanda riguarda la typehinting delle interfacce di ruolo .

L' esempio di codice ha due DataMappers che digitano l'interfaccia di cui hanno bisogno nel costruttore,

Il tipo FooDataMapper suggerisce l'interfaccia Preparable. Perché dipende da esso e nessun altro metodo dalla dipendenza.

Nell'altro mapper, BarDataMapper ho sostituito il suggerimento tipo con ??? in quanto richiede sia l'interfaccia Preparable che Queryable.

Come gestisco questo (cosa dovrebbe sostituire ???), typehinting uno di essi non sarebbe sufficiente, dovrei creare una nuova interfaccia (forse una che estenda il precedente accennato) e suggerire questa nuova interfaccia?

L'esempio di codice è un esempio ridotto in PHP e il tipo hint (???) si trova nell'ultima classe dichiarata.

<?php
// TWO ROLE INTERFACES, SMALL SEGREGATED PART OF A DBAL

Interface Preparable {
  public function prepare( .. );
}

Interface Queryable {
  public function query( ... );
}


// ADAPTER IMPLEMENTS SEGREGATION

class DbalAdapter implements Preparable, Queryable {
  private $dbal;

  public function __construct($dbal) 
  {
    private $this->dbal = $dbal;
  }

  public function prepare( .. ) 
  {
    ..
    return $this->dbal->prepare( .. );
  }

  public function query( .. ) 
  {
    ..
    return $this->dbal->query( .. );
  }
}


// DATAMAPPER CTOR HINTS FOR METHODS IT NEEDS TO USE

class FooDataMapper implements DataMapper {
  private $dbal;

  public function __construct(Preparable $dbal)
  {
    $this->dbal = $dbal;
  }

  public function create(Foo $Foo) 
  {
    ..
    $this->dbal->prepare( .. )
  }
}


// DATAMAPPER CTOR HINTS FOR METHODS IT NEEDS TO USE
// BUT THIS TIME NONE OF THE ROLE INTERFACES MATCH, BUILD A NEW INTERFACE?

class BarDataMapper implements DataMapper {
  private $dbal;
  public function __construct(??? $dbal) 
  {
    $this->dbal = $dbal;
  }

  public function SomeMethodThatNeedsBothPrepareNQuery(Bar $Bar) 
  {
    ..
    $this->dbal->query( .. )
    $this->dbal->prepare( .. )
  }
}

La soluzione iniziale a cui sto lavorando è una nuova interfaccia che estende quelle necessarie.

Attenzione la denominazione delle classi nel codice sono solo per la visualizzazione, potrebbe anche essere Fooable, BarAble ...

    
posta Ronni Skansing 28.01.2014 - 01:08
fonte

2 risposte

2

Il consumatore delle dipendenze è il responsabile della loro definizione (tramite le loro interfacce). Nel tuo esempio, BarDataMapper regole. Vedo due possibili scenari:

  1. Se BarDataMapper dipende da un singolo oggetto che implementa entrambi i metodi prepare() e query() , quindi yes , deve essere definita un'interfaccia PreparableAndQueryable corretta, inclusi i due di essi e passato al costruttore. Ma poi, forse vuoi trovare un altro nome significativo e non composto che non alluda a una cattiva separazione delle preoccupazioni.

  2. Se ha senso BarDataMapper a consumare dipendenze Preparable e Queryable indipendenti, il suo costruttore le prende come parametri separati, anche se alla fine c'è davvero un singolo oggetto che implementa entrambi interfacce . Chi sta davvero implementando le interfacce non dovrebbe preoccuparsi di quello che le consuma.

risposta data 29.01.2014 - 23:06
fonte
1

Penso che tu ti trovi in un caso limite, il che può significare che hai spinto l'ingegneria del software in un posto in cui PHP non può aiutarti molto o che hai qualche problema di concezione.

In base al principio di separazione delle interfacce l'interfaccia di DataMapper deve essere abbastanza rigorosa da consentire di impostare un'interfaccia e una sola che tutte le implementazioni di DataMappers devono corrispondere. Quelle implementazioni non dovrebbero aspettarsi altri oggetti specializzati.

Una possibile soluzione per il tuo problema di usare due interfacce contemporaneamente, potresti usare i tratti con metodi astratti (se > = PHP 5.4) invece di interfaccia. Ma non lo farei perché sta tentando di simulare "l'ereditarietà dell'interfaccia" utilizzando i tratti che compongono la capacità.

Se ciò che vuoi è suggerimento nel tuo IDE non sei obbligato a usare il suggerimento del tipo (che è ciò che stai facendo). È possibile utilizzare PHPDoc e l'IDE potrebbe riconoscere ciò che si sta facendo (continuo a consigliare PhpStorm):

/**
  * @param MySuperClass $a
  * @return void 
  */
public function myFunction($a) {
    // Here your IDE will know what kind of object is $a
}

Ultimo punto: non provare a fare Java con PHP. Ad un certo punto, se si desidera garantire quale sia l'oggetto fornito, è possibile utilizzare l'introspezione rapida per verificare il corretto utilizzo delle classi, delle sottoclassi, delle caratteristiche e dell'interfaccia corrette.

    
risposta data 29.01.2014 - 22:53
fonte

Leggi altre domande sui tag