Come gestire le complicazioni eccessive?

6

Spesso mi sorprendo a scrivere codice inutilmente complicato (triste ma vero). C'è qualche insieme di regole, disciplina, ecc. Per aiutare a evitarlo? (escluso il principio KISS, perché lo conosco ma spesso dimentico quando si tratta del codice reale:)

    
posta tika 20.05.2012 - 14:59
fonte

6 risposte

11

Come dice Antoine de St-Exupéry: "Un designer sa di aver raggiunto la perfezione non quando non c'è più nulla da aggiungere, ma quando non c'è più nulla da togliere".

Questo è un problema difficile e comune, ma è qualcosa che puoi affrontare nel corso dei prossimi anni. Riconoscere che si tratta di un problema è il passo più importante e, una volta che hai imparato a correggere i tipi di complicazioni che tendi ad aggiungere, inizierai a progettare senza di essi.

Quando ho capito di avere avuto questo problema all'inizio della mia carriera, ho trovato utile analizzare e rianalizzare ogni classe, funzione, variabile membro, variabile locale e chiamate di funzioni nidificate per vedere se le cose potevano essere consolidate o eliminate mentre si incontravano ancora i requisiti indicati. Fondamentalmente, codice golf.

    
risposta data 20.05.2012 - 15:54
fonte
8

Generalmente faccio queste cose per evitare complicazioni eccessive

  • Prima di iniziare a programmare, crea un piano e progetta un'interfaccia per il tuo codice. Pensa sempre a ciò che il tuo codice farà e cosa probabilmente non lo è. Essere realistici al riguardo, ma non utilizzare soluzioni bizzarre. Ogni funzione nell'interfaccia dovrebbe fare esattamente una cosa, se possibile ciò che fa dovrebbe dipendere solo dai suoi argomenti.
  • Una buona misura per vedere se il tuo codice è complicato è la profondità del nidificazione. Una volta che il mio codice è annidato cinque o più livelli, so che qualcosa è andato storto. Prova a suddividere il tuo codice in funzioni che esprimono diversi passaggi di ciò che vuoi fare. Aspettati che il compilatore generi un codice efficiente per te. I compilatori sono intelligenti.
  • Dividi il tuo codice in moduli che rappresentano unità funzionali del tuo programma. Ogni modulo dovrebbe contenere un insieme di funzioni che possono essere utilizzate insieme. Non lanciare oggetti non correlati in un modulo né scrivere un gruppo di moduli che vengono sempre usati insieme.
  • Non implementare funzionalità che non ti serviranno, ma tieni presente che potresti voler espandere il tuo programma
risposta data 20.05.2012 - 15:46
fonte
3

Forse dovresti dare un'occhiata ad alcune pubblicazioni sulla programmazione estrema. Questi ragazzi stanno cercando di evitare inutili complessità. Una fonte comune di complessità sta cercando di generalizzare anche se esiste una sola applicazione di qualsiasi cosa generalizzata. Penso che Kent Beck abbia consigliato di generalizzare qualcosa solo se l'hai già implementato in tre modi diversi. Per i primi tentativi dovresti "fare la cosa più semplice che possa funzionare".

    
risposta data 20.05.2012 - 16:42
fonte
0

Mi piacerebbe pensare di essere abbastanza bravo a mantenere le cose semplici, almeno quando uso C #, anche se lo scambio di stack è pieno di persone che sono migliori di me. Stai meglio con l'esperienza. Personalmente non mi piace pianificare in anticipo troppo, in particolare per i piccoli strumenti, perché non so esattamente quale direzione esisterò fino a quando non affonderò i denti nel progetto. Quindi, prima devo avere qualcosa di semi-lavorativo. Una volta fatto e non vedo più potenziali punti difficili, quindi inizio a cercare di semplificare le cose. Ora, il modo più semplice per semplificare le cose è quello di mantenere l'interfaccia utente e le funzionalità semplici per cominciare. Recentemente ho realizzato prototipi, quindi a volte è facile per me decidere cosa succede e cosa no. Se devi fornire delle stime e il codice va dritto al centro e sarà sottoposto a un controllo approfondito dal QA, allora probabilmente non puoi permetterti il tempo di rendere tutto perfetto a causa delle scadenze e di una migliore qualità. In queste situazioni, VUOI mantenere le cose semplici al fine di evitare / ridurre al minimo lo stress delle scadenze mancanti.

Se hai più libertà e vuoi deliziare gli utenti senza aver bisogno di un anno per farlo, chiedi alle persone un feedback specifico. Esegui un test di usabilità casuale per assicurarsi che altre persone possano utilizzare lo strumento. Consultare i colleghi più esperti su quale potrebbe essere un buon approccio. Implementa qualcosa che funzioni e pubblichi pezzi sul sito di revisione del codice per vedere come altri possono risolvere lo stesso problema meglio.

Se stai per decidere tra la libreria A, la libreria B o il rolling your own - chiedi su Stack Overflow per un consiglio. Se stai ancora imparando qualcosa come CSS o SQL o XAML - chiedi su Stack Overflow.

Vuoi trasformare un problema in pezzi, trovare una buona soluzione per ogni sotto-problema e poi metterlo insieme.

Lungo il percorso dovresti utilizzare strumenti per il ri-factoring, il controllo dello stile, TDD, ecc.

Per C #, consiglierei Resharper, StyleCop. Prova a trovare qualcosa per la tua lingua. Fondamentalmente, vuoi usare il tuo tempo in modo efficiente in modo da avere tempo per "post-mortem", refactoring, creare una libreria che

Una volta che sei nella fase di semplificazione / perfezionamento, non sei mai abbastanza fatto. Questo fa schifo se devi spostarti su un altro progetto e non toccare mai più questo codice a meno che non risolvi un bug. Se la posta in gioco non è così alta, puoi tornare al vecchio progetto e rimuovere linee e linee di codice una volta scoperti generici, alcune librerie, ecc. Ho già detto che Stack Overflow è una grande risorsa? Non essere un link .

Puoi imparare molto dal riscrivere il vecchio codice, in modo da evitare di commettere gli stessi errori in futuro. Spero che questo aiuti.

    
risposta data 20.05.2012 - 17:29
fonte
0

Anche se penso che sto facendo un buon lavoro di scrittura di un programma, è probabile che possa essere semplificato molto.

Trovo che la cosa più utile da fare sia chiedere "Indipendentemente da come lo fa, che cosa dovrebbe realizzare questo programma?" Ad esempio, se si tratta di un compilatore, dovrebbe leggere un file di codice e scrivere qualcosa che può essere eseguito. In quanto tale, se non fa nulla di inutile, sarà vincolato all'I / O.

Ho anche riscontrato che l'ottimizzazione delle prestazioni porta a semplificare, come in questo esempio Quindi, se sei abbastanza bravo a diagnosticare prestazioni e ricodifica per migliorarlo, questo da solo ti insegnerà ciò che potresti fare che è inutilmente complicato, quindi impari a non farlo. (Spesso è quello che ti è stato insegnato a fare.)

    
risposta data 20.05.2012 - 18:06
fonte
-1

Non credo di credere più nel principio KISS. Prima di tutto, sono stati sopravvalutati ...

Considera questa funzione

void process_payment(payment const& p) {

    account * a = get_account();
    if (!a) {
       std::cout << "No account information.\n";
       return;
    }
    ...
}

È semplicissimo. Se seguiamo il principio KISS, potremmo fare qualcosa di simile. La funzione NON è semplice da testare poiché ora dobbiamo reindirizzare l'output standard a qualcosa che i test possono elaborare. Puoi risolvere questo problema aggiungendo complessità all'interfaccia della funzione prendendo l'handle di output come parametro. Non è così semplice come si può fare e mi sono imbattuto in aderenti a KISS che sono davvero fuori di testa per cose come questa ... specialmente se stanno combattendo con i loro superiori sul fatto che i test unitari dovrebbero essere fatti.

Inoltre, ciò che è "semplice" è negli occhi di chi guarda. Proprio l'altro giorno ho preso delle cagate per usare un oggetto buffer che cresce come necessario piuttosto che malloc + memset + memcpy per copiare una stringa passata a me da un'API di rete. Secondo me l'uso di un oggetto buffer è più semplice perché è già lì, fa quello di cui ho bisogno (anche se farà di più), ecc ... Secondo l'opinione dell'altro, farlo manualmente è più semplice perché il buffer è eccessivo. Ovviamente ha ragione perché è il capo.

Ancora di più, di fronte alla decisione di utilizzare una variabile globale per consentire l'accesso da parte di molte funzioni e di far passare questa variabile come parametro, è abbastanza ovvio che la prima è molto più "semplice". È anche piuttosto ovvio che nella maggior parte dei casi è una cattiva scelta. I seguaci di KISS scelgono il primo e il loro codice si trasforma in questo nodo di spaghetti non sperimentato che non è nemmeno possibile concettualizzare poiché la modularità e il disaccoppiamento sono tutti usciti dalla finestra nel tentativo di mantenere le cose "semplici" ... e sì, con una misura ovvia e possibilmente ingenua di semplice è molto più semplice raggiungere e afferrare il tocco globale piuttosto che chiamare una funzione esistente solo per nascondere questo globale o aggirare un parametro.

Considera anche questo codice:

void somethingAboutStrings(char* in) {
    char buffer[128];
    strcpy(buffer, in);
    ...
}

Molto semplice, quello. Ho visto che troppi aderenti al KISS scrivono un codice C simile a quello, compreso quello che attualmente sto martellando su tutto ciò che faccio come "complicato". Si assumono così tanto e diventano più semplici di quanto sia sicuro. Chiunque conosca la lingua sa che la funzione di cui sopra è incredibilmente insicura e un giorno porterà a bug che richiedono ore e ore per risolverlo. È un codice come il precedente che dà davvero nomi C e C ++ e l'industria è piena di merda come questa, dalle applicazioni di base al settore finanziario e ad altri ... è terrificante per me. Ma questo è "semplice" e perché dovresti scrivere un sacco di codice di rilevamento degli errori e di protezione del buffer quando sai che l'input sarà sempre più corto di X?

La risposta a questa domanda è ovviamente che qualcuno non saprà che hai questo limite di dimensioni interno e arbitrario e lo supererà ... o che qualche errore finirà sulla linea - che è quello che è successo.

Dopo aver preso cagate per gli ultimi 8 mesi da questo aderente al KISS, sono diventato piuttosto cinico dell'idea e penso che probabilmente porti a più problemi che a prenderli. Scrivere codice riutilizzabile è una buona cosa. Scrivere codice testato è una buona cosa. Il disaccoppiamento è MOLTO buono ... e direi che alla fine rendono le cose più facili da gestire, più facili da leggere, ecc. Non sono, per quanto "semplici"; almeno non nel modo in cui ho visto quella parola usata di recente.

    
risposta data 20.05.2012 - 18:31
fonte

Leggi altre domande sui tag