Come gestisci un salto di complessità?

13

Sembra un'esperienza rara ma comune che a volte stai lavorando a un progetto e all'improvviso qualcosa si presenta inaspettatamente, getta una grossa chiave nelle opere e aumenta enormemente la complessità.

Ad esempio, stavo lavorando a un'applicazione che comunicava con i servizi SOAP su varie altre macchine. Ho montato un prototipo che funzionava bene, poi ho continuato a sviluppare un front end regolare e in generale ho messo tutto in funzione in un modo piacevole, abbastanza semplice e facile da seguire. Ha funzionato benissimo fino a quando non abbiamo iniziato a testare su una rete più ampia e improvvisamente le pagine hanno iniziato a scadere in quanto la latenza delle connessioni e il tempo necessario per eseguire calcoli su macchine remote hanno portato a richieste scadute per i servizi di sapone. È emerso che avevamo bisogno di cambiare l'architettura per far girare le richieste sui propri thread e memorizzare nella cache i dati restituiti in modo che potessero essere aggiornati progressivamente in background invece di eseguire calcoli su una richiesta per richiesta.

I dettagli di questo scenario non sono troppo importanti - anzi non è un grande esempio in quanto era piuttosto prevedibile e le persone che hanno scritto molte app di questo tipo per questo tipo di ambiente potrebbero averlo previsto - tranne che illustra un modo per iniziare con una premessa e un modello semplici e avere improvvisamente un'escalation di complessità nello sviluppo del progetto.

Quali strategie hai per affrontare questi tipi di cambiamenti funzionali di cui c'è bisogno - spesso come risultato di fattori ambientali piuttosto che di cambiamenti delle specifiche - più avanti nel processo di sviluppo o come risultato di test? Come bilanciare tra l'evitare l'ottimizzazione prematura / YAGNI / i rischi di overengineering della progettazione di una soluzione che mitiga i problemi possibili ma non necessariamente probabili anziché sviluppare una soluzione più semplice e facile che rischia di essere altrettanto efficace ma non include la preparazione per ogni eventualità possibile?

Modifica: la risposta di Crazy Eddie include "fai schifo e trova il modo meno costoso per implementare la nuova complessità". Questo mi ha fatto pensare a qualcosa che era implicito nella domanda, ma non ho sollevato specificamente.

Una volta colpito l'urto, incorporerai le modifiche necessarie. Fai la cosa che manterrà il progetto il più vicino possibile, ma potrebbe influire sulla manutenibilità o tornerai alla tua architettura e la rielaborerai a un livello più dettagliato che potrebbe essere più gestibile ma spingerà tutto indietro durante lo sviluppo?

    
posta glenatron 10.02.2011 - 15:51
fonte

8 risposte

8

Ciò che mi viene in mente è leggere l'agile adagio: affrontare le attività più rischiose e / o meno comprese prima all'interno del ciclo di vita del progetto . Cioè prova a mettere insieme uno scheletro funzionante del progetto il prima possibile, per dimostrare che il concetto funziona. Ciò a sua volta consente anche di eseguire qualsiasi tipo di test crudele per rilevare se l'architettura offre realmente la sua promessa in circostanze di vita reale. Inoltre, se c'è una nuova tecnologia / piattaforma / strumento sconosciuta inclusa nella soluzione, prendila subito sul piatto.

Se l'architettura core è OK, le funzionalità individuali possono essere aggiunte e testate in modo incrementale e refactored quando necessario, con costi relativamente minori. La necessità di cambiare l'architettura è il grande rischio, che si dovrebbe affrontare in anticipo. Questo dà un rapido riscontro: nel peggiore dei casi, se l'intero concetto cade a pezzi, lo conosciamo presto e possiamo abortire il progetto con una perdita minima.

    
risposta data 10.02.2011 - 16:09
fonte
6

Il tuo esempio ha toccato alcuni degli aspetti più impegnativi della programmazione, ovvero computing distribuito e programmazione concorrente , che sono sempre più utilizzati e rendono i programmatori sempre più difficili.

Anche la programmazione "normale" (thread singolo su una macchina) è così massicciamente complessa per qualsiasi programma non trofico, che ci vuole una grande abilità e anni di esperienza per ottenere risultati positivi - ma ancora lontani da " risolto". Anche a questo livello le complessità, per lo più dovute a esplosione combinatoria , superano di molto la capacità del cervello umano capire e capire. Pensare diversamente è sciocco.

L'elaborazione distribuita e la programmazione concorrente aggiungono altre due dimensioni alle dimensioni dello spazio "complessità", che cresce almeno in cubico (sp?) (n ^ 3) rispetto alla programmazione "normale". Per esempio, pensiamo a qualche nuova serie di problemi e a fallacies che dobbiamo affrontare. Anche giocare con un'idea, che potresti capire le interconnessioni e gli effetti collaterali a questa scala è ridicolo.

Ovviamente non ho nessun proiettile d'argento, ma sono sicuro che il errore più grande che puoi fare è pensare che tu capisca tutto & risolto.

Alcune idee su come affrontare tutto questo, oltre a ciò che altre risposte hanno già trattato:

  • Grande umiltà
  • Accetta che il tuo sistema / programma sia imperfetto, impermanente e incompleto .
  • Prepara errori
  • Abbraccia il cambiamento
  • Pianifica ridondanza
  • Pensa a verifica futura
  • Guarda (o studia) la biologia o la sociologia su come si comportano i sistemi complessi
  • Fai del tuo meglio per evitare lo stato mutabile. Vai a protocolli senza stato (come REST e HTTP).
  • La programmazione funzionale potrebbe alleviare parte del dolore

Credo di poter andare avanti all'infinito. Argomento molto interessante:)

    
risposta data 10.02.2011 - 21:05
fonte
2

Non sono d'accordo con lo spirito della risposta di @ Péter Török perché presuppone che un team (o un individuo) possa necessariamente prevedere gli elementi più rischiosi all'inizio del ciclo di vita del progetto. Ad esempio, nel caso dell'OP, il team non poteva prevedere la crescente complessità associata alla soluzione multi-thread fino a quando le loro schiene erano contro il muro.

La domanda dell'OP è buona e parla di un problema che hanno molti negozi di sviluppo software.

Ecco come vorrei affrontare il problema:

  1. Segui il consiglio di Fred Brooks e organizza i tuoi sviluppatori come un team chirurgico .
  2. Scegli un maestro-chirurgo saggio e "benevolo" che possa entrambi: A) Garner la fiducia e il rispetto dei suoi pari; e B) Prendere decisioni difficili in modo tempestivo.
  3. Aspettati che il master-chirurgo riduca la complessità nel front-end e nel back-end del processo di sviluppo.

Altro sul punto # 3:

  1. Il maestro chirurgo dovrebbe fare uno sforzo consapevole per proporre la soluzione più semplice che funzionerà. Anni di esperienza significativa dovrebbero mettere il maestro chirurgo in condizione di farlo.
  2. L'organizzazione più ampia, cioè i superiori del maestro-chirurgo, dovrebbe fornire al team tempo e risorse sufficienti per ridurre la complessità dopo la data di spedizione. Ciò consentirà al team di sviluppo di spedire il codice in modo tempestivo ed eseguire kaizen per ridurre la complessità in modo continuativo.
risposta data 10.02.2011 - 17:04
fonte
1

Codice alle interfacce

Quando si scrivono nuove funzionalità che si interfacciano con altre funzionalità, si crea un confine sotto forma di un'interfaccia (il tipo Java) attraverso la quale passano tutti. Questo sarà

  1. assicurati di avere il pieno controllo su quali funzionalità vengono utilizzate
  2. ti consente di avere più implementazioni della stessa funzionalità.
  3. mantieni la complessità generale verso il basso perché i moduli sono collegati solo in modo sottile invece di essere completamente intrecciati.
risposta data 10.02.2011 - 20:54
fonte
0

one can start with a simple premise and model and suddenly have an escalation of complexity well into the development of the project

Non sorprende.

Questo è lo sviluppo del software. Se non stai inventando qualcosa di nuovo, stai scaricando una soluzione esistente e collaudata.

C'è una via di mezzo.

Se stai inventando qualcosa di nuovo, allora ci deve essere almeno una caratteristica che non capisci completamente. (Per capirlo fully , dovresti avere un'implementazione funzionante, che useresti.)

Come gestirlo?

  1. Hai aspettative realistiche. Stai inventando qualcosa di nuovo. Lì deve essere parti che non capisci.

  2. Hai aspettative realistiche. Se sembra che funzioni bene la prima volta, hai trascurato qualcosa.

  3. Hai aspettative realistiche. Se fosse semplice, qualcun altro l'avrebbe fatto prima, e potevi semplicemente scaricare quella soluzione.

  4. Hai aspettative realistiche. Non puoi predire il futuro molto bene.

risposta data 10.02.2011 - 16:44
fonte
0

Progettare e codificare con l'obsolescenza in mente. Supponiamo che quello che codifichi oggi dovrà essere tagliato e sostituito domani.

    
risposta data 10.02.2011 - 17:34
fonte
0

L'ambiente dovrebbe far parte delle specifiche. Quindi un cambio di ambiente è un cambiamento alle specifiche. Se, d'altra parte, hai basato il tuo prototipo e il tuo design in un ambiente diverso da quello che era nelle specifiche, hai fatto un errore stupido. Ad ogni modo, lo fai su e trova il modo meno costoso per implementare la nuova complessità.

    
risposta data 10.02.2011 - 19:47
fonte
0

Come per la maggior parte dei problemi di programmazione, dipende , secondo me. Questo problema è così intrinseco al lavoro creativo, che non bisogna dimenticare che i fallimenti stanno per accadere, e questo è O.K. . La programmazione è un problema malvagio e di solito non conosci la soluzione giusta al problema finché non lo hai già risolto.

Tuttavia, ci sono una serie di fattori specifici locali che potrebbero entrare in gioco qui, come ad esempio:

  • Gli obiettivi per questo sistema. È una cosa una tantum? Hai intenzione di mantenere questo sistema funzionante a medio-lungo termine?

Per cose a breve termine, potrebbe non valerne la pena pensarci più che abbastanza per farlo funzionare. Il refactoring è costoso ed è qualcosa che non crea un valore finale immediato per il tuo utente. Tuttavia , non c'è praticamente nessun caso che io possa pensare al di fuori del software di eliminazione assoluta, dove è così breve che non vale la pena migliorare il tuo design. È molto più importante essere in grado di capire quello che hai fatto, e risolverlo rapidamente, che finire in questo momento. Se è a lungo termine, molto probabilmente pagherà alla fine (e probabilmente molto prima di quanto pensano tutti coinvolti), o l'inverso (non farlo causerà molto presto dolore invece di "quando dobbiamo aggiustarlo"). Sono quasi tentato di dire "prenditi sempre il tempo per migliorarlo", ma ci sono alcuni casi in cui ciò non è possibile.

  • Gli obiettivi della squadra. È più un "fai ora, ad ogni costo" o un "facciamolo"?

Questo dovrebbe influenzare enormemente le tue decisioni. Il tuo team sosterrà questa decisione o ti darà risorse per riprogettarlo, o richiederanno che la soluzione rapida sia fatta ora. Secondo me, se trovi che la squadra ti sta spingendo nella direzione sbagliata, è un'enorme bandiera rossa. Ho visto questo genere di cose finire in uno scenario in cui c'è costante estinzione di incendi in corso, dove non c'è mai tempo di riprogettare perché stai sempre correggendo i problemi creati dal tuo cattivo disegno. Ci può anche essere una via di mezzo, però: "nastro adesivo" adesso, aggiusta ASAP (ma fallo davvero).

  • La tua comprensione del problema. Perché la soluzione precedente non funzionava?

Davvero importante. Pensa a cos'è l'errore o il problema e perché sta accadendo. Questo tipo di situazione è una grande opportunità per trovare ipotesi, vincoli e interazioni imperfette (o mancanti). In generale, preferisci sempre capire meglio il tuo problema invece di risolvere il problema attuale. Questa è probabilmente la tua più grande difesa contro YAGNI / overengineering. Se capisci bene il tuo problema, allora risolverai it e non altri problemi.

Infine, cerca di costruire le cose nel modo giusto . Non sto parlando degli errori e dei problemi che affronti quando riesci a capire meglio il problema o il tuo errore umano intrinseco. Non intendo "non commettere errori e farlo diventare perfetto la prima volta": è impossibile. Voglio dire, prova a gestire bene la complessità nel tuo lavoro quotidiano, a correggere le finestre rotte, a mantenere il più semplice possibile, a migliorare il tuo codice e il tuo modo di pensare in ogni momento. In questo modo quando (non se) cambia bussa alla tua porta, puoi accoglierlo a braccia aperte anziché con un fucile.

    
risposta data 06.03.2015 - 23:14
fonte

Leggi altre domande sui tag