Baru-baru ini saya telah mengembangkan API saya sendiri dan dengan minat yang diinvestasikan dalam desain API, saya sangat tertarik bagaimana saya dapat meningkatkan desain API saya.
Salah satu aspek yang telah muncul beberapa kali adalah (bukan oleh pengguna API saya tetapi dalam diskusi saya mengamati tentang topik): orang harus tahu hanya dengan melihat kode memanggil API apa yang dilakukannya .
Sebagai contoh, lihat diskusi tentang GitHub ini untuk repo wacana , seperti:
foo.update_pinned(true, true);
Hanya dengan melihat kode (tanpa mengetahui nama parameter, dokumentasi, dll.) Orang tidak dapat menebak apa yang akan dilakukan - apa arti argumen ke-2? Perbaikan yang disarankan adalah memiliki sesuatu seperti:
foo.pin()
foo.unpin()
foo.pin_globally()
Dan itu sudah beres (argumen ke-2 adalah apakah akan pin foo secara global, saya kira), dan saya setuju dalam kasus ini nanti akan menjadi perbaikan.
Namun saya percaya mungkin ada contoh di mana metode untuk mengatur keadaan yang berbeda tetapi terkait secara logis akan lebih baik diekspos sebagai satu metode panggilan daripada yang terpisah, meskipun Anda tidak akan tahu apa yang dilakukannya hanya dengan melihat kode . (Jadi Anda harus mencari untuk melihat nama parameter dan dokumentasi untuk mencari tahu - yang secara pribadi saya akan selalu lakukan tidak peduli bagaimana jika saya tidak terbiasa dengan API).
Sebagai contoh saya memaparkan satu metode SetVisibility(bool, string, bool)
pada FalconPeer dan saya mengakui hanya melihat baris:
falconPeer.SetVisibility(true, "aerw3", true);
Anda tidak akan tahu apa yang dilakukannya. Ini menetapkan 3 nilai berbeda yang mengontrol "visibilitas" falconPeer
dalam arti logis: menerima permintaan bergabung, hanya dengan kata sandi dan membalas permintaan penemuan. Membagi ini menjadi 3 metode panggilan dapat menyebabkan pengguna API untuk mengatur satu aspek "visibilitas" lupa untuk mengatur orang lain yang saya paksa mereka pikirkan dengan hanya memaparkan satu metode untuk mengatur semua aspek "visibilitas" . Lebih jauh lagi ketika pengguna ingin mengubah satu aspek mereka hampir selalu ingin mengubah aspek lain dan sekarang dapat melakukannya dalam satu panggilan.
sumber
update
metode:foo.update(pinned=true, globally=true)
. Atau:foo.update_pinned(true, globally=true)
. Jadi, jawaban untuk pertanyaan Anda juga harus mempertimbangkan fitur bahasa, karena API yang baik untuk bahasa X mungkin tidak baik untuk bahasa Y dan sebaliknya.setSize(10, 20)
tidak dapat dibaca sepertisetSize(width=10, height=20)
ataurandom(distribution='gaussian', mean=0.5, deviation=1)
. Dalam bahasa dengan parameter bernama yang dipaksakan, boolean dapat menyampaikan jumlah informasi yang persis sama dengan menggunakan enum / konstanta bernama, sehingga mereka bisa bagus di API.Jawaban:
Keinginan Anda untuk tidak membaginya menjadi tiga pemanggilan metode benar-benar dapat dipahami, tetapi Anda memang memiliki opsi lain selain parameter boolean.
Anda bisa menggunakan enum:
Atau bahkan flag enum (jika bahasa Anda mendukungnya):
Atau Anda dapat menggunakan Obyek Parameter :
Pola Objek Parameter memberi Anda beberapa keuntungan lain yang mungkin bermanfaat bagi Anda. Ini membuatnya mudah untuk dilewatkan dan membuat serial suatu set parameter, dan Anda dapat dengan mudah memberikan nilai parameter "default" yang tidak ditentukan.
Atau Anda bisa menggunakan parameter boolean. Microsoft tampaknya selalu melakukannya dengan .NET Framework API, jadi Anda bisa mengangkat bahu dan berkata "jika itu cukup baik untuk mereka, itu cukup baik untuk saya".
sumber
Jelas, selalu ada pengecualian untuk aturan tersebut, tetapi seperti yang Anda jelaskan sendiri, ada keuntungan tertentu dalam memiliki API yang dapat dibaca. Argumen Boolean sangat menyusahkan, karena 1) mereka tidak mengungkapkan maksud dan 2) mereka menyiratkan bahwa Anda memanggil fungsi, di mana Anda sebenarnya harus memiliki dua, karena hal-hal yang berbeda akan terjadi tergantung pada bendera boolean.
Pertanyaan utamanya adalah: berapa banyak upaya yang ingin Anda investasikan agar API Anda lebih mudah dibaca? Semakin menghadap ke luar, semakin banyak upaya yang dapat dengan mudah dibenarkan. Jika itu adalah API yang hanya digunakan oleh satu unit lain, maka itu bukan masalah besar. Jika Anda berbicara tentang API REST di mana Anda berencana untuk membiarkan seluruh dunia kehilangan itu, maka Anda mungkin juga berinvestasi lebih banyak upaya untuk membuatnya lebih dimengerti.
Adapun contoh Anda, ada solusi sederhana: Rupanya, dalam kasus Anda visibilitas bukan hanya hal yang benar atau salah. Sebaliknya, Anda memiliki seluruh rangkaian hal yang Anda anggap "visibilitas". Salah satu solusi mungkin untuk memperkenalkan sesuatu seperti
Visibility
kelas, yang mencakup semua jenis visibilitas yang berbeda. Jika Anda selanjutnya menerapkan pola Builder untuk membuat ini, Anda mungkin berakhir dengan kode seperti berikut:sumber