
Bagaimana mengubah arsitektur produk monolitik untuk mempercepat pengembangannya, dan bagaimana membagi satu tim menjadi beberapa, sambil mempertahankan konsistensi kerja? Bagi kami, jawaban atas pertanyaan-pertanyaan ini adalah pembuatan API baru. Di bawah potongan Anda akan menemukan cerita rinci tentang jalan menuju solusi dan ikhtisar dari teknologi yang dipilih, tetapi untuk memulai - penyimpangan kecil.
Beberapa tahun yang lalu, saya membaca dalam sebuah artikel ilmiah bahwa semakin banyak waktu yang dibutuhkan untuk pelatihan penuh, dan dalam waktu dekat akan membutuhkan delapan puluh tahun untuk mendapatkan pengetahuan. Rupanya, di TI masa depan ini sudah datang.
Saya cukup beruntung untuk memulai pemrograman pada tahun-tahun itu ketika tidak ada pemisahan antara programmer backend dan front-end, ketika kata-kata "prototipe", "insinyur produk", "UX" dan "QA" tidak terdengar. Dunia lebih sederhana, pohon-pohon lebih tinggi dan lebih hijau, udaranya lebih bersih dan anak-anak bermain di halaman, bukannya mobil parkir. Tidak peduli bagaimana saya ingin kembali pada waktu itu, saya harus mengakui bahwa semua ini bukan tujuan dari supervillain, tetapi perkembangan masyarakat yang evolusioner. Ya, masyarakat bisa berkembang secara berbeda, tetapi, seperti yang Anda tahu, sejarah tidak menoleransi mood subjungtif.
Latar belakang
BILLmanager muncul tepat pada saat tidak ada pemisahan arah yang kaku. Itu memiliki arsitektur yang koheren, mampu mengendalikan perilaku pengguna, dan bahkan dapat diperluas dengan plugin. Waktu berlalu, tim mengembangkan produk, dan semuanya tampak baik-baik saja, tetapi fenomena aneh mulai diamati. Misalnya, ketika seorang programmer terlibat dalam logika bisnis, ia mulai membuat formulir dengan buruk, membuatnya tidak nyaman dan sulit dimengerti. Atau penambahan fungsi yang tampaknya sederhana membutuhkan waktu beberapa minggu: secara arsitektur, modul-modulnya dipasangkan dengan erat, jadi ketika mengubah satu, yang lain harus disesuaikan.
Kemudahan, ergonomi, dan pengembangan produk global secara umum bisa dilupakan ketika aplikasi mengalami kesalahan yang tidak diketahui. Jika sebelumnya seorang programmer berhasil melakukan pekerjaan dalam arah yang berbeda, maka dengan pertumbuhan produk dan persyaratan untuk itu, ini menjadi tidak mungkin. Pengembang melihat keseluruhan gambar dan memahami bahwa jika fungsi tidak bekerja dengan benar dan stabil, maka formulir, tombol, tes, dan promosi tidak akan membantu. Karena itu, ia menunda semuanya dan duduk untuk memperbaiki kesalahan yang ditakdirkan. Dia membuat prestasi kecilnya, yang tetap tidak dihargai oleh siapa pun (tidak ada lagi kekuatan untuk pengiriman yang benar ke klien), tetapi fungsinya mulai bekerja. Sebenarnya, sehingga prestasi kecil ini mencapai pelanggan, tim akan mencakup orang-orang yang bertanggung jawab untuk berbagai bidang: frontend dan backend, pengujian, desain, dukungan, promosi.
Tapi itu hanya langkah pertama. Tim telah berubah, dan arsitektur produk tetap secara teknis erat. Karena itu, tidak mungkin untuk mengembangkan aplikasi pada kecepatan yang diperlukan, ketika mengubah antarmuka, logika backend harus diubah, meskipun struktur data itu sendiri sering tetap tidak berubah. Sesuatu harus dilakukan dengan semua ini.
Frontend dan backend
Untuk menjadi seorang profesional dalam segala hal adalah panjang dan mahal, oleh karena itu dunia modern programmer terapan dibagi, sebagian besar, menjadi front-end dan back-end.
Semuanya tampak jelas di sini: kami merekrut programmer front-end, mereka akan bertanggung jawab untuk antarmuka pengguna, dan backend akhirnya akan dapat fokus pada logika bisnis, model data, dan kap mesin lainnya. Pada saat yang sama, backend, frontend, penguji dan desainer akan tetap berada dalam satu tim (karena mereka membuat produk yang sama, mereka hanya fokus pada bagian yang berbeda dari itu). Berada dalam satu tim berarti memiliki satu ruang informasi dan, lebih disukai, teritorial; mendiskusikan fitur-fitur baru bersama dan membongkar yang sudah jadi; mengoordinasikan pekerjaan pada tugas besar.
Untuk beberapa proyek baru yang abstrak ini sudah cukup, tetapi kami sudah memiliki aplikasi yang ditulis, dan volume pekerjaan yang direncanakan dan waktu pelaksanaannya jelas menunjukkan bahwa satu tim tidak dapat melakukannya. Ada lima orang di tim bola basket, 11 di tim sepak bola, dan kami memiliki sekitar 30 orang. Ini tidak cocok dengan tim scrum yang sempurna terdiri dari lima hingga sembilan orang. Itu perlu untuk memecah belah, tetapi bagaimana mempertahankan koherensi? Untuk bergerak, itu perlu untuk memecahkan masalah arsitektur dan organisasi.

"Kami akan melakukan segalanya dalam satu proyek, itu akan lebih nyaman", kata mereka ...
Arsitektur
Ketika suatu produk kedaluwarsa, tampaknya logis untuk meninggalkannya dan menulis yang baru. Ini adalah keputusan yang baik jika Anda dapat memprediksi waktu dan itu akan cocok untuk semua orang. Tetapi dalam kasus kami, bahkan dalam kondisi ideal, pengembangan produk baru akan memakan waktu bertahun-tahun. Selain itu, spesifikasi aplikasi adalah sedemikian rupa sehingga akan sangat sulit untuk beralih dari yang lama ke yang baru dengan perbedaan sepenuhnya. Kompatibilitas mundur sangat penting bagi pelanggan kami, dan jika tidak ada, mereka akan menolak untuk meningkatkan ke versi baru. Kelayakan berkembang dari awal dalam hal ini diragukan. Oleh karena itu, kami memutuskan untuk memutakhirkan arsitektur produk yang ada dengan tetap mempertahankan kompatibilitas mundur maksimal.
Aplikasi kami adalah monolith, antarmuka yang dibangun di sisi server. Frontend hanya menerapkan instruksi yang diterima darinya. Dengan kata lain, backend tidak bertanggung jawab atas antarmuka pengguna . Secara arsitektur, front-end dan back-end bekerja sebagai satu, oleh karena itu, mengubah satu, kami dipaksa untuk mengubah yang lain. Dan ini bukan yang terburuk, yang jauh lebih buruk - tidak mungkin untuk mengembangkan antarmuka pengguna tanpa pengetahuan mendalam tentang apa yang terjadi di server.
Itu perlu untuk memisahkan front-end dan back-end, untuk membuat aplikasi perangkat lunak yang terpisah: satu-satunya cara untuk mulai mengembangkannya adalah pada kecepatan dan volume yang diperlukan. Tetapi bagaimana melakukan dua proyek secara paralel, mengubah struktur mereka jika mereka sangat bergantung satu sama lain?
Solusinya adalah sistem tambahan - sebuah lapisan . Gagasan interlayer sangat sederhana: ia harus mengoordinasikan pekerjaan backend dan frontend dan mengambil semua biaya tambahan. Misalnya, sehingga ketika fungsi pembayaran didekomposisi di sisi backend, lapisan menggabungkan data, dan di sisi ujung depan, tidak ada yang perlu diubah; atau sehingga untuk kesimpulan ke dasbor semua layanan yang dipesan oleh pengguna, kami tidak melakukan fungsi tambahan pada backend, tetapi menggabungkan data dalam lapisan.
Selain itu, layer ini menambahkan kepastian pada apa yang bisa dipanggil dari server dan yang pada akhirnya akan kembali. Saya ingin agar permintaan operasi dimungkinkan tanpa mengetahui struktur internal fungsi yang menjalankannya.

Meningkatkan stabilitas dengan membagi bidang tanggung jawab.
Komunikasi
Karena ketergantungan yang kuat antara frontend dan backend, tidak mungkin untuk melakukan pekerjaan secara paralel, yang memperlambat kedua bagian tim. Secara terprogram membagi satu proyek besar menjadi beberapa, kami mendapat kebebasan bertindak di masing-masing, tetapi pada saat yang sama kami perlu mempertahankan konsistensi dalam pekerjaan.
Seseorang akan mengatakan bahwa konsistensi dicapai dengan meningkatkan soft skill. Ya, mereka perlu dikembangkan, tetapi ini bukan obat mujarab. Lihatlah lalu lintas, penting juga di sana bahwa pengemudi sopan, tahu bagaimana menghindari rintangan acak dan saling membantu dalam situasi sulit. Tapi! Tanpa peraturan lalu lintas, bahkan dengan komunikasi terbaik, kita akan mengalami kecelakaan di setiap persimpangan dan risiko tidak mencapai tempat tepat waktu.
Kami membutuhkan aturan yang sulit dilanggar. Seperti yang mereka katakan, untuk membuatnya lebih mudah untuk mematuhi daripada melanggar. Tetapi implementasi hukum apa pun tidak hanya membawa keuntungan, tetapi juga biaya tambahan, dan kami benar-benar tidak ingin memperlambat pekerjaan utama, menarik semua orang ke dalam proses. Oleh karena itu, kami membuat grup koordinasi, dan kemudian tim yang tujuannya adalah untuk menciptakan kondisi untuk pengembangan yang sukses dari berbagai bagian produk. Dia mengatur antarmuka yang memungkinkan proyek yang berbeda untuk bekerja secara keseluruhan - aturan yang lebih mudah untuk diikuti daripada melanggar.
Kami menyebut perintah ini "API", meskipun implementasi teknis dari API baru hanya sebagian kecil dari tugasnya. Saat bagian umum kode dimasukkan ke dalam fungsi terpisah, maka tim API mem-parsing masalah umum tim produk. Di sinilah koneksi frontend dan backend kami terjadi, sehingga anggota tim ini harus memahami secara spesifik setiap arah.
Mungkin "API" bukan nama yang paling cocok untuk tim, sesuatu tentang arsitektur atau visi berskala besar akan lebih cocok, tetapi, saya pikir, hal sepele ini tidak mengubah esensi.
API
Antarmuka akses fungsi pada server ada di aplikasi awal kami, tetapi tampak kacau untuk konsumen. Memisahkan frontend dan backend membutuhkan lebih banyak kepastian.
Sasaran untuk API baru telah muncul dari kesulitan sehari-hari dalam mengimplementasikan produk dan ide-ide desain baru. Kami membutuhkan:
- Konektivitas komponen sistem yang lemah sehingga backend dan frontend dapat dikembangkan secara paralel.
- Skalabilitas tinggi sehingga API baru tidak mengganggu fungsi bangunan.
- Stabilitas dan konsistensi.
Pencarian untuk solusi untuk API tidak dimulai dengan backend, seperti yang biasanya diterima, tetapi, sebaliknya, memikirkan apa yang dibutuhkan pengguna.
Yang paling umum adalah semua jenis API REST. Dalam beberapa tahun terakhir, model deskriptif telah ditambahkan kepada mereka melalui alat seperti angkuh, tetapi Anda perlu memahami bahwa ini adalah REST yang sama. Dan, pada kenyataannya, plus dan minus utamanya pada saat yang sama adalah aturan, yang bersifat deskriptif eksklusif. Artinya, tidak ada yang melarang pembuat API tersebut menyimpang dari postulat REST saat menerapkan bagian-bagian individual.
Solusi umum lainnya adalah GraphQL. Ini juga tidak sempurna, tetapi tidak seperti REST, GraphQL API bukan hanya model deskriptif, tetapi aturan nyata.
Sebelumnya, saya berbicara tentang sistem, yang seharusnya mengoordinasikan pekerjaan frontend dan backend. Interlayer persis tingkat menengah itu. Setelah mempertimbangkan opsi yang memungkinkan untuk bekerja dengan server, kami menetapkan GraphQL sebagai API untuk frontend . Tapi, karena backend ditulis dalam C ++, implementasi server GraphQL ternyata menjadi tugas yang tidak sepele. Saya tidak akan menjelaskan semua kesulitan dan trik yang kami jalani untuk mengatasinya, itu tidak membawa hasil nyata. Kami melihat masalah dari sisi lain dan memutuskan bahwa kesederhanaan adalah kunci kesuksesan. Oleh karena itu, kami menetapkan solusi yang terbukti: server Node.js terpisah dengan Express.js dan Apollo Server.
Selanjutnya, Anda harus memutuskan cara mengakses API backend. Pada awalnya kami melihat ke arah menaikkan REST API, kemudian kami mencoba menggunakan add-on di C ++ untuk Node.js. Sebagai hasilnya, kami menyadari bahwa semua ini tidak cocok untuk kami, dan setelah analisis terperinci untuk backend, kami memilih API berdasarkan layanan gRPC .
Setelah mengumpulkan bersama pengalaman yang diperoleh dalam menggunakan C ++, TypeScript, GraphQL dan gRPC, kami mendapat arsitektur aplikasi yang memungkinkan Anda mengembangkan backend dan frontend secara fleksibel, sambil terus menciptakan satu produk perangkat lunak.
Hasilnya adalah skema di mana front-end berkomunikasi dengan server perantara menggunakan permintaan GraphQL (tahu apa yang harus ditanyakan dan apa yang akan diterima sebagai imbalan). Server graphQL di resolvers memanggil fungsi API dari server gRPC, dan untuk ini mereka menggunakan skema Protobuf untuk komunikasi. Server API berbasis gRPC tahu dari mana layanan mikro untuk mengambil data, atau kepada siapa untuk mengirim permintaan. Layanan microser itu sendiri juga dibangun di atas gRPC, yang memastikan kecepatan pemrosesan kueri, pengetikan data, dan kemampuan untuk menggunakan berbagai bahasa pemrograman untuk pengembangannya.

Skema umum pekerjaan setelah perubahan arsitektur
Pendekatan ini memiliki sejumlah kekurangan, yang utamanya adalah pekerjaan tambahan untuk mengatur dan mengoordinasikan sirkuit, serta menulis fungsi tambahan. Tetapi biaya ini akan terbayar ketika ada lebih banyak pengguna API.
Hasil
Kami telah menempuh jalur evolusi mengembangkan produk dan tim. Mencapai kesuksesan atau usaha yang berubah menjadi kegagalan, mungkin terlalu dini untuk menilai, tetapi hasil antara dapat disimpulkan. Apa yang kita miliki sekarang:
- Frontend bertanggung jawab atas tampilan, dan backend bertanggung jawab atas data.
- Di ujung depan, fleksibilitas tetap dalam hal permintaan dan penerimaan data. Antarmuka tahu apa yang bisa Anda tanyakan ke server dan jawaban apa yang seharusnya.
- Backend memiliki kesempatan untuk mengubah kode dengan keyakinan bahwa antarmuka pengguna akan terus berfungsi. Menjadi mungkin untuk beralih ke arsitektur microservice tanpa perlu mengulang seluruh frontend.
- Sekarang Anda dapat menggunakan data tiruan untuk frontend ketika backend belum siap.
- Penciptaan skema kolaborasi menghilangkan masalah interaksi ketika tim memahami tugas yang sama secara berbeda. Jumlah iterasi untuk mengubah format data telah berkurang: kami bertindak berdasarkan prinsip "ukur tujuh kali, potong sekali".
- Sekarang Anda dapat merencanakan pekerjaan sprint secara paralel.
- Untuk mengimplementasikan satu layanan microser, Anda sekarang dapat merekrut pengembang yang tidak terbiasa dengan C ++.
Dari semua ini, saya akan menyebut kesempatan untuk secara sadar mengembangkan tim dan proyek sebagai pencapaian utama. Saya pikir kami mampu menciptakan kondisi di mana setiap peserta dapat lebih meningkatkan kompetensi mereka, fokus pada tugas dan tidak menyebarkan perhatian. Setiap orang diharuskan untuk bekerja hanya di situs mereka sendiri, dan sekarang dimungkinkan dengan keterlibatan tinggi dan tanpa pergantian yang konstan. Tidak mungkin menjadi seorang profesional dalam segala hal, tetapi sekarang tidak perlu bagi kita .
Artikel itu ternyata ulasan dan sangat umum. Tujuannya adalah untuk menunjukkan jalur dan hasil penelitian yang kompleks pada topik tentang bagaimana mengubah arsitektur dari sudut pandang teknis untuk melanjutkan pengembangan produk, serta untuk menunjukkan kesulitan organisasi dalam membagi tim menjadi bagian-bagian yang disepakati.
Di sini saya secara dangkal menyentuh masalah tim dan kerja tim pada satu produk, pilihan teknologi API (REST vs GraphQL), koneksi aplikasi Node.js dengan C ++, dll. Masing-masing topik ini menarik artikel yang terpisah, dan jika Anda tertarik, maka kami akan menulisnya.