Benjamin meminta saya untuk mengklarifikasi posisi saya, jadi saya mengedit posting saya sebelumnya dan menambahkan pemikiran lebih lanjut.
Bob Martin adalah penulis buku hebat berjudul Clean Code. Dalam buku itu ada bab (Bab 6.) yang disebut Objects and struktur Data, yang ia membahas perbedaan paling penting antara objek dan struktur data dan klaim bahwa kita harus memilih di antara mereka, karena mencampurkannya adalah ide yang sangat buruk.
Kebingungan ini kadang-kadang menyebabkan struktur hibrida yang kurang menguntungkan yang setengah objek dan setengah struktur data. Mereka memiliki fungsi yang melakukan hal-hal signifikan, dan mereka juga memiliki variabel publik atau pengakses publik dan mutator yang, untuk semua maksud dan tujuan, membuat variabel pribadi menjadi publik, menggoda fungsi eksternal lainnya untuk menggunakan variabel-variabel itu seperti cara program prosedural menggunakan suatu struktur data.4 Hibrida seperti itu membuat sulit untuk menambahkan fungsi baru tetapi juga membuatnya sulit untuk menambah struktur data baru. Mereka adalah yang terburuk dari kedua dunia. Hindari membuatnya. Mereka adalah indikasi dari desain kacau yang penulis tidak yakin - atau lebih buruk, tidak tahu - apakah mereka membutuhkan perlindungan dari fungsi atau jenis.
Saya pikir DOM adalah contoh dari hibrida objek dan struktur data ini. Sebagai contoh oleh DOM kami menulis kode seperti ini:
el.appendChild(node);
el.childNodes;
// bleeding internals
el.setAttribute(attr, val);
el.attributes;
// bleeding internals
el.style.color;
// at least this is okay
el = document.createElement(tag);
doc = document.implementation.createHTMLDocument();
// document is both a factory and a tree root
DOM harus jelas merupakan struktur data, bukan hibrid.
el.childNodes.add(node);
// or el.childNodes[el.childNodes.length] = node;
el.childNodes;
el.attributes.put(attr, val);
// or el.attributes[attr] = val;
el.attributes;
el.style.get("color");
// or el.style.color;
factory = new HtmlNodeFactory();
el = factory.createElement(document, tag);
doc = factory.createDocument();
Kerangka kerja jQuery adalah sekelompok prosedur, yang dapat memilih dan memodifikasi kumpulan node DOM dan melakukan banyak hal lainnya. Seperti yang ditunjukkan Laurent dalam posnya, jQuery adalah sesuatu seperti ini di bawah tenda:
html(select("#body"), "<p>hello</p>");
Pengembang jQuery menggabungkan semua prosedur ini ke dalam satu kelas, yang bertanggung jawab untuk semua fitur yang tercantum di atas. Jadi jelas melanggar Prinsip Tanggung Jawab Tunggal dan jadi itu adalah objek dewa. Satu-satunya hal karena tidak merusak apa pun, karena itu adalah kelas mandiri tunggal yang bekerja pada struktur data tunggal (kumpulan node DOM). Jika kita akan menambahkan subclass jQuery atau struktur data lain proyek akan runtuh sangat cepat. Jadi saya tidak berpikir kita bisa berbicara tentang oo dengan jQuery itu lebih prosedural daripada oo meskipun fakta bahwa mendefinisikan kelas.
Apa yang diklaim Laurent adalah omong kosong:
Jadi apa artinya semua itu? JQuery itu (seperti LINQ) bukan objek anti-pola Dewa. Ini bukan kasus pola yang sangat dihormati yang disebut Dekorator.
Pola Dekorator adalah tentang menambahkan fungsionalitas baru dengan menjaga antarmuka dan tidak mengubah kelas yang ada. Sebagai contoh:
Anda dapat mendefinisikan 2 kelas yang mengimplementasikan antarmuka yang sama, tetapi dengan implementasi yang sama sekali berbeda:
/**
* @interface
*/
var Something = function (){};
/**
* @argument {string} arg1 The first argument.
* @argument {string} arg2 The second argument.
*/
Something.prototype.doSomething = function (arg1, arg2){};
/**
* @class
* @implements {Something}
*/
var A = function (){
// ...
};
/**
* @argument {string} arg1 The first argument.
* @argument {string} arg2 The second argument.
*/
A.prototype.doSomething = function (arg1, arg2){
// doSomething implementation of A
};
/**
* @class
* @implements {Something}
*/
var B = function (){
// ...
};
/**
* @argument {string} arg1 The first argument.
* @argument {string} arg2 The second argument.
*/
B.prototype.doSomething = function (arg1, arg2){
// doSomething implementation of B
// it is completely different from the implementation of A
// that's why it cannot be a sub-class of A
};
Jika Anda memiliki metode yang hanya menggunakan antarmuka umum, maka Anda dapat menentukan satu atau lebih Dekorator alih-alih menyalin kode yang sama antara A dan B. Anda dapat menggunakan dekorator ini bahkan dalam struktur bersarang.
/**
* @class
* @implements {Something}
* @argument {Something} something The decorated object.
*/
var SomethingDecorator = function (something){
this.something = something;
// ...
};
/**
* @argument {string} arg1 The first argument.
* @argument {string} arg2 The second argument.
*/
SomethingDecorator.prototype.doSomething = function (arg1, arg2){
return this.something.doSomething(arg1, arg2);
};
/**
* A new method which can be common by A and B.
*
* @argument {function} done The callback.
* @argument {string} arg1 The first argument.
* @argument {string} arg2 The second argument.
*/
SomethingDecorator.prototype.doSomethingDelayed = function (done, arg1, arg2){
var err, res;
setTimeout(function (){
try {
res = this.doSomething(o.arg1, o.arg2);
} catch (e) {
err = e;
}
callback(err, res);
}, 1000);
};
Jadi Anda dapat mengganti instance asli dengan instance dekorator dalam kode level abstraksi yang lebih tinggi.
function decorateWithManyFeatures(something){
var d1 = new SomethingDecorator(something);
var d2 = new AnotherSomethingDecorator(d1);
// ...
return dn;
}
var a = new A();
var b = new B();
var decoratedA = decorateWithManyFeatures(a);
var decoratedB = decorateWithManyFeatures(b);
decoratedA.doSomethingDelayed(...);
decoratedB.doSomethingDelayed(...);
Kesimpulannya bahwa jQuery bukan Dekorator apa pun, karena ia tidak mengimplementasikan antarmuka yang sama dengan Array, NodeList atau objek DOM lainnya. Ini mengimplementasikan antarmuka itu sendiri. Modul tidak digunakan sebagai Dekorator juga, mereka hanya menimpa prototipe asli. Jadi pola dekorator tidak digunakan di seluruh jQuery lib. Kelas jQuery hanyalah sebuah adaptor besar yang memungkinkan kami menggunakan API yang sama oleh banyak browser yang berbeda. Dari perspektif oo memang berantakan, tetapi itu tidak terlalu penting, ia bekerja dengan baik, dan kami menggunakannya.
$
fungsi ataujQuery
objek.