Quando cerchi la frase "i costruttori non devono lavorare", in vari post del blog troverai il consiglio di non lasciare che il costruttore lavori. Nonostante questo, ho qualche problema a capire perché questo è il caso. Inoltre, questo post popolare suggerisce di prendere tale consiglio con un tocco di sale.
Ho un esempio di due implementazioni della stessa situazione. Nella situazione, un AFactory
ha un metodo createA
, utilizzando un B
. A
ha bisogno di un risultato di una query, che B
produce. Ci sono due modi per implementarlo:
Esempio 1:
class AFactory {
public function createA(B $b): A {
return new A($b->getQueryResult());
}
}
class A {
private $query_result;
public function __construct(array $query_result) {
$this->query_result = $query_result;
}
public function doFooWithQueryResult() {
// Do something with query result
}
public function doBarWithQueryResult() {
// Do something with query result
}
}
Nel primo esempio, la factory recupera il risultato della query e lo passa al costruttore di A
. A
quindi assegna semplicemente il risultato della query alla proprietà di classe corrispondente. Tuttavia, c'è un problema qui: A
non verifica se il risultato della query è una struttura dati valida, cioè un risultato di query effettivo adatto per A
. Non sa da dove viene. La responsabilità di questa convalida è ora trapelata al AFactory
e A
è diventata strettamente accoppiata a AFactory
. L'altra implementazione risolve questo problema, ma in seguito il costruttore esegue il lavoro. E a quanto pare è male.
Esempio 2:
class AFactory {
public function createA(B $b): A {
return new A($b);
}
}
class A {
private $query_result;
public function __construct(B $b) {
$this->query_result = $b->getQueryResult();
}
public function doFooWithQueryResult() {
// Do something with query result
}
public function doBarWithQueryResult() {
// Do something with query result
}
}