Guidelines 1.2

Coding best practices

Una nota sul linguaggio utilizzato:

  • “Non fare X” significa che non esiste motivo valido per violare la regola.
  • “Evita X” significa non farlo a meno di un valido motivo.
  • “Prediligi X ad Y” descrive una pratica sconsigliata, ed una alternativa da favorire a meno di un valido motivo.

Linee guida ad alto livello

  • Sii coerente.
  • Non riscrivere codice già esistente per seguire questa guida.
  • Non violare le linee guida senza un valido motivo. Se riesci a convincere un altro membro del tuo team, allora il motivo può considerarsi valido.

Generali

  • Non duplicare funzionalità già presenti in librerie di sistema.
  • Non fallire silenziosamente ingoiando eccezioni.
  • Non scrivere codice cercando di predire future necessità.
  • Evita di usare eccezioni per gestire control flow ordinario.
  • Mantieni il codice semplice, chiaro ed esplicito.
  • Evita di ottimizzare il codice. Non farlo mai senza profiling.

Principi di object-oriented design

  • Evita variabili globali e singletons.
  • Evita un numero di parametri superiore a 4.
  • Limita il numero di collaboratori di un oggetto (le entità da cui dipende l'oggetto).
  • Limita il numero di dipendenze di un oggetto (le entitità che dipendono dall'oggetto).
  • Prediligi la composizione rispetto all'ereditarietà.
  • Prediligi metodi brevi. Ottimo rimanere tra 1 e 5 righe.
  • Prediligi piccoli oggetti, con una singola responsabilità ben definita. Quando un oggetto supera le 100 righe, è probabile stia facendo troppe cose.
  • Tell, don’t ask.
  • Evita metodi che uniscono responsabilità query e command.

Ruby

  • Evita parametri opzionali. Il metodo forse sta facendo più del dovuto?
  • Evita inutile metaprogramming.
  • Evita il monkey-patching.
  • Prediligi la creazione di classi all'inclusione di moduli per condividere funzionalità tra più oggetti.
  • Prediligi lo scope private a protected. Usa protected solo per i metodi di comparazione come def ==(other), def <(other), e def >(other).
  • Effettua rescue di StandardError, non Exception.
  • Configurazione Rubocop

Rails

  • Evita di bypassare le validazioni con metodi quali save(validate: false)o <code>update_attribute.
  • Non modificare una migrazione dopo che è stata mergiata su master se il cambiamento voluto può essere introdotto con una seconda migrazione.
  • Non richiamare le classi dei modelli ActiveRecord all'interno dalle viste.
  • Non usare variabili d'istanza nei partials.
  • Non usare SQL o frammenti SQL (where('inviter_id IS NOT NULL')) al di fuori dei modelli.
  • Valida la presenza dell'associazione belongs_to (<code>user), non della foreign key (user_id).
  • Aggiungi un indice DB per ogni foreign key.
  • Imposta valori di default, validazioni di presenza o unicità nei modelli anche a livello di migrazione DB.
  • Mantieni db/schema.rb sotto version control.
  • Non fare riferimento a modelli ActiveRecord a livello di migrazione.
  • Nelle viste mailer usa named routes con suffissi _url. In tutti gli altri casi, usa il suffisso <code>_path.
  • Evita di instanziare più di un oggetto per azione nei controller.
  • Sfrutta solo una variabile di istanza per vista.
  • Assicurati che le migrazioni down funzionino.
  • Evita l'introduzione di nuovi metodi helper. Prediligi un'approccio ad oggetti tramite l'uso di presenters.
  • A livello di model ActiveRecord specifica unicamente validazioni, relazioni e scopes/query.
  • Non specificare a livello model ActiveRecord validazioni che necessitino il lookup di relazioni.

Testing

  • Mantieni un code coverage superiore al 90%.
  • Evita test ridondanti (uno e un solo test per funzionalità).
  • Evita its, <code>let!, specify e <code>subject in RSpec. Prediligi approcci espliciti e coerenti.
  • Specifica una sola expectation per test.
  • Separa le fasi di setup ed exercise dalla fase verify del test tramite blocchibefore.
  • Evita .any_instance, sfrutta il dependency injection.
  • Evita l'utilizzo di variabili di istanza.
  • Disabilita richieste HTTP verso servizi esterni tramite WebMock o FakeWeb.

Unit testing

  • Non testare i metodi privati (non stubbare il SUT).
  • Testa metodi di tipo query con expectations sul valore di ritorno.
  • Testa metodi di tipo command con expectations su diretti cambiamenti di stato provocati sull'interfaccia pubblica dell'oggetto.
  • Non testare chiamate di tipo query verso oggetti collaboratori.
  • Testa chiamate di tipo command verso oggetti collaboratori tramite stubs e spies (non mocks).
  • Mantieni gli stub in sync con l'API che vanno a simulare. Nel farlo prediligi approcci unit rispetto a test di integrazione.

Gemfile

  • Dichiara la versione ruby da utilizzare per un progetto.
  • Specifica la versione con ~> per le gemme che seguono il semantic versioning (<code>rspec, factory_girl, <code>capybara).
  • Specifica la versione esatta per gemme fragili (rails).
  • Non specificare una versione per gemme stabili e sicure (pg, <code>thin).

Background Jobs

  • Non persistere oggetti ActiveRecord serializzati nel job. Passa gli ID ed esegui la .find all'interno del metodo .perform.