Sto cercando di seguire il principio ASCIUTTO nella mia programmazione più che posso. Recentemente ho imparato modelli di progettazione in OOP e ho finito per ripetermi abbastanza.
Ho creato un pattern di repository insieme a modelli Factory e Gateway per gestire la mia persistenza. Sto utilizzando un database nella mia applicazione ma ciò non dovrebbe avere importanza dal momento che dovrei essere in grado di sostituire il gateway e passare a un altro tipo di persistenza, se lo desidera.
Il problema che ho creato per me è 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 pensavo di usare correttamente i modelli di progettazione e di mantenere buone pratiche, ma il problema con questa cosa è che quando aggiungo una nuova tabella, devo creare le stesse classi solo con altri nomi. Ciò solleva in me il sospetto che stia facendo qualcosa di sbagliato.
Ho pensato ad una soluzione in cui invece di interfacce avevo classi astratte che usando il nome della classe capivano la tabella che dovevano manipolare ma che non sembrava la cosa giusta da fare, e se decidessi di passare ad un archiviazione di file o memcache dove non ci sono tabelle.
Mi sto avvicinando correttamente a questo, o c'è una prospettiva diversa che dovrei guardare?