Apa yang Anda lakukan jika Anda mencapai jalan buntu desain dalam metode evolusi seperti Agile atau XP?


11

Ketika saya membaca posting blog terkenal Martin Fowler Is Design Dead? , salah satu kesan mencolok yang saya dapatkan adalah bahwa mengingat fakta bahwa dalam Agile Metodologi dan Pemrograman Ekstrim, desain serta pemrogramannya adalah evolusioner, selalu ada poin di mana hal-hal yang perlu direaktorkan ulang.

Mungkin saja ketika level programmer baik, dan mereka memahami implikasi desain dan tidak membuat kesalahan kritis, kode terus berkembang. Namun, dalam konteks normal, apa realitas dasar dalam konteks ini?

Di hari normal dengan beberapa pengembangan signifikan masuk ke produk, dan ketika perubahan kritis terjadi dalam persyaratan, bukankah itu menjadi kendala bahwa seberapa banyak yang kita inginkan, aspek desain mendasar tidak dapat dimodifikasi? (tanpa membuang bagian utama dari kode). Apakah tidak mungkin seseorang mencapai jalan buntu pada perbaikan lebih lanjut yang mungkin pada desain dan persyaratan?

Saya tidak menganjurkan praktik non-Agile di sini, tetapi saya ingin tahu dari orang-orang yang berlatih metode pengembangan tangkas atau berulang atau evolusi, seperti pengalaman nyata mereka.

Apakah Anda pernah mencapai jalan buntu seperti itu ? Bagaimana Anda berhasil menghindarinya atau menghindarinya? Atau ada langkah-langkah untuk memastikan bahwa desain tetap bersih dan fleksibel saat berevolusi?

Jawaban:


17

Saya baru saja membaca tautan artikel yang Anda posting, saya harus mengatakan Fowler telah membuat beberapa poin yang sangat bagus dan banyak hal yang dia katakan, saya telah melakukan advokasi dengan tim kami selama bertahun-tahun.

IMO, jika Anda melakukan desain yang layak, Anda tidak boleh masuk ke dalam situasi buntu. Saya selalu melihat perangkat lunak sebagai bagian dari blok bangunan . Saya masih percaya pada beberapa desain di muka, tetapi tujuan utamanya bukan untuk merancang seluruh produk, tetapi untuk memberikan arsitektur / arah secara keseluruhan sehingga tim Anda dapat memvisualisasikan gambaran umum yang sedang kita semua kerjakan. Jika Anda memiliki banyak potongan kubus dan segitiga, akan sangat membantu untuk menggambarkan bagaimana sebuah kastil akan disatukan sebelum Anda mulai menampar potongan-potongan bersama.

Karena saya berasal dari tanah OO, bagi saya setiap blok adalah kelas dan area permukaan blok itu adalah antarmuka publik (apa yang terlihat oleh kelas eksternal atau berasal). Jika Anda mengikuti prinsip SOLID yang baik, Anda akan memastikan bahwa setiap blok sangat sederhana dan memiliki antarmuka publik yang intuitif. Kembali ke analogi saya, Anda ingin memastikan kode Anda hanya membuat bentuk sederhana. Setiap kali Anda membuat kelas, yang terlalu kompleks (banyak fungsi, banyak variabel), Anda membuat bentuk yang sulit untuk digunakan kembali ketika persyaratan berubah.

Saya setuju dengan Fowler bahwa risiko / tantangan terbesar untuk desain evolusi adalah bahwa Anda membiarkan keputusan desain sesuai waktu pengkodean, dan Anda mengharapkan setiap pengembang individu untuk membuat keputusan itu. Di sinilah sistem dapat rusak jika Anda tidak memiliki mekanisme umpan balik yang tepat. Setiap kali fitur baru diminta, sangat menggoda untuk hanya menemukan fungsi yang perlu diperluas, meletakkan beberapa jenis kondisional di dalamnya dan hanya menambahkan sejumlah besar kode tepat di dalam fungsi itu. Dan kadang-kadang, ini mungkin yang dibutuhkan, tetapi ini juga (IMO) satu-satunya praktik paling umum yang mengarah pada komponen buntu. Ini tidak ada hubungannya dengan desain evolusi. Inilah yang disebut "tanpa desain".

Selama Anda meluangkan waktu untuk mundur dan berkata, tunggu sebentar, kelas ini sudah memiliki 15 variabel anggota, izinkan saya mengekstrak 6 dari ini dan dimasukkan ke dalam kelas mandiri mereka sendiri, perangkat lunak Anda akan terdiri dari sangat ringan - blok bangunan yang ringan, fleksibel dan dapat digunakan kembali. Tentu jika PM datang dan mengubah setengah persyaratan produk pada Anda, Anda mungkin harus mengambil beberapa blok Anda, meletakkannya kembali di rak dan menyusun beberapa yang baru (seperti ketika membangun sebuah kastil, Anda mungkin tidak menggunakan semua silinder Anda). Tetapi pada saat itu, itu hanya bagian dari berbisnis. Persyaratan diubah dan dengan menjaga kode Anda fleksibel dan modular, Anda harus dapat mengubah produk agar selaras dengan arah bisnis baru Anda.

Saya percaya pendekatan evolusi ini untuk desain bekerja dengan setiap tingkat keahlian insinyur. Secara pribadi, saya telah melakukan perangkat lunak untuk waktu yang sangat lama dan sebelum tim kami pindah ke metodologi tangkas, saya bertanggung jawab untuk pengiriman beberapa komponen utama dari PC dev saya hampir langsung ke pelanggan dengan hampir tidak ada QA. Pada saat yang sama komponen-komponen itu selalu tetap fleksibel dan dapat dipelihara.

Saya hanya mencoba mengatakan bahwa saya akan menganggap diri saya relatif layak dalam merancang perangkat lunak. Pada saat yang sama, jika Anda meminta saya untuk menulis dokumen desain 100 halaman, memberikannya kepada seorang pembuat kode dan berharap itu berfungsi, saya mungkin tidak bisa mendesain diri dari kantong kertas. Ketika mulai bekerja, kadang-kadang saya membuat sketsa beberapa diagram UML (sangat disederhanakan, bukan bahasa lengkap), tetapi ketika saya mulai coding, saya akan melakukan refactor sesuai kebutuhan dan kode terakhir saya tidak akan pernah terlihat seperti apa yang saya gambar sebelumnya. Bahkan jika saya menghabiskan satu atau dua bulan memikirkan setiap detail kecil, saya tidak dapat membayangkan orang lain dapat mengambil diagram saya dan menghasilkan perangkat lunak yang solid tanpa memodifikasi desain saat mereka sedang mengkode.

Di ujung lain spektrum, saat ini di tim saya (sekarang gesit dan saya sepenuhnya mendukung itu) kami memiliki beberapa orang yang bergabung dengan kami dari tanah tertanam di mana mereka hanya melakukan C selama 15 tahun terakhir. Saya jelas membantu dengan beberapa perencanaan awal dan menyusun kelas, tetapi saya juga memastikan untuk menindaklanjuti dengan ulasan kode reguler dan sesi brainstorming di mana kami membahas aplikasi prinsip SOLID dan desain. Mereka memang menghasilkan beberapa kode spageti yang membuat saya sedikit ngeri, tetapi dengan sedikit dorongan dari saya, mereka mulai refactoring apa yang sudah diproduksi dan yang lucu adalah bahwa salah satu dari mereka kembali kepada saya beberapa hari kemudian dan berkata, saya benci untuk mengatakannya tetapi setelah memindahkan kode itu, ini terlihat jauh lebih mudah dibaca dan dimengerti. Jalan buntu dihindari. Titik I ' Yang saya coba buat adalah bahwa bahkan seseorang yang benar-benar baru untuk OO dapat menghasilkan kode yang lumayan, selama ia memiliki seorang mentor dengan lebih banyak pengalaman, untuk mengingatkannya bahwa "desain evolusi" tidak sama dengan "tanpa desain". Dan bahkan beberapa kelas "yang lebih kompleks" tidak begitu menakutkan karena setiap kelas tidak memiliki banyak tanggung jawab (yaitu tidak banyak kode), jadi yang terburuk menjadi lebih buruk, jika satu kelas "jalan buntu", kami buang dan tulis kelas pengganti yang memiliki antarmuka publik yang sama (sejauh ini saya tidak pernah melihat kebutuhan untuk hal tak terduga ini dalam apa pun yang kami tulis dan saya sudah melakukan tinjauan kode dua kali seminggu).

Sebagai catatan akhir, saya juga sangat percaya pada dokumen desain (setidaknya untuk kondisi bisnis tim saya saat ini) tetapi tujuan utama untuk dokumen desain kami adalah Memori Organisasi , jadi dokumen yang sebenarnya ditulis setelah kode diproduksi dan refactored. Sebelum pengkodean, kita umumnya memiliki fase desain cepat (kadang-kadang tidak begitu cepat) di mana kita membuat sketsa kelas pada serbet / mspaint / visio dan saya selalu mengingatkan orang bahwa fase ini menghasilkan jalur untuk diikuti, bukan cetak biru dan ketika mereka mulai coding, segala sesuatu yang tidak masuk akal harus diubah. Bahkan dengan pengingat ini, orang yang lebih baru cenderung mencoba untuk memasukkan kembali kode yang sesuai ke dalam desain asli tidak peduli seberapa tidak alami rasanya bagi mereka. Ini biasanya muncul dalam ulasan kode.

Dang, saya banyak menulis. Maaf soal itu.


1
+1 Itu layak untuk setiap kata. Saya menemukan situasi ini seperti yang Anda gambarkan dan setelah batas waktu terpenuhi, minta mereka untuk membersihkan (baca refactor) lebih banyak dari apa yang saya pikir masuk akal dari desain. Tetapi seringkali orang menemukan pertanyaan yang sama berulang - Mengapa saya melakukan hal yang sama lagi? Saya kira sekarang saya punya jawabannya - jika Anda membutuhkan waktu lebih cepat untuk memasarkan, dan memungkinkan desain untuk berkembang, refactoring bukanlah kompensasi untuk dosa lama Anda, tetapi sebenarnya hal yang sah untuk dilakukan.
Dipan Mehta

Ya, Anda banyak menulis, tetapi itu adalah hal yang baik. Sangat menikmati membacanya :).
Radu Murzea

11

Saya akan mengatakan fenomena "buntu desain" adalah ortogonal untuk metode tangkas. Maksud saya adalah mungkin untuk melakukan waterfall, menghabiskan banyak waktu dimuka pada desain (buruk). Kemudian habiskan banyak waktu untuk mengimplementasikannya hanya untuk menemukan diri Anda di jalan buntu.

Jika ada, metode lincah akan membantu Anda menemukan sebelumnya bahwa Anda membuat pilihan desain yang buruk. Alasan untuk ini adalah bahwa jaminan simpanan Anda harus diselesaikan terlebih dahulu dan Anda harus fokus untuk memberikan peningkatan yang bermanfaat pada perangkat lunak. Jika desain Anda memungkinkan Anda untuk memberikan nilai tinggi dan kegunaannya itu sudah baik untuk sesuatu :-) Sebaliknya, Anda bisa memiliki desain yang buruk dalam situasi air terjun di mana Anda mungkin tidak mengetahui selama bertahun-tahun bahwa desain ini tidak dapat memberikan nilai dan manfaat apa pun - yang Anda miliki hanyalah ilusi bahwa desain itu bagus. Seperti yang mereka katakan, buktinya ada di puding.

Sisi sebaliknya adalah bahwa bahkan dalam metode gesit penting untuk memiliki visi yang layak untuk desain sistem yang mendorong keputusan dari iterasi ke iterasi. Saya pikir Ken Schwabber mengatakan sesuatu seperti jika Anda memiliki tim pengembang yang mengerikan mereka akan menghasilkan perangkat lunak yang buruk secara iterasi dengan iterasi. Agile berarti tidak menghabiskan banyak waktu di muka karena Anda terbatas pada apa yang dapat Anda pelajari atau bayangkan sebelum Anda mulai menerapkan ( dan persyaratan juga berubah). Namun, ada beberapa situasi di mana Anda harus melakukan pekerjaan dimuka (misalnya penelitian) dan kemudian Anda harus melakukannya.

Bagaimana Anda menghindari jalan buntu?

Saya akan mengatakan sebagian besar dengan mengantisipasi persyaratan di masa depan. Ini adalah sesuatu yang Anda dapatkan dengan pengalaman dan keakraban dengan proyek / produk serupa. Antisipasi ini adalah sebagian yang membantu Anda menempatkan desain yang baik di tempat karena Anda banyak bertanya kepada diri sendiri tentang "bagaimana jika" tentang sistem Anda saat ini. Bagi saya ini adalah komponen penting. Teknik seperti OO hanya membantu Anda ketika Anda sudah tahu apa yang Anda lakukan.

Apa yang Anda lakukan jika Anda menemui jalan buntu?

"Jalan buntu" tidak berbeda dari blok teknis lainnya yang akan Anda temukan selama pengembangan apa pun yang baru. Hal pertama yang harus disadari adalah bahwa sesungguhnya tidak ada "jalan buntu" yang memaksa Anda untuk mundur sepenuhnya. Paling tidak pembelajaran Anda sampai titik ini adalah apa yang memungkinkan Anda untuk terus maju sehingga upaya itu tidak sia-sia. Ketika Anda menemui jalan buntu, Anda memiliki masalah . Masalahnya adalah apa yang perlu diubah untuk memenuhi beberapa persyaratan baru (atau lama) dan bagaimana mengoptimalkan membuat perubahan ini. Yang harus Anda lakukan sekarang adalah menyelesaikan masalah ini. Bersyukurlah bahwa ini adalah perangkat lunak dan bukan, mis. Desain pesawat, karena perubahan jauh lebih mudah. Identifikasi masalah, perbaiki == refactor == rekayasa perangkat lunak. Terkadang banyak pekerjaan yang terlibat ...

Jika Anda menggunakan Scrum, perubahan ini secara alami harus didorong dari cerita pengguna (apa yang didapat pengguna dari perubahan ini?). Prosesnya akan dimulai dari satu cerita yang tidak dapat dengan mudah diakomodasi oleh desain saat ini (oops) dan diskusi akan terjadi dengan pemilik produk tentang cara memecah cerita ini. Anda terus menerapkan prinsip gesit melalui perubahan ini.

Beberapa perubahan persyaratan besar yang terkenal dari dunia OS yang muncul di benak saya:

Apa pun cara Anda melihatnya, ini banyak pekerjaan. Desain aslinya hampir pasti tidak memperhitungkan kemungkinan ini terjadi (yaitu portaility bukan persyaratan besar). Apakah desain itu OO atau tidak mungkin bukan faktor yang besar juga. Dalam desain yang baik, bagian platform tertentu akan agak terisolasi dan pekerjaan akan lebih mudah.


Sebenarnya versi awal Windows NT menerapkan "Hardware Extract Layer" dan mendukung DEC Apha serta x86. Karena tidak ada yang pernah membeli mesin berbasis DEC alpha ini diam-diam dijatuhkan. Saya akan membayangkan bahwa "kemerdekaan mesin" ini masih ada dalam format vestigial dalam rilis saat ini sehingga port ARM mungkin tidak terlalu sulit.
James Anderson

3

Saya memperbaiki proyek saya secara permanen dan juga menggunakan diagram kelas UML. Maksud saya, saya membuat satu atau lebih diagram kelas dengan paket. Setiap diagram disimpan pada akar paket. Setiap classifier UML memiliki Id sendiri yang dipetakan ke Java Id terkait. Itu berarti bahwa ketika saya membuka diagram saya secara otomatis diperbarui ke perubahan kode refactoring terbaru. Saya juga dapat langsung mengubah diagram kelas saya di tingkat grafis dan semua proyek saya segera dire-refored. Ini bekerja cukup baik tetapi tidak akan pernah menggantikan manusia. Diagram kelas UML saya juga hanya tampilan grafis dari kode saya. Sangat penting untuk tidak melakukan campur kode dan model seperti yang dilakukan eclipse EMF karena begitu refactoring dilakukan maka informasi model juga hilang. Saya tidak pernah menggunakan generator kode Model Driven Development karena ini tidak berguna. Saya tidak

Setelah mengatakan bahwa memiliki lebih dari 100 diagram kelas yang mewakili semua detail struktur proyek saya dan penuh catatan di mana-mana sangat membantu. Saya hanya membuat diagram kelas untuk proyek karena biasanya pengembang tidak punya waktu untuk belajar atau menggunakan diagram lain. Diagram kelas juga sangat baik karena diperbarui secara otomatis. Diagram kelas dapat dibuat setelah kode hanya dengan membalikkan paket dan menambahkan catatan. Cepat dan selalu akurat dan 100% berulang.

Tolong jangan membuat bingung antara pengembangan model didorong yang merupakan model menghasilkan kode dan biasanya menggunakan UML sebagai presentasi grafis dengan diagram kelas UML diperbarui dari kode. Hanya kode tersinkronisasi UML yang memiliki nilai nyata bagi saya jika beberapa kali pengulangan.

Maaf sudah terlalu lama tapi saya pikir kita harus memberikan kesempatan kedua untuk diagram kelas UML jika hanya digunakan sebagai tampilan grafis dari proyek kami. Ini berarti bahwa UML mencakup proyek penuh dan memiliki model tunggal yang disusun oleh diagram kelas besar yang mewakili proyek penuh. Akan konyol untuk memiliki ratusan tampilan kecil dan model untuk setiap tampilan dalam proyek yang memiliki ratusan tampilan :-)


1
+1 untuk menunjukkan gagasan kode pos UML! Cukup menarik, kami tidak pernah kembali ke dokumen diagram setelah kode!
Dipan Mehta

Ya, ini persis masalah dengan pengembangan berbasis model yang terkait dengan UML. Anda menghasilkan dokumentasi dan kemudian tidak pernah menggunakannya jika ada modifikasi proyek. Penggabungan model dan kode memungkinkan kami menggunakan UML dan mengubahnya sebanyak yang kami butuhkan.
UML_GURU

3

Saya telah mencapai jalan buntu kode saya dan kode lain karena desain yang buruk, perubahan arah, dll. Saya juga melihat banyak orang lain mengalami masalah ini. Kesalahan besar (setidaknya sepertinya kesalahan bagi saya) adalah keinginan langsung untuk membuang kode kerja dan mengimplementasikan semuanya dari bawah ke atas.

Saya mendekati setiap kasus dengan cara yang sama yang tampaknya bekerja dengan baik:

  • mengidentifikasi mengapa desain saat ini tidak berfungsi
  • datang dengan desain baru dan rencana transisi
  • beri tag pada kode yang tidak akan digunakan sebagai usang
  • hanya menerapkan apa yang saya butuhkan untuk desain baru untuk memenuhi kebutuhan segera
  • hapus kode yang membuat kode baru menjadi usang

Biaya:

  • lebih rumit karena 2 implementasi di basis kode pada saat yang sama
  • lebih banyak total biaya per perbaikan fitur / bug daripada melakukan desain ulang penuh / implementasi ulang dengan asumsi kasus penggunaan yang baik dan tes

Manfaat:

  • setidaknya urutan besarnya risiko lebih kecil karena Anda masih memiliki desain / kode kerja lama
  • lebih cepat memasarkan untuk fitur 1 hingga n-1 yang tidak memerlukan desain ulang penuh
  • jika produk / kode akhirnya mati sebelum Anda selesai mendesain ulang penuh, Anda akan menghemat waktu pengembangan
  • pendekatan iteratif dan semua manfaat di dalamnya

2

Sekitar satu atau dua bulan yang lalu, proyek kami saat ini agak macet karena beberapa keputusan desain yang buruk (dan kurangnya banyak desain di satu tempat), dengan gaya pengembangan SCRUM.

Solusi kami (dan apa yang saya yakini sebagai standar untuk SCRUM) adalah mencurahkan seluruh sprint (~ 2 minggu) hanya untuk refactoring. Tidak ada fungsi baru yang ditambahkan selama ini, tetapi kami dapat berpikir tentang basis kode saat ini, dan merancang sistem yang jauh lebih baik untuk apa yang kami lakukan.

Kami sekarang melewati rintangan itu, dan telah menambahkan fitur baru lagi.


Ini adalah gesekan besar lainnya untuk ditemukan. Harus mengatakan kepada pelanggan - bahwa kita sekarang sedang membangun hal yang sama - fitur yang bukan hal baru, setelah versi pertama diserahkan! Seberapa sering, dan sering (jika pernah) Anda mampu untuk mengatakan ini kepada pelanggan? atau bagaimana Anda menjelaskan?
Dipan Mehta

Anda memiliki dua opsi dasar, baik pertama-tama Anda hanya mengatakan kebenaran yang sederhana - bahwa meskipun apa yang telah Anda kerjakan itu berantakan dan perlu dirapihkan untuk bergerak maju atau kedua yang Anda katakan bahwa Anda sedang membangun infrastruktur untuk mendukung pembangunan yang sedang berjalan ( yang tidak kalah benar tetapi berputar sehingga menjadi sedikit lebih positif). Anda dapat menyelesaikan keduanya dengan mengatakan bahwa untuk memberikan fungsionalitas, kami mengeluarkan hutang teknis yang sekarang harus dibayar kembali.
Murph

@Dipan Mehta: Yah, misalkan pelanggan menginginkan rumah dua lantai. Anda mendesainnya dan mengirimkannya. Kemudian mereka ingin memiliki empat lantai tambahan. Anda berkata, yah, saya harus menghabiskan waktu ini hanya untuk membuat bangunan yang sekarang lebih kuat sehingga akan menampung empat lantai tambahan. Jadi saya tidak berpikir ini harus menjadi masalah bagi pelanggan jika rencana awal hanya mencakup dua lantai. Jika enam lantai direncanakan sejak awal, ya, itu bisa menjadi masalah untuk memberi tahu pelanggan.
Giorgio

@DipanMehta Kami juga sedikit beruntung karena pelanggan tidak perlu tahu tentang proyek ini. Ini merupakan upgrade ke produk yang mereka gunakan saat ini, dengan tanggal penyelesaian semi-samar sekitar akhir tahun ini. Jadi mereka bahkan tidak perlu tahu tentang penundaan untuk refactoring;) (Manajer yang menangani sebagian besar keputusan desain ada di rumah)
Izkata

2

Kunci untuk membatasi biaya perubahan desain adalah menjaga kode tetap kering. Ini akan mengarahkan sebagian besar kode aplikasi ke tingkat yang sangat tinggi, di mana sebagian besar kode secara langsung menyatakan niatnya, dan relatif sedikit menentukan mekanisme. Jika Anda melakukan ini, maka keputusan desain akan memiliki ekspresi sekecil mungkin dalam kode, dan perubahan desain akan memiliki biaya sekecil mungkin.


2

Kunci untuk menghindari jalan buntu desain adalah mengenali sedini mungkin ketika desain Anda perlu berubah, dan mengubahnya kemudian. Masalah terbesar datang bukan dengan terus mengembangkan desain Anda, tetapi dengan menolak untuk mengembangkan desain Anda sampai itu merupakan masalah besar.

Sebagai contoh, Netflix memiliki fitur profil, di mana anggota keluarga yang berbeda dapat menagih ke paket yang sama, tetapi memiliki antrian yang terpisah. Beberapa tahun yang lalu, mereka mengumumkan bahwa mereka harus membatalkan fitur itu, karena hanya sekitar 10% dari pengguna mereka yang menggunakannya, tetapi karena peretasan pada implementasi, itu memakan banyak sekali pekerjaan pemeliharaan. Setelah keributan, mereka menggigit peluru dan melakukan desain ulang yang mahal untuk mempertahankan pelanggan tersebut.

Saya yakin ada beberapa insinyur yang mengenali desain suboptimal ketika mereka pertama kali menambahkan fitur itu. Jika mereka mengubahnya saat itu, itu tidak akan menjadi masalah besar.


1

Bukannya Fred Brooks yang mengatakan sesuatu seperti "Berencana membuang yang pertama"? Jangan merasa terlalu murung tentang hal itu, desain buntu juga muncul dalam proyek yang mencoba melakukan semua desain di muka juga. Redesain terjadi di semua jenis pengembangan, baik karena itu adalah desain yang tidak bisa dijalankan sejak awal (20% terakhir yang diklik- "iblis ada dalam detail") atau karena pelanggan mengubah fokus mereka. Tidak ada kebutuhan nyata untuk bel alarm, jangan terlalu khawatir.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.