Recentemente ho assistito a sempre più problemi simili a quelli spiegati in questo articolo sulle intersezioni delle funzionalità . Un altro termine per questo sarebbe linee di prodotto, anche se tendo ad attribuirle a prodotti realmente diversi, mentre di solito incontro questi problemi sotto forma di possibili configurazioni di prodotto.
L'idea di base di questo tipo di problema è semplice: aggiungi una funzione a un prodotto, ma in qualche modo le cose si complicano a causa di una combinazione di altre funzionalità esistenti. Alla fine, il QA trova un problema con una rara combinazione di funzionalità che nessuno ha mai pensato prima e che avrebbe dovuto essere una semplice correzione di bug potrebbe persino trasformarsi in una richiesta di modifiche di progettazione importanti.
Le dimensioni di questo problema di intersezione delle feature sono di una complessità strabiliante. Supponiamo che la versione attuale del software abbia funzioni N
e tu aggiunga una nuova funzionalità. Semplifichiamo anche le cose dicendo che ognuna delle funzioni può essere attivata o disattivata solo, quindi hai già 2^(N+1)
di possibili combinazioni di funzioni da considerare. A causa della mancanza di termini migliori di parole / ricerca, mi riferisco all'esistenza di queste combinazioni come problema di intersezione di caratteristiche . (Punti bonus per una risposta inclusi riferimenti (s) per un termine più stabilito.)
Ora la domanda con cui lotto è come affrontare questo problema di complessità a ogni livello del processo di sviluppo. Per ovvi motivi di costo, non è pratico fino al punto di essere utopico, di voler affrontare ciascuna combinazione individualmente. Dopotutto, cerchiamo di evitare gli esponenziali algoritmi di complessità per una buona ragione, ma trasformare lo stesso processo di sviluppo in un mostro di dimensioni esponenziali è destinato a portare a un totale fallimento.
Quindi, come ottenere il miglior risultato in modo sistematico che non esploda i budget e sia completo in un modo accettabile, utile e professionalmente accettabile.
-
Specifica: quando specifichi una nuova funzione: come ti assicuri che funzioni bene con tutti gli altri bambini?
Vedo che è possibile esaminare sistematicamente ciascuna funzione esistente in combinazione con la nuova funzione, ma ciò sarebbe isolato rispetto alle altre funzionalità. Data la natura complessa di alcune funzionalità, questa visione isolata è spesso già così coinvolta da richiedere un approccio strutturato tutto in sé, per non parlare del fattore
2^(N-1)
causato dalle altre funzionalità che uno ha volutamente ignorato. -
Implementazione: quando implementi una funzione, come assicurati che il tuo codice interagisca / intersechi correttamente in tutti i casi.
Ancora una volta, mi sto interrogando sulla pura complessità. Conosco varie tecniche per ridurre il potenziale di errore di due feature intersecanti, ma nessuna che possa scalare in modo ragionevole. Presumo però che una buona strategia durante le specifiche dovrebbe tenere a bada il problema durante l'implementazione.
-
Verifica: quando collaudi una funzione, come gestisci il fatto che puoi testare solo una frazione di questo spazio di intersezione della funzione?
È abbastanza difficile sapere che testare una singola funzione in isolamento non garantisce nulla vicino a un codice privo di errori, ma quando si riduce che a una frazione di
2^-N
sembra che centinaia di test non lo siano anche coprendo una singola goccia d'acqua in tutti gli oceani combinati. Ancor peggio, gli errori più problematici sono quelli che derivano dall'intersezione di caratteristiche, che non ci si potrebbe aspettare che possano causare problemi - ma come si fa a testare per questi se non si prevede un incrocio così strong?
Mentre mi piacerebbe sentire come gli altri affrontano questo problema, sono principalmente interessato alla letteratura o agli articoli che analizzano l'argomento in modo più approfondito. Quindi, se segui personalmente una certa strategia, sarebbe bello includere le fonti corrispondenti nella tua risposta.