Domanda

I sviluppare e mantenere un grande (500k + LOC) WinForms App scritti in C # 2.0. E 'multi-utente ed è attualmente distribuito su circa 15 macchine. Lo sviluppo del sistema è in corso (può essere pensato come un perpetual beta), e c'è molto poco fatto per proteggere gli utenti da potenziali nuovi bug che potrebbero essere introdotte in una build settimanale.

Per questo motivo, tra gli altri, ho trovato me stesso diventando molto affidamento su Edit-e-proseguire nel debugger. Non solo aiuta con bug-caccia e bug-fixing, ma in alcuni casi con sviluppo in corso pure. Trovo estremamente prezioso per essere in grado di eseguire codice appena scritto nel contesto di un'applicazione in esecuzione - non c'è bisogno di ricompilare e aggiungere un punto di ingresso specifico per il nuovo codice (dover aggiungere opzioni di menu fittizi, pulsanti, ecc per l'applicazione e ricordando di rimuoverli prima della prossima generazione di produzione) -. tutto può essere provato e testato in tempo reale senza arrestare il processo

tengo edit-and-proseguire in così alta considerazione che il codice attivamente scrivere per essere pienamente compatibile con esso. Per esempio, io evito:

  • metodi anonimi e delegati in linea (a meno che non del tutto impossibile per riscrivere)
  • metodi generici (salvo stabile, codice utilità immutabile)
  • Targeting progetti a 'Qualsiasi CPU' (vale a dire non in esecuzione a 64-bit)
  • L'inizializzazione campi in corrispondenza del punto di dichiarazione (inizializzazione viene spostato al costruttore)
  • scrittura blocchi enumeratore che uso yield (tranne nel codice di utilità)

Ora, sono pienamente consapevole del fatto che la nuova lingua dispone in C # 3 e 4 sono in gran parte incompatibili con edit-e-continua (espressioni lambda, LINQ, ecc). Questo è uno dei motivi per cui ho resistito spostamento del progetto fino ad una versione più recente del quadro.

La mia domanda è se è buona norma evitare di utilizzare questi costrutti più avanzati a favore di codice che è molto, molto facile da eseguire il debug? C'è legittimità in questo tipo di sviluppo, o è uno spreco? Inoltre, cosa importante, eseguire una di questi costrutti (espressioni lambda, i metodi anonimi, ecc) incorrere in spese generali di prestazione / memoria che ben scritto, edit-e-continua-compatibile codice potrebbe evitare? ... o fare il funzionamento interno del compilatore C # fanno tali costrutti avanzati correre più veloce di manuale-scritto, il codice 'espansa'?

È stato utile?

Soluzione

Senza voler banale suono - è buona norma per i test unità di scrittura / integrazione, piuttosto che fare affidamento su Edit-Continua.

In questo modo, spendere lo sforzo una volta, e ogni altra volta è 'libero' ...

Ora sto non suggerendo unità retrospettivamente scrittura per tutto il codice; piuttosto, ogni volta che si deve correggere un bug, inizia scrivendo un test (o più comunemente prove multiple) che conferma la correzione.

Come @ Dave Swersky menziona nei commenti, libro Mchael piume, lavorando in modo efficace con Legacy Codice è una risorsa buona (è legacy 5 minuti dopo che hai scritto, giusto?)

Sì, penso che sia un errore da evitare nuovi costrutti C # a favore di consentire per la modifica e continuare; Ma penso anche che sia un errore per abbracciare nuovi costrutti solo per il gusto di farlo, e soprattutto se si portano a più difficile da capire il codice.

Altri suggerimenti

Mi piace 'Modifica e Continua'. Trovo è un enorme fattore abilitante per lo sviluppo interattivo / debug e anch'io trovo molto fastidioso quando non funziona.

Se 'Modifica e continuazione' aids tua metodologia di sviluppo poi con tutti i mezzi a fare scelte per facilitare esso, tenendo presente il valore di ciò che si stanno dando in su.

Uno dei miei fastidi ricorrenti è che tutto ciò modifica in una funzione con le espressioni lambda a tema 'Modifica e Continua'. Se io viaggio su di esso abbastanza io possa scrivere l'espressione lambda. Sono sulla recinzione con le espressioni lambda. Posso fare alcune cose più veloce con loro, ma non lo fanno save me tempo se finisco per scriverle in un secondo momento.

Nel mio caso, ho evitare usando le espressioni lambda, quando non ho davvero bisogno di. Se ottengono nel modo io li avvolgere in una funzione in modo che posso 'Modifica e continuazione' il codice che li usa. Se sono gratuite io scrivo fuori.

Il tuo approccio non ha bisogno di essere in bianco e nero.

ha voluto chiarire queste cose un po '

  

è buona norma evitare di utilizzare questi costrutti più avanzati a favore di codice che è molto, molto facile da eseguire il debug?

Modifica e continuazione non è realmente il debug, si sta sviluppando. Faccio questa distinzione perché le nuove caratteristiche di C # sono molto debuggable. Ogni versione del linguaggio aggiunge il supporto per il debugging nuovo linguaggio caratteristiche per renderli il più semplice possibile il debug.

  

tutto può essere provato e testato in tempo reale senza interrompere il processo.

Questa affermazione è fuorviante. E 'possibile con Modifica e continuazione per verificare un cambiamento corregge un problema molto specifico. E 'molto più difficile per verificare che il cambiamento è corretto e non si rompe una serie di altre questioni. Vale a dire perché modifica e continuare non modifica i binari sul disco e quindi non permette di elementi quali unit testing.

Nel complesso, però sì, penso che sia un errore da evitare nuovi C # costrutti a favore di consentire per la modifica e continuare. Modifica e continuazione è una grande caratteristica (c'è piaciuto molto quando l'ho incontrato nei miei C ++ giorni). Ma il suo valore come un server di produzione aiutante non costituiscono per i guadagni producitivy dal nuovo C # caratteristiche IMHO.

  

La mia domanda è se è buona norma evitare di utilizzare questi costrutti più avanzati a favore di codice che è molto, molto facile da eseguire il debug

Direi che ogni volta che si stanno costringendo voi stessi a scrivere il codice che è il seguente:

  1. Meno espressiva
  2. Maggiore
  3. ripetuta (da evitare metodi generici)
  4. non portabile (non eseguire il debug e il test a 64 bit ??!?!?)

si aggiunge al costo complessivo di manutenzione molto più che la perdita del "Modifica e continuazione" funzionalità nel debugger.

vorrei scrivere il miglior codice possibile, non il codice che rende una caratteristica del vostro lavoro IDE.

Mentre non v'è nulla di intrinsecamente sbagliato con il vostro approccio, lo fa si limiti alla quantità di espressività compreso dal IDE. Il tuo codice diventa un riflesso di sue capacità, non il linguaggio, e quindi il tuo valore complessivo nel mondo dello sviluppo diminuisce perché si sta tenendo te indietro da imparare altre tecniche per aumentare la produttività. Evitare LINQ a favore di Edit-e-Continue si sente come un costo opportunità enorme per me personalmente, ma il paradosso è che si deve acquisire una certa esperienza con esso prima si può sentire in quel modo.

Inoltre, come è stato detto in altre risposte, unit test del codice rimuove il necessità per eseguire l'intera applicazione per tutto il tempo, e risolve così il vostro dilemma in un modo diverso. Se non è possibile fare clic destro nel vostro IDE e prova solo le 3 linee di codice che ti interessano, si sta facendo troppo lavoro durante lo sviluppo già.

Si dovrebbe introdurre integrazione continua, che può aiutare a trovare ed eliminare i bug prima della distribuzione del software. Soprattutto i grandi progetti (ritengo 500k abbastanza grande) bisogno di una sorta di convalida.

http://www.codinghorror.com/ blog / 2006/02 / rivisitando-edit-e-continue.html

Per quanto riguarda la domanda specifica: non evitare questi costrutti e non fare affidamento sulle tue folli abilità di debug - cercare di evitare a tutti i bug (in software distribuito). test di scrittura di unità invece.

Ho anche lavorato su progetti di grandi dimensioni permanente-beta.

Ho usato metodi anonimi e delegati in linea per mantenere alcuni relativamente semplici pezzi di uso-one logica vicino al loro unico luogo di utilizzo.

Ho usato metodi generici e classi per il riutilizzo e l'affidabilità.

Ho inizializzato classi nei costruttori come piena misura del possibile, di mantenere invarianti di classe e di eliminare la possibilità di errori causati da oggetti in stati non validi.

Ho usato blocchi di enumerazione per ridurre la quantità di codice necessario per creare una classe enumeratore a poche righe.

Tutti questi sono utili nel mantenere un grande progetto in rapida evoluzione in uno stato affidabile.

Se non posso edit-e-continua, edito e ricominciare. Questo mi costa pochi secondi la maggior parte del tempo, un paio di minuti in caso di brutto. Ne vale la pena per le ore che una maggiore capacità di ragionare sul codice e una maggiore affidabilità attraverso il riutilizzo mi salva.

C'è un sacco farò per rendere più facile trovare i bug, ma non se sarà rendere più facile avere gli insetti troppo.

Si potrebbe provare Test Driven Development . Ho trovato molto utile per evitare di usare il debugger a tutti. Si parte da un nuovo test (per esempio test di unità), e quindi si esegue solo in questo test di unità per controllare il vostro sviluppo - non è necessario l'intera applicazione in esecuzione tutto il tempo. E questo significa che non è necessario modificare-and-continua!

So che TDD è il ronzio-parola corrente, ma in realtà funziona per me. Se ho bisogno di usare il debugger lo prendo come un fallimento personale:)

Basandosi su Modifica e Cont. suoni come se c'è molto poco tempo speso per la progettazione di nuove funzionalità, consentono unit test da solo. Ciò che trovo ad essere cattivo perché probabilmente si finisce per fare un sacco di debugging e bug fixing, e, talvolta, le correzioni di bug causa più bug, giusto?

Tuttavia, è molto difficile da giudicare se si dovrebbe o non dovrebbe utilizzare le funzioni linguistiche o no, perché questo dipende anche da molti, molti altri fattori: reqs progetto, le scadenze di rilascio, le competenze del team, costo del codice di gestibilità dopo refactoring, a citarne alcuni.

Spero che questo aiuti!

Il problema ti sembra di essere avendo è:

  

Ci vuole troppo tempo per ricostruire te app,   avviare di nuovo e arrivare alla punta   di interfaccia utente si sta lavorando.

Come è già stato detto, unit test contribuirà a ridurre il numero di volte in cui è necessario eseguire la vostra applicazione per trovare / bug fix sul codice di nessuno UI; tuttavia essi non aiutano con questioni come il layout dell'interfaccia utente.

In passato ho scritto un'applicazione di test che caricherà rapidamente l'interfaccia utente sto lavorando su e riempirlo con dati fittizi, in modo da ridurre il tempo di ciclo.

separare il codice nessuna interfaccia utente in altre classi che possono essere testati con test di unità, vi permetterà di fare utilizzare tutti i costrutti C # in quelle classi. Poi si può solo limitare i costrutti in uso nel codice utente la sua auto.

Quando ho iniziato a scrivere un sacco di test di unità, il mio utilizzo di “edit-and-continue” è andato giù, ho come difficilmente lo uso a parte il codice utente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top