Ho preso il codice base per un'applicazione ruby-on-rails che si affida molto ai callback di ActiveRecord per eseguire le regole di dominio.
L'applicazione può essere confrontata con un'applicazione bancaria, in cui un cliente ha un account. Su ogni account è possibile registrare una Transazione (una somma di denaro che viene inserita o rimossa dall'account). L'account ha un saldo_bancario che viene aggiornato ogni volta che viene creata una transazione. Questo aggiornamento avviene come un callback di ActiveRecord.
class Account < ActiveRecord::Base
has_many :transactions
def update_account_balance
account_balance = 0
self.transaction_logs.each do |transaction|
account_balance = account_balance + (transaction.amount + transaction.commission)
end
self.account_balance = account_balance
end
end
class Transaction < ActiveRecord::Base
belongs_to :account
after_save :update_account_value
def update_account_value
self.account.update_account_balance
self.account.save!
end
end
Trovo che questo modo di codificare rende molto difficile capire cosa succede (e cosa succede quando si verifica un errore). Inoltre, poiché l'account deve caricare tutte le transazioni, questo sarà più pesante man mano che vengono aggiunte sempre più transazioni.
Se avessi sviluppato un'applicazione come questa in .NET (in cui sono molto più familiare) avrei creato qualcosa del genere:
public class Account {
public void AddTransaction(decimal amount) {
this.Transactions.Add(new Transaction(amount));
this.AccountValue += amount;
}
}
Quindi assicurati che un oggetto Transaction sia immutabile.
Sono molto tentato di ridefinire il sistema in qualcosa del genere. Ma dovrei? Sarebbe il "modo rotaie"?
L'inconveniente, per quanto posso dire, è che il mio controller deve gestire in modo esplicito il controllo delle transazioni del database, cosa che è accaduta implicitamente nel Transaction.save! chiamata attualmente chiamata nell'applicazione. Ci sono altri fattori di cui dovrei essere a conoscenza?