Saya telah menemukan banyak istilah "pemrograman ke antarmuka bukan implementasi", dan saya pikir saya agak mengerti apa artinya. Tetapi saya ingin memastikan bahwa saya memahami manfaatnya dan kemungkinan implementasinya.
"Pemrograman ke antarmuka" berarti, jika memungkinkan, seseorang harus merujuk ke tingkat kelas yang lebih abstrak (antarmuka, kelas abstrak, atau terkadang superclass), daripada merujuk pada implementasi konkret.
Contoh umum di Jawa, adalah menggunakan:
List myList = new ArrayList();
bukannya ArrayList myList = new ArrayList();
.
Saya punya dua pertanyaan tentang ini:
Saya ingin memastikan bahwa saya memahami manfaat utama dari pendekatan ini. Saya pikir manfaatnya kebanyakan fleksibilitas. Mendeklarasikan objek sebagai referensi tingkat lebih tinggi, daripada implementasi konkret, memungkinkan lebih banyak fleksibilitas dan pemeliharaan sepanjang siklus pengembangan dan seluruh kode. Apakah ini benar? Apakah fleksibilitas merupakan manfaat utama?
Apakah ada lebih banyak cara 'pemrograman ke antarmuka'? Atau "mendeklarasikan variabel sebagai antarmuka daripada implementasi konkret" satu-satunya implementasi konsep ini?
Saya tidak berbicara tentang Java construct Interface . Saya berbicara tentang prinsip OO "pemrograman ke antarmuka, bukan implementasi". Dalam prinsip ini, "antarmuka" dunia mengacu pada "supertipe" dari suatu kelas - antarmuka, kelas abstrak, atau superclass sederhana yang lebih abstrak dan lebih konkret daripada subkelas yang lebih konkret.
sumber
Jawaban:
Ini tidak benar . Atau setidaknya, itu tidak sepenuhnya benar.
Poin yang lebih penting datang dari perspektif desain program. Di sini, "pemrograman ke antarmuka" berarti memfokuskan desain Anda pada apa yang dilakukan kode, bukan bagaimana melakukannya. Ini adalah perbedaan penting yang mendorong desain Anda ke arah kebenaran dan fleksibilitas.
Gagasan utamanya adalah perubahan domain jauh lebih lambat daripada perangkat lunak. Katakanlah Anda memiliki perangkat lunak untuk melacak daftar belanjaan Anda. Di tahun 80-an, perangkat lunak ini akan bekerja melawan baris perintah dan beberapa file datar pada floppy disk. Maka Anda mendapat UI. Maka Anda mungkin meletakkan daftar di database. Kemudian mungkin pindah ke cloud atau ponsel atau integrasi facebook.
Jika Anda merancang kode secara khusus di sekitar implementasi (floppy disk dan baris perintah), Anda tidak akan siap untuk perubahan. Jika Anda mendesain kode di sekitar antarmuka (memanipulasi daftar belanjaan) maka implementasinya bebas untuk diubah.
sumber
List myList = new ArrayList()
bukannyaArrayList myList = new ArrayList()
. (Pertanyaan ada di komentar berikutnya)List
/ArrayList
Tidak apa yang saya bicarakan sama sekali. Ini lebih seperti menyediakanEmployee
objek daripada set tabel tertaut yang Anda gunakan untuk menyimpan catatan Karyawan. Atau menyediakan antarmuka untuk beralih melalui lagu, dan tidak peduli jika lagu itu diacak, atau di CD, atau streaming dari internet. Itu hanya urutan lagu.Pemahaman saya tentang "pemrograman ke antarmuka" berbeda dari apa yang disarankan pertanyaan atau jawaban lainnya. Yang tidak mengatakan bahwa pemahaman saya benar, atau bahwa hal-hal dalam jawaban lain bukanlah ide yang baik, hanya saja mereka tidak seperti yang saya pikirkan ketika saya mendengar istilah itu.
Pemrograman ke antarmuka berarti bahwa ketika Anda disajikan dengan beberapa antarmuka pemrograman (baik itu perpustakaan kelas, satu set fungsi, protokol jaringan atau apa pun) Anda tetap menggunakan hanya hal-hal yang dijamin oleh antarmuka. Anda mungkin memiliki pengetahuan tentang implementasi yang mendasarinya (Anda mungkin telah menulisnya), tetapi Anda tidak boleh menggunakan pengetahuan itu.
Sebagai contoh, katakanlah API memberi Anda beberapa nilai buram yang merupakan "pegangan" untuk sesuatu yang internal. Pengetahuan Anda mungkin memberi tahu Anda bahwa pegangan ini benar-benar sebuah penunjuk, dan Anda dapat men-dereferensi dan mengakses beberapa nilai, yang memungkinkan Anda untuk dengan mudah menyelesaikan beberapa tugas yang ingin Anda lakukan. Tetapi antarmuka tidak memberi Anda opsi itu; itu pengetahuan Anda tentang implementasi tertentu yang dilakukan.
Masalah dengan ini adalah bahwa ia menciptakan hubungan yang kuat antara kode Anda dan implementasi, persis apa yang seharusnya mencegah antarmuka. Bergantung pada politik, itu bisa berarti bahwa implementasi tidak lagi dapat diubah, karena itu akan merusak kode Anda, atau bahwa kode Anda sangat rapuh dan terus melanggar setiap peningkatan atau perubahan implementasi yang mendasarinya.
Contoh besar dari ini adalah program yang ditulis untuk Windows. WinAPI adalah sebuah antarmuka, tetapi banyak orang menggunakan trik yang berfungsi karena implementasi khusus di, katakanlah Windows 95. Trik ini mungkin membuat program mereka lebih cepat, atau memungkinkan mereka untuk melakukan hal-hal dalam kode kurang dari yang seharusnya diperlukan. Tetapi trik ini juga berarti bahwa program akan macet di Windows 2000, karena API diterapkan secara berbeda di sana. Jika program itu cukup penting, Microsoft mungkin benar-benar maju dan menambahkan beberapa hack untuk implementasi mereka sehingga program akan terus bekerja, tetapi biaya yang meningkat kompleksitas (dengan semua masalah yang terjadi) dari kode Windows. Ini juga membuat hidup menjadi sangat sulit bagi orang-orang Wine, karena mereka mencoba mengimplementasikan WinAPI juga, tetapi mereka hanya dapat merujuk pada dokumentasi untuk bagaimana melakukan ini,
sumber
Saya hanya dapat berbicara tentang pengalaman pribadi saya, karena ini juga tidak pernah diajarkan secara formal kepada saya.
Poin pertama Anda benar. Fleksibilitas yang diperoleh berasal dari ketidakmampuan untuk secara tidak sengaja meminta detail implementasi dari kelas konkret di mana mereka tidak boleh diminta.
Misalnya, pertimbangkan
ILogger
antarmuka yang saat ini diimplementasikan sebagaiLogToEmailLogger
kelas konkret . TheLogToEmailLogger
kelas mengekspos semuaILogger
metode dan properti, tetapi juga terjadi untuk memiliki properti implementasi khusussysAdminEmail
.Ketika logger Anda digunakan dalam aplikasi Anda, itu seharusnya tidak menjadi perhatian dari kode memakan untuk mengatur
sysAdminEmail
. Properti ini harus ditetapkan selama pengaturan logger dan harus disembunyikan dari dunia.Jika Anda mengkode terhadap implementasi konkret, maka Anda mungkin secara tidak sengaja mengatur properti implementasi saat menggunakan logger. Sekarang, kode aplikasi Anda secara erat digabungkan ke logger Anda, dan beralih ke logger lain akan memerlukan decoupling kode Anda dari yang asli.
Dalam pengertian ini, pengkodean ke antarmuka melonggarkan kopling .
Mengenai poin kedua Anda: Alasan lain yang saya lihat untuk pengkodean ke antarmuka adalah untuk mengurangi kompleksitas kode.
Sebagai contoh, bayangkan saya memiliki permainan dengan antarmuka berikut
I2DRenderable
,I3DRenderable
,IUpdateable
. Tidak jarang satu komponen game memiliki konten 2D dan 3D yang dapat diurai. Komponen lain mungkin hanya 2D dan lainnya hanya 3D.Jika rendering 2D dilakukan oleh satu modul, maka masuk akal untuk mempertahankan koleksi
I2DRenderable
s. Tidak masalah jika objek dalam koleksinya jugaI3DRenderable
atauIUpdateble
sebagai modul lain akan bertanggung jawab untuk merawat aspek-aspek objek.Menyimpan objek yang dapat
I2DRenderable
di render sebagai daftar menjaga kompleksitas rendering class tetap rendah. 3D Rendering dan Update logic tidak menjadi perhatiannya sehingga aspek-aspek objek anak-anaknya dapat dan harus diabaikan.Dalam hal ini, pengkodean ke antarmuka menjaga kompleksitas tetap rendah dengan mengisolasi kekhawatiran .
sumber
Mungkin ada dua penggunaan kata antarmuka yang digunakan di sini. Antarmuka yang Anda maksudkan terutama dalam pertanyaan Anda adalah Java Interface . Itu secara khusus konsep Java, lebih umum itu adalah antarmuka bahasa pemrograman.
Saya akan mengatakan bahwa pemrograman ke antarmuka adalah konsep yang lebih luas. API REST yang sekarang populer yang tersedia untuk banyak situs web adalah contoh lain dari konsep pemrograman yang lebih luas untuk antarmuka di tingkat yang lebih tinggi. Dengan membuat lapisan di antara cara kerja kode Anda dan dunia luar (orang-orang di internet, program lain, bahkan bagian lain dari program yang sama) Anda dapat mengubah apa pun di dalam kode Anda selama Anda tidak mengubah apa yang dunia luar mengharapkan, di mana itu ditentukan oleh antarmuka, atau kontrak yang ingin Anda hormati.
Itu kemudian memberikan Anda fleksibilitas untuk memperbaiki kode internal Anda tanpa harus mengatakan semua hal lain yang bergantung pada antarmuka.
Ini juga berarti bahwa kode Anda harus lebih stabil. Dengan tetap berpegang pada antarmuka maka Anda tidak boleh merusak kode orang lain. Ketika Anda benar-benar harus mengubah antarmuka maka Anda dapat merilis versi utama baru (1.abc ke 2.xyz) dari API yang menandakan bahwa ada perubahan yang melanggar pada antarmuka versi baru.
Seperti @Doval tunjukkan dalam komentar pada jawaban ini ada juga kesalahan lokal. Ini saya pikir semua bermuara pada enkapsulasi. Sama seperti Anda akan menggunakannya untuk objek dalam desain Berorientasi Objek, jadi konsep ini juga berguna di tingkat yang lebih tinggi.
sumber
Analogi Dunia Nyata mungkin membantu:
Colokan listrik listrik di Antarmuka.
Iya nih; benda tiga pin di ujung kabel daya dari TV, radio, penyedot debu, mesin cuci, dll.
Setiap alat yang memiliki steker utama (yaitu mengimplementasikan antarmuka "memiliki steker listrik") dapat diperlakukan dengan cara yang persis sama; mereka semua dapat dicolokkan ke stopkontak di dinding dan dapat menarik daya dari soket itu.
Apa setiap alat individu tidak sama sekali berbeda. Anda tidak akan terlalu jauh membersihkan karpet dengan TV dan kebanyakan orang tidak menonton mesin cuci mereka untuk hiburan. Tetapi semua peralatan ini memiliki perilaku yang sama yaitu dapat dicolokkan ke stopkontak dinding.
Itulah yang membuat Anda mendapatkan Antarmuka. Perilaku
terpadu yang dapat dilakukan oleh banyak Kelas Obyek berbeda, tanpa perlu komplikasi Warisan.
sumber
Istilah "pemrograman ke antarmuka" terbuka untuk banyak interpretasi. Antarmuka dalam pengembangan perangkat lunak adalah kata yang sangat umum. Inilah cara saya menjelaskan konsep ini kepada pengembang junior yang telah saya latih selama bertahun-tahun.
Dalam arsitektur perangkat lunak ada berbagai batasan alami. Contoh umum termasuk
Yang penting, adalah bahwa ketika batas-batas alami ini ada, mereka diidentifikasi dan kontrak tentang bagaimana batas itu berperilaku ditentukan. Anda menguji perangkat lunak Anda bukan dengan apakah "pihak lain" berperilaku, tetapi apakah interaksi Anda sesuai dengan spesifikasi.
Konsekuensi dari ini adalah:
Sementara banyak dari ini dapat berhubungan dengan kelas dan antarmuka, penting untuk menyadari bahwa itu juga berkaitan dengan model data, protokol jaringan dan dalam cara yang lebih umum bekerja dengan banyak pengembang
sumber