Letture

 

Database as a fortress

Pubblicato translation missing: it.datetime.distance_in_words.almost_x_years fa da Andrea

Qualche giorno fa durante dei controlli sul database di una applicazione che avevo contribuito a scrivere abbiamo casualmente trovato un paio di record non validi.
La cosa mi ha lasciato abbastanza sorpreso, visto che il codice applicativo era stato scritto in modo da impedire la creazione di questo genere di record invalidi (dati duplicati):

class Referral < ActiveRecord::Base
  belongs_to :travel_plan
  # ...
  validates_uniqueness_of :url, :scope => :travel_plan_id
end

A quanto pare questo non è stato sufficiente. Poco male, sia perché il fenomeno è stato molto limitato (due casi su oltre 200 mila record), sia perché esiste un rimedio molto semplice per questo tipo di problema: inserire delle constraint direttamente al livello del database.
Ruby on Rails rende molto semplice questo tipo di operazione attraverso l’uso di una migration:

class RemoveDuplicatedReferrals < ActiveRecord::Migration
  # ...
  add_index :referrals, [:url, :travel_plan_id], :unique => true
end

A questo punto mi sento piuttosto sicuro che il problema non si ripresenterà in futuro.
L’ultimo step necessario per considerare la faccenda definitivamente risolta è gestire l’eccezione generata all’interno dell’applicazione in caso di insert fallito a livello del database:

class TravelPlan < ActiveRecord::Base
  has_many :referrals
  # ...
  def add_referral_vote(referer)
    referrals.create(:url => referer) 
  rescue ActiveRecord::StatementInvalid
    false
  end
end

La lezione che possiamo trarre da questo caso è che se abbiamo veramente a cuore la validità dei dati salvati nel nostro database non dovremmo accontentarci dei controlli a livello applicativo.

I dati sono spesso il vero patrimonio di una azienda, soprattutto se sono stati raccolti in molti anni di lavoro, pertanto è buona cosa salvaguardarli nel migliore dei modi possibile, anche a costo di perdere un po’ di tempo rinforzando il database dall’interno con ulteriori controlli di validità, univocità eccetera.
Una scelta di questo genere potrebbe rallentare il processo di sviluppo dell’applicazione, soprattutto durante la fase iniziale di prototipizzazione. E’ per questo che in genere preferisco effetturare queste modifiche quando veramente serve, ovvero una volta che l’applicazione ha raggiunto una forma piuttosto stabile o è pronta per andare in produzione.

Archiviato in Ruby on Rails, debugging

commenti