Tidak masalah seberapa erat satu hal dengan yang lain jika hal lainnya tidak pernah berubah. Saya telah menemukan bahwa umumnya lebih produktif selama bertahun-tahun untuk fokus pada mencari lebih sedikit alasan untuk hal-hal untuk berubah, untuk mencari stabilitas, daripada untuk membuatnya lebih mudah untuk berubah dengan mencoba mencapai bentuk penggabungan yang paling longgar.
Decoupling yang saya temukan sangat berguna, sampai pada titik di mana saya kadang-kadang menyukai duplikasi kode sederhana untuk memisahkan paket. Sebagai contoh dasar, saya punya pilihan untuk menggunakan perpustakaan matematika saya untuk mengimplementasikan perpustakaan gambar. Saya tidak dan hanya menggandakan beberapa fungsi matematika dasar yang mudah untuk disalin.
Sekarang perpustakaan gambar saya benar-benar independen dari perpustakaan matematika dengan cara di mana tidak peduli apa pun perubahan yang saya buat untuk lib matematika saya, itu tidak akan mempengaruhi perpustakaan gambar. Itu menempatkan stabilitas sebagai yang utama dan terpenting. Pustaka gambar sekarang lebih stabil, karena memiliki lebih sedikit alasan untuk berubah secara drastis, karena dipisah dari pustaka lain yang dapat berubah (selain pustaka standar C yang semoga tidak boleh berubah). Sebagai bonus juga mudah untuk digunakan ketika itu hanya sebuah perpustakaan mandiri yang tidak perlu menarik banyak lib lain untuk membangun dan menggunakannya.
Stabilitas sangat membantu saya. Saya suka membangun koleksi kode yang telah teruji baik yang memiliki lebih sedikit dan lebih sedikit alasan untuk berubah di masa depan. Itu bukan mimpi pipa; Saya memiliki kode C yang telah saya gunakan dan gunakan lagi sejak akhir 80-an yang tidak berubah sama sekali sejak itu. Memang diakui hal-hal tingkat rendah seperti pixel-oriented dan kode terkait geometri sementara banyak hal tingkat tinggi saya menjadi usang, tetapi itu adalah sesuatu yang masih banyak membantu untuk dimiliki. Itu hampir selalu berarti perpustakaan yang bergantung pada semakin sedikit hal, jika tidak ada yang eksternal sama sekali. Keandalan naik dan naik jika perangkat lunak Anda semakin tergantung pada fondasi stabil yang menemukan sedikit atau tidak ada alasan untuk berubah. Lebih sedikit bagian yang bergerak benar-benar bagus, bahkan jika dalam praktiknya bagian yang bergerak jauh lebih besar jumlahnya daripada bagian yang stabil.
Kopling longgar berada dalam nada yang sama, tetapi saya sering menemukan bahwa kopling longgar jauh lebih stabil daripada kopling tidak. Kecuali jika Anda bekerja dalam tim dengan desainer dan klien antarmuka yang jauh lebih unggul yang tidak berubah pikiran daripada yang pernah saya kerjakan, bahkan antarmuka murni sering menemukan alasan untuk berubah dengan cara yang masih menyebabkan kerusakan cascading di seluruh kode. Gagasan bahwa stabilitas dapat dicapai dengan mengarahkan dependensi ke abstrak daripada beton hanya berguna jika desain antarmuka lebih mudah untuk mendapatkan yang benar saat pertama kali daripada implementasi. Saya sering menemukannya terbalik ketika pengembang mungkin telah menciptakan implementasi yang sangat baik, jika tidak luar biasa, mengingat persyaratan desain yang menurut mereka harus dipenuhi, hanya untuk menemukan di masa depan bahwa persyaratan desain berubah sepenuhnya.
Jadi saya suka mendukung stabilitas dan decoupling lengkap sehingga saya setidaknya dapat dengan percaya diri mengatakan, "Perpustakaan kecil yang terisolasi ini yang telah digunakan selama bertahun-tahun dan diamankan dengan pengujian menyeluruh hampir tidak memiliki kemungkinan memerlukan perubahan apa pun yang terjadi di dunia luar yang kacau ini. . " Ini memberi saya sedikit kewarasan tidak peduli apa perubahan desain yang disebut untuk luar.
Kopling dan Stabilitas, Contoh ECS
Saya juga suka sistem entitas-komponen dan mereka memperkenalkan banyak kopling ketat karena semua ketergantungan sistem pada komponen mengakses dan memanipulasi data mentah secara langsung, seperti:
Semua dependensi di sini cukup ketat karena komponen hanya mengekspos data mentah. Ketergantungan tidak mengalir ke abstraksi, mereka mengalir ke data mentah yang berarti bahwa setiap sistem memiliki jumlah pengetahuan maksimum yang mungkin tentang setiap jenis komponen yang mereka minta untuk akses. Komponen tidak memiliki fungsionalitas dengan semua sistem mengakses dan merusak data mentah. Namun, sangat mudah untuk berpikir tentang sistem seperti ini karena sangat datar. Jika suatu tekstur keluar edan, maka Anda tahu dengan sistem ini segera bahwa hanya komponen rendering dan pengecatan yang mengakses komponen tekstur, dan Anda mungkin dapat dengan cepat mengesampingkan sistem rendering karena hanya membaca dari tekstur secara konseptual.
Sementara alternatif yang digabungkan secara longgar mungkin adalah ini:
... dengan semua dependensi yang mengalir ke fungsi abstrak, bukan data, dan setiap hal dalam diagram itu memperlihatkan antarmuka publik dan fungsionalitasnya sendiri. Di sini semua dependensi mungkin sangat longgar. Objek mungkin bahkan tidak secara langsung bergantung satu sama lain dan berinteraksi satu sama lain melalui antarmuka murni. Masih sangat sulit untuk berpikir tentang sistem ini, terutama jika ada yang salah, mengingat jalinan interaksi yang kompleks. Juga akan ada lebih banyak interaksi (lebih banyak kopling, meskipun lebih longgar) daripada ECS karena entitas harus tahu tentang komponen yang mereka agregat, bahkan jika mereka hanya tahu tentang antarmuka publik abstrak masing-masing.
Juga jika ada perubahan desain untuk apa pun, Anda mendapatkan lebih banyak kerusakan berjenjang daripada ECS, dan biasanya akan ada lebih banyak alasan dan godaan untuk perubahan desain karena setiap hal mencoba memberikan antarmuka dan abstraksi berorientasi objek yang bagus. Itu segera datang dengan gagasan bahwa masing-masing dan setiap hal kecil akan mencoba untuk memaksakan kendala dan keterbatasan pada desain, dan kendala-kendala itu sering kali yang menuntut perubahan desain. Fungsionalitas jauh lebih terbatas dan harus membuat asumsi desain lebih banyak daripada data mentah.
Saya telah menemukan dalam praktiknya jenis sistem ECS "flat" di atas jauh lebih mudah untuk dipikirkan daripada bahkan sistem yang paling longgar digabungkan dengan sarang laba-laba kompleks yang longgar dan, yang paling penting bagi saya, saya menemukan beberapa alasan. untuk versi ECS yang perlu mengubah komponen yang ada karena komponen bergantung tidak memiliki tanggung jawab kecuali untuk menyediakan data yang sesuai yang diperlukan agar sistem berfungsi. Bandingkan kesulitan mendesain IMotion
antarmuka murni dan objek gerak konkret yang mengimplementasikan antarmuka yang menyediakan fungsionalitas canggih sambil mencoba mempertahankan invarian terhadap data pribadi vs. komponen gerak yang hanya perlu menyediakan data mentah yang relevan untuk menyelesaikan masalah dan tidak repot dengan fungsionalitas.
Fungsionalitas jauh lebih sulit untuk mendapatkan yang benar daripada data, itulah sebabnya saya pikir seringkali lebih baik untuk mengarahkan aliran ketergantungan terhadap data. Lagi pula, berapa banyak perpustakaan vektor / matriks di luar sana? Berapa banyak dari mereka yang menggunakan representasi data yang persis sama dan hanya berbeda secara fungsional? Tak terhitung, namun kita masih memiliki begitu banyak meskipun representasi data yang identik karena kita ingin perbedaan fungsi yang halus. Berapa banyak perpustakaan gambar di luar sana? Berapa banyak dari mereka yang merepresentasikan piksel dengan cara yang berbeda dan unik? Hampir tidak ada, dan sekali lagi menunjukkan bahwa fungsionalitas jauh lebih tidak stabil dan cenderung terhadap perubahan desain daripada data dalam banyak skenario. Tentu saja di beberapa titik kita membutuhkan fungsionalitas, tetapi Anda dapat merancang sistem di mana sebagian besar dependensi mengalir ke data, dan tidak menuju abstraksi atau fungsionalitas secara umum. Seperti itu akan memprioritaskan stabilitas di atas kopling.
Fungsi paling stabil yang pernah saya tulis (jenis yang saya gunakan dan gunakan kembali sejak akhir 80-an tanpa harus mengubahnya sama sekali) adalah semua yang bergantung pada data mentah, seperti fungsi geometri yang baru saja menerima serangkaian mengapung dan bilangan bulat, bukan yang bergantung pada Mesh
objek atau IMesh
antarmuka yang kompleks , atau penggandaan vektor / matriks yang hanya bergantung pada float[]
atau double[]
, bukan yang bergantung pada FancyMatrixObjectWhichWillRequireDesignChangesNextYearAndDeprecateWhatWeUse
.