Saya mencoba mengikuti prinsip KERING dalam pemrograman saya sekuat yang saya bisa. Baru-baru ini saya telah belajar pola desain di OOP dan akhirnya saya mengulangi cukup banyak.
Saya telah membuat pola Repositori bersama dengan pola Pabrik dan Gateway untuk menangani kegigihan saya. Saya menggunakan database dalam aplikasi saya tapi itu tidak masalah karena saya harus bisa menukar Gateway dan beralih ke jenis kegigihan lain jika saya mau.
Masalah yang akhirnya saya buat sendiri adalah bahwa saya membuat objek yang sama untuk jumlah tabel yang saya miliki. Misalnya ini akan menjadi objek yang saya butuhkan untuk menangani tabel 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);
}
}
Kemudian controller saya terlihat seperti
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));
}
}
Jadi saya pikir saya menggunakan pola desain dengan benar dan menjaga praktik yang baik, tetapi masalah dengan hal ini adalah ketika saya menambahkan tabel baru, saya harus membuat kelas yang sama hanya dengan nama lain. Ini menimbulkan kecurigaan pada saya bahwa saya mungkin melakukan sesuatu yang salah.
Saya memikirkan solusi di mana alih-alih antarmuka saya memiliki kelas abstrak yang menggunakan nama kelas mencari tahu tabel yang mereka butuhkan untuk memanipulasi tetapi itu sepertinya bukan hal yang tepat untuk dilakukan, bagaimana jika saya memutuskan untuk beralih ke penyimpanan file atau memcache di mana tidak ada tabel.
Apakah saya mendekati ini dengan benar, atau adakah perspektif berbeda yang harus saya lihat?
sumber
Jawaban:
Masalah yang Anda tangani cukup mendasar.
Saya telah mengalami masalah yang sama ketika saya bekerja untuk sebuah perusahaan yang membuat aplikasi J2EE besar yang terdiri dari beberapa ratus halaman web dan lebih dari satu juta setengah baris kode Java. Kode ini menggunakan ORM (JPA) untuk kegigihan.
Masalah ini menjadi lebih buruk ketika Anda menggunakan teknologi pihak ke-3 di setiap lapisan arsitektur dan semua teknologi membutuhkan representasi data mereka sendiri.
Masalah Anda tidak dapat diselesaikan pada tingkat bahasa pemrograman yang Anda gunakan. Menggunakan pola itu baik tetapi seperti yang Anda lihat menyebabkan pengulangan kode (lebih tepatnya: pengulangan desain).
Cara saya melihatnya hanya ada 3 solusi yang mungkin. Dalam praktiknya solusi ini turun ke hal yang sama.
Solusi 1: Gunakan beberapa kerangka kerja ketekunan lainnya yang memungkinkan Anda untuk hanya menyatakan apa yang harus dipertahankan. Mungkin ada semacam kerangka kerja di sekitar. Masalah dengan pendekatan ini adalah agak naif karena tidak semua pola Anda terkait dengan kegigihan. Anda juga ingin menggunakan pola untuk kode antarmuka pengguna sehingga Anda akan membutuhkan kerangka kerja GUI yang dapat menggunakan kembali representasi data dari kerangka kerja ketekunan yang Anda pilih. Jika Anda tidak dapat menggunakannya kembali, Anda harus menulis kode pelat ketel untuk menjembatani representasi data kerangka GUI dan kerangka kerja bertahan .. dan ini bertentangan dengan prinsip KERING lagi.
Solusi 2: Gunakan bahasa pemrograman lain - yang lebih kuat - yang memiliki konstruksi yang memungkinkan Anda untuk mengekspresikan desain berulang sehingga Anda dapat menggunakan kembali kode desain. Ini mungkin bukan pilihan bagi Anda, tetapi anggaplah untuk sesaat. Kemudian lagi ketika Anda mulai membuat antarmuka pengguna di atas lapisan ketekunan Anda akan ingin bahasa lagi menjadi cukup kuat untuk mendukung pembuatan GUI tanpa harus menulis kode pelat ketel. Tidak mungkin ada bahasa yang cukup kuat untuk melakukan apa yang Anda inginkan karena sebagian besar bahasa bergantung pada kerangka kerja pihak ketiga untuk membangun GUI yang masing-masing memerlukan representasi data mereka sendiri untuk bekerja.
Solusi 3: Mengotomatiskan pengulangan kode dan desain menggunakan beberapa bentuk pembuatan kode. Kekhawatiran Anda adalah harus mengulangi pola dan desain karena kode tangan berulang-ulang kode / desain melanggar prinsip KERING. Saat ini ada kerangka pembuat kode yang sangat kuat di luar sana. Bahkan ada "meja kerja bahasa" yang memungkinkan Anda dengan cepat (setengah hari ketika Anda tidak memiliki pengalaman) membuat bahasa pemrograman Anda sendiri dan menghasilkan kode apa pun (PHP / Java / SQL - file teks apa pun yang dapat dipikirkan) menggunakan bahasa itu. Saya memiliki pengalaman dengan XText tetapi MetaEdit dan MPS juga baik-baik saja. Saya sangat menyarankan Anda untuk memeriksa salah satu meja kerja bahasa ini. Bagi saya itu adalah pengalaman paling membebaskan dalam kehidupan profesional saya.
Menggunakan Xtext Anda dapat membuat mesin Anda menghasilkan kode berulang. Xtext bahkan menghasilkan editor penyorotan sintaks untuk Anda dengan penyelesaian kode untuk spesifikasi bahasa Anda sendiri. Dari titik itu, Anda cukup mengambil gerbang dan kelas pabrik dan mengubahnya menjadi templat kode dengan meninju lubang di dalamnya. Anda memberi mereka makan ke generator Anda (yang disebut oleh parser bahasa Anda yang juga sepenuhnya dihasilkan oleh Xtext) dan generator akan mengisi lubang di template Anda. Hasilnya adalah kode yang dihasilkan. Dari titik itu Anda dapat melakukan pengulangan kode di mana saja (kode kegigihan kode GUI, dll.).
sumber
Masalah yang Anda hadapi adalah masalah lama: kode untuk objek persisten sering terlihat serupa untuk setiap kelas, itu hanya kode boilerplate. Itulah sebabnya beberapa orang pintar menemukan Object Relational Mappers - mereka memecahkan masalah itu dengan tepat. Lihat posting SO sebelumnya untuk daftar ORM untuk PHP.
Ketika ORM yang ada tidak menderita kebutuhan Anda, ada juga alternatif: Anda dapat menulis generator kode Anda sendiri, yang mengambil deskripsi meta objek Anda untuk bertahan dan menghasilkan bagian berulang kode dari itu. Itu sebenarnya tidak terlalu sulit, saya melakukan ini di masa lalu untuk beberapa bahasa pemrograman yang berbeda, saya yakin itu juga akan mungkin untuk mengimplementasikan hal-hal seperti itu juga di PHP.
sumber
Model::getByPK
metode dan dalam contoh di atas saya akan bisa melakukanComment::getByPK
tetapi mendapatkan data dari database dan membangun objek semua terkandung dalam kelas objek data, yang merupakan masalah yang saya coba pecahkan dengan menggunakan pola desain .