Jadi, kami menjual klien produk perangkat lunak B2B.
Pada presentasi, dia menyukai semuanya, tetapi selama implementasi ternyata ada sesuatu yang tidak cocok. Tentu saja Anda dapat mengatakan bahwa Anda harus mengikuti "praktik terbaik", dan mengubah diri Anda menjadi suatu produk, dan bukan sebaliknya. Ini dapat berfungsi jika Anda memiliki merek yang kuat (misalnya, tiga huruf besar, dan Anda dapat mengirim ketiga huruf kecil). Jika tidak, mereka akan dengan cepat menjelaskan kepada Anda bahwa pelanggan mencapai segalanya berkat proses bisnisnya yang unik, dan mari kita ganti produk Anda dengan lebih baik atau tidak akan berhasil. Ada opsi untuk menolak dan merujuk pada kenyataan bahwa lisensi telah dibeli, dan tidak ada tempat untuk pergi dari kapal selam. Tetapi di pasar yang relatif sempit, strategi seperti itu tidak akan bekerja untuk waktu yang lama.
Kami harus memodifikasi.
Pendekatannya
Ada beberapa pendekatan dasar untuk adaptasi produk.
Monolith
Setiap perubahan dilakukan langsung ke kode sumber produk, tetapi termasuk dalam opsi tertentu. Dalam produk-produk tersebut, sebagai suatu peraturan, ada bentuk-bentuk mengerikan dengan pengaturan, yang, agar tidak menjadi bingung, diberi nomor atau kodenya. Kerugian dari pendekatan ini adalah bahwa kode sumber berubah menjadi spageti besar, di mana ada begitu banyak kasus penggunaan yang berbeda sehingga menjadi sangat panjang dan mahal untuk dipelihara. Setiap opsi selanjutnya membutuhkan lebih banyak sumber daya. Kinerja produk semacam itu juga menyisakan banyak hal yang diinginkan. Dan jika bahasa di mana produk ditulis tidak mendukung praktik modern seperti warisan dan polimorfisme, maka semuanya menjadi sangat sedih.
Salin
Klien diberi seluruh kode sumber produk dengan lisensi untuk memodifikasinya. Seringkali, vendor tersebut memberi tahu pelanggan bahwa mereka tidak akan mengadaptasi produk itu sendiri, karena akan terlalu mahal (jauh lebih menguntungkan bagi vendor untuk menjual lisensi daripada menghubungi layanan). Tetapi mereka memiliki agen outsourcing yang akrab yang mempekerjakan karyawan yang relatif murah dan berkualitas tinggi di suatu tempat di negara ketiga yang siap membantu mereka. Ada juga situasi di mana perbaikan akan dilakukan langsung oleh spesialis pelanggan (jika mereka memiliki unit kepegawaian). Dalam kasus seperti itu, kode sumber diambil sebagai titik awal, dan kode yang dimodifikasi tidak akan memiliki koneksi dengan apa yang semula, dan akan menjalani hidupnya sendiri. Dalam hal ini, Anda dapat dengan aman menghapus setidaknya setengah dari produk asli dan menggantinya dengan logika Anda sendiri.
Penggabungan
Ini adalah campuran dari dua pendekatan pertama. Tetapi di dalamnya, pengembang yang memperbaiki kode harus selalu ingat: "penggabungan akan datang". Ketika versi baru dari produk sumber dirilis, ia harus dalam kebanyakan kasus secara manual menggabungkan perubahan dalam sumber dan kode yang dimodifikasi. Masalahnya adalah bahwa dalam setiap konflik akan perlu untuk mengingat mengapa perubahan tertentu dibuat, dan ini bisa sangat lama. Dan jika kode refactoring dilakukan dalam produk asli (misalnya, blok kode hanya disusun ulang), maka penggabungan akan sangat memakan waktu.
Modularitas
Secara logis pendekatan yang paling benar. Kode sumber produk dalam hal ini tidak mengalami perubahan, dan modul tambahan ditambahkan yang memperluas fungsionalitas. Namun, untuk mengimplementasikan skema semacam itu, produk harus memiliki arsitektur yang memungkinkannya diperluas dengan cara ini.
Deskripsi
Selanjutnya dengan contoh saya akan menunjukkan bagaimana kami memperluas produk yang dikembangkan berdasarkan platform
lsFusion terbuka dan gratis.
Elemen kunci dari sistem adalah modul. Modul adalah file teks dengan ekstensi
lsf , yang berisi
kode lsFusion . Dalam setiap modul, baik logika domain (fungsi, kelas, tindakan) dan logika presentasi (formulir, navigator) dideklarasikan. Modul, sebagai aturan, terletak di direktori, dibagi dengan prinsip logis. Suatu produk adalah kumpulan modul yang mengimplementasikan fungsinya dan disimpan dalam repositori terpisah.
Modul saling tergantung. Satu modul tergantung pada yang lain jika menggunakan logikanya (misalnya, merujuk ke properti atau formulir).
Ketika klien baru muncul, repositori terpisah (Git atau Subversion) diluncurkan untuk itu, di mana modul dengan modifikasi yang diperlukan akan dibuat. Repositori ini mendefinisikan apa yang disebut modul teratas. Ketika server mulai, hanya modul-modul yang akan terhubung, yang bergantung langsung atau transitif melalui modul lain. Ini memungkinkan klien untuk menggunakan tidak semua fungsi produk, tetapi hanya bagian yang ia butuhkan.
Jenkins membuat tugas yang menggabungkan modul produk dan klien ke dalam satu file jar, yang kemudian diinstal pada server produksi atau pengujian.
Pertimbangkan beberapa kasus utama peningkatan yang muncul dalam praktik:
Misalkan kita memiliki modul
Pesanan dalam produk, yang menggambarkan logika pesanan standar:
Pelanggan
X ingin menambahkan persentase diskon dan harga diskon untuk garis pesanan.
Pertama, modul
OrderX baru dibuat di repositori pelanggan. Di headernya, dependensi ditempatkan pada modul
Order asli:
Dalam modul ini, kami mendeklarasikan properti baru di mana bidang tambahan akan dibuat dalam tabel, dan menambahkannya ke formulir:
Kami membuat harga diskon tidak tersedia untuk direkam. Ini akan dihitung sebagai peristiwa terpisah ketika harga awal atau persentase diskon berubah:
Sekarang Anda perlu mengubah perhitungan jumlah pada baris pesanan (harus memperhitungkan harga diskon kami yang baru dibuat). Untuk melakukan ini, kami biasanya membuat "titik masuk" tertentu di mana modul lain dapat menyisipkan perilaku mereka. Alih-alih deklarasi awal dari properti penjumlahan dalam modul Pesanan, kami menggunakan yang berikut ini:
Dalam hal ini, nilai properti
penjumlahan akan dikumpulkan dalam satu KASUS, di mana KAPAN dapat tersebar di berbagai modul. Dijamin bahwa jika modul A tergantung pada modul B, maka semua KAPAN modul B akan bekerja lebih lambat dari KAPAN modul A. Untuk menghitung dengan benar
jumlah diskon, deklarasi berikut ditambahkan ke modul
OrderX :
Akibatnya, jika diskon ditetapkan, jumlahnya akan dikenakan padanya, jika tidak, ekspresi asli.
Misalkan klien ingin menambahkan batasan bahwa jumlah pesanan tidak boleh melebihi jumlah tertentu. Dalam modul
OrderX yang sama,
kami mendeklarasikan properti tempat nilai batas akan disimpan, dan menambahkannya ke formulir
opsi standar (Anda dapat membuat formulir terpisah dengan pengaturan jika Anda mau):
Kemudian, dalam modul yang sama, kami mendeklarasikan jumlah pesanan, menunjukkannya pada formulir dan menambahkan batas kelebihannya:
Dan akhirnya, klien diminta untuk sedikit mengubah desain formulir pengeditan pesanan: untuk membuat tajuk pesanan di sebelah kiri garis dengan pemisah, serta untuk selalu menunjukkan harga dengan akurasi dua karakter. Untuk melakukan ini, kode berikut ditambahkan ke modulnya, yang mengubah desain standar yang dihasilkan dari formulir pemesanan:
Sebagai hasilnya, kami mendapatkan dua modul
Order (dalam produk), di mana logika dasar pesanan diimplementasikan, dan
OrderX (di pelanggan), di mana logika diskon yang diperlukan diimplementasikan:
Perlu dicatat bahwa modul
OrderX dapat disebut
OrderDiscount dan ditransfer langsung ke produk. Kemudian, jika perlu, akan memungkinkan bagi setiap pelanggan untuk dengan mudah menghubungkan fungsionalitas dengan diskon.
Ini jauh dari semua kemungkinan yang disediakan platform untuk memperluas fungsionalitas dalam modul individual. Misalnya, menggunakan pewarisan, Anda dapat mengimplementasikan logika
register secara modular.
Jika ada perubahan dalam kode sumber produk yang bertentangan dengan kode dalam modul dependen, kesalahan akan dihasilkan ketika server mulai. Misalnya, jika formulir
pemesanan dihapus dalam modul
Pesanan , maka pada saat mulai akan ada kesalahan bahwa formulir
pemesanan tidak ditemukan dalam modul
OrderX . Juga, kesalahan akan disorot dalam
IDE . Selain itu, IDE memiliki fungsi untuk mencari semua kesalahan dalam proyek, yang memungkinkan Anda untuk mengidentifikasi semua masalah yang terjadi karena memperbarui versi produk.
Dalam praktiknya, kami memiliki semua repositori (dari produk dan semua pelanggan) yang terhubung ke proyek yang sama, jadi kami dengan tenang mereformasi produk, sambil mengubah logika dalam modul pelanggan di mana ia digunakan.
Kesimpulan
Arsitektur mikromodular tersebut memberikan manfaat berikut:
- Setiap pelanggan hanya terhubung fungsi yang dia butuhkan . Struktur basis datanya hanya berisi bidang-bidang yang ia gunakan. Antarmuka solusi akhir tidak mengandung elemen yang tidak perlu. Server dan klien tidak melakukan acara dan pemeriksaan yang tidak perlu.
- Fleksibilitas dalam perubahan fungsionalitas dasar . Langsung di proyek klien, Anda dapat membuat perubahan pada segala bentuk produk, menambahkan acara, objek dan properti baru, tindakan, mengubah desain, dan banyak lagi.
- Pengiriman perbaikan baru yang dibutuhkan oleh pelanggan dipercepat secara signifikan . Dengan setiap permintaan perubahan, Anda tidak perlu memikirkan bagaimana itu akan memengaruhi pelanggan lain. Karena hal ini, banyak perbaikan dapat dilakukan dan dioperasikan sesegera mungkin (seringkali dalam beberapa jam).
- Skema yang lebih nyaman untuk memperluas fungsionalitas produk . Pertama, fungsionalitas apa pun dapat dimasukkan untuk pelanggan tertentu yang siap untuk mencobanya, dan kemudian, jika implementasi yang sukses, modul-modul tersebut sepenuhnya ditransfer ke gudang produk.
- Kemandirian basis kode . Karena banyak perbaikan disediakan di bawah kontrak layanan pelanggan, secara resmi, seluruh kode yang dikembangkan di bawah kontrak ini adalah milik pelanggan. Dengan skema ini, dipastikan pemisahan kode produk yang dimiliki oleh vendor dari kode yang dimiliki oleh klien. Atas permintaan, kami mentransfer repositori ke server klien, tempat ia dapat memodifikasi fungsionalitas yang ia butuhkan dengan pengembangnya sendiri. Selain itu, jika pemasok melisensikan modul produk individual, pelanggan tidak memiliki kode sumber modul yang tidak ada lisensi. Dengan demikian, ia tidak memiliki kemampuan teknis untuk menghubungkan mereka secara independen yang melanggar ketentuan perizinan.
Skema modularitas yang dijelaskan di atas dengan bantuan ekstensi dalam pemrograman paling sering disebut
mix in . Sebagai contoh, Microsoft Dynamics baru-baru ini memperkenalkan konsep ekstensi, yang juga memungkinkan Anda untuk memperluas modul dasar. Namun, banyak pemrograman tingkat rendah diperlukan di sana, yang pada gilirannya membutuhkan kualifikasi pengembang yang lebih tinggi. Selain itu, tidak seperti lsFusion, perluasan acara dan pembatasan membutuhkan "titik masuk" awal ke produk untuk memanfaatkan ini.
Saat ini, sesuai dengan skema yang dijelaskan di atas, kami mendukung dan menerapkan
sistem ERP untuk ritel dengan lebih dari 30 pelanggan yang relatif besar, yang terdiri dari lebih dari 1000 modul. Di antara pelanggan ada jaringan FMCG, serta apotek, toko pakaian, toko rantai drogerie, grosir dan lain-lain. Dalam produk, masing-masing, ada kategori terpisah dari modul yang terhubung tergantung pada industri dan proses bisnis yang digunakan.