parnaud (2) [Avatar] Offline
#1
Is this code really what you intended to show:

val balance = DB.getBalance(account)
balance.amount === Amount(0, USD)

val incBalance = balance.credit(Amount(100, USD))
balance.amount === Amount(100, USD)

val decBalance = balance.debit(Amount(20, USD))
balance.amount === Amount(80, USD)

Since balance is immutable, the amount will always stay at 0.
The assertions seem incorrect to me, and when you debit 20 USD, I suppose that you'd rather call it on the incBalance object.

Moreover, this code seems only marginally better than before. Granted: you no longer have a shared state, so code referring to the original amount will still see the initial amount (zero). But if you handle two deposits in independent threads, you are still in trouble: the immutable design does not help; and you need some central system which ensures atomicity of the updates of the data persisted in the store.
debasish.ghosh (44) [Avatar] Offline
#2
Re: Listing 1.4 Immutable Balance model
Good catch regarding the assertions! Copy paste FTW .. will fix in the next MEAP smilie.

Regarding your observations on thread-safety, we have not yet addressed these concerns. The idea is to show that getting rid of the shared state enables you to perform safe operations (in this context debit & credit) without causing any ambiguity in the Balance abstraction. We have not yet taken care of atomicity of writes - but each Balance instance that you get after doing an operation is consistent. Thanks for bringing this up - I will add a note in this context.

Thanks.
parnaud (2) [Avatar] Offline
#3
Re: Listing 1.4 Immutable Balance model
Great, thanks!
302255 (2) [Avatar] Offline
#4
I feel confused about what the Balance is.
It’s not a service but it seems do the work service should do.
What the Balance here is?Just an abstraction of model behavior?
Debasish Ghosh (111) [Avatar] Offline
#5
Hi -

The idea of how I wanted to model Balance has changed than what it is in the current MEAP. The next MEAP will address the modifications. Just to give you a heads up, here's what the latest version looks like. It's actually a Value Object as part of Account. And Account is now the main abstraction .. Here's Listing 1.4 from the unpublished version ..

type Amount = BigDecimal

case class Balance(amount: Amount = 0)

class Account(val no: String, val name: String,
val dateOfOpening: Date, val balance: Balance = Balance()) { #A

def debit(a: Amount) = { #B
if (balance.amount < a)
throw new Exception("Insufficient balance in account")
new Account(no, name, dateOfOpening, Balance(balance.amount – a))
}

def credit(a: Amount) =
new Account(no, name, dateOfOpening, Balance(balance.amount + a))
}

Hope this clarifies. The changes will be part of the next MEAP.

Thanks.