Cara lain untuk menanyakan hal ini adalah; mengapa program cenderung monolitik?
Saya sedang memikirkan sesuatu seperti paket animasi seperti Maya, yang digunakan orang untuk berbagai alur kerja yang berbeda.
Jika kemampuan animasi dan pemodelan dibagi menjadi aplikasi mereka sendiri dan dikembangkan secara terpisah, dengan file-file dilewatkan di antara mereka, bukankah mereka akan lebih mudah untuk dipelihara?
If the animation and modelling capabilities were split into their own separate application and developed separately, with files being passed between them, would they not be easier to maintain?
Jangan mencampur lebih mudah untuk memperpanjang dengan lebih mudah untuk mempertahankan modul -per se tidak bebas dari komplikasi atau desain yang meragukan. Maya bisa menjadi neraka di bumi untuk dipertahankan sementara pluginnya tidak. Atau sebaliknya.Jawaban:
Iya. Secara umum dua aplikasi yang lebih kecil dan lebih kompleks lebih mudah dirawat daripada yang besar.
Namun, Anda mendapatkan bug jenis baru saat semua aplikasi bekerja bersama untuk mencapai tujuan. Untuk membuat mereka bekerja bersama, mereka harus bertukar pesan dan orkestrasi ini bisa salah dengan berbagai cara, meskipun setiap aplikasi mungkin berfungsi dengan sempurna. Memiliki sejuta aplikasi kecil memiliki masalah tersendiri.
Aplikasi monolitik benar-benar pilihan default yang Anda dapatkan ketika Anda menambahkan lebih banyak fitur ke satu aplikasi. Ini adalah pendekatan termudah ketika Anda mempertimbangkan masing-masing fitur sendiri. Hanya setelah tumbuh besar Anda dapat melihat keseluruhan dan berkata "Anda tahu apa, ini akan bekerja lebih baik jika kita memisahkan X dan Y".
sumber
Kenyataannya jarang yang sesederhana itu.
Berpisah tentu saja tidak membantu mencegah bug itu terjadi. Terkadang membantu menemukan bug lebih cepat. Aplikasi yang terdiri dari komponen kecil yang terisolasi dapat memungkinkan lebih banyak individu (semacam "unit" -) pengujian untuk komponen-komponen itu, yang kadang-kadang membuatnya lebih mudah untuk menemukan akar penyebab bug tertentu, dan memungkinkannya untuk memperbaikinya lebih cepat.
Namun,
bahkan aplikasi yang tampaknya monolitik dari luar dapat terdiri dari banyak komponen yang dapat diuji unit di dalamnya, sehingga pengujian unit tidak selalu lebih sulit untuk aplikasi monolitik
seperti yang sudah disebutkan Ewan, interaksi beberapa komponen menimbulkan risiko dan bug tambahan. Dan debugging sistem aplikasi dengan komunikasi antar proses yang kompleks bisa jauh lebih sulit daripada men-debug aplikasi satu proses
Ini juga sangat tergantung pada seberapa baik aplikasi yang lebih besar dapat dipecah menjadi beberapa komponen, dan seberapa luas antarmuka antar komponen, dan bagaimana antarmuka tersebut digunakan.
Singkatnya, ini sering merupakan trade-off, dan tidak ada di mana jawaban "ya" atau "tidak" benar secara umum.
Apakah mereka? Lihatlah di sekeliling Anda, ada gazillions aplikasi Web di dunia yang tidak terlihat sangat monolitik bagi saya, justru sebaliknya. Ada juga banyak program yang tersedia yang menyediakan model plugin (AFAIK bahkan perangkat lunak Maya yang Anda sebutkan).
"Pemeliharaan yang lebih mudah" di sini sering berasal dari kenyataan bahwa bagian-bagian berbeda dari suatu aplikasi dapat dikembangkan lebih mudah oleh tim yang berbeda, sehingga beban kerja yang didistribusikan lebih baik, tim khusus dengan fokus yang lebih jelas, dan seterusnya.
sumber
Saya harus tidak setuju dengan mayoritas yang satu ini. Memisahkan aplikasi menjadi dua yang terpisah tidak dengan sendirinya membuat kode lebih mudah dipelihara atau dipikirkan.
Memisahkan kode menjadi dua executable hanya mengubah struktur fisik kode, tetapi bukan itu yang penting. Apa yang menentukan seberapa kompleks suatu aplikasi, adalah seberapa erat bagian-bagian berbeda yang membuatnya. Ini bukan properti fisik, tetapi yang logis .
Anda dapat memiliki aplikasi monolitik yang memiliki pemisahan yang jelas dari berbagai keprihatinan dan antarmuka yang sederhana. Anda dapat memiliki arsitektur layanan microser yang bergantung pada detail implementasi dari layanan microser lainnya dan secara erat digabungkan dengan yang lainnya.
Yang benar adalah bahwa proses bagaimana membagi satu aplikasi besar menjadi yang lebih kecil, sangat membantu ketika mencoba untuk membangun antarmuka dan persyaratan yang jelas untuk setiap bagian. Dalam berbicara DDD itu akan datang dengan konteks terbatas Anda. Tetapi apakah Anda kemudian membuat banyak aplikasi kecil atau satu aplikasi besar yang memiliki struktur logis yang sama lebih merupakan keputusan teknis.
sumber
Lebih mudah mempertahankannya setelah Anda selesai membelahnya, ya. Tetapi membelah mereka tidak selalu mudah. Mencoba untuk membagi sepotong program menjadi perpustakaan yang dapat digunakan kembali mengungkapkan di mana pengembang asli gagal memikirkan di mana jahitannya seharusnya. Jika satu bagian dari aplikasi menjangkau jauh ke bagian lain dari aplikasi, itu bisa sulit untuk diperbaiki. Ripping lapisan memaksa Anda untuk mendefinisikan API internal lebih jelas, dan inilah yang akhirnya membuat basis kode lebih mudah untuk dipelihara. Reusability dan rawatan adalah produk dari lapisan yang didefinisikan dengan baik.
sumber
Penting untuk diingat bahwa korelasi bukanlah sebab-akibat.
Membangun monolit besar dan kemudian membaginya menjadi beberapa bagian kecil mungkin atau mungkin tidak mengarah pada desain yang baik. (Ini dapat meningkatkan desain, tetapi tidak dijamin.)
Tetapi desain yang baik sering mengarah pada sistem yang dibangun sebagai beberapa bagian kecil daripada monolit besar. (Monolith bisa menjadi desain terbaik, kemungkinannya kecil.)
Mengapa bagian-bagian kecil lebih baik? Karena mereka lebih mudah untuk dipikirkan. Dan jika mudah beralasan tentang kebenaran, Anda lebih mungkin mendapatkan hasil yang benar.
Mengutip CAR Hoare:
Jika itu masalahnya, mengapa ada orang yang membangun solusi rumit atau monolitik yang tidak perlu? Hoare memberikan jawabannya dalam kalimat berikutnya:
Dan kemudian di sumber yang sama (Kuliah Penghargaan Turing 1980):
sumber
Ini bukan pertanyaan dengan jawaban ya atau tidak. Pertanyaannya bukan hanya kemudahan perawatan, tetapi juga pertanyaan tentang penggunaan keterampilan secara efisien.
Secara umum, aplikasi monolitik yang ditulis dengan baik adalah efisien. Komunikasi antar-proses dan antar-perangkat tidaklah murah. Memecah satu proses tunggal mengurangi efisiensi. Namun, menjalankan segala sesuatu pada satu prosesor dapat membebani prosesor dan memperlambat kinerja. Ini adalah masalah skalabilitas dasar. Ketika jaringan memasuki gambar, masalahnya menjadi lebih rumit.
Aplikasi monolitik yang ditulis dengan baik yang dapat beroperasi secara efisien sebagai satu proses pada satu server dapat dengan mudah dipelihara dan bebas dari cacat, tetapi masih belum efisien dalam menggunakan pengkodean dan keterampilan arsitektur. Langkah pertama adalah memecah proses menjadi perpustakaan yang masih mengeksekusi sebagai proses yang sama, tetapi dikodekan secara independen, mengikuti disiplin kohesi dan kopling longgar. Pekerjaan yang bagus pada level ini meningkatkan rawatan dan jarang mempengaruhi kinerja.
Tahap selanjutnya adalah membagi monolit menjadi proses terpisah. Ini lebih sulit karena Anda masuk ke wilayah yang sulit. Sangat mudah untuk memperkenalkan kesalahan kondisi balapan. Overhead komunikasi meningkat dan Anda harus berhati-hati terhadap "antarmuka mengobrol." Imbalannya bagus karena Anda mematahkan penghalang skalabilitas, tetapi potensi cacat juga meningkat. Aplikasi multi-proses lebih mudah dipertahankan pada level modul, tetapi keseluruhan sistem lebih rumit dan lebih sulit untuk dipecahkan. Perbaikan bisa sangat rumit.
Ketika proses didistribusikan ke server terpisah atau ke implementasi gaya cloud, masalahnya semakin sulit dan hasilnya lebih besar. Skalabilitas melambung. (Jika Anda mempertimbangkan implementasi cloud yang tidak menghasilkan skalabilitas, pikirkan dengan keras.) Tetapi masalah yang masuk pada tahap ini bisa sangat sulit untuk diidentifikasi dan dipikirkan.
sumber
Tidak ada . itu tidak membuatnya lebih mudah untuk dirawat. Jika ada, selamat datang untuk lebih banyak masalah.
Mengapa?
Anda sekarang memiliki dua produk yang perlu:
Anda sekarang memiliki tiga pasar konsumen: Modellers, Animators dan Modeller Animators
Itu dikatakan basis kode yang lebih kecil sama mudah untuk mempertahankan pada tingkat aplikasi, Anda hanya tidak akan mendapatkan makan siang gratis. Ini adalah masalah yang sama di jantung Micro-Service / Any-Modular-Architecture. Ini bukan obat mujarab, kesulitan pemeliharaan di tingkat aplikasi diperdagangkan untuk kesulitan pemeliharaan di tingkat orkestrasi. Masalah-masalah itu masih merupakan masalah, hanya saja tidak ada dalam basis kode lagi, mereka harus dihindari, atau diselesaikan.
Jika memecahkan masalah pada level orkestrasi lebih sederhana maka menyelesaikannya pada setiap level aplikasi maka masuk akal untuk membaginya menjadi dua basis kode dan menangani masalah orkestrasi.
Kalau tidak, jangan lakukan itu, Anda akan lebih baik dilayani dengan meningkatkan modularitas internal aplikasi itu sendiri. Dorong keluar bagian-bagian kode ke dalam kohesif dan lebih mudah untuk mempertahankan pustaka tempat aplikasi bertindak sebagai plugin. Bagaimanapun, monolit hanyalah lapisan orkestrasi dari lanskap perpustakaan.
sumber
Ada banyak jawaban bagus, tetapi karena hampir mati saya akan melemparkan topi saya ke atas ring juga.
Dalam pengalaman saya sebagai insinyur perangkat lunak, saya menemukan ini bukan masalah sederhana. Ini sangat tergantung pada ukuran , skala , dan tujuan aplikasi. Aplikasi yang lebih lama berdasarkan inersia yang diperlukan untuk mengubahnya, umumnya monolitik karena ini adalah praktik umum untuk waktu yang lama (Maya akan memenuhi syarat dalam kategori ini). Saya menganggap Anda berbicara tentang aplikasi yang lebih baru secara umum.
Dalam aplikasi yang cukup kecil yang lebih atau kurang perhatian tunggal overhead yang diperlukan untuk mempertahankan banyak bagian yang terpisah umumnya melebihi utilitas memiliki pemisahan. Jika itu dapat dipertahankan oleh satu orang, itu mungkin dapat dibuat monolitik tanpa menyebabkan terlalu banyak masalah. Pengecualian untuk aturan ini adalah ketika Anda memiliki banyak bagian yang berbeda (frontend, backend, mungkin beberapa lapisan data di antaranya) yang mudah dipisahkan (secara logis).
Dalam aplikasi yang sangat besar, bahkan satu masalah, membaginya masuk akal dalam pengalaman saya. Anda mendapat manfaat mengurangi subset dari kelas bug yang mungkin ditukar dengan bug lain (terkadang lebih mudah untuk dipecahkan). Secara umum, Anda juga dapat memiliki tim orang yang bekerja dalam isolasi yang meningkatkan produktivitas. Namun banyak aplikasi akhir-akhir ini terbelah dengan sangat halus, kadang-kadang merugikan mereka sendiri. Saya juga berada di tim di mana aplikasi terpecah di begitu banyak layanan microser yang tidak perlu sehingga memperkenalkan banyak overhead ketika hal-hal berhenti berbicara satu sama lain. Selain itu, harus memiliki semua pengetahuan tentang bagaimana masing-masing bagian berbicara dengan bagian lain menjadi lebih sulit dengan setiap perpecahan berturut-turut. Ada keseimbangan, dan seperti yang Anda tahu dari jawaban di sini cara untuk melakukannya tidak terlalu jelas,
sumber
Untuk aplikasi UI, tidak mungkin mengurangi jumlah keseluruhan bug tetapi akan mengubah keseimbangan campuran bug ke masalah yang disebabkan oleh komunikasi.
Berbicara tentang pengguna yang menghadapi aplikasi / situs UI - pengguna sangat tidak sabar dan membutuhkan waktu respons yang rendah. Ini membuat komunikasi terhambat menjadi bug. Akibatnya seseorang akan berdagang potensi penurunan bug karena penurunan kompleksitas komponen tunggal dengan bug yang sangat keras dan persyaratan waktu komunikasi lintas proses / lintas mesin.
Jika unit data yang ditangani oleh program besar (yaitu gambar) maka penundaan lintas-proses akan lebih lama dan lebih sulit untuk dihilangkan - sesuatu seperti "terapkan transformasi ke gambar 10MB" akan langsung mendapatkan + 20 MB disk / IO jaringan selain itu ke 2 konversi dari format dalam memori ke format serializabe dan kembali. Sebenarnya tidak banyak yang dapat Anda lakukan untuk menyembunyikan waktu yang diperlukan untuk melakukannya dari pengguna.
Selain itu komunikasi apa pun dan terutama disk IO tunduk pada pemeriksaan AntiVirus / Firewall - ini pasti menambah lapisan lain yang sulit untuk mereproduksi bug dan bahkan lebih banyak penundaan.
Membagi "program" monolitik bersinar di mana keterlambatan komunikasi tidak kritis atau sudah tidak dapat dihindari
Perhatikan bahwa ini berlaku untuk aplikasi desktop dan juga situs web - bagian program yang menghadap pengguna cenderung "monolitik" - semua kode interaksi pengguna yang dikaitkan dengan satu bagian data biasanya berjalan dalam satu proses tunggal (bukan tidak biasa untuk dipecah memproses berdasarkan per-bagian-dari-data seperti halaman HTML atau gambar tetapi ortogonal untuk pertanyaan ini). Bahkan untuk sebagian besar situs dasar dengan input pengguna Anda akan melihat logika validasi berjalan di sisi klien bahkan jika membuatnya sisi server akan lebih modular dan mengurangi kompleksitas / duplikasi kode.
sumber
Mencegah? Yah, tidak, tidak juga.
Yaitu semua bug yang bahkan tidak Anda ketahui miliki, yang baru Anda temukan ketika mencoba membagi seluruh kekacauan itu menjadi bagian-bagian yang lebih kecil. Jadi, dengan cara tertentu, itu mencegah bug dari membuat penampilan mereka di produksi - tetapi bug sudah ada di sana.
Bug dalam aplikasi monolitik berpotensi menurunkan seluruh sistem dan mencegah pengguna berinteraksi dengan aplikasi Anda sama sekali. Jika Anda membagi aplikasi itu menjadi komponen, sebagian besar bug akan —dengan desain — hanya memengaruhi salah satu komponen.
Jika Anda ingin pengalaman pengguna tetap sama, Anda harus menyertakan logika baru untuk semua komponen yang berkomunikasi (melalui layanan REST, melalui panggilan sistem OS, apa pun yang Anda miliki) sehingga mereka dapat berinteraksi dengan mulus dari POV pengguna.
Sebagai contoh sederhana: aplikasi monolitik Anda memungkinkan pengguna membuat model dan menghidupkannya tanpa meninggalkan aplikasi. Anda membagi aplikasi menjadi dua komponen: pemodelan dan animasi. Sekarang pengguna Anda harus mengekspor model aplikasi pemodelan ke file, kemudian menemukan file dan kemudian membukanya dengan aplikasi animasi ... Hadapi saja, beberapa pengguna tidak akan seperti itu, jadi Anda harus memasukkan logika baru untuk aplikasi pemodelan untuk mengekspor file dansecara otomatis meluncurkan aplikasi animasi dan membuatnya membuka file. Dan logika baru ini, sesederhana mungkin, dapat memiliki sejumlah bug mengenai serialisasi data, akses dan izin file, pengguna mengubah jalur instalasi aplikasi, dll.
Ketika Anda memutuskan untuk membagi aplikasi monolitik menjadi komponen yang lebih kecil, Anda (semoga) melakukannya dengan lebih banyak pengetahuan dan pengalaman tentang sistem daripada ketika pertama kali dirancang, dan berkat itu Anda dapat menerapkan sejumlah refaktor untuk membuat kode. lebih bersih, lebih sederhana, lebih efisien, lebih tangguh, lebih aman. Dan refactoring ini dapat, dengan cara, membantu mencegah bug. Tentu saja, Anda juga bisa menerapkan refactoring yang sama ke aplikasi monolitik untuk mencegah bug yang sama, tetapi Anda tidak melakukannya karena sangat monolitik sehingga Anda takut menyentuh sesuatu di UI dan melanggar logika bisnis ¯ \ _ (ツ) _ / ¯
Jadi saya tidak akan mengatakan Anda mencegah bug hanya dengan memecah aplikasi monolitik menjadi komponen yang lebih kecil, tetapi Anda memang membuatnya lebih mudah untuk mencapai titik di mana bug dapat lebih mudah dicegah.
sumber