Ikhtisar
Menjelaskan latar belakang dan prinsip menghilangkan hambatan menulis kontrak API dan tipe yang sama dua kali saat mengembangkan backend dan frontend bersama, serta mengubah pekerjaan pengembangan yang berulang seperti string field MongoDB, router, dan handler menjadi generasi berbasis sumber.
Kisah asal
Saya bekerja di backend dan frontend secara bersamaan. Saat membuat satu fitur, saya menulis endpoint dan DTO request/response di Java WebFlux, dan kemudian di frontend saya harus menulis URL dan tipe TypeScript yang sama. Untuk menyesuaikan dokumen Swagger, saya harus memindahkan informasi yang sudah ada di backend ke format lain sekali lagi.
Titik tersumbat terbesar adalah proses menulis ulang kontrak API yang dibuat di backend agar dapat digunakan oleh frontend. Jika salah satu dari URL, metode HTTP, parameter path/query, atau struktur request/response diubah secara berbeda di kedua sisi, masalah baru terdeteksi setelah kompilasi. Ini bukan hanya pekerjaan yang merepotkan, tetapi ketidaksesuaian yang muncul karena orang mengelola informasi yang sama dua kali menjadi masalah yang lebih besar.
Saya juga ingin mengurangi pengulangan saat membuat RouterFunction dan handler baru. Jika saya menambahkan referensi seperti ApiAccountHandler::search ke router, saya pikir kerangka kelas handler dan metode yang tidak ada seharusnya dibuat secara otomatis. Saat menulis query MongoDB, mengulangi nama field entitas sebagai string seperti "username" juga merepotkan dan rentan terhadap kesalahan ketik, jadi saya juga menambahkan fitur untuk membaca sumber entitas dan membuatnya menjadi enum Java dalam alat yang sama.
Dengan demikian, pembuatan Swagger/OpenAPI, pembuatan kerangka handler, dan pembuatan enum field entitas Mongo telah dibuat terlebih dahulu, dan setelah itu, saat menggunakan RSocket, pembuatan AsyncAPI juga ditambahkan. Meskipun masing-masing tampak seperti ide terpisah, titik awalnya sama. Ini adalah tentang tidak menulis ulang fakta yang sudah ditulis di sumber backend oleh manusia, dan membiarkan alat pengembangan membuat bagian yang dapat dibaca mesin.
Filosofi pengembangan
Berdasarkan sumber backend
Menggunakan informasi yang sudah ada di RouterFunction, handler, DTO, dan entitas sebagai sumber untuk dokumentasi API dan kode yang dihasilkan. Kuncinya adalah tidak mengelola kontrak yang sama di file terpisah.
Memilih otomatisasi saat pengembangan daripada sihir runtime
Ini bukan framework yang mencegat permintaan produksi, tetapi menganalisis sumber di lingkungan pengembangan lokal dan menghasilkan file nyata. Hasilnya dapat diperiksa secara visual dan dikelola versinya.
Mengikuti konvensi proyek dengan cara yang dapat diprediksi
Tidak bertujuan untuk compiler universal yang memahami semua kode Java. Saya lebih memprioritaskan menganalisis struktur endpoint fungsional WebFlux yang saya gunakan secara nyata dengan aturan yang jelas.
Menghilangkan segmen koneksi yang berulang
Membuat Swagger di endpoint backend dan menghubungkan alur di mana generator frontend membaca dokumen itu untuk membuat service dan tipe dalam satu rantai otomatis.
Apa yang dibaca di backend
sumber RouterFunction
Membaca metode HTTP, jalur bersarang, referensi metode pengendali, dan predikat.
Sumber pengendali
Membaca body permintaan, nilai query/path, dan tipe penerbit respons.
Request / Response DTO
Menghubungkan tipe Java yang sudah ditulis di backend ke skema OpenAPI.
Sumber entitas Mongo
Membaca nama raw penyimpanan field Java dan @Field, koleksi @Document.
Pengendali RSocket
Membaca rute @MessageMapping dan tipe payload request/response.
Apa yang dibuat alih-alih menulis ulang
swagger.json
Membuat endpoint REST menjadi kontrak API yang dapat digunakan oleh layanan front-end dan generator tipe TypeScript.
asyncapi-rsocket.json
Membuat kontrak untuk rute RSocket dan payload yang dapat dibaca oleh generator klien RSocket front-end.
Sumber pengendali
Menghasilkan dan memperbaiki kerangka kelas dan metode berdasarkan referensi pengendali yang ditulis di RouterFunction.
{Entity}Fields enum
Membuat enum untuk nama raw penyimpanan field Java entitas agar tidak terulang.
Enum CollectionNames
Menghasilkan nama koleksi yang dideklarasikan di @Document agar dapat digunakan sebagai string.
Alur otomatisasi dalam proyek saat ini
• Menulis RouterFunction, pengendali, dan DTO request/response Java di backend.
• Watcher profil lokal mendeteksi perubahan sumber dan memperbarui swagger.json atau asyncapi-rsocket.json.
• Skrip pembuatan @byeolnaerim/typed-rx-http di front-end membaca dokumen dan menghasilkan fungsi layanan serta tipe TypeScript.
• Di kode layar, tidak perlu menulis ulang URL dan tipe respons, cukup mengimpor fungsi yang dihasilkan.
• Ketika entitas berubah, enum field yang digunakan dalam query dan enum koleksi juga diperbarui.