Haruskah saya menulis antarmuka API sebelum implementasi?

14

Saya telah mempelajari lebih dalam pemrograman "terorganisir" baru-baru ini dan saya telah belajar bahwa saya harus pemrograman ke antarmuka, bukan implementasi. Dengan mengingat hal itu, apakah akan lebih baik untuk "membuat sketsa" proyek dalam antarmuka sebelum menulis implementasi untuk itu jika memungkinkan?

Dan jika ini masalahnya, dalam kasus menggunakan perpustakaan pihak ke-3 (yaitu Lidgren), haruskah saya membungkusnya dalam antarmuka juga dan menyelesaikannya melalui wadah IOC, atau apakah boleh membuka mereka ke antarmuka?

Dan Pantry
sumber
Dalam pengalaman pribadi saya - ada baiknya merancang arsitektur terlebih dahulu - tanggung jawab masing-masing kelas. Anda tidak harus menuliskannya, pikirkan saja atau buat sketsa di atas kertas. Maka ini tentang preferensi pribadi tetapi saya sarankan untuk menulis komentar doc terlebih dahulu untuk setiap metode yang Anda mulai terapkan. Menulis dokumen benar-benar membuat Anda berpikir tentang fungsionalitas sebelum mulai menulis kode.
Sulthan
Ya, dan programkan ke antarmuka (atau kelas abstrak untuk masalah ini) sebelum Anda mengimplementasikannya. Ini membantu mendapatkan aliran pesan dari klien ke server dan sebaliknya "benar" sebelum macet (dan diinvestasikan dalam) implementasi. Presentasi slide yang sangat baik tentang masalah ini: Bagaimana Mendesain API yang Baik & Mengapa Itu Penting
Marjan Venema

Jawaban:

8

Sayangnya, Anda akan menemukan ini seringkali bermuara pada preferensi pribadi.

Apa yang telah Anda jelaskan sejauh ini, tampaknya bagus. Bahkan, jika Anda ingin (dan saya merekomendasikannya), Anda dapat menggunakan pendekatan berikut:

  1. Tulis kerangka aplikasi Anda sebagai Antarmuka, kelas abstrak (stubbed), dan kelas (juga stubbed)
  2. Tulis pengujian Anda terhadap antarmuka dan bertopik itu (akan gagal untuk saat ini)
  3. Tulis implementasi Anda (tes Anda akan mulai berlalu saat Anda menyelesaikan implementasi Anda)

Anda fokus mencoba menulis lebih banyak kode "terorganisir". Mengikuti TDD akan membantu Anda dengan ini.

Beberapa poin tambahan:

  • Kontainer IoC nyaman. Gunakan mereka dan DI sebanyak yang Anda bisa.
  • Apakah membungkus perpustakaan pihak ke-3. Ini akan melonggarkan kopling antara kode Anda (kode yang Anda kontrol) dan kode pihak ketiga (kode yang tidak Anda kontrol)
MetaFight
sumber
1
Ini adalah apa yang awalnya saya pikirkan tetapi saya diberitahu itu akan melanggar prinsip YAGNI. Masalah yang saya temukan dengan banyak proyek saya yang tidak pernah selesai adalah mereka dengan cepat menjadi tidak terpelihara dengan jumlah kode gumpalan yang saya tulis, karena saya tidak mengaturnya dengan baik atau merencanakan rencana serangan saya.
Dan Pantry
bagian mana yang akan melanggar YAGNI?
MetaFight
Membungkus perpustakaan pihak ke-3.
Dan Pantry
2
Saya kira itu bermuara pada: Apa peluang perpustakaan pihak ke-3 berubah? Jika ada kemungkinan 0% dari ini, maka YAGNI yakin. Tapi, itu jarang terjadi. Selain itu, membungkus lib pihak ke-3 Anda dapat membuat kode Anda yang lain lebih mudah untuk unit test (jika, misalnya, Anda tidak bisa mengejek perpustakaan pihak ke-3)
MetaFight
1
@DanPantry: Membungkus perpustakaan pihak ketiga bukanlah pelanggaran YAGNI, tetapi perlindungan yang sangat dibutuhkan terhadap "kutu perpustakaan pihak ketiga dari kode Anda sendiri". Ini bukan hanya tentang bisa menukar perpustakaan, tetapi seperti MetaFight juga mengatakan pertahanan terhadap perubahan dalam versi yang lebih baru dari perpustakaan yang sebaliknya akan memerlukan perubahan di seluruh kode Anda sendiri. Dengan membungkus pustaka (dan terutama tipe spesifiknya: kelas, enum, struct dll), Anda mengisolasi kode Anda sendiri dan memiliki satu titik untuk berubah ketika perpustakaan berubah (untuk alasan apa pun).
Marjan Venema
13

Ya, Anda harus membuat kode terhadap antarmuka daripada implementasi yang diketahui, dan ya, Anda harus membuat antarmuka terlebih dahulu daripada membuatnya muncul dari kode Anda sendiri.

Alasan kedua rekomendasi ini sebagian besar sama: pemrograman komputer sebagian besar tentang faktor manusia. Banyak yang menemukan ini mengejutkan, tetapi pertimbangkan: ada sejumlah cara yang hampir tak terbatas untuk memecahkan masalah komputasi yang sama yang bekerja sama baiknya. Hampir semuanya benar-benar mustahil untuk dipahami oleh siapa pun yang tidak menulisnya (atau bahkan kepada penulis beberapa waktu kemudian).

Oleh karena itu, rekayasa perangkat lunak yang baik sebagian besar tentang bagaimana mencapai efek yang diinginkan (perhitungan yang benar dengan efisiensi yang masuk akal) dengan cara yang memungkinkan kode sumber untuk dikerjakan nanti. Antarmuka dan API adalah bagian penting dari disiplin itu: mereka memungkinkan Anda untuk memikirkan masalah pada satu tingkat deskripsi pada satu waktu. Ini jauh lebih mudah daripada memikirkan aturan konsistensi bisnis dan tentang implementasi daftar tertaut pada saat yang sama, dan karenanya memaksakan pemisahan kekhawatiran secara paksa lebih baik daripada membiarkan pemrogram klien untuk menggunakan kode Anda dengan cara apa pun yang diinginkannya.

Ini sulit dipercaya bagi banyak programmer koboi, yang yakin bahwa mereka memahami semua yang mereka tulis, jauh lebih baik daripada pemikir rata-rata, dan dapat menangani semua kerumitan yang membuat kesulitan programmer "lebih rendah". Tidak menyadari batas kognitif sendiri adalah fenomena yang sangat umum - inilah sebabnya praktik terbaik dalam organisasi kode sangat penting (dan sering diabaikan).

Untuk mengulang, antarmuka dan penghalang API sebagian besar baik , bahkan ketika Anda hanya bekerja sama dengan diri sendiri. Adapun perpustakaan eksternal, jika mereka membawa API yang dipikirkan dengan matang, saya tidak melihat masalah dalam menggunakannya karena selama Anda tidak mengantisipasi harus menukar perpustakaan itu dengan yang lain. Kalau tidak, lapisan pembungkus atau anti korupsi bisa menjadi ide yang sangat bagus.

Kilian Foth
sumber
Saya suka poin Anda tentang SE sebagian besar tentang mencapai efek yang diinginkan dengan cara yang memungkinkan kode sumber untuk dikerjakan nanti. Saya berharap saya bisa mengatakannya dengan baik di pekerjaan terakhir saya, di mana saya selalu berjuang untuk kode bersih!
MetaFight
Apakah ada konvensi penamaan untuk API yang hanya antarmuka yang akhirnya akan saya gunakan di semua tempat? Seperti, jika saya melakukan pola perintah, apakah saya menyebutnya "perintah"?
Mengintai
@StevieV Ada berbagai, misalnya IBlahdiimplementasikan oleh Blah, atau Blahdiimplementasikan oleh BlahImpl. Saya tidak suka keduanya, dan cenderung menggunakan yang Blahditerapkan oleh OralBlah, WrittenBlahatau ASLBlah. Tetapi seperti biasa, lebih penting untuk menyesuaikan dengan basis kode dan harapan Anda yang ada daripada dengan standar umum apa pun.
Kilian Foth
4

Daripada hanya pemrograman untuk antarmuka, mengapa tidak melihat ke Test Driven Development / Design (TDD)?

Banyak orang menganggap TDD sebagai praktik pengujian, tetapi sebenarnya ini adalah pendekatan desain tempat Anda membiarkan tes mengekspos bagaimana kode Anda akan digunakan melalui tes (awalnya melalui unit test, tetapi juga bisa melalui tes integrasi).

Pemrograman ke antarmuka adalah senjata penting dalam perangkat Anda, tetapi seperti kebanyakan hal, itu tidak selalu merupakan solusi / teknik / praktik yang tepat, karena tidak selalu diperlukan. Anda harus memprogram ke antarmuka di mana Anda perlu.

Menggunakan TDD akan memaksa Anda untuk menjelajahi di mana antarmuka seperti itu penting dan di mana itu, terus terang, tidak masalah. Dan pada akhirnya, Anda harus memiliki serangkaian unit test yang cukup bagus di seluruh basis kode Anda.

Sedangkan untuk menggunakan perpustakaan pihak ke-3 saya akan sangat menyarankan membungkusnya dalam abstraksi Anda sendiri jika perlu; dan jangan biarkan klien API Anda "tahu" tentang mereka.

Semoga berhasil!

[edit: lihat jawaban megaflight - sepenuhnya setuju]

rupjones
sumber
2
TDD secara implisit membuat Anda berpikir dalam hal antarmuka daripada implmenetasi, meskipun mungkin bukan deklarasi "antarmuka" formal.
DougM
1
Ini jawaban yang bagus. +1 untuk menyarankan TDD, yang saya pikir adalah solusi untuk masalah nyata OP dari mana harus memulai saat mengerjakan proyek baru, dan saya akan memberi +1 lagi jika saya bisa untuk "Menggunakan TDD akan memaksa Anda untuk menjelajahi di mana antarmuka seperti itu itu penting dan di mana itu, terus terang, tidak masalah. "
Benjamin Hodgson
2

Saya pikir itu berlebihan. Jika pengguna API Anda tidak perlu dipaksa untuk mengimplementasikan / menggunakan sesuatu dengan cara tertentu maka saya akan meninggalkannya. Antarmuka adalah kontrak, jika saya tidak membutuhkannya, mengapa memberi saya satu?

Saya pikir orang terlalu sering menggunakan antarmuka. Anda menambahkan lapisan kompleksitas yang tidak diperlukan dalam kebanyakan kasus.

Kyle Johnson
sumber
Saya pikir, orang - orang di bawah antarmuka. Jika Anda ingin membuat karya yang dapat digunakan kembali, antarmuka tidak hanya tambahan "menyenangkan untuk memiliki", tetapi hal utama yang harus diperhatikan. Selain implementasi yang sebenarnya tentunya.
JensG
1

Memprogram melawan kontrak hampir selalu merupakan ide yang bagus. Kontrak itu tidak harus berupa antarmuka, melainkan dapat dipenuhi oleh kelas sebagai gantinya. Menurut pendapat saya, antarmuka telah menjadi agak sering digunakan bersama dengan DI karena masalah pengujian unit dan kerangka kerja mengejek.

Saya pribadi lebih suka untuk hanya membawa antarmuka ketika saya sangat mungkin memiliki atau memiliki lebih dari 1 implementasi kontrak. Antarmuka sangat bagus untuk repositori di mana saya ingin mengabstraksi akses data, tetapi mungkin kurang begitu untuk logika bisnis standar saya yang cenderung relatif tidak fleksibel.

Sekarang tidak memiliki antarmuka dapat menyebabkan masalah dengan pengujian unit, terutama untuk puritan. Tapi saya tertarik mengejek dependensi eksternal program saya, bukan dependensi internalnya. Saya ingin pengujian saya melakukan validasi kode, bukan menggemakan struktur kode.

Peter Smith
sumber