Rumah> Java> javaTutorial> teks badan

Amalan reka bentuk API untuk Java

WBOY
Lepaskan: 2024-08-30 06:02:02
asal
225 orang telah melayarinya

API design practices for Java

Oleh: BJ Hargrave

Fahami beberapa amalan reka bentuk API yang harus digunakan semasa mereka bentuk API Java. Amalan ini berguna, secara umum, dan memastikan API boleh digunakan dengan betul dalam persekitaran modular, seperti OSGi dan Sistem Modul Platform Java (JPMS). Sesetengah amalan adalah preskriptif dan ada yang proskriptif. Dan, sudah tentu, amalan reka bentuk API lain yang baik juga digunakan.

Persekitaran OSGi menyediakan masa jalan modular menggunakan konsep pemuat kelas Java untuk menguatkuasakan pengkapsulan jenisketerlihatan. Setiap modul akan mempunyai pemuat kelasnya sendiri yang akanberwayarkepada pemuat kelas modul lain untuk berkongsi pakej yang dieksport dan menggunakan pakej yang diimport.

JPMS, yang diperkenalkan dalam Java 9, menyediakan platform modular menggunakan konsep kawalan capaian daripada Spesifikasi Bahasa Java untuk menguatkuasakan pengekapan jeniskebolehcapaian. Setiap modul mentakrifkan pakej yang dieksport dan dengan itu boleh diakses oleh modul lain. Secara lalai, modul dalam lapisan JMPS semuanya berada dalam pemuat kelas yang sama.

Sesuatu pakej boleh mengandungi API. Terdapat duaperananpelanggan untuk pakej API ini:Pengguna APIdanpembekal API. Pengguna API menggunakan API yang dilaksanakan oleh penyedia API.

Dalam amalan reka bentuk berikut, kami membincangkan bahagian awam bagi sesuatu pakej. Ahli dan jenis pakej, yang bukan umum atau dilindungi (iaitu, peribadi atau lalai boleh diakses), tidak boleh diakses di luar pakej dan dengan itu butiran pelaksanaan pakej.

Pakej Java mestilah unit yang padu dan stabil

Pakej Java mesti direka bentuk untuk memastikan bahawa ia adalah unitpadudanstabil. Dalam Java modular, pakej ialah entiti yang dikongsi antara modul. Satu modul boleh mengeksport pakej supaya modul lain boleh menggunakan pakej tersebut. Oleh kerana pakej adalah unit perkongsian antara modul, pakej mestilah kohesif kerana semua jenis dalam pakej mesti berkaitan dengan tujuan khusus pakej. Pakej beg grab seperti java.util tidak digalakkan kerana jenis dalam pakej sedemikian selalunya tidak mempunyai kaitan antara satu sama lain. Pakej tidak kohesif sedemikian boleh mengakibatkan banyak kebergantungan kerana bahagian pakej yang tidak berkaitan merujuk pakej lain yang tidak berkaitan dan perubahan kepada satu aspek pakej memberi kesan kepada semua modul yang bergantung pada pakej walaupun modul mungkin tidak menggunakan bahagian tersebut. pakej yang telah diubah suai.

Memandangkan pakej adalah unit yang dikongsi, kandungannya mesti diketahui umum dan API yang terkandung hanya tertakluk kepada perubahan dalam cara yang serasi apabila pakej itu berkembang dalam versi masa hadapan. Ini bermakna pakej tidak boleh menyokong superset atau subset API; contohnya, lihat javax.transaction sebagai pakej yang kandungannya tidak stabil. Pengguna sesuatu pakej mestilah dapat mengetahui jenis yang terdapat dalam pakej tersebut. Ini juga bermakna bahawa pakej harus dihantar oleh satu entiti (contohnya, balang
fail) dan tidak berpecah merentas berbilang entiti kerana pengguna pakej mesti tahu bahawa keseluruhan pakej ada.

Selain itu, pakej mesti berkembang dengan cara yang serasi berbanding versi akan datang. Jadi pakej harus diversi dan nombor versinya mesti berkembang mengikut peraturan untuk versi semantik. Terdapat juga kertas putih OSGi pada versi semantik.

Walau bagaimanapun, pengesyoran versi semantik untuk perubahan versi utama untuk pakej adalah bermasalah. Evolusi pakej mestilah pertambahan fungsi. Dalam versi semantik, ini meningkatkan versi kecil. Apabila anda mengalih keluar fungsi, itu membuat perubahan yang tidak serasi pada pakej, bukannya meningkatkan major
versi anda mesti beralih ke nama pakej baharu meninggalkan pakej asal masih serasi. Untuk memahami sebab ini penting dan perlu, lihat kertas kerja ini mengenai Versi Import Semantik untuk Go dan pembentangan ucaptama yang sangat baik ini oleh Rich Hickey di Clojure/conj 2016. Kedua-duanya membuat kes untuk berpindah ke nama pakej baharu dan bukannya menukar major versi apabila membuat perubahan yang tidak serasi pada pakej.

Minimumkan gandingan pakej

Jenis dalam pakej boleh merujuk kepada jenis dalam pakej lain. Sebagai contoh, jenis parameter dan jenis pulangan kaedah dan jenis medan. Gandingan antara pakej ini mencipta apa yang dipanggilmenggunakankekangan pada pakej. Ini bermakna pengguna API mesti menggunakan pakej rujukan yang sama seperti penyedia API agar mereka berdua memahami jenis yang dirujuk.

Secara umumnya, kami ingin meminimumkan gandingan pakej ini untuk meminimumkan kekangan penggunaan pada pakej. Ini memudahkan resolusi pendawaian dalam persekitaran OSGi dan meminimumkan kebergantungan kipas-out memudahkan penggunaan.

Antara muka diutamakan berbanding kelas

Untuk API, antara muka diutamakan berbanding kelas. Ini adalah amalan reka bentuk API yang agak biasa yang juga penting untuk Java modular. Penggunaan antara muka membenarkan kebebasan pelaksanaan serta pelbagai pelaksanaan. Antara muka adalah penting untuk memisahkan pengguna API daripada pembekal API. Ia membenarkan pakej yang mengandungi antara muka API digunakan oleh kedua-dua penyedia API yang melaksanakan antara muka dan pengguna API yang memanggil kaedah pada antara muka. Dengan cara ini, pengguna API tidak mempunyai pergantungan langsung pada pembekal API. Kedua-duanya hanya bergantung pada pakej API.

Kelas abstrak kadangkala merupakan pilihan reka bentuk yang sah dan bukannya antara muka, tetapi secara amnya antara muka ialah pilihan pertama terutamanya kerana kaedah lalai boleh ditambah pada antara muka.

Akhir sekali, API selalunya memerlukan beberapa kelas konkrit yang kecil seperti jenis acara dan jenis pengecualian. Ini bagus tetapi jenisnya pada umumnya tidak boleh diubah dan tidak bertujuan untuk subkelas oleh pengguna API.

Elakkan statik

Statik harus dielakkan dalam API. Jenis tidak boleh mempunyai ahli statik. Kilang statik harus dielakkan. Penciptaan instance harus dipisahkan daripada API. Sebagai contoh, pengguna API harus menerima contoh objek jenis API melalui suntikan kebergantungan atau pendaftaran objek seperti pendaftaran perkhidmatan OSGi atau java.util.ServiceLoader dalam JPMS.

Mengelakkan statik juga merupakan amalan yang baik untuk membuat API yang boleh diuji kerana statik tidak boleh dipermainkan dengan mudah.

Bujang

Kadangkala terdapat objek tunggal dalam reka bentuk API. Walau bagaimanapun, akses kepada objek tunggal tidak boleh melalui statik seperti kaedah getInstance statik atau medan statik. Apabila objek tunggal diperlukan, objek itu hendaklah ditakrifkan oleh API sebagai tunggal dan diberikan kepada pengguna API melalui suntikan kebergantungan atau pendaftaran objek seperti yang dinyatakan di atas.

Elakkan andaian pemuat kelas

API selalunya mempunyai mekanisme kebolehlanjutan di mana pengguna API boleh membekalkan nama kelas yang mesti dimuatkan oleh penyedia API. Pembekal API kemudiannya mesti menggunakan Class.forName (mungkin menggunakan pemuat kelas konteks benang) untuk memuatkan kelas. Mekanisme jenis ini menganggap keterlihatan kelas daripada penyedia API (atau pemuat kelas konteks benang) kepada pengguna API. Reka bentuk API mesti mengelakkan andaian pemuat kelas. Salah satu perkara utama modulariti ialah enkapsulasi jenis. Satu modul (contohnya, penyedia API) mestilah tidak mempunyai keterlihatan/kebolehcapaian kepada butiran pelaksanaan modul lain (contohnya, pengguna API).

Reka bentuk API mesti mengelak daripada menghantar nama kelas antara pengguna API dan penyedia API dan mesti mengelakkan andaian mengenai hierarki pemuat kelas dan keterlihatan/kebolehcapaian jenis. Untuk menyediakan model kebolehlanjutan, reka bentuk API harus mempunyai objek kelas pas pengguna API, atau lebih baik lagi, objek contoh kepada pembekal API. Ini boleh dilakukan melalui kaedah dalam API atau melalui pendaftaran objek seperti pendaftaran perkhidmatan OSGi. Lihat corak papan putih.

Kelas java.util.ServiceLoader, apabila tidak digunakan dalam modul JPMS, juga mengalami andaian pemuat kelas kerana ia menganggap semua penyedia boleh dilihat daripada pemuat kelas konteks benang atau pemuat kelas yang dibekalkan. Andaian ini secara amnya tidak benar dalam persekitaran modular walaupun JPMS membenarkan pengisytiharan modul untuk mengisytiharkan modul menyediakan atau menggunakan
Perkhidmatan terurus ServiceLoader.

Jangan anggap kekal

Banyak reka bentuk API menganggap hanya fasa pembinaan di mana objek dibuat seketika dan ditambah pada API tetapi mengabaikan fasa pemusnahan yang boleh berlaku dalam sistem dinamik. Reka bentuk API harus mempertimbangkan bahawa objek boleh datang dan ia boleh pergi. Sebagai contoh, kebanyakan API pendengar membenarkan pendengar ditambah dan dialih keluar. Tetapi kebanyakan reka bentuk API hanya menganggap objek ditambah dan tidak pernah dialih keluar. Contohnya, banyak sistem suntikan pergantungan tidak mempunyai cara untuk menarik balik objek yang disuntik.

Dalam persekitaran OSGi, modul boleh ditambah dan dialih keluar, jadi reka bentuk API yang boleh menampung dinamik sedemikian adalah penting. Spesifikasi Perkhidmatan Pengisytiharan OSGi
mentakrifkan model suntikan pergantungan untuk OSGi yang menyokong dinamik ini termasuk penarikan balik objek yang disuntik.

API 소비자와 API 공급자에 대한 명확한 문서 유형 역할

서문에서 언급했듯이 API 패키지 클라이언트에는 API 소비자와 API 제공자라는 두 가지 역할이 있습니다. API 소비자는 API를 사용하고 API 공급자는 API를 구현합니다. API의 인터페이스(및 추상 클래스) 유형의 경우 API 설계에서 API 제공자에 의해서만 구현되는 유형과 API 소비자가 구현할 수 있는 유형을 명확하게 문서화하는 것이 중요합니다. 예를 들어, 리스너 인터페이스는 일반적으로 API 소비자에 의해 구현됩니다
API 제공업체에 인스턴스가 전달됩니다.

API 제공자는 API 소비자와 API 제공자가 구현한 유형의 변경에 민감합니다. 공급자는 API 공급자 유형의 새로운 변경 사항을 구현해야 하며 API 소비자 유형의 새로운 변경 사항을 이해하고 호출할 가능성이 있어야 합니다. API 소비자는 일반적으로 API 소비자가 새 기능을 호출하기 위해 변경을 원하지 않는 한 API 공급자 유형의 (호환 가능한) 변경 사항을 무시할 수 있습니다. 그러나 API 소비자는 API 소비자 유형의 변경에 민감하므로 새 기능을 구현하려면 수정이 필요할 수 있습니다. 예를 들어, javax.servlet 패키지에서 ServletContext 유형은 서블릿 컨테이너와 같은 API 제공자에 의해 구현됩니다. ServletContext에 새 메소드를 추가하려면 새 메소드를 구현하기 위해 모든 API 제공자를 업데이트해야 하지만 API 소비자는 새 메소드를 호출하지 않는 한 변경할 필요가 없습니다. 그러나 Servlet 유형은 API 소비자에 의해 구현되며 Servlet에 새 메소드를 추가하려면 모든 API 소비자를 수정하여 새 메소드를 구현해야 하며 모든 API 공급자도 새 메소드를 활용하도록 수정해야 합니다. 따라서 ServletContext 유형에는 API 제공자 역할이 있고 Servlet 유형에는 API 소비자 역할이 있습니다.

일반적으로 API 소비자는 많고 API 제공자는 적기 때문에 API 진화는 API 소비자 유형 변경을 고려할 때 매우 신중해야 하며 API 제공자 유형 변경에 대해서는 좀 더 여유를 가져야 합니다. 업데이트된 API를 지원하려면 소수의 API 공급자를 변경해야 하지만 API가 업데이트될 때 많은 기존 API 소비자를 변경하도록 요구하고 싶지 않기 때문입니다. API 소비자는 API 소비자가 새 API를 활용하려는 경우에만 변경하면 됩니다.

OSGi Alliance는 API 패키지에서 유형의 역할을 표시하기 위해 문서 주석, ProviderType 및 ConsumerType을 정의합니다. 이러한 주석은 API에서 사용할 수 있도록 osgi.annotation jar에서 사용할 수 있습니다.

결론

다음번에 API를 설계할 때 이러한 API 설계 방식을 고려하십시오. 그러면 API를 모듈식 Java 및 비모듈식 Java 환경 모두에서 사용할 수 있습니다.

Atas ialah kandungan terperinci Amalan reka bentuk API untuk Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!