Berurusan dengan Persimpangan Fitur


11

Baru-baru ini saya menyaksikan semakin banyak masalah yang serupa dengan yang dijelaskan dalam artikel ini tentang persimpangan fitur. Istilah lain untuk itu adalah lini produk, meskipun saya cenderung menghubungkan ini dengan produk yang sebenarnya berbeda, sedangkan saya biasanya menghadapi masalah ini dalam bentuk kemungkinan konfigurasi produk.

Gagasan dasar dari jenis masalah ini sederhana: Anda menambahkan fitur ke suatu produk, tetapi entah bagaimana hal menjadi rumit karena kombinasi dari fitur yang ada lainnya. Akhirnya, QA menemukan masalah dengan kombinasi fitur yang jarang ada yang tidak dipikirkan sebelumnya dan apa yang seharusnya menjadi perbaikan bug sederhana bahkan dapat berubah menjadi membutuhkan perubahan desain besar.

Dimensi dari masalah persimpangan fitur ini adalah kompleksitas yang mengejutkan. Katakanlah versi perangkat lunak saat ini memiliki Nfitur dan Anda menambahkan satu fitur baru. Mari kita sederhanakan juga dengan mengatakan bahwa masing-masing fitur dapat dihidupkan atau dimatikan saja, maka Anda sudah memiliki 2^(N+1)kemungkinan kombinasi fitur untuk dipertimbangkan. Karena kurangnya kata-kata yang lebih baik / istilah pencarian, saya menyebut keberadaan kombinasi ini sebagai masalah persimpangan fitur . (Poin bonus untuk jawaban termasuk referensi untuk jangka waktu yang lebih mapan.)

Sekarang pertanyaan yang saya perjuangkan adalah bagaimana menangani masalah kompleksitas ini pada setiap tingkat proses pengembangan. Untuk alasan biaya yang jelas, tidak praktis sampai menjadi utopis, ingin mengatasi setiap kombinasi secara individual. Bagaimanapun, kami mencoba untuk menjauh dari algoritma kompleksitas eksponensial untuk alasan yang baik, tetapi untuk mengubah proses pengembangan itu sendiri menjadi monster berukuran eksponensial terikat untuk mengarah pada kegagalan total.

Jadi, bagaimana Anda mendapatkan hasil terbaik dengan cara sistematis yang tidak meledakkan anggaran apa pun dan lengkap dengan cara yang layak, bermanfaat, dan diterima secara profesional.

  • Spesifikasi: Ketika Anda menentukan fitur baru - bagaimana Anda memastikan bahwa fitur itu berfungsi baik dengan semua anak lain?

    Saya dapat melihat bahwa seseorang dapat secara sistematis memeriksa setiap fitur yang ada dalam kombinasi dengan fitur baru - tetapi itu akan menjadi isolasi dari fitur-fitur lainnya. Mengingat sifat kompleks dari beberapa fitur, pandangan terisolasi ini sering sudah sangat terlibat sehingga perlu pendekatan terstruktur sendiri, apalagi 2^(N-1)faktor yang disebabkan oleh fitur lain yang satu sengaja diabaikan.

  • Implementasi: Ketika Anda mengimplementasikan fitur - bagaimana Anda memastikan kode Anda berinteraksi / berpotongan dengan benar dalam semua kasus.

    Sekali lagi, saya bertanya-tanya tentang kerumitan semata. Saya tahu berbagai teknik untuk mengurangi potensi kesalahan dari dua fitur berpotongan, tetapi tidak ada yang akan skala dengan cara yang masuk akal. Saya berasumsi, bahwa strategi yang baik selama spesifikasi harus menjaga masalah selama implementasi.

  • Verifikasi: Ketika Anda menguji suatu fitur - bagaimana Anda menghadapi fakta, bahwa Anda hanya dapat menguji sebagian kecil dari ruang persimpangan fitur ini?

    Cukup sulit untuk mengetahui bahwa menguji satu fitur dalam isolasi tidak menjamin apa pun di dekat kode bebas kesalahan, tetapi ketika Anda menguranginya menjadi sepersekian 2^-N, sepertinya ratusan tes bahkan tidak mencakup setetes air pun di semua samudera yang digabungkan . Lebih buruk lagi, kesalahan yang paling bermasalah adalah kesalahan yang berasal dari persimpangan fitur, yang orang mungkin tidak harapkan menyebabkan masalah - tapi bagaimana Anda menguji ini jika Anda tidak mengharapkan persimpangan yang kuat?

Sementara saya ingin mendengar bagaimana orang lain mengatasi masalah ini, saya terutama tertarik pada literatur atau artikel yang menganalisis topik ini secara lebih mendalam. Jadi, jika Anda secara pribadi mengikuti strategi tertentu, alangkah baiknya untuk menyertakan sumber yang sesuai dalam jawaban Anda.


6
Arsitektur aplikasi yang dirancang dengan bijaksana dapat mengakomodasi fitur-fitur baru tanpa membalikkan dunia; pengalaman adalah leveler hebat di sini. Yang mengatakan, arsitektur seperti itu tidak selalu mudah untuk mendapatkan benar pada percobaan pertama, dan kadang-kadang Anda harus membuat penyesuaian yang sulit. Masalah pengujian belum tentu menjadi masalah Anda, jika Anda tahu cara merangkum fitur dan fungsi dengan benar dan menutupinya dengan unit test yang memadai.
Robert Harvey

Jawaban:


6

Kami sudah tahu secara matematis bahwa verifikasi suatu program tidak mungkin dalam waktu yang terbatas dalam kasus yang paling umum, karena masalah penghentian. Jadi masalah seperti ini bukanlah hal baru.

Dalam praktiknya, desain yang baik dapat memberikan decoupling sehingga jumlah fitur berpotongan jauh lebih kecil dari 2 ^ N, meskipun tentu saja tampaknya berada di atas N bahkan dalam sistem yang dirancang dengan baik.

Sejauh sumber, menurut saya bahwa hampir setiap buku atau blog tentang desain perangkat lunak secara efektif berusaha mengurangi 2 ^ N sebanyak mungkin, meskipun saya tidak tahu ada yang melemparkan masalah dalam istilah yang sama seperti Anda melakukan.

Sebagai contoh bagaimana desain mungkin membantu dalam hal ini, dalam artikel tersebut disebutkan beberapa persimpangan fitur terjadi karena replikasi dan pengindeksan keduanya dipicu oleh eTag. Jika mereka memiliki saluran komunikasi lain untuk memberi sinyal kebutuhan masing-masing secara terpisah, maka mungkin mereka dapat mengontrol urutan peristiwa dengan lebih mudah dan memiliki lebih sedikit masalah.

Atau mungkin tidak. Saya tidak tahu apa-apa tentang RavenDB. Arsitektur tidak dapat mencegah masalah persimpangan fitur jika fitur benar-benar saling terkait, dan kita tidak pernah tahu sebelumnya kita tidak akan menginginkan fitur yang benar-benar memiliki kasus terburuk dari persimpangan 2 ^ N. Tetapi arsitektur setidaknya dapat membatasi persimpangan karena masalah implementasi.

Bahkan jika saya salah tentang RavenDB dan eTags (dan saya hanya menggunakannya demi argumen - mereka adalah orang-orang pintar dan mungkin sudah benar), harus jelas bagaimana arsitektur dapat membantu. Kebanyakan pola yang dibicarakan orang dirancang secara eksplisit dengan tujuan mengurangi jumlah perubahan kode yang diperlukan oleh fitur baru atau yang berubah. Ini berjalan mundur - misalnya "Pola Desain, Elemen Perangkat Lunak Berorientasi Objek Reusable", kata pengantar "Setiap pola desain memungkinkan beberapa aspek arsitektur bervariasi secara independen dari aspek lain, sehingga membuat sistem lebih kuat untuk jenis tertentu perubahan".

Maksud saya adalah, orang bisa merasakan Big O dari persimpangan fitur dalam praktek dengan, baik, melihat apa yang terjadi dalam praktek. Dalam meneliti jawaban ini, saya menemukan bahwa sebagian besar analisis titik fungsi / upaya pengembangan (yaitu - produktivitas) ditemukan kurang dari pertumbuhan linier upaya proyek per titik fungsi, atau sangat sedikit di atas pertumbuhan linier. Yang saya temukan agak mengejutkan. Ini memiliki contoh yang cukup mudah dibaca.

Ini (dan studi serupa, beberapa di antaranya menggunakan titik fungsi alih-alih baris kode) tidak membuktikan fitur intersection tidak terjadi dan menyebabkan masalah, tetapi sepertinya bukti yang masuk akal bahwa itu tidak merusak dalam prakteknya.


0

Ini tidak akan menjadi jawaban terbaik dengan cara apa pun, tetapi saya telah memikirkan beberapa hal yang bersinggungan dengan poin dalam pertanyaan Anda, jadi saya pikir saya akan menyebutkannya:

Dukungan Struktural

Dari sedikit yang saya lihat, ketika fitur buggy dan / atau tidak cocok dengan yang lain itu sebagian besar disebabkan oleh dukungan yang buruk yang diberikan oleh struktur inti / kerangka kerja program untuk mengelola / mengoordinasikannya. Menghabiskan lebih banyak waktu menyempurnakan dan menyempurnakan inti, saya pikir, harus memudahkan penambahan fitur baru.

Satu hal yang saya temukan umum dalam aplikasi tempat saya bekerja adalah bahwa struktur suatu program telah diatur untuk menangani salah satu dari jenis objek atau proses tetapi banyak ekstensi yang telah kami lakukan atau ingin miliki. harus dilakukan dengan menangani banyak jenis. Jika ini diperhitungkan lebih pada awal desain aplikasi, maka itu akan membantu menambahkan fitur-fitur ini nanti.

Ini menjadi sangat penting ketika menambahkan dukungan untuk beberapa X yang melibatkan kode berulir / asinkron / event-driven karena hal-hal itu bisa menjadi sangat buruk dengan cepat - Saya sudah senang debugging sejumlah masalah yang berkaitan dengan ini.

Mungkin sulit untuk membenarkan upaya semacam ini di muka, terutama untuk prototipe atau proyek satu kali - meskipun beberapa prototipe atau satu kali terus digunakan lagi atau sebagai (dasar) sistem akhir, artinya pengeluaran akan sia-sia dalam jangka panjang.

Rancangan

Saat merancang inti program, memulai dengan pendekatan top-down dapat membantu mengubah hal-hal menjadi potongan yang dapat dikelola dan memungkinkan Anda membungkus kepala Anda di sekitar domain masalah; setelah itu saya pikir pendekatan bottom-up harus digunakan - ini akan membantu membuat hal-hal lebih kecil, lebih fleksibel, dan lebih baik untuk ditambahkan nanti. (Seperti disebutkan dalam tautan, melakukan hal-hal dengan cara ini membuat implementasi fitur yang lebih kecil, yang berarti lebih sedikit konflik / bug.)

Jika Anda fokus pada blok penyusun inti sistem dan memastikan semuanya berinteraksi dengan baik, maka apa pun yang dibangun dengan menggunakannya mungkin juga akan berperilaku baik dan harus berintegrasi lebih baik dengan sistem lainnya.

Ketika fitur baru ditambahkan, saya pikir rute yang sama bisa diambil dalam mendesainnya seperti yang diambil mendesain sisa kerangka kerja: menguraikannya kemudian pergi dari bawah ke atas. Jika Anda dapat menggunakan kembali salah satu blok asli dari kerangka kerja dalam mengimplementasikan fitur maka itu pasti akan membantu; setelah selesai, Anda dapat menambahkan blok baru yang Anda dapatkan dari fitur ke yang sudah ada dalam kerangka inti, mengujinya dengan set blok asli - dengan cara itu mereka akan kompatibel dengan sisa sistem dan dapat digunakan di masa depan fitur juga.

Menyederhanakan!

Saya telah mengambil sikap minimalis pada desain akhir-akhir ini, mulai dengan menyederhanakan masalah, kemudian menyederhanakan solusinya. Jika waktu dapat dibuat sesaat, menyederhanakan iterasi desain pada suatu proyek maka saya dapat melihat bahwa menjadi sangat membantu ketika menambahkan hal-hal di kemudian hari.

Bagaimanapun, itu 2c saya.

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.