Sto cercando di seguire il principio DRY nella mia programmazione il più forte possibile. Recentemente ho imparato modelli di progettazione in OOP e ho finito per ripetermi un bel po '.
Ho creato un modello di repository insieme a modelli Factory e Gateway per gestire la mia persistenza. Sto usando un database nella mia applicazione, ma non dovrebbe importare dal momento che dovrei essere in grado di scambiare il Gateway e passare a un altro tipo di persistenza, se lo desidero.
Il problema che ho finito per creare da solo è che creo gli stessi oggetti per il numero di tabelle che ho. Ad esempio questi saranno gli oggetti di cui ho bisogno per gestire una tabella comments
.
class Comment extends Model {
protected $id;
protected $author;
protected $text;
protected $date;
}
class CommentFactory implements iFactory {
public function createFrom(array $data) {
return new Comment($data);
}
}
class CommentGateway implements iGateway {
protected $db;
public function __construct(\Database $db) {
$this->db = $db;
}
public function persist($data) {
if(isset($data['id'])) {
$sql = 'UPDATE comments SET author = ?, text = ?, date = ? WHERE id = ?';
$this->db->prepare($sql)->execute($data['author'], $data['text'], $data['date'], $data['id']);
} else {
$sql = 'INSERT INTO comments (author, text, date) VALUES (?, ?, ?)';
$this->db->prepare($sql)->execute($data['author'], $data['text'], $data['date']);
}
}
public function retrieve($id) {
$sql = 'SELECT * FROM comments WHERE id = ?';
return $this->db->prepare($sql)->execute($id)->fetch();
}
public function delete($id) {
$sql = 'DELETE FROM comments WHERE id = ?';
return $this->db->prepare($sql)->execute($id)->fetch();
}
}
class CommentRepository {
protected $gateway;
protected $factory;
public function __construct(iFactory $f, iGateway $g) {
$this->gateway = $g;
$this->factory = $f;
}
public function get($id) {
$data = $this->gateway->retrieve($id);
return $this->factory->createFrom($data);
}
public function add(Comment $comment) {
$data = $comment->toArray();
return $this->gateway->persist($data);
}
}
Quindi il mio controller sembra
class Comment {
public function view($id) {
$gateway = new CommentGateway(Database::connection());
$factory = new CommentFactory();
$repo = new CommentRepository($factory, $gateway);
return Response::view('comment/view', $repo->get($id));
}
}
Quindi ho pensato di utilizzare correttamente i modelli di progettazione e di mantenere le buone pratiche, ma il problema è che quando aggiungo una nuova tabella, devo creare le stesse classi solo con altri nomi. Ciò solleva il sospetto in me che io possa fare qualcosa di sbagliato.
Ho pensato a una soluzione in cui invece di interfacce avevo classi astratte che usando il nome della classe capiscono la tabella che devono manipolare ma che non sembra la cosa giusta da fare, e se decidessi di passare a un archivio di file o memcache dove non ci sono tabelle.
Mi sto avvicinando correttamente a questo, o c'è una prospettiva diversa che dovrei guardare?