Saya ingin membedakan antara dua cara yang berbeda dalam mendekati pemrograman berorientasi objek
- Simulasi: objek Anda mewakili objek domain nyata, Anda telah memprogramnya untuk menangani fungsionalitas apa pun yang terkait dengan domain itu. Objek yang diprogram dengan cara ini cenderung memiliki banyak keadaan yang bisa berubah dan kolaborator tersembunyi yang digunakan untuk mengimplementasikan fungsi ini.
- Fungsi Records +: objek Anda hanyalah kumpulan data dan fungsi yang beroperasi di atas data itu. Objek yang diprogram dengan cara ini lebih cenderung tidak berubah, untuk mengambil lebih sedikit tanggung jawab dan memungkinkan seseorang untuk menyuntikkan kolaborator.
Aturan praktisnya adalah bahwa objek yang diprogram dengan cara pertama akan memiliki lebih banyak metode dan lebih banyak void
metode daripada cara kedua. Katakanlah kita akan menulis simulator penerbangan dan merancang kelas pesawat. Kami akan memiliki sesuatu seperti:
class Plane {
void accelerate();
void deccelerate();
void toggleRightFlaps();
void toggleLeftFlaps();
void turnRudderRight();
void turnRudderLeft();
void deployLandingGear();
void liftLandingGear();
// etc.
void tick() throws PlaneCrashedException;
}
Ini mungkin sedikit lebih ekstrem daripada yang mungkin ditemui, tetapi hal ini jelas. Jika Anda ingin mengimplementasikan antarmuka semacam ini, Anda harus tetap di dalam objek:
- Semua informasi tentang keadaan peralatan pesawat.
- Semua informasi tentang kecepatan / akselerasi pesawat.
- Kecepatan refresh dari simulasi kami (untuk menerapkan centang).
- Rincian lengkap tentang model 3d simulasi dan fisika untuk menerapkan centang.
Menulis unit test untuk objek yang ditulis dalam mode ini sangat sulit karena:
- Anda harus menyediakan semua bit data yang berbeda dan kolaborator yang dibutuhkan objek ini pada awal pengujian Anda (membuat contoh ini bisa sangat membosankan).
- Ketika Anda ingin menguji suatu metode, Anda mengalami dua masalah: a) antarmuka seringkali tidak mengekspos data yang cukup untuk Anda uji (sehingga Anda akhirnya harus menggunakan mengejek / refleksi untuk memverifikasi harapan) b) ada banyak komponen yang terikat menjadi satu yang harus Anda verifikasi berperilaku dalam setiap tes.
Pada dasarnya Anda mulai dengan antarmuka yang terlihat masuk akal dan seperti itu cocok dengan domain dengan baik, tetapi kebaikan simulasi telah membuat Anda tertarik untuk membuat objek yang benar-benar sulit untuk diuji.
Namun, Anda dapat membuat objek yang akan memenuhi tujuan yang sama. Anda ingin rem Plane
menjadi bit yang lebih kecil. Memiliki PlaneParticle
yang melacak bit fisik pesawat, posisi, kecepatan, akselerasi, roll, yaw, dll, dll, mengungkap dan memungkinkan seseorang untuk memanipulasi ini. Kemudian suatu PlaneParts
objek dapat melacak status. Anda akan mengirim tick()
ke tempat yang sama sekali berbeda, misalnya memiliki PlanePhysics
parameter objek oleh, misalnya, gaya gravitasi, yang tahu diberi PlaneParticle
dan PlaneParts
bagaimana meludahkan yang baru PlaneParticle
. Semua ini bisa sepenuhnya berubah, meskipun tidak harus untuk beberapa contoh.
Anda sekarang memiliki keunggulan ini dalam hal pengujian:
- Setiap komponen individu memiliki lebih sedikit pekerjaan dan lebih mudah diatur.
- Anda dapat menguji komponen Anda secara terpisah.
- Objek-objek ini dapat lolos dengan mengekspos internal mereka (terutama jika mereka dibuat abadi), sehingga orang tidak perlu kepintaran untuk mengukurnya.
Inilah triknya: pendekatan berorientasi objek kedua yang saya jelaskan sangat dekat dengan pemrograman fungsional. Mungkin dalam program fungsional murni catatan Anda dan fungsi Anda terpisah dan tidak terikat bersama dalam objek, pasti program fungsional akan memastikan bahwa semua hal ini. Apa yang saya pikir benar-benar membuat unit testing mudah adalah
- Unit kecil (ruang keadaan kecil).
- Fungsinya dengan input minimal (tidak ada input tersembunyi).
- Fungsinya dengan output minimal.
Pemrograman fungsional mendorong hal-hal ini (tetapi seseorang dapat menulis program yang buruk dalam paradigma apa pun) tetapi mereka dapat dicapai dalam program berorientasi objek. Dan saya akan lebih menekankan bahwa pemrograman fungsional dan pemrograman berorientasi objek tidak kompatibel.