Sebagai seorang pengembang C ++ saya cukup terbiasa dengan file header C ++, dan merasa bermanfaat memiliki semacam "dokumentasi" paksa di dalam kode. Saya biasanya memiliki waktu yang buruk ketika saya harus membaca beberapa kode C # karena itu: Saya tidak memiliki semacam peta mental dari kelas yang saya kerjakan.
Mari kita asumsikan bahwa sebagai insinyur perangkat lunak saya merancang kerangka kerja program. Apakah terlalu gila untuk mendefinisikan setiap kelas sebagai kelas abstrak yang tidak diterapkan, mirip dengan apa yang akan kita lakukan dengan header C ++, dan biarkan pengembang mengimplementasikannya?
Saya menduga mungkin ada beberapa alasan mengapa seseorang bisa menemukan ini menjadi solusi yang mengerikan tetapi saya tidak yakin mengapa. Apa yang harus dipertimbangkan seseorang untuk solusi seperti ini?
sumber
Jawaban:
Alasan ini dilakukan di C ++ berkaitan dengan membuat kompiler lebih cepat dan lebih mudah diimplementasikan. Ini bukan desain untuk membuat pemrograman lebih mudah.
Tujuan dari file header adalah untuk memungkinkan kompiler melakukan pass cepat super cepat untuk mengetahui semua nama fungsi yang diharapkan dan mengalokasikan lokasi memori untuk mereka sehingga mereka dapat direferensikan ketika dipanggil dalam file cp, bahkan jika kelas yang mendefinisikannya memiliki belum diuraikan.
Mencoba mereplikasi konsekuensi dari batasan perangkat keras lama di lingkungan pengembangan modern tidak disarankan!
Menentukan antarmuka atau kelas abstrak untuk setiap kelas akan menurunkan produktivitas Anda; apa lagi yang bisa Anda lakukan dengan waktu itu ? Juga, pengembang lain tidak akan mengikuti konvensi ini.
Bahkan, pengembang lain mungkin menghapus kelas abstrak Anda. Jika saya menemukan antarmuka dalam kode yang memenuhi kedua kriteria ini, saya menghapusnya dan membuatnya keluar dari kode:
1. Does not conform to the interface segregation principle
2. Only has one class that inherits from it
Yang lain adalah, ada alat yang disertakan dengan Visual Studio yang melakukan apa yang ingin Anda capai secara otomatis:
Class View
Object Browser
Solution Explorer
Anda dapat mengklik pada segitiga untuk mengeluarkan kelas untuk melihat fungsi, parameter, dan jenis kembali.Cobalah salah satu di atas sebelum mencurahkan waktu untuk mereplikasi file header C ++ di C #.
Selain itu, ada alasan teknis untuk tidak melakukan ini ... itu akan membuat biner akhir Anda lebih besar dari yang seharusnya. Saya akan mengulangi komentar ini oleh Mark Benningfield:
Juga, disebutkan oleh Robert Harvey, secara teknis, padanan terdekat dari header di C # adalah antarmuka, bukan kelas abstrak.
sumber
Pertama, pahami bahwa kelas yang benar-benar abstrak hanyalah antarmuka yang tidak dapat melakukan banyak pewarisan.
Kelas tulis, ekstrak antarmuka, adalah aktivitas yang mematikan otak. Sedemikian rupa sehingga kita memiliki refactoring untuk itu. Sangat disayangkan. Mengikuti pola "setiap kelas mendapat antarmuka" ini tidak hanya menghasilkan kekacauan tetapi juga melewatkan intinya.
Antarmuka tidak boleh dianggap hanya sebagai pernyataan resmi apa pun yang dapat dilakukan oleh kelas. Antarmuka harus dianggap sebagai kontrak yang dipaksakan oleh kode klien menggunakan merinci kebutuhan itu.
Saya sama sekali tidak kesulitan menulis antarmuka yang saat ini hanya memiliki satu kelas yang mengimplementasikannya. Saya sebenarnya tidak peduli jika tidak ada kelas yang mengimplementasikannya. Karena saya sedang memikirkan apa yang saya perlukan menggunakan kode. Antarmuka mengungkapkan apa yang diminta menggunakan kode. Apa pun yang terjadi kemudian dapat melakukan apa yang disukainya asalkan memenuhi harapan-harapan ini.
Sekarang saya tidak melakukan ini setiap kali satu objek menggunakan yang lain. Saya melakukan ini ketika melewati batas. Saya melakukannya ketika saya tidak ingin satu objek tahu persis objek lain yang diajak bicara. Yang merupakan satu-satunya cara polimorfisme akan bekerja. Saya melakukannya ketika saya mengharapkan objek yang kode klien saya bicarakan cenderung berubah. Saya tentu tidak melakukan ini ketika apa yang saya gunakan adalah kelas String. Kelas String bagus dan stabil dan saya merasa tidak perlu berjaga-jaga agar tidak berubah pada saya.
Ketika Anda memutuskan untuk berinteraksi langsung dengan implementasi konkret daripada melalui abstraksi, Anda memperkirakan bahwa implementasinya cukup stabil untuk memercayai untuk tidak berubah.
Bahwa di situlah cara saya meredam Prinsip Ketergantungan Pembalikan . Anda seharusnya tidak secara fanatik menerapkan ini pada segalanya. Ketika Anda menambahkan abstraksi Anda benar-benar mengatakan Anda tidak percaya pilihan menerapkan kelas menjadi stabil selama umur proyek.
Ini semua mengasumsikan Anda mencoba mengikuti Prinsip Terbuka Tertutup . Prinsip ini penting hanya ketika biaya yang terkait dengan membuat perubahan langsung ke kode yang ditetapkan adalah signifikan. Salah satu alasan utama orang tidak setuju tentang betapa pentingnya objek decoupling adalah karena tidak semua orang mengalami biaya yang sama ketika melakukan perubahan langsung. Jika pengujian ulang, kompilasi ulang, dan redistribusi seluruh basis kode Anda sepele bagi Anda, maka menyelesaikan kebutuhan untuk perubahan dengan modifikasi langsung kemungkinan merupakan penyederhanaan yang sangat menarik dari masalah ini.
Tidak ada jawaban yang mati otak untuk pertanyaan ini. Antarmuka atau kelas abstrak bukanlah sesuatu yang harus Anda tambahkan ke setiap kelas dan Anda tidak bisa hanya menghitung jumlah kelas implementasi dan memutuskan itu tidak diperlukan. Ini tentang berurusan dengan perubahan. Yang berarti Anda mengantisipasi masa depan. Jangan kaget jika Anda salah. Buat sesederhana mungkin tanpa menyudutkan diri.
Jadi tolong, jangan menulis abstraksi hanya untuk membantu kami membaca kode. Kami punya alat untuk itu. Gunakan abstraksi untuk memisahkan apa yang perlu dipisahkan.
sumber
Ya itu akan mengerikan karena (1) Ini memperkenalkan kode yang tidak perlu (2) Ini akan membingungkan pembaca.
Jika Anda ingin memprogram dalam C # Anda harus membiasakan diri membaca C #. Kode yang ditulis oleh orang lain tidak akan mengikuti pola ini.
sumber
Tes unit
Saya sangat menyarankan agar Anda menulis tes Unit daripada mengacaukan kode dengan antarmuka atau kelas abstrak (kecuali jika diperlukan karena alasan lain).
Tes unit yang ditulis dengan baik tidak hanya menjelaskan antarmuka kelas Anda (seperti file header, kelas abstrak atau antarmuka yang akan dilakukan) tetapi juga menjelaskan, dengan contoh, fungsi yang diinginkan.
Contoh: Di mana Anda mungkin telah menulis file header myclass.h seperti ini:
Sebaliknya, dalam c # tulis tes seperti ini:
Tes yang sangat sederhana ini menyampaikan informasi yang sama dengan file header. (Kita harus memiliki kelas bernama "MyClass" dengan fungsi tanpa parameter "Foo") Sementara file header lebih kompak, tes berisi informasi yang jauh lebih banyak.
Peringatan: suatu proses memiliki insinyur senior yang memasok (gagal) tes untuk pengembang lain untuk memecahkan bentrokan dengan metodologi seperti TDD, tetapi dalam kasus Anda itu akan menjadi peningkatan besar.
sumber