Menciptakan sistem baru adalah proses multi-tahap: elaborasi konsep dan desain, desain arsitektur, implementasi, pengujian, rilis. Desain dan implementasi arsitektur adalah tahapan yang menjadi perhatian utama pengembang.
Kebanyakan pengembang suka terlibat dalam arsitektur, memikirkan bagaimana sistem atau bagiannya akan diatur dari awal. Jika seseorang yang telah memikirkan arsitektur sistem dan akan mengimplementasikannya, tidak ada masalah dengan motivasi: programmer akan menerima kepuasan dari realisasi ide-idenya. Tetapi jika satu pemikiran arsitektur, dan yang lain akan terlibat dalam implementasi, maka yang terakhir mungkin memiliki kemarahan alami: mereka memikirkan segalanya untuk saya, tetapi bisakah saya melakukan apa yang tertulis?

Bagaimana menghindari situasi seperti itu, mengapa implementasi bisa tidak kalah menarik daripada penjabaran arsitektur, dan kadang-kadang lebih, akan dibahas dalam artikel ini.
Pendahuluan
Arsitektur yang dipikirkan dengan matang dapat digunakan sebagai dasar untuk tugas pemecahan : implementasi setiap komponen yang cukup terpisah menjadi subtugas yang terpisah.
Misalnya, jika ada saluran pipa untuk permintaan pemrosesan, yang disusun secara arsitektur dalam gaya pipa & filter , maka subtugas akan menjadi implementasi dari setiap langkah pemrosesan (setiap langkah memiliki subtugas sendiri) dan subtugas lain untuk menghubungkan semua langkah bersama.
Meskipun arsitektur yang dipikirkan dengan matang dan pengelompokan menjadi subtugas memberikan gambaran umum tentang cara membuat sistem dan memungkinkan Anda untuk mengevaluasi biaya tenaga kerja, mereka tidak cukup untuk mengimplementasikan rencana tersebut. Deskripsi subtugas akan mengatakan apa yang harus dilakukan komponen, mungkin berisi persyaratan untuk kecepatan dan konsumsi memori, tetapi tidak akan memberikan instruksi komprehensif tentang cara melakukannya.
Faktanya adalah bahwa ada banyak opsi untuk membuat komponen yang memenuhi persyaratan yang ditentukan. Banyak tergantung pada bagaimana itu akan diterapkan: fleksibilitas kode, ekstensibilitasnya, kemudahan dukungan, dll. Kami mendekati konsep desain kode .
Konsep Desain Kode
Terkadang desain kode disebut arsitektur atau organisasi kode, terkadang bahkan hanya arsitektur. Saya tetap berpegang pada desain kode istilah karena kontras dengan arsitektur sistem dan menarik garis yang jelas di antara mereka. Untuk lebih spesifik, pertimbangkan sebuah contoh.
Katakanlah kita sedang mengembangkan backend situs yang mendapatkan popularitas. Jumlah server telah melampaui beberapa puluh, pemirsa bertambah, dan kami memutuskan bahwa kami ingin mengumpulkan analitik tentang perilaku pengguna di situs: popularitas halaman mengunjungi, frekuensi penggunaan fitur tergantung pada profil pengguna, dll.
Sejumlah masalah arsitektur dan teknologi muncul: di mana menyimpan metrik, cara mentransfernya melalui jaringan, apa yang harus dilakukan jika toko metrik tidak tersedia, bagaimana layanan backend akan mencatat metrik, dll. Arsitektur hanya perlu menjawab pertanyaan-pertanyaan ini, menentukan komponen solusi dan menetapkan persyaratan untuknya.
Misalkan kita telah mengembangkan arsitektur: kita akan menggunakan InfluxDB sebagai penyimpanan, transfer metrik melalui jaringan menggunakan UDP ke telegraf , dan untuk menghindari ketidaktersediaan penyimpanan, kita akan menyimpan metrik dalam Kafka yang direplikasi di beberapa server. Semua metrik akan menjalankan layanan backend -> telegraf -> Kafka -> InfluxDB. Untuk menulis metrik, backend memutuskan untuk menulis modul yang mengimplementasikan fungsi transfer metrik di telegraf menggunakan UDP.
Modul untuk merekam metrik adalah komponen terpisah dari sistem, penulisan adalah sub-tugas terpisah yang dapat dipercayakan kepada pengembang. Subtugas ini memiliki banyak solusi dan pertanyaan yang perlu dijawab: metrik akan dikirim secara sinkron atau tidak sinkron; bagaimana akses simultan beberapa thread backend akan disinkronkan, apa yang akan menjadi kelas / fungsi utama.
Pertanyaan-pertanyaan ini berada di luar deskripsi arsitektur solusi, tetapi jawaban mereka memiliki konsekuensi yang luas. Sebagai contoh, jika selama operasi solusi menjadi jelas bahwa tumpukan teknologi tidak optimal dan Anda perlu mengganti telegraf dengan solusi alternatif, maka pembagian modul yang salah ke dalam kelas tidak akan memungkinkan hal ini tanpa menulis ulang seluruh modul. Jawaban atas pertanyaan-pertanyaan ini adalah domain dari desain kode .
Pengembangan desain kode adalah tahap desain terpisah , yang terletak antara pengembangan arsitektur sistem dan pengkodean. Menggambar garis antara arsitektur dan desain kode memungkinkan Anda untuk merancang sistem tanpa mempertimbangkan semua detail dan mengevaluasi biaya tenaga kerja dalam waktu yang terbatas. Di sisi lain, menyoroti pengembangan desain kode sebagai tahap implementasi terpisah memungkinkan Anda untuk meningkatkan kualitas implementasi sistem, mengurangi biaya perbaikan lebih lanjut, dan meningkatkan kemudahan dukungan.
Kebutuhan untuk memikirkan desain kode pada tahap implementasi sebelum pengkodean membuat implementasi menarik : tugas-tugas merancang desain kode bisa tidak kalah menarik daripada merancang seluruh sistem di tingkat arsitektur. Gagasan ini diungkapkan oleh Brooks di bulan mitos manusia .
Tentu saja, menggambar garis antara arsitektur dan desain kode mungkin tidak mudah, mari kita melihat lebih dekat masalah ini.
Batas antara arsitektur dan desain kode
Secara ideologis, desain arsitektur dan kode berada pada level desain yang berbeda: arsitektur dipikirkan pada tahap paling awal, ketika ada sedikit kepastian, dan memikirkan desain kode menambah detail. Dengan demikian, mereka dieksekusi pada titik yang berbeda dalam waktu: arsitektur lebih dekat ke awal, dan desain kode selama implementasi subtugas.
Menggambar batas antara dua tahap desain ini tergantung pada sejumlah faktor, berikut adalah yang utama:
- Sejauh mana komponen mempengaruhi sistem. Kadang-kadang perangkat seluruh sistem dapat secara signifikan bergantung pada perangkat komponen individualnya. Dalam hal ini, Anda perlu mendesain komponen pada tahap pengembangan arsitektur, dan bukan pada tahap implementasi.
- Kehadiran antarmuka yang jelas untuk komponen. Dimungkinkan untuk mengisolasi desain komponen sebagai subtugas hanya jika ia dengan jelas mendefinisikan apa yang harus dilakukan komponen ini dan bagaimana ia akan berinteraksi dengan bagian lain dari sistem.
- Perkiraan realistis dari upaya untuk melengkapi subtugas. Tugas itu mungkin terlalu besar untuk dapat mengevaluasi biaya tenaga kerja dengan akurasi yang memadai. Dalam hal ini, lebih baik untuk merancang tugas secara lebih rinci dan memecahnya menjadi subtugas sendiri untuk memberikan penilaian biaya tenaga kerja yang lebih memadai.
Ada beberapa kasus khusus di mana Anda dapat menarik garis yang baik antara desain arsitektur dan desain kode.
Komponen memiliki API yang ketat.
Sebagai contoh, dalam praktik saya ada tugas: untuk mengimplementasikan di atas UNIX socket API untuk menangkap / melepaskan sumber daya OS yang digunakan oleh daemon yang ada. Tugas ini muncul dalam kerangka arsitektur yang dipilih untuk fitur epik baru. Dalam kerangka arsitektur, itu agak tingkat tinggi untuk menggambarkan API, dan desain rinci dilakukan kemudian, selama implementasi.
Modul / kelas dengan antarmuka yang diberikan
Cara termudah untuk mendelegasikan desain bagian dari sistem monolitik adalah dengan menyoroti modul atau kelas, mendeskripsikan antarmuka dan tugasnya. Modul yang dialokasikan sebagai subtugas yang terpisah tidak boleh terlalu besar. Sebagai contoh, perpustakaan klien untuk akses ke database shard tidak diragukan lagi merupakan modul yang terpisah, tetapi tugas mengimplementasikan perpustakaan ini akan sulit untuk dievaluasi dengan biaya tenaga kerja tanpa desain yang lebih rinci. Di sisi lain, tugas menerapkan kelas yang terlalu kecil akan sepele. Misalnya, jika subtugas “untuk mengimplementasikan fungsi yang memeriksa keberadaan folder yang diberikan oleh jalur yang diberikan” muncul, maka arsitekturnya dipikirkan dengan sangat rinci.
Komponen kecil dengan persyaratan tetap
Jika komponen cukup kecil dan masalah yang diselesaikannya ditentukan secara ketat, maka biaya tenaga kerja untuk implementasi dapat diperkirakan dengan akurasi yang cukup, dan implementasi komponen itu sendiri akan meninggalkan ruang untuk desain. Contoh: proses yang berjalan pada mahkota dan menghapus file dan direktori lama secara rekursif di jalur yang diberikan.
Antipatterns
Ada beberapa skenario ketika distribusi antara pemikiran arsitektur dan implementasi tidak benar, beberapa di antaranya dibahas di bawah ini.
Semuanya dirancang dengan detail terkecil.
Diagram UML terperinci dibangun, tanda tangan dari masing-masing metode dari setiap kelas ditentukan, algoritma untuk menerapkan metode individual dijelaskan ... Menurut deskripsi terperinci seperti itu, Anda dapat mengimplementasikan sistem dengan paling cepat, sungguh, karena semuanya direncanakan dengan detail sedemikian rupa sehingga tidak ada ruang untuk kreativitas sama sekali, ambil dan lakukan tertulis Jika tujuannya adalah agar pengembang membuat kode apa yang mereka katakan kepadanya secepat mungkin, maka ya, Anda bisa.
Namun, jika Anda menggali sedikit lebih dalam, itu akan menjadi jelas sejumlah kekurangan dalam organisasi kerja dalam nada ini. Pertama, untuk mendesain segala sesuatu dalam detail seperti itu, Anda harus menghabiskan banyak waktu pada desain itu sendiri. Apa yang biasanya dipikirkan pengembang sebelum implementasi, arsitek akan pikirkan dalam skema ini: semua desain bergeser lebih dekat ke awal proyek, yang dapat meningkatkan durasinya. Lagi pula, jika Anda tidak memecah pekerjaan desain menjadi bagian-bagian, maka Anda tidak akan dapat memparalelkannya. Kedua, kurangnya pekerjaan desain selama implementasi akan sangat mengurangi motivasi pengembang: melakukan apa yang mereka katakan dapat bermanfaat bagi pemula, tetapi pengembang yang berpengalaman akan bosan. Ketiga, pendekatan ini umumnya dapat mengurangi kualitas output: sistem, yang tidak dibagi menjadi komponen yang cukup independen, akan lebih sulit untuk dipertahankan dan dikembangkan.
Arsitektur selalu dirancang oleh satu pengembang, sisanya samping merokok hanya sadar
Pertama-tama, beberapa kasus harus dicatat ketika ini dapat bermanfaat. Pertama, ini adalah tim di mana ada banyak pemula dan hanya satu programmer yang berpengalaman. Dalam hal ini, pemula tidak memiliki pengalaman yang cukup untuk mendesain arsitektur untuk melakukan pekerjaan dengan kualitas yang memadai, sementara pada saat yang sama, implementasi arsitektur yang dipikirkan dengan matang akan membantu mereka untuk meningkatkan level mereka. Kedua, ini adalah proyek besar yang melibatkan beberapa tim. Kemudian desain arsitektur proyek dibagi menjadi dua tingkatan: arsitek memikirkannya secara keseluruhan, dan masing-masing tim - arsitektur komponen dalam area tanggung jawabnya.
Tetapi pertimbangkan satu tim yang terdiri dari spesialis yang cukup berpengalaman. Jika tugas arsitektural akan selalu ditugaskan hanya untuk satu, katakanlah, pengembang yang paling berpengalaman, maka pengembang lain tidak akan dapat sepenuhnya mengungkapkan kemampuan mereka. Arsitektur sistem akan satu sisi, karena setiap orang memiliki serangkaian teknik yang ia terapkan. Jika pengembang yang berbeda memikirkan arsitektur komponen / subsistem yang berbeda, ini akan memfasilitasi pertukaran pengalaman dan pengembangan anggota tim. Bahkan anggota tim yang tidak terlalu berpengalaman kadang-kadang harus diberikan tugas arsitektur: ini akan meningkatkan level mereka dan meningkatkan keterlibatan mereka dalam proyek.
Kesimpulan
Kehadiran tahap desain dalam implementasi adalah faktor utama yang membuat tugas implementasi menarik. Tentu saja, ada yang lain: penggunaan teknologi baru, tugas penelitian, tetapi mereka, sebagai aturan, jauh lebih jarang terjadi. Jika tugas implementasi tidak memerlukan desain dan akan terdiri dari pengkodean sederhana, maka ini akan sangat memengaruhi motivasi pengembang dan tidak akan mengizinkan penggunaan keterampilan mereka.
Merancang desain kode pada tahap implementasi memungkinkan Anda untuk dengan cepat membuat estimasi yang memadai tentang biaya tenaga kerja, lebih memaralelkan pekerjaan, dan secara umum meningkatkan kualitas sistem.
Kebutuhan untuk merancang desain kode selama implementasi adalah apa yang membuat implementasi bekerja menarik di mata pengembang.
Tidak ada salahnya melakukan kesalahan, tidak termasuk pekerjaan desain dari penerapan subtugas, sama seperti Anda tidak harus selalu mempercayakan tugas arsitektur hanya kepada pengembang yang paling berpengalaman.