
Halo semuanya!
Perusahaan kami membuat layanan untuk menyimpan dan memproses data dari perangkat industri (pompa, bor dan peralatan industri lainnya). Kami menyimpan data pelanggan kami dan menyediakan fungsionalitas untuk analisis mereka: membuat laporan, grafik, dan banyak lagi lainnya.
Dan dalam perjalanannya, kami memperhatikan bahwa integrasi setiap klien baru sangat tertunda, dan jumlah berbagai kesalahan terus meningkat. Kemudian menjadi jelas bahwa sudah waktunya untuk berurusan dengan ini. Seperti yang ditunjukkan oleh analisis situasi, departemen TI masing-masing klien kami mengembangkan solusi mereka sendiri untuk mengumpulkan data secara lokal dari perangkat dan mengirimkannya ke layanan kami. Ini memperumit fakta bahwa, dengan mempertimbangkan kekhasan industri, tidak selalu ada akses ke Internet dan perlu untuk menyimpan data secara lokal dan mengirimkannya sesegera mungkin. Dan ada sejumlah besar nuansa seperti itu, yang mengarah pada peningkatan jumlah kesalahan.
Dan kemudian kami menyadari bahwa solusi terbaik dalam situasi ini adalah mengembangkan SDK dan memberikannya kepada klien. Segera saya mulai mencari praktik terbaik dan pertimbangan tentang pengembangan SDK dan sangat terkejut - praktis tidak ada apa-apa di RuNet, tetapi hanya ada sedikit informasi tentang Internet Basurmani dan tersebar. Nah, tugasnya jelas, dipikirkan dan diimplementasikan.
Tetapi kurangnya informasi tentang topik ini yang menciptakan keinginan untuk memberi tahu masyarakat tentang pemikiran, keputusan yang dibuat, dan kesimpulan tentang pengembangan SDK. Artikel ini membahas solusi untuk .NET, tetapi ini adalah konsep, sehingga akan menarik bagi banyak orang. Detail di bawah potongan!
Sudah saatnya ditentukan
Mari kita mulai dengan mendefinisikan apa itu SDK dan mengapa itu mungkin diperlukan.
SDK (dari perangkat pengembangan perangkat lunak bahasa Inggris) adalah seperangkat alat pengembangan yang memungkinkan spesialis perangkat lunak untuk membuat aplikasi untuk paket perangkat lunak tertentu, perangkat lunak pengembangan dasar, platform perangkat keras, sistem komputer, konsol game, sistem operasi dan platform lainnya. SDK memanfaatkan setiap platform dan mengurangi waktu integrasi.
...
Seorang insinyur perangkat lunak biasanya menerima SDK dari pengembang sistem target.
Ya, itu masuk akal. Dengan kata sederhana, SDK adalah paket perpustakaan, sehingga klien dapat dengan mudah dan cepat mulai bekerja dengan sistem Anda (dalam artikel ini kami akan berbicara tentang layanan kami, tetapi semua yang dijelaskan dalam artikel ini berlaku untuk jenis SDK lainnya) atau melakukan tindakan yang sama.
Namun, seperti pendekatan apa pun, SDK Path memiliki kelebihan dan kekurangan.
Manfaatnya
Integrasi kecepatan tinggi dari klien baru - pelanggan Anda perlu menulis lebih sedikit kode.
Penggunaan kembali kode - kode yang sama digunakan di beberapa tempat sekaligus. Kita dapat mengatakan bahwa ini adalah duplikasi dari paragraf sebelumnya, tetapi kita berbicara tentang fakta bahwa logika kerja ada di mana-mana sepi, yang menyiratkan
Prediktabilitas perilaku - menggunakan perpustakaan yang sama membawa perilaku sistem ke standar tertentu, yang sangat memudahkan pencarian dan penghapusan kesalahan dan kerentanan.
Kualitas kode adalah tempat di mana banyak orang ingin menghemat dalam pengujian (maaf atas anggaran, tenggat waktu, dan alasan lainnya). Jelas bahwa di dunia nyata untuk menguji semua bagian proyek dengan tes adalah tugas yang sangat melelahkan. Tetapi secara kualitatif menguji semua modul SDK, dan kemudian menggunakannya adalah cara untuk meningkatkan persentase cakupan pengujian, yang akan mengarah pada pengurangan jumlah kesalahan.
Dokumentasi adalah skenario yang sama dengan tes. Mendokumentasikan seluruh proyek cukup bermasalah. Menggunakan kembali SDK meningkatkan persentase cakupan dokumentasi, yang menurunkan ambang batas bagi karyawan baru untuk memasuki proyek dan umumnya membantu dalam kehidupan.
Semua keuntungan, pada kenyataannya, adalah konsekuensi dari hal yang paling penting - kami menulis kode dengan kualitas yang sangat tinggi sekali, dan kemudian menggunakannya kembali .
Kekurangan
Persyaratan kualitas tinggi dari kode SDK adalah hasil dari keunggulan utama. Kesalahan dalam SDK akan menghasilkan kesalahan di semua sistem yang menggunakannya.
Setting Constraints - SDK adalah sekumpulan perpustakaan untuk mengimplementasikan skrip standar . Terkadang pengembang SDK percaya bahwa selain mengimplementasikan salah satu skenario yang disediakan, klien tidak memerlukan apa-apa, bahwa klien lebih mudah melakukan semuanya dari awal sendiri daripada membangun alas dari kruk untuk SDK.
Ketergantungan dan pembaruan - saat memperluas fungsionalitas (misalnya, menyesuaikan solusi untuk klien tertentu), Anda akan merilis versi baru perpustakaan. Tetapi ada dependensi, kumpulan versi pustaka yang berbeda untuk klien yang berbeda, dan Anda perlu memonitor kompatibilitas mundur atau versi ketat.
Kapan SDK benar-benar dibutuhkan
Anda memiliki beberapa skenario standar yang diterapkan lagi dari waktu ke waktu - pada kenyataannya, kasus kami.
Pengembangan internal - dalam berbagai proyek Anda menggunakan sistem logging, konfigurasi sistem, bekerja dengan HttpRequest, database, file? Membangun SDK internal - satu set perpustakaan untuk penggunaan internal. Anda dapat memperluas fungsionalitas SDK kapan saja, tetapi kecepatan pengembangan proyek baru, persentase cakupan dengan tes dan dokumentasi akan meningkat, dan ambang batas bagi pengembang baru untuk masuk akan berkurang.
Ketika SDK cenderung menjadi berlebihan
Skenario penggunaan tidak didefinisikan atau terus berubah - biarkan penerapan solusi khusus untuk pelanggan dan bantu mereka. Tidak perlu membuat keajaiban wunderwaffle, yang hanya akan mengganggu. Sangat relevan untuk perusahaan dan startup muda.
Anda tidak tahu bagaimana melakukannya secara kualitatif - saya punya berita buruk untuk Anda: sekarang saatnya untuk belajar. Tetapi memberikan keputusan yang bengkok kepada klien sangat, sangat salah. Bagaimanapun, pelanggan harus dihormati.
Jadi, kami memutuskan apa SDK itu, dengan kelebihan dan kekurangannya, dan kapan kami membutuhkannya. Jika setelah itu Anda menyadari bahwa SDK benar-benar diperlukan - saya mengundang Anda untuk memulai "jalur SDK" dan mencari tahu apa yang seharusnya dan bagaimana melakukannya?
"Apakah kamu menyukai Lego?" - Modularitas
Bayangkan semua skenario yang mungkin untuk menggunakan SDK (Anda sudah memutuskan mengapa Anda membutuhkannya, kan?) Dan buat skrip untuk perpustakaan. Apa yang bukan pilihan? Tapi ini pendekatan yang buruk, jadi kami tidak akan melakukannya. Dan kita akan menjadi seperti ini:
- pisahkan semua skrip menjadi beberapa langkah
- mengidentifikasi langkah-langkah umum
- buat daftar modul yang menerapkan semua langkah yang mungkin (satu modul bertanggung jawab untuk mengimplementasikan sesuatu yang spesifik, misalnya, bekerja dengan konfigurasi)
Sebagai contoh, dengan mempertimbangkan spesifikasi tugas, kita membutuhkan semua logika yang akan ditetapkan dari konfigurasi. Kami mengimplementasikan modul untuk bekerja dengan konfigurasi (baca, tulis, perbarui, konfirmasikan, dan konfigurasi proses) dan kami akan menggunakannya dalam semua modul lainnya.
Dan untuk implementasi skenario standar, kami benar-benar akan membuat modul - modul "kontrol", yang masing-masing mengimplementasikan satu skenario spesifik, menggunakan modul lain dari SDK yang sama. Jadi, untuk implementasi skenario standar, klien hanya perlu menghubungkan modul kontrol skrip (dan dia akan menarik semua dependensi), dan untuk implementasi yang tidak standar, kami menggunakan modul dasar, juga menggunakan kembali kode.
Inilah tepatnya alasan mengapa SDK tidak boleh menjadi satu perpustakaan (walaupun saya benar-benar ingin, saya mengerti. Lagi pula, ketika seluruh SDK berada dalam satu perpustakaan, Anda bisa melupakan dependensi dan segala sesuatu yang terhubung dengan mereka), tetapi menjadi satu set perpustakaan. Keuntungan tambahan dari pendekatan ini adalah pengurangan "berat" program klien - ini akan menarik SDK kelas berat, dan hanya akan menarik modul yang diperlukan.
Tetapi Anda seharusnya tidak menghasilkan modul, karena semakin banyak modul, semakin sakit kepala dari ketergantungan mereka! Yaitu Penting untuk membagi logika menjadi modul dengan benar, menjaga keseimbangan antara keputusan "semua dalam satu" dan "setiap modul memiliki modul sendiri."
"Jadi itu mungkin?!" - fleksibilitas
Menyediakan klien dengan berbagai antarmuka untuk bekerja dengan perpustakaan Anda. Saya akan memberi contoh:
public void LoadConfiguration(string filename); public async Task LoadConfigurationAsync(string filename);
Jika Anda hanya menyediakan versi sinkron, maka ketika menerapkan aplikasi asinkron, klien akan dipaksa untuk melakukan pembungkus asinkron dari metode sinkron Anda. Jika Anda hanya menyediakan versi asinkron, situasinya mirip. Berikan kedua hal ini kepada klien dan dia akan berterima kasih.
Generik akan menjadi nilai tambah yang bagus. Sebagai contoh, kami memiliki kelas untuk bekerja dengan konfigurasi yang mengimplementasikan metode untuk mengemas konfigurasi ke dalam sebuah string, memuat konfigurasi dari file, dll. Konfigurasi modul tertentu akan diwarisi dari kelas dasar kami, tetapi untuk bekerja dengan kelas baru kami juga perlu menyediakan metode unpacking.
class BaseConfiguration{ public BaseConfiguration FromString(string source){...} public BaseConfiguration FromString(string source,Type configurationType){...} public T FromString<T>(string source) where T:BaseConfiguration } class CustomConfiguration : BaseConfiguration{}
Dengan demikian, kami telah menyediakan klien dengan tiga implementasi yang dapat ia gunakan. Generik sangat nyaman, tetapi ketika bekerja dengan tipe dinamis, mereka dapat dipanggil hanya melalui refleksi, yang tidak menguntungkan. Prinsip umum universalitas, saya harap, jelas.
"Parent 1, Parent 2, Children []" - Penamaan
Apa bagian tersulit dalam seorang programmer? Ciptakan nama untuk variabel.
Namun demikian ... Penamaan modul, kelas, properti, dan metode yang tepat akan sangat membantu mereka yang akan bekerja dengan SDK Anda. Contoh tidak memerlukan komentar:
Contoh Kinect 2.0 SDK
var skeletons = new Skeleton[0]; using (var skeletonFrame = e.OpenSkeletonFrame()) { if (skeletonFrame != null) { skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo(skeletons); } } if (skeletons.Length == 0) { return; } var skel = skeletons.FirstOrDefault(x => x.TrackingState == SkeletonTrackingState.Tracked); if (skel == null) { return; } var rightHand = skel.Joints[JointType.WristRight]; XValueRight.Text = rightHand.Position.X.ToString(CultureInfo.InvariantCulture); YValueRight.Text = rightHand.Position.Y.ToString(CultureInfo.InvariantCulture); ZValueRight.Text = rightHand.Position.Z.ToString(CultureInfo.InvariantCulture);
Semuanya jelas dari nama-nama kelas dan metode. Dan jika ada penyelesaian kode dalam IDE Anda, maka sering kali mungkin untuk tidak melihat dokumentasi jika semuanya sudah jelas.
"Saya yakin bahwa jika Kematian tahu apa itu birokrasi, orang tidak akan pernah mati, selamanya mengantre ..." - Dokumentasi
Tetapi meskipun semua modul, kelas, metode, dan properti diberi nama dengan sangat indah dan mendesak, Anda masih perlu menulis dokumentasi. Pertama, itu akan sangat menyelamatkan Anda (jumlah pertanyaan pelanggan dikurangi dengan urutan besarnya. Semuanya ada dalam dokumentasi), dan kedua, selalu jelas mengapa Anda melakukan ini dan bukan sebaliknya.
Dokumentasi dalam SDK biasanya sederhana dan ringkas. Biasanya dibagi menjadi dua bagian: Tutorial - kursus selangkah demi selangkah dalam gaya "Membangun kota dalam 10 menit" dan bagian Referensi - referensi untuk segala sesuatu yang dapat dilakukan menggunakan SDK ini.
Kami memilih cara termudah - ringkasan + artikel. Kami menambahkan atribut Xml untuk metode dan kelas yang bercahaya di intellisense sebagai tooltips. Dengan menggunakan Docfx, kami membuat dokumentasi tentang atribut-atribut ini dan mendapatkan dokumentasi yang terperinci dan nyaman, yang dilengkapi dengan artikel yang menggambarkan kasus penggunaan dan contoh.
"- Agar tetap bersih! - Bagaimana saya membersihkannya dengan garpu?" - Menguji
Apa yang bisa dikatakan tentang pengujian sebagai bagian dari diskusi SDK ... Harus ada! Solusi terbaik adalah TDD (terlepas dari kenyataan bahwa saya memiliki sikap negatif terhadap pendekatan ini, dalam hal ini saya memutuskan untuk menggunakannya). Ya, waktu yang lama. Ya, membosankan. Tetapi di masa depan Anda tidak akan menggantung diri dari kejatuhan konstan SDK di samping dan konsekuensi dari kejatuhan ini.
Inti dari situasi ini adalah bahwa dengan memberikan SDK kepada klien Anda kehilangan kendali: Anda tidak dapat dengan cepat memperbaiki kesalahan, sulit untuk menemukan kesalahan ini, dan Anda akan terlihat cukup bodoh dalam situasi seperti itu. Oleh karena itu - uji. Tes lebih baik. Dan sekali lagi. Dan untuk berjaga-jaga, uji tes Anda. Dan tes tes. Jadi, sesuatu yang saya terbawa, tetapi pentingnya menguji SDK, saya harap, jelas.
"Seorang korban yang tidak bisa menolak masa lalunya dikonsumsi olehnya" - Logi
Karena Anda memberikan SDK ke perusahaan pihak ketiga, akibatnya Anda kehilangan kendali atas situasi tersebut, jika terjadi kesalahan (pada tahap pengujian Anda semua memutuskan "itu akan berhasil," bukan?), Sebuah proses yang agak lama dan menyakitkan menunggu Anda untuk mencari kesalahan ini. Di sinilah log membantu Anda.
Log semuanya , benar-benar segalanya, dan jika terjadi kesalahan, mintalah log kepada klien Anda. Dengan cara ini Anda akan menghemat banyak waktu dan tidak dapat menggosok wajah Anda di depan klien.
"Alarm! Achtung! Perhatian!" - Kesalahan

Sambil memikirkan banyak hal tentang kesalahan, saya sampai pada kesimpulan yang menarik - bukan metode tunggal di SDK Anda yang harus memberikan kesalahan yang tidak dijelaskan dalam dokumentasi . Anda harus mengakui bahwa itu sangat tidak menyenangkan ketika Anda menghubungkan perpustakaan pihak ketiga untuk bekerja dengan HttpRequest, dan ia melempar beberapa NullPointerException dan StackTrace pada Anda, yang akan membawa Anda ke dalam perut perpustakaan. Dan Anda harus terjun ke "perut" ini, mencoba memahami seberapa dalam lubang kelinci itu, dan apa, sebenarnya, masalahnya.
Oleh karena itu, saya mengusulkan solusi berikut - mendeklarasikan daftar tertutup dari kemungkinan pengecualian dan mendokumentasikannya. Tetapi, karena Anda tidak dapat memastikan bahwa Anda telah menyediakan segalanya, bungkus metode dalam try-catch, dan kesalahan yang tertangkap dalam yang dinyatakan. Misalnya, ConfigurationException yang akan berisi InnerException adalah kesalahan yang diketahui. Ini akan memungkinkan pengembang pihak ketiga untuk menangkap semua kesalahan yang mungkin terjadi, tetapi jika sesuatu terjadi, cepat cari tahu apa masalahnya.
Versi atau "bagaimana tidak menggigit ekormu"
Untuk menghindari masalah di masa depan, saya sangat merekomendasikan menggunakan versi ketat. Pilih sistem versi yang cocok untuk Anda dan gunakan. Tetapi jika versi baru perpustakaan tidak memiliki kompatibilitas ke belakang, ini harus ditunjukkan. Bagaimana mengatasinya - menurut Anda. Tetapi Anda pasti harus memikirkannya.
"A Train That Could" - Menyebarkan
Kebutuhan akan relevansi dokumentasi dan versi menimbulkan persyaratan untuk kebenaran penyebaran. Dalam keputusan kami, kami menggunakan solusi berikut (kruk, tetapi mereka bekerja).
Ketika perlu untuk merilis rilis baru, pengembang menarik bat'nik dengan nomor rilis, dan kemudian file batch:
- membangun rilis
- menempatkan semua perpustakaan di arsip
- membangun versi terbaru dari dokumentasi (docfx)
- menunjukkan versi rilis dalam dokumentasi dan atas nama arsip
- menempatkan semua yang terbaru di repositori git
- WebApp di MS Azure menarik komit git segar dan menerbitkan perubahan
Pada output kami mendapatkan versi terbaru dari situs dengan dokumentasi, dari mana Anda dapat mengunduh arsip dengan versi terbaru dari SDK.
Rencana ke depan termasuk mengemas semuanya ke dalam paket Nuget dan menerbitkannya ke repositori Nuget lokal.
Saya sarankan memperhatikan hal ini, karena Anda dapat secara signifikan mengurangi jumlah sakit kepala yang disebabkan oleh kurangnya informasi yang relevan tentang versi baru perpustakaan.
Poin penting dalam dokumentasi adalah contoh penggunaan. Namun selain itu, sering kali diminta untuk tidak menyediakan perpustakaan, tetapi aplikasi yang mengimplementasikan skenario paling standar. Saya sarankan membuat aplikasi ini dengan kode sumber yang terbuka dan berkomentar dengan baik, yang akan memungkinkan Anda untuk membunuh dua burung dengan satu batu - menyediakan aplikasi yang berfungsi dan memberikan contoh menggunakan SDK.
Kesimpulan
Pengembangan SDK telah menjadi tugas baru yang menarik bagi saya, yang telah mengangkat banyak masalah arsitektur penting. Banyak hal yang dijelaskan dalam artikel adalah hal-hal yang jelas (bagi saya), tetapi saya menganggap penting untuk mengumumkan bahkan hal-hal yang jelas untuk mendapatkan gambaran besar yang jelas.
PS
Terima kasih telah membaca, saya akan senang atas komentar Anda. Saya harap artikel ini bermanfaat bagi Anda.