Saya baru saja membaca kutipan dari buku "Growing Object-Oriented Software" yang menjelaskan beberapa alasan mengapa mengejek kelas beton tidak dianjurkan.
Di sini beberapa contoh kode unit-test untuk kelas MusicCentre:
public class MusicCentreTest {
@Test public void startsCdPlayerAtTimeRequested() {
final MutableTime scheduledTime = new MutableTime();
CdPlayer player = new CdPlayer() {
@Override
public void scheduleToStartAt(Time startTime) {
scheduledTime.set(startTime);
}
}
MusicCentre centre = new MusicCentre(player);
centre.startMediaAt(LATER);
assertEquals(LATER, scheduledTime.get());
}
}
Dan penjelasan pertamanya:
Masalah dengan pendekatan ini adalah bahwa ia meninggalkan hubungan antara objek yang tersirat. Saya harap kami telah menjelaskan sekarang bahwa tujuan Pengembangan Didorong-Tes dengan Mock Objects adalah untuk menemukan hubungan antara objek. Jika saya subkelas, tidak ada dalam kode domain untuk membuat hubungan seperti itu terlihat, hanya metode pada objek. Ini membuatnya lebih sulit untuk melihat apakah layanan yang mendukung hubungan ini mungkin relevan di tempat lain dan saya harus melakukan analisis lagi lain kali saya bekerja dengan kelas.
Saya tidak tahu apa yang dia maksud ketika dia mengatakan:
Ini membuatnya lebih sulit untuk melihat apakah layanan yang mendukung hubungan ini mungkin relevan di tempat lain dan saya harus melakukan analisis lagi lain kali saya bekerja dengan kelas.
Saya mengerti bahwa layanan ini sesuai dengan MusicCentre
metode yang disebut startMediaAt
.
Apa yang dia maksud dengan "di tempat lain"?
Kutipan lengkap ada di sini: http://www.mockobjects.com/2007/04/test-smell-mocking-concrete-classes.html
Jawaban:
Penulis posting itu mempromosikan penggunaan Antarmuka atas penggunaan kelas anggota.
It turns out that my MusicCentre object only uses the starting and stopping methods on the CdPlayer, the rest are used by some other part of the system. I'm over-specifying my MediaCentre by requiring it to talk to a CdPlayer, what it actually needs is a ScheduledDevice.
Hubungan yang dia khawatirkan akan ditemukan kembali nanti adalah fakta bahwa kelas MediaCentre tidak membutuhkan semua objek CdPlayer. Klaimnya adalah bahwa dengan menggunakan Antarmuka (mungkin terbatas hanya mulai | berhenti) bahwa lebih mudah untuk memahami apa sebenarnya interaksi itu.
"di tempat lain" berarti bahwa objek lain mungkin memiliki hubungan yang sama terbatasnya, dan objek anggota penuh tidak diperlukan - subset dari fungsionalitas yang dibungkus melalui Antarmuka harus memadai.
Klaim mulai lebih masuk akal ketika Anda meledakkan semua fungsionalitas potensial:
Sekarang klaimnya tentang "Aku hanya perlu mulai & berhenti" lebih masuk akal. Menggunakan objek anggota konkret alih-alih Antarmuka membuatnya kurang jelas bagi pengembang masa depan tentang apa yang benar - benar diperlukan. Menjalankan tes unit dari MediaCentre pada semua fungsi lain di dalam CdPlayer adalah usaha pengujian yang sia-sia karena mereka termasuk dalam status "tidak peduli". Jika
Record
fungsi ini tidak berfungsi dalam kasus ini, kami benar-benar tidak peduli karena tidak diperlukan. Tetapi pengelola masa depan tidak perlu mengetahui hal itu berdasarkan kode, seperti yang tertulis.Pada akhirnya, premis penulis adalah hanya menggunakan apa yang dibutuhkan dan menjelaskan kepada pengelola masa depan apa yang diperlukan sebelumnya. Tujuannya adalah untuk meminimalkan pengerjaan ulang / analisis ulang modul kode selama pemeliharaan selanjutnya.
sumber
Setelah banyak memikirkannya, saya mendapatkan interpretasi yang mungkin dari kutipan ini:
"Layanan" yang dikutip sesuai dengan "fakta penjadwalan". Ini dapat diekspresikan oleh antarmuka yang diberi nama dan "fokus-pada-satu-peran" bernama "ScheduledDevice" atau dinyatakan secara implisit oleh implementasi metode konkret yang tidak bergantung pada antarmuka apa pun.
Dalam sampel di atas, penjadwalan diekspresikan oleh seluruh objek berfitur lengkap bernama
CDPlayer
. Dengan demikian, itu masih mengarah pada hubungan implisit antaraMusicCentre
dan "fakta penjadwalan".Jadi jika kita mulai menyuntikkan kelas beton dan mengejeknya ke objek tingkat tinggi; ketika kita ingin menguji yang ini, kita harus menganalisis setiap objek "konkrit" yang disuntikkan untuk melihat apakah itu menyajikan hubungan spesifik yang HARUS DILAKUKAN karena mereka HIDDEN (implisit). Sebaliknya, pengkodean SELALU melalui antarmuka memungkinkan pengembang untuk mengetahui secara langsung hubungan seperti apa yang akan dilayani oleh objek tingkat tinggi dan karenanya mendeteksi fitur yang harus diejek untuk mengisolasi unit-test.
sumber
Layanan yang saya maksud di sini adalah CDPlayer.scheduleToStartAt (). Itulah yang disebut MediaCentre - kolaborator yang perlu berfungsi. MediaCentre adalah objek yang diuji.
Idenya adalah bahwa jika saya membuat eksplisit apa yang bergantung pada MediaCentre, bukan kelas implementasi, saya dapat memberikan peran dependensi itu nama dan membicarakannya. Yang perlu diketahui MediaCentre adalah bahwa ia berbicara dengan ScheduledDevices. Seiring perubahan sistem lainnya, saya tidak perlu mengubah MediaCentre kecuali fitur-fiturnya berubah.
Apakah itu membantu?
sumber