Come posso superare la paralisi mediante analisi durante la codifica?


37

Quando inizio un nuovo progetto, spesso inizio immediatamente a pensare ai dettagli dell'implementazione. "Dove inserirò DataBaseHandler? Come dovrei usarlo? Le classi che vogliono usarlo dovrebbero estendersi da qualche superclasse astratta ...? Dovrei usare un'interfaccia? Quale livello di astrazione userò nella mia classe che contiene metodi per inviare richieste e analizzare dati? "

Finisco per un lungo periodo di stallo perché voglio programmare estensibilità e riusabilità. Ma mi sembra quasi impossibile superare il pensiero di come implementarlo perfettamente.

E poi, se provo solo a dire "fanculo, fallo!", Colpisco un muro di mattoni abbastanza rapidamente perché il mio codice non è organizzato, mischio livelli di astrazioni, ecc.

Quali sono alcune tecniche / metodi che hai per lanciarti in un nuovo progetto e allo stesso tempo creare una struttura logica / modulare che si ridimensionerà bene?

- - MODIFICA - -

Bene, questo è già il tipo di domanda a cui è difficile accettare una risposta, ma voleva ottenere un feedback in più, vedere se c'è un consenso. TDD sembra davvero bello e, francamente, intendevo ottenere più veloce usando JUnit, ecc. Allo stesso tempo, cosa pensano i fan di TDD del fatto che un punto legittimo in relazione a TDD risolve il mio problemi particolari, è che TDD non sembra davvero affrontare la questione del design. Certo, sono d'accordo che TDD mi aiuterà a definire ciò che voglio fare e quindi posso gradualmente esaminare il come, ma ci sono molti diversi modelli / strutture di progettazione generali che potrebbero passare attraverso i test unitari. Questo è tutto: testa singole UNITÀ. Immagino di essere un po 'confuso ... Non lo so. Forse io'

Grazie!


2
Fai un passo indietro, prendi carta e penna, disegna l'immagine più grande. questo ti aiuterà a progettare l'implementazione in un modo più strutturato piuttosto che perdere te stesso nei dettagli ...
Darknight

Questa è un'ottima domanda Questa è una trappola in cui sono stato anche colpevole di cadere.
Corv1nus,

Risposte:


16

Consiglio di usare Test-Driven-Development , ci vuole un po 'per abituarsi soprattutto quando si lavora con un buon IDE come l'eclissi, ma i vantaggi sono grandi.

Fondamentalmente quello che fai è scrivere i test sul tuo codice prima di scrivere il codice stesso. Quindi sei costretto a guardare il tuo codice dal punto di vista di come verrà utilizzato, il che significa che le tue interfacce evolvono più scenari implementerai.

Un'altra caratteristica è che si implementano in blocchi molto piccoli (diventano più grandi quanto più si è esperti nella tecnica e nella programmazione), quindi ti costringe a concentrarti ogni volta su un problema molto piccolo e ben definito.

E anche dal momento che scrivi per la prima volta un test e solo successivamente esegui, hai un test fallito di fronte a te. Quindi, se sei come la maggior parte dei programmatori, non ti lascerai trasportare da un'analisi folle perché penserai: "Devo far funzionare questo test".

Un breve esempio di Java:
dire che voglio sviluppare un programma che legge e scrive un messaggio da un db.

Quindi inizio con la prima azione ben definita, ho bisogno di un DB:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
}

ok, quindi qui vedo che devo implementare la classe DbConnector.getDB in modo che restituisca il DB, fino a quando questo test fallisce. Vado e lo faccio ...

Non aggiungo la prossima cosa che voglio fare, carico il messaggio dal DB:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
}

Ora ho aggiunto un'altra piccola funzionalità al DB che è quella di recuperare un messaggio, vado e implemento quello, una volta finito continuo ad andare avanti una funzione alla volta fino a raggiungere qualcosa del genere:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
  message = "foo bar";
  db.storeMessage(message);
  message = db.fetchMessage();
  assertEquals("foo bar", message);
}

Potrebbe sembrare un esempio molto semplice, ma funziona anche per compiti più complessi. So che all'inizio richiede molto tempo, ma man mano che ti ci abitui vedi che in effetti è molto più efficiente. Per uno si evita la paralisi mediante analisi e per un altro si ottiene un codice molto più robusto che di solito ha meno bug e attraversa meno iterazioni.


4
E TDD ti costringe a refactoring molto, quindi stai entrando in una modalità di lavoro di refactoring continuo che ti aiuterà a sfondare il muro di mattoni di codice incasinato, come programmers.stackexchange.com/questions/86364/… menzionato.
rabbia

In realtà trovo che l'aspetto del primo test del TDD sia un ostacolo in questo tipo di circostanze. Se ho abbastanza problemi a progettare l'interfaccia stessa, come sarà più facile o più ovvio progettare i test? Questo e l'onere del refattore all'inizio del tentativo di progettare qualcosa è troppo alto. Mi chiedo come gli altri lo affrontino.
Steven Evers,

1
@SnOrfus, giusto. TDD funziona bene quando hai i tuoi moduli e vuoi concentrarti su cosa contro come. Ma quei moduli potrebbero essere organizzati in vari modi. Il modo in cui sono raggruppati, quale tipo di struttura utilizzerai non viene chiarito attraverso TDD.
Modalità di lusso

5
Hmmmm sembra un fanboy TDD ..... Cosa è mai successo usando carta e penna per disegnare un'architettura? o sono vecchio stile e non abbastanza "alla moda" ....
Darknight,

1
Carta e penna (o lavagna) sono buone. Disegna il piano generale, il quadro generale. Se non si adatta a un pezzo di carta, è troppo complicato. Una volta che hai il piano generale, puoi occuparti di BDD, derisione, ecc.
Donal Fellows,

10

Questo succede a me, quindi ho preso l'abitudine di accettare (e abbracciare) una mentalità di continuo refactoring. Faccio la cosa più semplice che potrebbe funzionare, quindi la pulisco, la organizzo, la disaccoppiamento, la collaudo e vado avanti.

Questo non vuol dire che non ci sia molta pianificazione in corso, ma succede molto rapidamente e più spesso come scarabocchi su rottami o nella mia testa. Tutto sommato, a volte chiamo questo piccolo processo micro-iterazioni perché impiegano 5-20 minuti ciascuna e dall'esperienza ci vogliono 2-3 per finire ciò su cui sto lavorando (a seconda di ciò che sto facendo, ovviamente).

Come nota a margine: ho istruito un certo numero di persone in diverse forme di scrittura (relazioni, saggi e scrittura tecnica in generale) e questo è lo stesso modo in cui riesco a scrivere cose per superare il blocco dello scrittore. "Basta cancellare qualsiasi cosa sul tuo argomento che mi viene in mente sulla pagina. Quindi avremo senso da esso e lo separeremo in paragrafi e controlleremo il flusso. Se necessario, lo riscriveremo persino."


1
+1 per menzionare la scrittura. Di recente ho adottato l'approccio di refactoring frequente dalla codifica e l'ho applicato alla scrittura; funziona molto bene per me.
Zsolt Török,

2

Alcune cose che potrebbero funzionare:

  • Identifica il problema principale che stai cercando di risolvere: qual è il cuore della cosa che vuoi fare? Implementa proprio questo e il minimo indispensabile del codice di supporto per farlo funzionare. Una volta che funziona per la tua soddisfazione, costruisci iterativamente, refactoring senza pietà ad ogni passo.
  • Vedi se altri paradigmi di programmazione funzionano per te. Nonostante tutti i suoi meriti, la programmazione orientata agli oggetti non è la risposta a tutti i problemi e non tutti i cervelli dei programmatori funzionano in questo modo. Impara un linguaggio (puro) funzionale; scrivere un codice procedurale; tuffarsi al livello hardware e fare un po 'di C o forse anche un assemblatore; ecc. Alcune lingue che potrebbero scuotere la mente (supponendo che stai attualmente utilizzando qualcosa come C ++ / Java / C # / VB / ...): Haskell, ML, Lisp (vari dialetti tra cui scegliere), Erlang, Prolog, Smalltalk, Javascript (se lasci andare il tentativo di farlo comportare come Java e abbraccia invece la sua natura di chiusura), C, Pascal, awk e probabilmente una dozzina di più. La caratteristica fondamentale è che devono essere molto diversi da quelli che usi ora. Questo non è qualcosa che vuoi fare su un grande progetto con molto in ballo,
  • Utilizzare un metodo di progettazione radicalmente diverso. Vedi se riesci a raccogliere il design da un'angolazione diversa. Suppongo che di solito inizi a progettare organizzando le tue lezioni; che ne dici di iniziare con le strutture dati per un cambiamento? O che ne dici di progettare prima l'interfaccia utente, disegnando letteralmente moduli di input prima di progettare qualsiasi funzionalità?

1

Per molte decisioni di progettazione può essere utile fare uno "spike" che è uno sforzo di ricerca breve e limitato nel tempo in cui è possibile esplorare alcune opzioni di architettura o progettazione codificando un prototipo da buttare via. Ad esempio potresti esplorare l'uso di alcune librerie open source o come organizzerai le tue classi e interfacce. La chiave è di mantenerlo breve in modo da poter provare un altro approccio se il primo è insoddisfacente e si spera che acquisirai abbastanza conoscenza nell'esercizio per prendere meglio le decisioni sull'architettura o per dimostrare il concetto. L'esercizio stesso prevede una codifica immediata che aiuta a uscire dal "blocco degli scrittori" senza necessariamente impegnarsi con "il lavoro fatto" troppo presto.

Dopodiché è utile utilizzare l'approccio TDD o BDD menzionato da Asaf per proseguire con l'attuazione del progetto.


+1 Sono d'accordo. Pianifica di buttare via il primo tentativo. Trattalo come un'esperienza di apprendimento. Ne ho buttati via almeno sei, prima di pensare di voler restare con il settimo.
Mike Dunlavey,

1

Non ne avrai bisogno , quindi non pensare troppo all'inizio.

Investi più tempo per definire, capire l'obiettivo e il problema.

"Estensibilità e riusabilità" è il risultato naturale del ciclo di vita di programmi software ben scritti.


0

Presumo che stiamo guardando un progetto di medie dimensioni.
Vorrei iniziare andando sul tavolo da disegno. È necessario disporre dei requisiti funzionali e non funzionali prima di eseguire questa operazione. In primo luogo verrebbe fuori l'archiviazione del software, vale a dire guardare qualsiasi modello architettonico che soddisfi le vostre esigenze
Una volta deciso su come appare la vostra architettura, dovreste passare al design di basso livello i, e guardare tutte le entità, le classi e le funzionalità . Qui, proverai di nuovo a identificare i modelli di progettazione che si adattano. Nel processo, saprai quali sono le tue classi di base e le interfacce di cui avresti bisogno
Puoi quindi creare il framework ed eseguire alcuni test rapidi per vedere se questo soddisfa tutti i requisiti non funzionali
Vorrei quindi seguire Test Driven Development come suggerito da @Asaf.

Ricorda, nonostante il tempo speso nel design e nell'architettura, sii sempre disposto a rivisitare l'architettura in caso di necessità.


0

Penso che questa sia un'ottima domanda e nulla funzionerà per tutti. Penso che tale paralisi sia un sottoprodotto naturale di diventare sempre più competente nel tuo campo. Detto questo, ecco alcune cose che faccio che aiutano, ma non risolve il problema:

  • Metti da parte il tuo progetto incontaminato e lavora sulla versione fuggiasca. Questa è la versione in cui ti dici: a. Il codice non dovrebbe essere carino. In effetti, dite a voi stessi che non sono consentiti importanti refactoring e riformattazioni. Lascia che sia assolutamente disorganizzato e libera te stesso dai legami della buona codifica. b. Deve solo funzionare. c. Mi sorprende sempre quello che apprendo sullo spazio problematico quando lancio tutte le altre preoccupazioni. Finisco anche con piccoli bocconcini che spesso mi aiutano a trovare il giusto design in un modo più illuminato.

  • Metti da parte un intervallo di tempo decente in cui ti trovi nel progetto, solo senza un computer. Cerca di concettualizzare ciò che stai davvero cercando di realizzare e cerca quel magico zen che trascende la follia di OO / Design Pattern.


0

Dai un'espressione concreta ai tuoi pensieri: scrivili / scrivili, disegnali o altro. Questo ti aiuterà a rivisitare i tuoi pensieri quando necessario; ti impedirà di andare in cerchio; ti aiuta a pensare più chiaramente.

Ogni volta che mi vedo andare da nessuna parte e ovunque a pensare a qualcosa, li scrivo e mi aiuta a pensare chiaramente.


0

Di solito parto da zero, creo il prototipo più semplice possibile e faccio funzionare qualcosa. Utilizzare il prototipo per decodificare i casi di test del percorso felice, i casi di test per guidare le interfacce e quindi pensare ai contratti pre / post per aiutare a costruire la copertura dei test.

Non preoccuparti di astrazione, ottimizzazione o verifica fino a quando il problema non è stato completamente compreso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.