Last active
February 6, 2017 20:10
-
-
Save texdc/f541e54a8d384cd1dc7de738cb1fe3f5 to your computer and use it in GitHub Desktop.
Assuming that Akka had a Dart SDK...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library ddd.account; | |
import 'account_event.dart'; | |
import 'package:akka/akka.dart' show TypedActor; | |
class _AccountState { | |
static const String _UNKNOWN_ACCOUNT = 'unknown'; | |
final String accountNumber; | |
final num balance; | |
bool get _isUnknown => accountNumber == _UNKNOWN_ACCOUNT; | |
_AccountState([this.accountNumber = _UNKNOWN_ACCOUNT, this.balance = 0]) { | |
if (accountNumber == null || accountNumber.trim().isEmpty()) { | |
throw new ArgumentError.value(accountNumber, 'accountNumber', 'Cannot be null or empty.'); | |
} | |
if (balance == null || balance < 0) { | |
throw new ArgumentError.value(balance, 'balance', 'Cannot be null or less than 0.'); | |
} | |
} | |
_AccountState open(String anAccountNumber, num anAmount) => _isUnknown ? new _AccountState(anAccountNumber, anAmount) : this; | |
_AccountState deposit(num anAmount) => _isUnknown ? this : new _AccountState(accountNumber, balance + anAmount); | |
_AccountState withdraw(num anAmount) => _isUnknown ? this : new _AccountState(accountNumber, balance - anAmount); | |
} | |
class Account extends TypedActor { | |
_AccountState _state; | |
String get accountNumber => _state.accountNumber; | |
num get balance => _state.balance; | |
bool get isOverdrawn => balance < 0; | |
Account(EventBus anEventBus, [this._state = new _AccountState()]) : super(anEventBus) { | |
events.when((event) => event is OpenAccount).listen(_open); | |
events.when((event) => event is DepositFunds).listen(_deposit); | |
events.when((event) => event is WithdrawFunds).listen(_withdraw); | |
} | |
Map<String, String> toMap() => { | |
'accountNumber' : accountNumber, | |
'balance' : balance.toString() | |
}; | |
void _open(OpenAccount aCommand) { | |
if (!aCommand.requestorCanOpen) { | |
events.trigger(new OpenProhibited(aCommand.requestor)); | |
return; | |
} | |
_state = _state.open(aCommand.accountNumber, aCommand.initialBalance); | |
events.trigger(new AccountOpened(accountNumber, balance)): | |
} | |
void _deposit(DepositFunds aCommand) { | |
if (!aCommand.requestorCanDeposit) { | |
events.trigger(new DepositProhibited(accountNumber, aCommand.amount)); | |
return; | |
} | |
_state = _state.deposit(aCommand.amount); | |
events.trigger(new FundsDeposited(accountNumber, aCommand.amount)); | |
} | |
void _withdraw(WithdrawFunds aCommand) { | |
if (balance <= 0 && !aCommand.requestorCanOverdraw) { | |
events.trigger(new WithdrawalProhibited(accountNumber, aCommand.amount)); | |
return; | |
} | |
_state = _state.withdraw(aCommand.amount); | |
events.trigger(new FundsWithdrawn(accountNumber, aCommand.amount)); | |
} | |
String toString() => '[Account] accountNumber: $accountNumber, balance: $balance'; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library ddd.account.event; | |
abstract class AccountEvent { | |
final String accountNumber; | |
AccountEvent(this.accountNumber) { | |
if (accountNumber == null || accountNumber.trim().isEmpty) { | |
throw new ArgumentError.notNull('accountNumber'); | |
} | |
} | |
} | |
class OpenAccount extends AccountEvent { | |
final num initialBalance; | |
final Role requestor; | |
bool get requestorCanOpen => requestor.canOpen; | |
OpenAccount(String anAccountNumber, this.initialBalance, this.requestor) : super(anAccountNumber) { | |
if (initialBalance == null || initialBalance < 0) { | |
throw new ArgumentError.notNull('initialBalance'); | |
} | |
if (requestor == null) throw new ArgumentError.notNull('requestor'); | |
} | |
} | |
class OpenProhibited { | |
final Role requestor; | |
OpenProhibited(this.requestor) { | |
if (requestor == null) throw new ArgumentError.notNull('requestor'); | |
} | |
} | |
abstract class ProhibitionEvent extends AccountEvent { | |
final num amountRequested; | |
ProhibitionEvent(String anAccountNumber, this.amountRequested) : super(anAccountNumber) { | |
if (amountRequested == null) throw new ArgumentError.notNull('amountRequested'); | |
} | |
} | |
class DepositProhibited extends ProhibitionEvent { | |
DepositProhibited(String anAccountNumber, num anAmountRequested) : super(anAccountNumber, anAmountRequested); | |
} | |
class WithdrawalProhibited extends ProhibitionEvent { | |
WithdrawalProhibited(String anAccountNumber, anAmountRequested) : super(anAccountNumber, anAmountRequested); | |
} | |
abstract class FundsCommand { | |
final num amount; | |
final Role requestor; | |
FundsCommand(this.amount, this.requestor) { | |
if (amount == null || amount < 0) { | |
throw new ArgumentError.notNull('amount'); | |
} | |
if (requestor == null) throw new ArgumentError.notNull('requestor'); | |
} | |
} | |
class DepositFunds extends FundsCommand { | |
bool get requestorCanDeposit => requestor.canDeposit; | |
DepositFunds(num anAmount, Role aRequestor) : super(anAmount, aRequestor); | |
} | |
class WithdrawFunds extends FundsCommand { | |
bool get requestorCanOverdraw => requestor.canOverdraw; | |
WithdrawFunds(num anAmount, Role aRequestor) : super(anAmount, aRequestor); | |
} | |
class AccountOpened extends AccountEvent { | |
final num initialBalance; | |
AccountOpened(String anAccountNumber, this.initialBalance) : super(anAccountNumber) { | |
if (initialBalance == null || initialBalance < 0) { | |
throw new ArgumentError.notNull('initialBalance'); | |
} | |
} | |
} | |
abstract class FundsEvent extends AccountEvent { | |
final num amount; | |
FundsEvent(String anAccountNumber, this.amount) : super(anAccountNumber) { | |
if (amount == null || amount < 0) { | |
throw new ArgumentError.notNull('amount'); | |
} | |
} | |
} | |
class FundsDeposited extends FundsEvent { | |
FundsDeposited(String anAccountNumber, num anAmount) : super(anAccountNumber, anAmount); | |
} | |
class FundsWithdrawn extends FundsEvent { | |
FundsWithdrawn(String anAccountNumber, num anAmount) : super(anAccountNumber, anAmount); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment