Di recente ho assistito a sempre più problemi simili a quelli spiegati in questo articolo sulle intersezioni di funzioni. Un altro termine sarebbe linee di prodotto, anche se tendo ad attribuirle a prodotti effettivamente 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 funzionalità 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 cosa avrebbe dovuto essere un semplice bugfix potrebbe persino trasformarsi in richiedere importanti modifiche alla progettazione.
Le dimensioni di questo problema di intersezione di caratteristiche sono di una complessità strabiliante. Supponiamo che la versione corrente del software abbia N
funzionalità e tu aggiunga una nuova funzionalità. Semplifichiamo anche le cose dicendo che ciascuna delle funzionalità può essere attivata o disattivata solo, quindi hai già 2^(N+1)
possibili combinazioni di funzionalità da considerare. A causa della mancanza di migliori termini di formulazione / ricerca, mi riferisco all'esistenza di queste combinazioni come problema di intersezione di caratteristiche . (Punti bonus per una risposta che includono riferimenti a un termine più definito.)
Ora la domanda con cui ho difficoltà è come affrontare questo problema di complessità ad ogni livello del processo di sviluppo. Per ovvi motivi di costo, non è pratico fino al punto di essere utopistici, voler affrontare ogni combinazione individualmente. Dopotutto, proviamo a stare lontani dagli algoritmi di complessità esponenziale 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 esplode alcun budget ed è completo in un modo decente, utile e professionalmente accettabile.
Specifica: quando si specifica una nuova funzione, come si fa a garantire che funzioni bene con tutti gli altri bambini?
Vedo che si potrebbe esaminare sistematicamente ogni funzionalità esistente in combinazione con la nuova funzionalità, ma sarebbe in isolamento dalle altre funzionalità. Data la natura complessa di alcune caratteristiche, questa visione isolata è spesso già così coinvolta che ha bisogno di un approccio strutturato tutto in sé, per non parlare del
2^(N-1)
fattore causato dalle altre caratteristiche che uno ha ignorato volontariamente.Implementazione: quando si implementa una funzionalità, come assicurarsi che il codice interagisca / intersechi correttamente in tutti i casi.
Ancora una volta, mi chiedo la pura complessità. Conosco varie tecniche per ridurre il potenziale di errore di due funzioni che si intersecano, ma nessuna che si ridimensionerebbe in modo ragionevole. Presumo però che una buona strategia durante la specifica dovrebbe tenere a bada il problema durante l'implementazione.
Verifica: quando provi 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 al codice privo di errori, ma quando lo si riduce a una frazione di
2^-N
esso sembra che centinaia di test non coprano nemmeno una singola goccia d'acqua in tutti gli oceani messi insieme . Ancor peggio, gli errori più problematici sono quelli che derivano dall'intersezione di funzionalità, che non ci si potrebbe aspettare di portare a problemi - ma come si fa a testare questi se non ci si aspetta un'intersezione così forte?
Anche se vorrei sapere 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 determinata strategia, sarebbe bello includere nella tua risposta fonti corrispondenti.