Saya membaca beberapa posting blog pagi ini, dan menemukan ini :
Jika satu-satunya kelas yang pernah mengimplementasikan antarmuka Pelanggan adalah CustomerImpl, Anda tidak benar-benar memiliki polimorfisme dan substitusi karena pada praktiknya tidak ada yang menggantikan pada saat runtime. Itu adalah generalitas palsu.
Itu masuk akal bagi saya, karena mengimplementasikan antarmuka menambah kompleksitas dan, jika hanya ada satu implementasi, orang mungkin berpendapat bahwa itu menambah kompleksitas yang tidak perlu. Menulis kode yang lebih abstrak daripada yang perlu sering dianggap sebagai kode bau yang disebut "generalisasi spekulatif" (juga disebutkan dalam posting).
Tetapi, jika saya mengikuti TDD, saya tidak dapat (dengan mudah) membuat tes ganda tanpa generalisasi spekulatif itu, baik dalam bentuk implementasi antarmuka atau opsi polimorfik kami yang lain, membuat kelas dapat diwariskan dan metodenya virtual.
Jadi, bagaimana kita merekonsiliasi pengorbanan ini? Apakah layak untuk menjadi spekulatif umum untuk memfasilitasi pengujian / TDD? Jika Anda menggunakan tes ganda, apakah ini dianggap sebagai implementasi kedua dan dengan demikian menjadikan generalitas tidak lagi spekulatif? Haruskah Anda mempertimbangkan kerangka kerja mengejek kelas berat yang memungkinkan mengejek kolaborator beton (mis. Mol versus Moq di dunia C #)? Atau, haruskah Anda menguji dengan kelas-kelas yang konkret dan menulis apa yang dapat dianggap sebagai tes "integrasi" sampai desain Anda secara alami membutuhkan polimorfisme?
Saya ingin sekali membaca pendapat orang lain tentang masalah ini - terima kasih sebelumnya atas pendapat Anda.
sumber
Jawaban:
Saya pergi dan membaca posting blog, dan saya setuju dengan banyak apa yang penulis katakan. Namun, jika Anda menulis kode menggunakan antarmuka untuk tujuan pengujian unit, saya akan mengatakan bahwa implementasi tiruan dari antarmuka adalah implementasi kedua Anda. Saya berpendapat bahwa itu benar-benar tidak menambah banyak kerumitan pada kode Anda, terutama jika pertukaran tidak melakukannya mengakibatkan kelas Anda menjadi sangat erat dan sulit untuk diuji.
sumber
Stream
kelas, tetapi tidak ada kopling ketat.Menguji kode secara umum tidak mudah. Jika ya, kita sudah melakukannya sejak lama, dan tidak melakukan hal itu hanya dalam 10-15 tahun terakhir. Salah satu kesulitan terbesar selalu dalam menentukan bagaimana menguji kode yang telah ditulis secara kohesif, dan diperhitungkan dengan baik, dan dapat diuji tanpa melanggar enkapsulasi. Kepala sekolah BDD menyarankan agar kita memfokuskan hampir seluruhnya pada perilaku, dan dalam beberapa hal tampaknya menyarankan bahwa Anda tidak benar-benar perlu khawatir tentang perincian batin sedemikian besar, tetapi ini seringkali dapat membuat hal-hal yang cukup sulit untuk diuji jika ada. banyak metode pribadi yang melakukan "hal-hal" dengan cara yang sangat tersembunyi, karena dapat meningkatkan kompleksitas keseluruhan tes Anda untuk menangani semua hasil yang mungkin di tingkat yang lebih umum.
Mengejek dapat membantu sampai batas tertentu, tetapi sekali lagi cukup terfokus secara eksternal. Ketergantungan Injeksi juga dapat bekerja dengan sangat baik, sekali lagi dengan mengejek atau menguji ganda, tetapi ini juga dapat mengharuskan Anda mengekspos elemen baik melalui antarmuka, atau secara langsung, bahwa Anda mungkin lebih suka tetap tersembunyi - ini terutama benar jika Anda ingin memiliki tingkat keamanan paranoid yang bagus tentang kelas-kelas tertentu dalam sistem Anda.
Bagi saya, juri masih belum yakin apakah akan merancang kelas Anda agar lebih mudah diuji. Ini dapat menimbulkan masalah jika Anda merasa perlu memberikan tes baru sambil mempertahankan kode lawas. Saya menerima bahwa Anda harus dapat menguji segala sesuatu dalam suatu sistem, namun saya tidak suka gagasan mengekspos - bahkan secara tidak langsung - internal privat suatu kelas, hanya agar saya dapat menulis tes untuk mereka.
Bagi saya, solusinya selalu mengambil pendekatan yang cukup pragmatis, dan menggabungkan sejumlah teknik yang sesuai dengan setiap situasi tertentu. Saya menggunakan banyak tes ganda yang diwarisi untuk mengekspos sifat batin dan perilaku untuk pengujian saya. Saya mengejek segala sesuatu yang dapat dilampirkan ke kelas saya, dan di mana itu tidak akan mengganggu keamanan kelas saya, saya akan memberikan sarana untuk menimpa atau menyuntikkan perilaku untuk keperluan pengujian. Saya bahkan akan mempertimbangkan untuk menyediakan antarmuka yang lebih berdasarkan peristiwa jika itu akan membantu meningkatkan kemampuan untuk menguji kode
Di mana saya menemukan kode "yang tidak dapat diuji" , saya mencari tahu apakah saya bisa menolak untuk membuat hal-hal lebih dapat diuji. Di mana Anda memiliki banyak kode pribadi yang tersembunyi di balik layar, sering kali Anda akan menemukan kelas-kelas baru yang menunggu untuk dikeluarkan. Kelas-kelas ini dapat digunakan secara internal, tetapi seringkali dapat diuji secara independen dengan perilaku yang kurang pribadi, dan seringkali lapisan akses dan kompleksitasnya lebih sedikit. Namun satu hal yang harus saya hindari adalah menulis kode produksi dengan kode uji bawaan. Dapat tergoda untuk membuat " test lug " yang menghasilkan kengerian seperti itu
if testing then ...
, yang menunjukkan masalah pengujian yang tidak sepenuhnya didekonstruksi dan dipecahkan secara tidak lengkap.Anda mungkin terbantu untuk membaca buku Pola Tes xUnit Gerard Meszaros , yang mencakup semua hal semacam ini dengan lebih rinci daripada yang bisa saya baca di sini. Saya mungkin tidak melakukan semua yang dia sarankan, tetapi itu membantu untuk memperjelas beberapa situasi tes rumit yang harus dihadapi. Pada akhirnya, Anda ingin dapat memenuhi persyaratan pengujian sambil tetap menerapkan desain pilihan Anda, dan membantu untuk memiliki pemahaman yang lebih baik tentang semua opsi agar dapat memutuskan dengan lebih baik di mana Anda mungkin perlu berkompromi.
sumber
Apakah bahasa yang Anda gunakan memiliki cara untuk "mengejek" objek untuk pengujian? Jika demikian, antarmuka yang mengganggu ini bisa hilang.
Pada catatan yang berbeda mungkin ada alasan untuk memiliki SimpleInterface dan satu-satunya ComplexThing yang mengimplementasikannya. Mungkin ada bagian dari ComplexThing yang Anda tidak ingin dapat diakses oleh pengguna SimpleInterface. Ini tidak selalu karena pembuat kode OO-ish yang terlalu bersemangat.
Saya akan menjauh sekarang dan membiarkan semua orang melompat pada fakta bahwa kode yang melakukan ini "baunya tidak enak" kepada mereka.
sumber
Saya akan menjawab dalam dua bagian:
Anda tidak perlu antarmuka jika Anda hanya tertarik pada pengujian. Saya menggunakan kerangka kerja mengejek untuk tujuan itu (di Jawa: Mockito atau easymock). Saya percaya bahwa kode yang Anda desain tidak boleh dimodifikasi untuk tujuan pengujian. Menulis kode yang dapat diuji, sama dengan menulis kode modular, jadi saya cenderung menulis kode modular (dapat diuji) dan hanya menguji kode antarmuka publik.
Saya telah bekerja di sebuah proyek Java yang besar dan aku menjadi sangat yakin bahwa menggunakan read-only (hanya getter) interface adalah yang cara untuk pergi (silakan perhatikan bahwa aku penggemar besar dari kekekalan). Kelas implementasi mungkin memiliki setter, tapi itu detail implementasi yang tidak boleh diekspos ke lapisan luar. Dari perspektif lain saya lebih suka komposisi daripada warisan (modularitas, ingat?), Jadi antarmuka juga membantu di sini. Saya bersedia membayar biaya generalisasi spekulatif daripada menembak diri saya sendiri.
sumber
Saya telah melihat banyak keuntungan sejak saya mulai pemrograman lebih ke antarmuka di luar polimorfisme.
Banyak orang akan setuju bahwa lebih banyak, kelas yang lebih kecil lebih baik daripada lebih sedikit, kelas yang lebih besar. Anda tidak harus terlalu fokus pada satu waktu dan setiap kelas memiliki tujuan yang jelas. Yang lain mungkin mengatakan Anda menambah kompleksitas dengan memiliki lebih banyak kelas.
Adalah baik untuk menggunakan alat untuk meningkatkan produktivitas, tetapi saya pikir hanya mengandalkan kerangka kerja Mock dan di tempat seperti membangun testibilitas dan modularitas langsung ke dalam kode akan menghasilkan kode kualitas yang lebih rendah dalam jangka panjang.
Semua dalam semua, saya percaya itu telah membantu saya menulis kode kualitas yang lebih tinggi dan manfaatnya jauh lebih besar daripada konsekuensinya.
sumber