it-swarm.it

Quali "buone pratiche" popolari non sono sempre le migliori, e perché?

Le "migliori pratiche" sono ovunque nel nostro settore. A la ricerca di Google sulle "migliori pratiche di codifica" genera quasi 1,5 milioni di risultati. L'idea sembra portare conforto a molti; basta seguire le istruzioni e tutto andrà bene.

Quando leggo un best practice - per esempio, ne ho appena letti diversi in Clean Code recentemente - mi innervosisco. Questo significa che dovrei sempre usare questa pratica? Ci sono condizioni associate? Ci sono situazioni in cui potrebbe essere no essere una buona pratica? Come posso sapere con certezza fino a quando non avrò imparato di più sul problema?

Molte delle pratiche menzionate in Clean Code non sono state adatte a me, ma onestamente non sono sicuro che ciò sia dovuto al fatto che sono potenzialmente cattive o se è solo il mio pregiudizio personale. So che molte persone di spicco nel settore tecnologico sembrano pensare che non ci sono buone pratiche , quindi almeno i miei dubbi assillanti mi mettono in buona compagnia.

Il numero di best practice di cui ho letto è semplicemente troppo numeroso per elencarlo qui o porre domande individuali, quindi vorrei formulare questa frase come una domanda generale:

Quali pratiche di codifica che sono comunemente etichettate come "migliori pratiche" possono essere non ottimali o addirittura dannose in determinate circostanze? Quali sono queste circostanze e perché rendono la pratica povera?

Preferirei conoscere esempi ed esperienze specifici.

100
Steven Evers

Penso che tu abbia colpito l'unghia sulla testa con questa affermazione

Odierei prendere le cose al valore nominale e non pensarci criticamente

Ignoro quasi tutte le migliori pratiche quando non viene fornita una spiegazione sul perché esiste

Raymond Chen mette meglio in questo articolo quando dice

Un buon consiglio viene fornito con una logica in modo da poter dire quando diventa un cattivo consiglio. Se non capisci perché qualcosa dovrebbe essere fatto, allora sei caduto nella trappola della programmazione di culto del carico e continuerai a farlo anche quando non è più necessario o addirittura diventa deleteria.

125
Conrad Frix

Potrebbe anche buttarlo sul ring:

Premature optimization is the root of all evil.

No, non lo è.

Il preventivo completo:

"Dovremmo dimenticare le piccole efficienze, diciamo circa il 97% delle volte: l'ottimizzazione prematura è la radice di tutti i mali. Eppure non dovremmo rinunciare alle nostre opportunità in quel 3% critico".

Ciò significa che puoi sfruttare specifici miglioramenti strategici delle prestazioni durante tutto il processo di progettazione. Significa che usi strutture di dati e algoritmi coerenti con gli obiettivi di prestazione . Significa che sei a conoscenza di considerazioni di progettazione che influiscono sulle prestazioni. Ma significa anche che non si ottimizza in modo frivolo quando si fa ciò ti darà piccoli guadagni a spese della manutenibilità.

Le applicazioni devono essere ben progettate, in modo che non cadano alla fine quando si applica un piccolo carico su di esse e quindi si finisce per riscriverle. Il pericolo con la citazione abbreviata è che, troppo spesso, gli sviluppatori lo usano come una scusa per non pensare alle prestazioni fino alla fine, quando potrebbe essere troppo tardi per fare qualcosa al riguardo. È meglio ottenere buone prestazioni fin dall'inizio, a condizione che non ci si concentri sulle minuzie.

Supponiamo che tu stia creando un'applicazione in tempo reale su un sistema incorporato. Scegli Python come linguaggio di programmazione, perché "L'ottimizzazione prematura è la radice di tutti i mali." Ora non ho nulla contro Python, ma è una lingua interpretata Se la potenza di elaborazione è limitata e una certa quantità di lavoro deve essere eseguita in tempo reale o quasi in tempo reale, e si sceglie una lingua che richiede più potenza di elaborazione per il lavoro di quello che hai, sei regalmente fregato, perché ora devi ricominciare da capo con un linguaggio capace.

95
Robert Harvey

Un ritorno per funzione/metodo.

94
iMacUwhAK

Non reinventare la ruota è un dogma ampiamente mal utilizzato. La sua idea è che se esiste una soluzione adatta, usala invece di crearne una tua; oltre allo sforzo di risparmio, la soluzione esistente è probabilmente meglio implementata (senza errori, efficiente, testata) rispetto a quella che verrebbe inizialmente. Fin qui tutto bene.

Il problema è che raramente esiste una soluzione adatta al 100%. Potrebbe esistere una soluzione adatta all'80% e il suo utilizzo probabilmente va bene. Ma come circa il 60% adatto? 40%? Dove disegni la linea? Se non disegni la linea, potresti finire con l'incorporare una libreria gonfia al tuo progetto perché stai usando il 10% delle sue caratteristiche - solo perché vuoi evitare di "reinventare la ruota".

Se reinventi la ruota, otterrai esattamente quello che vuoi. Imparerai anche a imparare a costruire le ruote. L'apprendimento facendo non dovrebbe essere sottovalutato. E alla fine, una ruota personalizzata potrebbe essere migliore della ruota generica standard.

87
Joonas Pulakka

"Unit Test Everything."

Ho sentito dire spesso che tutto il codice dovrebbe avere unit test, un punto su cui non sono d'accordo. Quando si dispone di un test per un metodo, qualsiasi modifica all'output o alla struttura di quel metodo deve essere effettuata due volte (una volta nel codice, una volta nel test).

Pertanto, i test unitari dovrebbero essere, a mio avviso, proporzionali alla stabilità strutturale del codice. Se sto scrivendo un sistema a strati dal basso verso l'alto, il mio livello di accesso ai dati avrà test del wazoo; il mio livello di logica aziendale sarà testato abbastanza bene, il mio livello di presentazione avrà alcuni test e le mie opinioni non avranno quasi nessun test.

78
Fishtoaster

Sempre programma per le interfacce.

A volte ci sarà una sola implementazione. Se ritardiamo il processo di estrazione di un'interfaccia fino al momento in cui ne vediamo la necessità, spesso scopriremo che non è necessario.

57
Eric Wilson

Non usare nulla di open source (o non Microsoft per te sviluppatori .NET)

Se Microsoft non lo ha sviluppato, non lo usiamo qui. Vuoi usare ORM - EF, vuoi usare IOC - Unity, vuoi fare il login - blocco applicativo di registrazione aziendale. Esistono così tante librerie migliori - eppure sono sempre bloccato a ordinare dal menu del dollaro del mondo dello sviluppo. Lo giuro ogni volta che ascolto le Best Practices di Microsoft, penso alle "Linee guida nutrizionali di McDonald". Certo, probabilmente vivrai se le seguirai, ma sarai anche malnutrito e sovrappeso.

  • Nota che potrebbe non essere la tua best practice, ma è una pratica comune seguita quasi ovunque io abbia lavorato.
46
Watson

Orientamento oggetto

C'è il presupposto, solo perché il codice è "orientato agli oggetti", è magicamente buono. Quindi le persone continuano a spremere la funzionalità in classi e metodi, solo per essere orientati agli oggetti.

40
LennyProgrammers

Tutto il codice dovrebbe essere commentato.

No, non dovrebbe essere. Qualche volta hai un codice ovvio, ad esempio i setter non dovrebbero essere commentati, fino a quando non fanno qualcosa di speciale. Inoltre, perché dovrei commentare questo:

/** hey you, if didn't get, it's logger. */
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
35
Vladimir Ivanov

Metodologie, in particolare mischia. Non riesco a mantenere una faccia seria quando sento gli adulti usare la frase "Scrum Master". Sono così stanco di sentire la protesta degli sviluppatori che alcuni aspetti della Metodologia X non funzionano per la loro azienda, solo per essere raccontati dal Guru So-and-So che la ragione per cui non funziona è che in realtà non sono dei veri professionisti di Metodologia X. "Scrum più forte, è necessario, mio ​​studente Padawan!"

Ci sono pepite di saggezza nelle metodologie agili, molte delle quali, ma sono spesso ricoperte da un tale letame che non riesco a combattere il mio riflesso del vomito. Prendi questo bit da pagina di mischia di Wikipedia :

Numerosi ruoli sono definiti in Scrum. Tutti i ruoli rientrano in due gruppi distinti - maiali e polli - in base alla natura del loro coinvolgimento nel processo di sviluppo.

Veramente? Maiali e galline, dici? Affascinante! Non vedo l'ora di presentare questo al mio capo ...

32
evadeflow

Mappatura relazionale oggetto ... http://en.wikipedia.org/wiki/Object-relational_mapping

Non voglio mai essere sottratto ai miei dati, né voglio perdere quel preciso controllo e ottimizzazione. La mia esperienza con questi sistemi è stata estremamente scarsa ... Le query generate da questi livelli di astrazione sono persino peggiori di quelle che ho visto off-shoring.

25
Fosco

Scrivere i nomi delle funzioni come se fossero frasi inglesi:

Draw_Foo()
Write_Foo()
Create_Foo()

ecc. Potrebbe sembrare fantastico, ma è un problema quando stai imparando un'API. Quanto è più facile cercare un indice per "Tutto ciò che inizia con Foo"?

Foo_Draw()
Foo_Write()
Foo_Create()

eccetera.

22
Colen

YAGNI

( Non ne avrai bisogno )

Questo approccio mi è costato ore e ore quando ho dovuto implementare funzionalità su una base di codice esistente, in cui un'attenta pianificazione avrebbe incluso queste funzionalità in anticipo.

Le mie idee sono state spesso respinte a causa di YAGNI, e la maggior parte delle volte qualcuno ha dovuto pagare per quella decisione in seguito.

(Naturalmente si potrebbe sostenere che una base di codice ben progettata consentirebbe anche l'aggiunta di funzionalità in un secondo momento, ma la realtà è diversa)

22

MVC - Trovo spesso che nascondere molti problemi di web design nell'approccio MVC si basa più sul rendere felice un framework (Rails ecc.) Che sulla semplicità o struttura. MVC è una delle preferite degli "astronauti dell'architettura" che sembrano apprezzare le impalcature eccessive rispetto alla semplicità. YMMV.

class-based OO - secondo me incoraggia strutture complesse di stato mutevole. gli unici casi convincenti che ho trovato per class-based OO nel corso degli anni sono i esempi banali di "forma-> rettangolo-> quadrato" che formano il capitolo 1 di qualsiasi libro OO

22
Brad Clawsie

Per SQL

  1. Non usare i trigger
  2. Nascondi sempre le tabelle dietro le viste

In ordine:

  1. Sono una caratteristica che ha il suo posto. Hai più percorsi di aggiornamento per una tabella o richiedi il controllo al 100%?

  2. Solo perché? Vorrei che se stessi eseguendo il refactoring per mantenere un contratto, ma non quando ho letto che le persone cambiano il punto di vista per adattarsi a qualsiasi modifica del tavolo

Modificare:

Numero 3: Evitare * con EXISTS. Prova 1/0. Funziona. L'elenco delle colonne non viene valutato secondo lo standard SQL. Pagina 191

20
gbn

Modelli di design per lo più. Sono sovrautilizzati e sottoutilizzati.

20
Geek

Il principio di responsabilità unica

("ogni classe dovrebbe avere una sola responsabilità; in altre parole, ogni classe dovrebbe avere una, e una sola, ragione per cambiare")

Non sono d'accordo. Penso che un metodo dovrebbe avere solo una ragione per cambiare, e tutti i metodi in una classe dovrebbero avere un relazione logica tra loro , ma la classe stessa potrebbe effettivamente do diverse cose (correlate).

Nella mia esperienza, questo principio troppo spesso viene applicato in modo troppo zelante e si finisce con molte piccole classi con un metodo. Entrambi i negozi agili in cui ho lavorato lo hanno fatto.

Immagina se i creatori dell'API .Net avessero avuto questo tipo di mentalità: anziché List.Sort (), List.Reverse (), List.Find () ecc., Avremmo hanno le classi ListSorter, ListReverser e ListSearcher!

Piuttosto che discutere più contro l'SRP (che in sé non è terribile in teoria), condividerò alcune delle mie esperienze aneddotiche a lungo termine:


In un posto in cui ho lavorato, ho scritto un semplice risolutore di flusso massimo che consisteva in cinque classi: un nodo, un grafico, un creatore di grafici, un risolutore di grafici e una classe per usare il grafico -creatore/solutori per risolvere un problema del mondo reale. Nessuno era particolarmente complesso o lungo (il solutore era di gran lunga il più lungo con circa 150 righe). Tuttavia, è stato deciso che le classi avevano troppe "responsabilità", quindi i miei colleghi hanno iniziato a riformattare il codice. Al termine, le mie 5 classi erano state estese a 25 classi, le cui linee di codice totali erano più del triplo di quelle che erano in origine. Il flusso del codice non era più ovvio, né lo scopo dei nuovi test unitari; Ora ho avuto difficoltà a capire cosa facesse il mio codice.


Allo stesso posto, quasi ogni classe aveva un solo metodo (la sua unica "responsabilità"). Seguire il flusso all'interno del programma era quasi impossibile e la maggior parte dei test unitari consisteva in test che questa classe chiamava codice da un'altra classe, entrambi i cui scopi erano ugualmente un mistero per me. C'erano letteralmente centinaia di classi in cui avrebbero dovuto esserci (IMO) solo dozzine. Ogni classe ha fatto solo una "cosa", ma anche con convenzioni di denominazione come "AdminUserCreationAttemptorFactory", era difficile dire la relazione tra le classi.


In un altro posto (che aveva anche la mentalità classi-dovrebbe-avere-solo-un-solo), stavamo cercando di ottimizzare un metodo che impiegava il 95% del tempo durante una certa operazione. Dopo averlo (piuttosto stupidamente) ottimizzato un po ', ho rivolto la mia attenzione verso perché è stato chiamato un bajillion volte. Veniva chiamato in un ciclo in una classe ... il cui metodo veniva chiamato in un ciclo in un'altra classe ... che veniva anche chiamato in un ciclo ...

Tutto sommato, c'erano 13 livelli di loop distribuiti su 13 classi (sul serio). Ciò che una classe stava effettivamente facendo era impossibile da determinare semplicemente osservandolo: dovevi tracciare un grafico mentale di quali metodi chiamasse e quali metodi chiamassero quei metodi, e così via. Se tutto fosse stato raggruppato in un unico metodo, sarebbe stato lungo solo circa 70 righe con il nostro metodo problematico nidificato all'interno di cinque livelli immediatamente evidenti di loop.

La mia richiesta di trasformare queste 13 classi in una classe è stata respinta.

Ora che hai menzionato Clean Code, sebbene contenga alcune buone idee, penso che la sua ossessione di trasformare tutti i metodi in sottometodi e quelli in sotto-metodi ecc. Sia stata portata troppo avanti. Invece di un paio di metodi a dieci righe, dovresti preferire venti linee (presumibilmente ben definite) a una linea. Ovviamente qualcuno pensa che sia pulito, ma a me sembra molto peggio della versione originale.

Inoltre, sostituendo semplici elementi elementari come

0 == memberArray.length

all'interno di una classe con una chiamata al metodo della classe come

isEmpty()

è un discutibile IMHO "miglioramento". Aggiunta: La differenza è che il primo controllo fa esattamente quello che dice: controlla se la lunghezza dell'array è 0. Ok, isEmpty() potrebbe anche controllare la lunghezza dell'array. Ma potrebbe anche essere implementato in questo modo:

return null != memberArray ? 0 == memberArray.length : true;

Cioè, include un controllo null implicito! Questo potrebbe essere un buon comportamento per un metodo pubblico - se l'array è nullo, allora qualcosa è certamente vuoto - ma quando parliamo di interni di classe, non va bene. Mentre l'incapsulamento verso l'esterno è un must, class internals deve sapere esattamente cosa sta succedendo all'interno della classe. Non puoi incapsulare la classe da se stessa . Esplicito è meglio di implicito.


Questo non significa che rompere i metodi lunghi o comportare confronti logici non vada bene; certo che lo è, ma fino a che punto farlo - dove si trova il punto debole - è ovviamente una questione di gusti. Abbattere un metodo lungo si traduce in più metodi e ciò non viene fornito gratuitamente. Devi saltare il codice sorgente per vedere cosa sta realmente succedendo, quando puoi vederlo a colpo d'occhio se tutte quelle cose fossero in un unico metodo.

Vorrei anche dire che in alcuni casi un metodo a 1 riga è troppo corto per meritare di essere un metodo.

14
Joonas Pulakka

"Sii liberale con i commenti"

I commenti sono sicuramente una buona cosa, ma troppi sono altrettanto cattivi se non peggio che non sufficienti. Perché? Bene, le persone tendono a mettere a punto i commenti se ne vedono troppi inutili. Non sto dicendo che puoi avere un codice perfettamente autocompattante, ma è preferibile un codice che necessita di commenti per una spiegazione.

13
Jason Baker

GoTo Considerato dannoso

Se stai implementando una macchina a stati, un'istruzione GOTO può avere più senso (leggibilità e codice efficiente) di un approccio di "programmazione strutturata". È stato davvero preoccupato per alcuni colleghi quando il primo pezzo di codice che ho scritto in un nuovo lavoro includeva non solo una ma diverse dichiarazioni di goto. Fortunatamente erano abbastanza intelligenti da rendersi conto che in realtà era la soluzione migliore in questo caso particolare.

Qualsiasi "best practice" che non consenta eccezioni sensate e documentate alle sue regole è semplicemente spaventosa.

12
MZB

I sacrifici che facciamo per rendere testabile il codice

Salto attraverso molti cerchi per rendere testabile il mio codice, ma non faccio finta che non lo farei se avessi la scelta. Tuttavia, sento spesso persone che spingono l'idea che si tratti di "buone pratiche". Queste pratiche includono (scritto nella lingua di .Net, ma si applica anche ad altre lingue):

  • Creazione di un'interfaccia per ogni classe. Questo raddoppia il numero di classi ( file) da gestire e duplica il codice. Sì, programmazione dell'interfaccia è buono, ma è a questo che servono gli specificatori pubblici/privati.
  • Ogni classe non istanziata all'avvio necessita di una factory. Chiaramente, new MyClass() è molto più semplice della scrittura di una factory, ma ora il metodo che crea non può essere testato in isolamento. Se non fosse per questo, farei solo 1/20 del numero di classi di fabbrica che faccio ora.
  • Rendi pubblica ogni classe, che vanifica lo scopo di avere degli identificatori di accesso sulle classi. Tuttavia, le classi non pubbliche non sono accessibili (e quindi testate) da altri progetti, quindi l'unica altra opzione è spostare tutto il codice di test nello stesso progetto (e quindi rilasciarlo con il prodotto finale).
  • Iniezione delle dipendenze. Chiaramente dover dare ogni altra classe Uso un campo e un parametro costruttore è significativamente più lavoro che semplicemente crearli quando ne ho bisogno; ma poi non posso più testare questa classe in isolamento.
  • Il singolo principio di responsabilità, che mi ha causato così tanti mal di testa che l'ho spostato nella sua risposta propria .

Quindi cosa potremmo fare per risolvere questo problema? Avremmo bisogno di un drastico cambiamento nell'architettura del linguaggio:

  • Avremmo bisogno della capacità di deridere le lezioni
  • Avremmo bisogno della possibilità di testare metodi privati ​​di classi interne, da un altro progetto (questo può sembrare una vulnerabilità di sicurezza, ma non vedo alcun problema se il testato è costretto a nominare le sue classi tester) .
  • L'iniezione di dipendenza (o la posizione del servizio), nonché qualcosa di equivalente al nostro modello di fabbrica esistente, dovrebbe essere una parte della lingua core.

In breve, abbiamo bisogno di un linguaggio progettato da zero tenendo conto della testabilità .

Separazione delle applicazioni in livelli; Livello dati, Livello aziendale, Livello interfaccia utente

Il motivo principale per cui non mi piace questo è che la maggior parte dei luoghi che seguono questo metodo usano framework molto fragili per farlo. OSSIA Il livello dell'interfaccia utente è codificato a mano per gestire gli oggetti del livello aziendale, gli oggetti del livello aziendale sono codificati a mano per gestire le regole e il database aziendali, il database è SQL ed è già abbastanza fragile e gestito dal gruppo "DBA" a cui non piace il cambiamento.

Perché è così male? La richiesta di miglioramento più comune è probabilmente "Ho bisogno di un campo sullo schermo X che ha Y." Scoppio! Hai solo una nuova funzionalità che interessa ogni singolo livello e, se separi i livelli con diversi programmatori, è diventato un grosso problema che coinvolge più persone e gruppi, per un cambiamento molto semplice.

Inoltre, non so quante volte ho litigato con argomenti del genere. "Il campo del nome è limitato a una lunghezza massima di 30, si tratta di un livello dell'interfaccia utente, un livello aziendale o un problema del livello dati?" E ci sono cento argomenti e nessuna risposta giusta. La risposta è la stessa, influisce su tutti i livelli, non si vuole rendere stupida l'interfaccia utente e passare attraverso tutti i livelli, e fallire nel database, solo così l'utente scopre che la sua voce è troppo lunga. Se lo cambi, influisce su tutti i livelli, ecc.

Anche gli "strati" tendono a perdere; Se uno strato è fisicamente separato dai confini di processo/macchina (UI Web I.E. e logica di backend aziendale), le regole vengono duplicate per far funzionare tutto ragionevolmente bene. Cioè alcune logiche aziendali finiscono nell'interfaccia utente, anche se si tratta di una "regola aziendale", poiché l'utente ha bisogno che l'interfaccia utente sia reattiva.

Se il framework utilizzato o l'architettura utilizzata è resistente a piccole modifiche e perdite, ovvero basato su metadati e regolato dinamicamente su tutti i livelli, può essere meno doloroso. Ma la maggior parte dei framework è una vera seccatura, che richiede modifiche dell'interfaccia utente, modifiche del livello aziendale e modifiche al database, per ogni piccola modifica, e che causa più lavoro e meno aiuto di quanto la tecnica dovrebbe produrre.

Probabilmente mi sbatterò per questo, ma eccolo :)

10
Jay

JavaBeans

L'uso di JavaBeans in Java. Vedi la mia domanda Perché non dovrei usare POJO immutabili invece di JavaBeans? su StackOverflow.

9
Jonas

User Stories/Use Cases/Personas

Comprendo la necessità di questi quando programmate per un settore che non conoscete, ma penso che quando sono implementati in piena forza diventano troppo corporativi e diventano una perdita di tempo.

7
riwalk

80 limiti di carattere/linea sono stupidi

Capisco che alcuni compromessi devono essere fatti per adattarsi al ritmo del corridore più lento sul lato della GUI (limitazioni della risoluzione dello schermo, ecc.) Ma perché questa regola si applica alla formattazione del codice?

Vedi ... C'era questa piccola invenzione chiamata barra di scorrimento orizzontale creata per gestire lo spazio dello schermo virtuale al di fuori del limite di pixel più a destra. Perché gli sviluppatori, che sono riusciti a creare grandi strumenti per migliorare la produttività come l'evidenziazione della sintassi e il completamento automatico, non lo usano?

Certo, ci sono editor CLI usati religiosamente dai dinosauri * nix che seguono le vecchie e stanche limitazioni dei loro terminali VT220 ma perché tutti noi siamo tenuti allo stesso standard?

Dico, avvita il limite di 80 caratteri. Se i dinosauri sono abbastanza epici da hackerare su emacs/vim tutto il giorno, perché non dovrebbe essere in grado di creare un'estensione che avvolge automaticamente le linee o offre funzionalità di scorrimento orizzontale ai loro IDE CLI?

I monitor da 1920x1080 pixel alla fine diventeranno la norma e gli sviluppatori di tutto il mondo vivono ancora con le stesse limitazioni senza influenzare il motivo per cui lo fanno tranne che è quello che gli anziani hanno detto di fare quando hanno appena iniziato a programmare.

80 limiti di caratteri sono non una buona pratica ma una pratica di nicchia per una minoranza di programmatori e dovrebbero essere trattati come tali.

Edit:

È comprensibile che a molti sviluppatori non piaccia la barra di scorrimento orizzontale perché richiede un gesto del mouse, quindi ... Perché non aumentare il limite di larghezza della colonna a un numero più alto (di 80) per quelli di noi che usano i display moderni.

Quando i monitor di computer 800x600 sono diventati la norma per la maggior parte degli utenti, gli sviluppatori Web hanno aumentato la larghezza del loro sito Web per soddisfare la maggior parte ... Perché gli sviluppatori non possono fare lo stesso.

7
Evan Plaice

Misura, misura, misura

Così bene, misura via, ma per isolando bug delle prestazioni, la misurazione funziona così come la successiva eliminazione. Ecco il metodo che uso.

Ho cercato di rintracciare la fonte della "saggezza" misura-misura. Qualcuno con una soapbox abbastanza alta l'ha detto, e ora viaggia.

5
Mike Dunlavey

Usa Singletons

Quando dovresti avere solo un'istanza di qualcosa. Non posso non sono d'accordo di più. Non utilizzare mai un singleton e allocarlo una volta sola e passare il puntatore/oggetto/riferimento secondo necessità. Non c'è assolutamente alcun motivo per non farlo.

5
user2528

Il mio insegnante richiede che inizio tutti i miei identificatori (escluse le costanti) con lettere minuscole, ad es. myVariable.

So che sembra una cosa minore, ma molti linguaggi di programmazione richiedono variabili per iniziare con lettere maiuscole. Apprezzo la coerenza, quindi è mia abitudine iniziare tutto con lettere maiuscole.

5
Maxpm

tilizzando int non firmato come iteratore

Quando impareranno che usare int firmato è molto più sicuro e meno soggetto a bug. Perché è così importante che l'indice di array possa essere solo un numero positivo, che tutti sono felici di trascurare il fatto che 4 - 5 è 4294967295?

5
AareP

I metodi non dovrebbero essere più lunghi di una singola schermata

Concordo pienamente con il principio della responsabilità singola, ma perché le persone lo percepiscono nel senso che "una funzione/metodo non può avere più di una singola responsabilità al massimo livello di granularità logica"?

L'idea è semplice Una funzione/metodo dovrebbe svolgere un compito. Se parte di quella funzione/metodo può essere utilizzata altrove, tagliarla nella propria funzione/metodo. Se potrebbe essere utilizzato altrove nel progetto, spostarlo nella propria classe o in una classe di utilità e renderlo accessibile internamente.

Avere una classe che contiene 27 metodi helper che vengono chiamati una sola volta nel codice è stupido, uno spreco di spazio, un inutile aumento della complessità e un enorme dispendio di tempo. Sembra più una buona regola per le persone che vogliono apparire impegnate nel refactoring del codice ma non producono molto.

Ecco la mia regola ...

Scrivi funzioni/metodi per realizzare qualcosa

Se ti trovi in ​​procinto di copiare/incollare del codice, chiediti se sarebbe meglio creare una funzione/metodo per quel codice. Se una funzione/metodo viene chiamata una sola volta in un'altra funzione/metodo, c'è davvero un punto nel farlo in primo luogo (verrà chiamata più spesso in futuro). È utile aggiungere più salti in/out di funzioni/metodi durante il debug (vale a dire, il salto aggiunto rende il debug più facile o più difficile)?

Concordo pienamente sul fatto che funzioni/metodi superiori a 200 righe debbano essere esaminati, ma alcune funzioni svolgono solo un compito in altrettante righe e non contengono parti utili che possono essere astratte/utilizzate sul resto del progetto.

Lo guardo da una prospettiva di sviluppo API ... Se un nuovo utente dovesse guardare il diagramma di classe del tuo codice, quante parti di quel diagramma avrebbero senso all'interno del più grande progetto e quante esisterebbero solo come aiutanti di altre parti interne al progetto.

Se dovessi scegliere tra due programmatori: il primo ha la tendenza a scrivere funzioni/metodi che provano a fare troppo; il secondo rompe ogni parte di ogni funzione/metodo al massimo livello di granularità; Vorrei scegliere le prime mani verso il basso. Il primo otterrebbe di più (ovvero scrivere più carne dell'applicazione), il suo codice sarebbe più facile da eseguire il debug (a causa di un minor numero di salti in/out di funzioni/metodi durante il debug), e perderebbe meno tempo a impegnarsi nel perfezionamento di come il codice sembra vs perfezionare il modo in cui funziona il codice.

Limitare le astrazioni non necessarie e non inquinare il completamento automatico.

4
Evan Plaice

Absolutist, rigoroso, incapsulamento

Concordo principalmente con l'incapsulamento, ma è stato un vero liberatore infrangere temporaneamente tale regola per convertire un codice procedurale in OOP utilizzando il Array to Object refactoring . ( Ho bisogno di un po 'di spinta per scioglierti un po'. Grazie, Martin Fowler)

  • Vettore

    ->

  • nuova classe con matrice come proprietà pubblica

    ->

  • passare attraverso il codice client/aggiungere accessori

    ->

  • solo allora incapsulalo e rendilo privato/protetto

2
JW01

Over generalization.

Il blocco quadrato NON si adatta al foro del cerchio!

1
PMV

Solo uno a cui riesco a pensare è la formattazione Java if istruzioni come questa:

if (condition) ...

invece di

if(condition) ...

Per la maggior parte, ho scoperto che le migliori pratiche sono le migliori, e qualsiasi riserva iniziale che ho con loro tende ad essere fuori luogo o annullata da preoccupazioni più significative.

1
Armand

"Se non è rotto, non aggiustarlo". Il codice è sempre rotto. Il motivo per cui nessuno dice allo sviluppatore originale è che loro

  1. penso che sia colpa loro,
  2. non so chi contattare,
  3. non riesco a ottenere supporto per parlare con un "tecnico",
  4. non può essere disturbato, o
  5. non so come descrivere il problema in modo sufficientemente dettagliato.
1
l0b0

Favorire sempre nomi lunghi, espliciti, variabili e di routine rispetto alla forma abbreviata

es. favorendo Autenticazione over AuthN

This bit me , quando i percorsi dei file MS sono diventati così lunghi che il mio Copia di lavoro di Subversion non è stato caricato sul mio PC.

Vedi: https://stackoverflow.com/questions/3282303/my-choice-of-class-names-is-hampered-by-windows-xp-max-path-length-issues-with-sv

1
JW01

Tendo a ignorare quasi tutte le migliori pratiche quando si esegue un progetto relativamente piccolo, una tantum, come scrivere un parser necessario per migrare i file. Quando tutto ciò di cui ho bisogno è il risultato, una volta non mi interessa la leggibilità, la scalabilità, la manutenibilità, ecc.

1
user281377

Il threading è la risposta per tutti i problemi di prestazione

Non sono d'accordo con quello per molte ragioni.

  • In generale, l'indicizzazione e la memorizzazione nella cache temporale aumentano notevolmente le prestazioni. Ovviamente potresti aver bisogno di usare "bandiere sporche". Rendi il tuo design tutto disordinato e roba del genere ...

  • I problemi che derivano dal sovrappeso multi-thread sono vantaggiosi in termini di tempo e denaro.

  • Ciò che la tecnologia multi-core ci ha veramente portato è un migliore multi-tasking (eseguendo un paio di applicazioni alla stessa velocità). L'utilizzo di programmi multithreading abilmente scritti è solo un effetto collaterale.

0
AareP

CONTINUA DICHIARAZIONE IS BAD

Qui farò riferimento agli standard di codifica C++ del veicolo congiunto Strike Fighter:

Regola 190 di AV (Regola 57 MISRA) L'istruzione continue non deve deve essere utilizzata.

e un mio professore:

"THE CONTINUE STATEMENT IS BAD"

La loro logica è che interrompe il flusso di controllo e rende il codice meno leggibile. L'uso di istruzioni nidificate se è un approccio più pulito.

Tuttavia, lo trovo più leggibile:

 
for(int i = 0; i < CONST_FOO; ++i) {
    if(aTwo[i] == NULL) continue;
    aTwo[i]->DoBar();
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
    //...do other stuff with aTwo[i]
}
 

Di questo:

 
for(int i = 0; i < CONST_FOO; ++i) {
    if(aTwo[i] != NULL) {
        aTwo[i]->DoBar();
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
        //...do other stuff with aTwo[i]
    }
}
 

Questo è un esempio molto semplicistico, (immagina che gli if annidati superino molto più di un livello) ma è simile alla ridicola "solo una dichiarazione di ritorno per funzione" "migliore" pratica. Impedisce al debugger di saltare (possibilmente a diverse pagine di distanza), meno rientri generalmente rendono il codice facilmente leggibile, ecc.

0
Casey

In JavaScript molte persone considerano la migliore pratica di scrivere tutti i punti e virgola di cui avrebbero bisogno in altri linguaggi di ramo C (e molti di loro non hanno timore di sottolineare "errore" ogni volta che vedono codice che potrebbe avere più punti e virgola). Non ne ho mai trovato bisogno, il loro ruolo di marcatore visivo è già ricoperto da cambiamenti di linea.

In una nota a margine, è un po 'divertente vedere un compilatore che richiede punti e virgola, ma genera comunque con sicurezza l'errore "Punto e virgola mancante". "Sappiamo entrambi cosa intendevi scrivere, ma devo rifiutare la tua candidatura perché non mi è permesso formalmente distinguere tra spazi e cambi di riga."

Numerose altre best practice in stile JavaScript/C sono in circolazione, ma nessuna di queste si avvicina in termini di hype senza argomenti qualificati.

Modifica: è perfettamente possibile minimizzare il codice senza punto e virgola Closure Compiler li inserirà secondo necessità.

0
aaaaaaaaaaaa

Bene, uno dei miei pulsanti di scelta rapida è analisi delle prestazioni . Le persone dicono

L'ottimizzazione prematura è la radice di tutti i mali.

E poi dicono che la citazione completa è:

Dobbiamo dimenticare le piccole efficienze, diciamo circa il 97% delle volte: l'ottimizzazione prematura è la radice di tutti i mali. Eppure non dovremmo rinunciare alle nostre opportunità in quel 3% critico.

Il che ha perfettamente senso quando si discute di "algoritmi": materiale accademico intelligente in cui il 3% del programma potrebbe essere costituito da due righe di codice.

Lavoro in 10 ^ 6 app di linea, con 10 ^ 5 metodi in 10 ^ 4 classi, lavorato su anni da una dozzina di programmatori e tester, sottoposti a numerose revisioni e rilasci, dove quella citazione non ha alcuna rilevanza. In genere i tempi di drenaggio sono singole righe di codice che possono essere "opportunità", ma nessuno potrebbe mai indovinare dove si trovano.

OTOH, la gente dice "profilo", o dice "misura misura". Bene bene. Lo dicono, ma non lo fanno spesso. Potrebbe essere, il motivo per cui non lo fanno è non funziona molto bene .

Questa risposta dice di più a riguardo, e indica cosa funziona .

0
Mike Dunlavey

Associazione dati

Lo odio e lo adoro. (Dipende dalla complessità del progetto)

0
Amir Rezaei