web-dev-qa-db-ja.com

インターフェイス分離の原則-複数のインターフェイスを示唆するタイプ

質問はロールインターフェイスのタイプヒントについてです。

コード例には、コンストラクターで必要なインターフェイスをタイプヒントする2つのDataMappersがあります。

FooDataMapperタイプは、Preparableインターフェースを示唆しています。それはそれに依存しており、依存関係から他の方法はないからです。

他のマッパーでは、BarDataMapperは型ヒントを???に置き換えました。 PreparableインターフェースとQueryableインターフェースの両方が必要なためです。

これをどのように処理しますか(何を置き換える必要がありますか?)、それらの1つをタイプヒントするだけでは不十分です。新しいインターフェイス(おそらく前述のインターフェイスを拡張するもの)を作成して、この新しいインターフェイスをヒントする必要がありますか?

コード例はPHPの要約例であり、型ヒント(???)は最後に宣言されたクラスにあります。

<?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( .. )
  }
}

私が最初に思いついた解決策は、必要なものを拡張する新しいインターフェースを作ることです。

コード内のクラスの名前は表示のみであり、Fooable、BarAbleである可能性があることに注意してください...

1
Ronni Skansing

consumerの依存関係は、(それらのインターフェースによって)それらを定義する責任があります。あなたの例では、BarDataMapperルール。考えられるシナリオは2つあります。

  1. BarDataMapperprepare()メソッドとquery()メソッドの両方を実装する単一のオブジェクトに依存している場合、yes、適切なPreparableAndQueryableインターフェイスそれらの2つを含めて定義し、コンストラクターに渡す必要があります。しかし、おそらくあなたは、関心の分離が悪いことを示唆していない、別の意味のある、構成されていない名前を見つけたいと思うでしょう。

  2. BarDataMapperが独立したPreparableQueryableの依存関係を消費することが理にかなっている場合、そのコンストラクターは、最終的に実際にone両方のインターフェースを実装する単一のオブジェクト。誰が実際にインターフェースを実装しているのか、それを消費する人を悩ませるべきではありません。

2
rucamzu

あなたは1つのエッジケースに立っていると思います。これは、PHPがあまり役に立たない場所でソフトウェアエンジニアリングを推進したか、何らかの概念上の問題があることを意味します。

インターフェイス分離の原則による DataMapperインターフェイスは、すべてのDataMappers実装が一致する必要がある1つのインターフェイスと1つだけを設定するのに十分厳密である必要があります。これらの実装は、これ以上特殊なオブジェクトを期待するべきではありません。

1つの可能な解決策 2つのインターフェースを同時に使用する問題については、インターフェースの代わりに抽象メソッド(> = PHP 5.4)の場合)で特性を使用できます。特性構成機能を使用して「インターフェースの継承」を模倣しようとしているので、私はそれをしません。

もしあなたが望むのはあなたのIDEあなたは型ヒントを使うことに制約されていない(あなたがしていることです)の提案です。あなたはPHPDocとあなたの=を使うことができますIDEあなたがしていることを認識するかもしれません(私はPhpStormをお勧めし続けます):

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

最後のポイント:PHPでJavaを実行しようとしないでください。提供されたオブジェクトが何であるかを確認したい場合は、クイックイントロスペクションを使用して適切なクラスの適切な使用法を確認できます。サブクラス、特性、およびインターフェース。

1
AsTeR