Kriteria untuk desain yang buruk

Hidup berjalan cukup sederhana: seringkali, untuk menjadi pintar, Anda hanya perlu tidak melakukan hal-hal bodoh. Ini juga berlaku untuk pengembangan perangkat lunak: dalam banyak kasus, untuk melakukan sesuatu dengan baik, Anda hanya perlu tidak melakukannya dengan buruk.

Sebagian besar pemrogram memiliki pengalaman dengan bagian-bagian sistem yang dirancang dengan buruk. Namun yang lebih menyedihkan lagi, sebagian besar dari Anda akan mengalami pengalaman menyedihkan saat menyadari bahwa Andalah pencipta sistem semacam itu. Kami menginginkan yang terbaik, tetapi ternyata seperti biasa.

Sebagian besar pengembang tidak bercita-cita untuk arsitektur yang buruk, dan untuk banyak sistem ada saatnya mereka mulai mengatakan bahwa arsitekturnya buruk. Mengapa ini terjadi? Apakah desain arsitektur buruk sejak awal, atau menjadi buruk seiring berjalannya waktu?

Akar masalah ini adalah kurangnya definisi desain yang “buruk”.

Bagi saya, pemahaman tentang kualitas desain dan alasan "kerusakan" itulah yang merupakan kualitas terpenting bagi setiap programmer. Seperti dalam kebanyakan kasus lainnya, hal utama adalah mengidentifikasi masalah, dan ini akan menjadi masalah teknologi untuk menyelesaikannya.

Definisi "desain yang buruk"

Jika Anda memutuskan untuk menyombongkan kode Anda di depan sesama pemrogram, kemungkinan besar Anda akan mendapat ejekan sebagai tanggapan: "Siapa yang melakukan ini?", 'Mengapa seperti itu?' dan "Saya akan melakukan sesuatu secara berbeda." Ini sangat sering terjadi.

Semua orang berbeda, tetapi Anda tetap menulis kode untuk sesama programmer, jadi dalam proses pengembangan setiap fitur, Anda selalu memerlukan fase peninjauan ketika orang lain melihat kode Anda.

Tetapi bahkan jika banyak hal dapat dilakukan dengan cara yang berbeda, ada seperangkat kriteria yang akan disetujui oleh semua pengembang. Bagian kode apa pun yang memenuhi persyaratannya tetapi masih menunjukkan satu (atau lebih) karakteristik adalah desain yang buruk.

Desain Buruk:

  • Sulit untuk diubah karena setiap perubahan mempengaruhi terlalu banyak bagian lain dari sistem. ( Kekakuan , Kekakuan ).
  • Saat perubahan dilakukan, bagian lain dari sistem tiba-tiba rusak. ( Kerapuhan , Kerapuhan).
  • Kode sulit untuk digunakan kembali di aplikasi lain karena terlalu sulit untuk mengeluarkannya dari aplikasi saat ini. ( Imobilitas , Imobilitas).

Dan lucunya, hampir tidak mungkin menemukan bagian dari sistem yang tidak mengandung salah satu dari karakteristik ini (yaitu, fleksibel, andal, dan dapat digunakan kembali), memenuhi persyaratan, dan pada saat yang sama desainnya buruk. .

Dengan demikian, kita dapat menggunakan ketiga karakteristik ini untuk menentukan dengan jelas apakah suatu desain itu "buruk" atau "baik".

Penyebab "Desain Buruk"

Apa yang membuat desain menjadi kaku, rapuh, dan tidak dapat digerakkan? Saling ketergantungan modul yang kaku.

Sebuah desain kaku jika tidak dapat dengan mudah diubah. Kekakuan ini disebabkan oleh fakta bahwa satu perubahan pada sepotong kode dalam sistem anyaman menghasilkan perubahan berjenjang pada modul-modul yang bergantung. Ini selalu terjadi ketika satu orang sedang mengerjakan kode.

Ini segera memperumit seluruh proses pengembangan komersial: ketika jumlah perubahan kaskade tidak dapat diprediksi oleh perancang atau pengembang, tidak mungkin untuk memperkirakan dampak dari perubahan tersebut. Oleh karena itu, mereka mencoba untuk menunda perubahan tersebut tanpa batas waktu.

Dan ini pada gilirannya membuat biaya perubahan tidak dapat diprediksi. Menghadapi ketidakpastian tersebut, pengelola enggan melakukan perubahan, sehingga desain resmi menjadi kaku.

Pada titik tertentu, proyek Anda melewati "cakrawala peristiwa" dan pasti akan jatuh ke dalam "lubang hitam" arsitektur kaku.

Kerapuhan adalah kecenderungan suatu sistem untuk rusak di banyak tempat setelah satu perubahan. Biasanya masalah baru terjadi di tempat-tempat yang secara konseptual tidak berhubungan dengan tempat perubahan. Kerapuhan seperti itu sangat merusak kepercayaan pada desain dan pemeliharaan sistem.

Ini biasanya terjadi ketika tidak ada metode privat. Cukup membuat semua metode menjadi publik, dan Anda akan dikutuk dengan penampilan arsitektur yang rapuh. Enkapsulasi membantu mengatasi hal ini pada tingkat mikro. Tetapi pada level makro, Anda memerlukan arsitektur modular.

Ketika sebuah proyek memiliki arsitektur yang rapuh, pengembang tidak dapat menjamin kualitas produknya.

Perubahan sederhana di satu bagian aplikasi menyebabkan bug di bagian lain yang tidak terkait. Memperbaiki kesalahan ini menyebabkan lebih banyak masalah, dan proses pengawalan berubah menjadi anjing terkenal yang mengejar ekornya sendiri.

Desainnya tidak bergerak ketika bagian yang diperlukan dari sistem terikat kuat dengan detail lain yang tidak diinginkan. Terlalu banyak kode mereka sendiri, pendekatan dan solusi unik mereka sendiri.

Apakah Anda ingat JUL logger, yang pengembangnya membuat level logging mereka sendiri tanpa alasan yang jelas? Inilah masalahnya.

Untuk memberikan gambaran kepada desainer tentang betapa mudahnya menggunakan kembali desain yang sudah ada, cukup pikirkan betapa mudahnya menggunakannya dalam aplikasi baru.

Jika desain digabungkan dengan erat, maka perancang ini akan ngeri dengan banyaknya pekerjaan yang diperlukan untuk memisahkan bagian sistem yang diperlukan dari detail yang tidak perlu. Dalam kebanyakan kasus, desain seperti itu tidak dapat digunakan kembali, karena biaya pemisahannya lebih besar daripada pengembangannya dari awal.

Relevansi

Semuanya berubah, tetapi semuanya tetap sama. (Pepatah Cina)

Pertanyaan yang sangat bagus telah diajukan di atas. Apa bahaya dari sistem rapuh dan kaku? Ya, karena proses mengelola proyek semacam itu menjadi tidak dapat diprediksi dan dikendalikan. Dan harganya selangit.

Bagaimana seorang manajer dapat memberi atau tidak memberikan lampu hijau untuk menambahkan beberapa fitur jika dia tidak tahu berapa lama sebenarnya waktu yang diperlukan? Bagaimana cara memprioritaskan tugas jika Anda tidak dapat memperkirakan waktu dan kompleksitas pelaksanaannya secara memadai?

Dan bagaimana pengembang dapat melunasi hutang teknis yang sama ketika kita akan membayarnya, dan kita tidak dapat memahami berapa banyak yang akan kita peroleh sampai kita mendapatkan?

Masalah dengan penggunaan kembali atau pengujian kode juga sangat relevan. Tes unit berfungsi tidak hanya untuk menguji beberapa asumsi tentang unit yang diuji, tetapi juga untuk menentukan tingkat kohesinya dan dapat berfungsi sebagai indikator penggunaan kembali.

Berikut adalah kutipan dari Bob Martin untuk kasus ini: “Untuk menggunakan kembali kode Anda, Anda perlu melakukan upaya untuk menggunakannya kembali lebih murah daripada biaya pengembangan dari awal . ” Kalau tidak, tidak ada yang akan peduli dengan masalah ini.

Penggunaan prinsip dan pola desain melayani satu tujuan - untuk membuat desain menjadi baik. Jika penggunaannya tidak memberi Anda keuntungan apa pun (atau sebaliknya, melanggar prinsip "desain yang baik"), maka ada sesuatu di konservatori Anda yang salah dan, mungkin, alat tersebut sudah mulai digunakan untuk tujuan lain.