How to handle Order status changes with State Design Pattern - oop

Currently, I'm working on the Order Microservice, where I have two methods related to order status changes store(Order order) and updateStatus(int orderId, String status), I'll explain later.
There are four states of the Order:
Waiting -> Expired
Waiting -> Canceled
Waiting -> Purchased
Purchased -> Canceled
I've provided the state flow diagram below, to make it clear (hopefully)
When the order created then the status will be "Waiting", if the user has paid it then the status becomes "Purchased", if the buyer or product owner cancel it then the status becomes "Canceled", and if the time exceeded then the status becomes "Expired".
For every microservice I want to work on, I'll be implementing Gang Of Four design pattern if possible, and for the order status I decided to implement state design pattern since it is related and from what I refer in many blogs, like in the document status stuff (DRAFT, ON REVIEW, etc), audio player stuff (PAUSED, PLAYED, etc) and so on.
This is what I've done:
Base State
public interface OrderStatus {
void updateStatus(OrderContext orderContext);
}
Waiting state
public class WaitingState implements OrderStatus {
// omited for brevity
#Override
public void updateStatus(OrderContext orderContext) {
orderContext.getOrder().setStatus("Waiting");
}
}
Purchased State
public class PurchasedState implements OrderStatus {
// omited for brevity
#Override
public void updateStatus(OrderContext orderContext) {
orderContext.getOrder().setStatus("Purchased");
}
}
Other states
..
Context:
public class OrderContext {
private OrderStatus currentStatus;
private Order order;
public OrderContext(OrderStatus currentStatus, Order order) {
this.currentStatus = currentStatus;
this.order = order;
}
public void updateState() {
currentStatus.updateStatus(this);
}
public OrderStatus getCurrentStatus() {
return currentStatus;
}
public void setCurrentStatus(OrderStatus currentStatus) {
this.currentStatus = currentStatus;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
The client is the OrderServiceImpl which I called from OrderController.
public class OrderServiceImpl implements OrderService {
// omited for brevity
#Override
public Order store(Order order) {
WaitingState state = WaitingState.getInstance();
OrderContext context = new OrderContext(state, order);
context.updateState();
// do other stuff
}
#Override
public void updateStatus(int orderId, String status) {
Order order = orderRepository.findById(id);
// but how about this?? this still requires me to use if/else or switch
}
}
As you can see, I can do it while creating the Order in the store(Order order) method, but I have no idea to do it in updateStatus(int orderId, String status) since it is still required to check status value to use the right state.
switch (status) {
case "EXPIRED": {
ExpiredState state = ExpiredState.getInstance();
OrderContext context = new OrderContext(state, order);
context.updateState();
// do something
break;
}
case "CANCELED": {
CanceledState state = CanceledState.getInstance();
OrderContext context = new OrderContext(state, order);
context.updateState();
// do something
break;
}
// other case
default:
// do something
break;
}
The exact reason to implement the state design pattern is to minimize "the switch stuff/hardcoded checking" and the flexibility for adding more state without breaking current code (Open/Close principle), but maybe I'm wrong, maybe I'm lack of knowledge, maybe I'm too naive to decide to use this pattern.
But at the end of the day, I found out that I still need to use the switch stuff to use the state pattern.
Then, what's the right way to handle the order status changes?

The exact reason to implement the state design pattern is to minimize "the switch stuff/hardcoded checking" and the flexibility for adding more state without breaking current code (Open/Close principle)
Polymorphism does not replace all conditional logic.
but maybe I'm wrong, maybe I'm lack of knowledge, maybe I'm too naive to decide to use this pattern.
Consider what behaviors actually change in response to an order's status change. If no behaviors change, there's no reason to use the State pattern.
For example, if the order's behavior does not change, assigning an integer (or enum) or string as an order status is fine:
enum OrderStatus {
WAITING,
CANCELLED,
EXPIRED,
PURCHASED
}
class Order {
private OrderStatus status;
public Order() {
status = OrderStatus.WAITING;
}
public void setStatus(OrderStatus s) {
status = s;
}
public void doOperation1() {
System.out.println("order status does not affect this method's behavior");
}
public void doOperation2() {
System.out.println("order status does not affect this method's behavior");
}
public void doOperation3() {
System.out.println("order status does not affect this method's behavior");
}
}
If doOperation()s remain the same despite status changes, this code works fine.
However, real problems start to occur when doOperation()s' behaviors change due to status changes. What you'll end up with is methods that look like this:
...
public void doOperation3() {
switch (status) {
case OrderStatus.WAITING:
// waiting behavior
break;
case OrderStatus.CANCELLED:
// cancelled behavior
break;
case OrderStatus.PURCHASED:
// etc
break;
}
}
...
For many operations, this is unmaintainable. Adding more OrderStatus will become complex and affect many Order operations, violating the Open/Closed Principal.
The State pattern is meant to address this problem specifically. Once you identify which behaviors change, you extract them to an interface. Let's imagine doOperation1() changes:
interface OrderStatus {
void doOperation1();
}
class WaitingOrderStatus implements OrderStatus {
public void doOperation1() {
System.out.println("waiting: doOperation1()");
}
public String toString() {
return "WAITING";
}
}
class CancelledOrderStatus implements OrderStatus {
public void doOperation1() {
System.out.println("cancelled: doOperation1()");
}
public String toString() {
return "CANCELLED";
}
}
class Order implements OrderStatus {
private OrderStatus status;
public Order() {
status = new WaitingOrderStatus();
}
public void setStatus(OrderStatus s) {
status = s;
}
public void doOperation1() {
status.doOperation1();
}
public void doOperation2() {
System.out.println("order status does not affect this method's behavior");
}
public void doOperation3() {
System.out.println("order status does not affect this method's behavior");
}
}
class Code {
public static void main(String[ ] args) {
Order o = new Order();
o.doOperation1();
}
}
Adding new states is easy and it adheres to the Open/Closed Principal.

Related

Changing aggregate behavior during its lifetime

Imagine that we have an Aggregate that has a life cycle, such that it can change its behavior during its lifetime. During the first part of its life, it can do some things and during the second part, it can do other things.
I´d like to hear opinions on how should we restrict what the aggregate can do on each phase.
To make it a little more tangible, lets take an financial trade as an aggreagate example.
A trader creates a trade informing the contract, and its price.
A risk manager validates a trade, giving a reason for such.
The BackOffice can submit the trade to the ledger, providing accounting information.
After the trade is submitted, the accounting information can never be changed.
The trade clearly has 3 distinct phases, which I´ll call Typed, Validated and Submitted
My first thought is to pollute the aggregate with InvalidOperationExceptions, which I really don´t like:
public class Trade
{
private enum State { Typed, Validated, Submited }
private State _state = State.Typed;
public Guid Id { get; }
public Contract Contract { get; }
public decimal Price { get; }
public Trade (Guid id, Contract contract, decimal price) { ... }
private string _validationReason = null;
private AccountingInformation _accInfo = null;
public void Validate(string reason) {
if (_state != State.Typed)
throw new InvalidOperationException (..)
...
_validationReason = reason;
_state = State.Validated;
}
public string GetValidationReason() {
if (_state == State.Typed)
throw new InvalidOperationException (..)
return _validationReason;
}
public void SubmitToLedger(AccountingInformation info) {
if ((_state != State.Validated))
throw new InvalidOperationException (..)
...
}
public AccountingInfo GetAccountingInfo() { .. }
}
I can do something like a Maybe pattern, to avoid the exceptions on the Get... methods. But that would not work for the behavior methods (Validate, SubmitToLedger, etc)
Oddly, if I were to be working on a functional language (such as F#), I would probably create a different type for each state.
type TypedTrade = { Id : Guid; Contract: Contract; Price : decimal }
type ValidatedTrade = { Id : Guid;
Contract: Contract;
Price : decimal;
ValidationReason : string}
type SubmittedTrade = { Id : Guid;
Contract: Contract;
Price : decimal;
ValidationReason : string;
AccInfo : AccountingInfo }
// TypedTrade -> string -> ValidatedTrade
let validateTrade typedTrade reason =
...
{ Id = typedTrade.Id; Contract = typedTrade.Contract;
Price = typedTrade.Price; Reason = reason }
// ValidatedTrade -> AccountingInfo -> SubmittedTrade
let submitTrade validatedTrade accInfo =
...
{ Id = validatedTrade.Id;
Contract = validatedTrade.Contract;
Price = validatedTrade.Price;
Reason = validatedTrad.Reason;
AccInfo = accInfo }
And the problem would gracefully go away. But to do that in OO, I would have to make my aggregate immutable and maybe create some kind o hierarchy (in which I would have to hide base methods !? ouch!).
I just wanted an opinion on what you guys do on these situations, and if there is a better way.
I like the idea of having different types for each state. Its a clean design in my opinion. From a logical view a newly created trade is definitly something different than a submitted trade.
public Interface ITrade
{
Guid Id { get; }
Contract Contract { get; }
decimal Price { get; }
}
public class Trade : ITrade
{
public Trade(Guid id, Contract contract, decimal price)
{
Id = id;
Contract = contract;
Price = price;
}
Guid Id { get; }
Contract Contract { get; }
decimal Price { get; }
public ValidatedTrade Validate(string reason)
{
return new ValidatedTrade(this, reason);
}
}
public class ValidatedTrade : ITrade
{
private ITrade trade;
private string validationReason;
public ValidatedTrade(Trade trade, string validationReason)
{
this.trade = trade;
this.validationReason = validationReason;
}
Guid Id { get { return trade.Id; } }
Contract Contract { get { return trade.Contract ; } }
decimal Price { get { return trade.Price ; } }
public string GetValidationReason()
{
return validationReason;
}
public SubmittedTrade SubmitToLedger(AccountingInfo accountingInfo)
{
return new SubmittedTrade(this, accountingInfo);
}
}
public class SubmittedTrade : ITrade
{
private ITrade trade;
private AccountingInfo accountingInfo;
public SubmittedTrade(ValidatedTrade trade, AccountingInfo accountingInfo)
{
this.trade = trade;
this.accountingInfo = accountingInfo;
}
Guid Id { get { return trade.Id; } }
Contract Contract { get { return trade.Contract ; } }
decimal Price { get { return trade.Price ; } }
public AccountingInfo GetAccountingInfo() { .. }
}
You could have one class per state instead of a single class. See this post by Greg Young : http://codebetter.com/gregyoung/2010/03/09/state-pattern-misuse/
The usual problem with the State pattern is the friction with persistence concerns and especially ORMs. It's up to you to decide if the better robustness and type safety is worth the trouble.

Switch value to decide which subclass to use

I have an abstract class Payment, which is implemented by several PaymentTypes
public abstract class Payment
{
protected int contract;
public Payment(int contract)
{
this.contract = contract;
}
public abstract bool Aprove();
}
and then, two classes which implement it
public class PaymentA : Payment
{
public PaymentA(int contract) : base(contract)
{
this.contract = contract;
}
public override bool Aprove()
{
return true;
}
}
public class PaymentB : Payment
{
public PaymentB(int contract) : base(contract)
{
this.contract = contract;
}
public override bool Aprove()
{
return true;
}
}
Now, I need to create PaymentA or PaymentB depending on a form field
static void Main(string[] Args)
{
int contract = 1;
Payment payment;
switch (rbtPaymentType)
{
case (int)EPaymentTypes.A:
payment = new PaymentA(contract);
break;
case (int)EPaymentTypes.B:
payment = new PaymentB(contract);
break;
}
payment.Aprove(); //Use of unassigned local variable
}
I have two questions:
1 - Is it well constructed so I can call payment.Aprove() no matter which type of payment it is?
2 - How can I do the method call if the object is not initialized? I get error "Use of unassigned local variable"
Thanks in advance
1 - Is it well constructed so I can call payment.Aprove() no matter which type of payment it is?
Yes, for simple application it's ok. If you want to make it a little better you can use simple factory like so:
public class PaymentFactory
{
public Payment CreatePayment(int rbtPaymentType, int contract)
{
switch (rbtPaymentType)
{
case (int)EPaymentTypes.A:
return new PaymentA(contract);
case (int)EPaymentTypes.B:
return new PaymentB(contract);
default:
throw new Exception("Unknown payment type");
}
}
}
class Program
{
static void Main(string[] Args)
{
int contract = 1;
Payment payment = null;
int rbtPaymentType = 1;
PaymentFactory paymentFactory = new PaymentFactory();
payment = paymentFactory.CreatePayment(rbtPaymentType, contract);
payment.Aprove();
}
}
Whenever you switch over something to create a new instance you should think about encapsulating it in factory. This way you don't have to repeat the same switch in other place if you want to create another instance of Payment.
2 - How can I do the method call if the object is not initialized? I get error "Use of unassigned local variable"
You can assign it to null like I've shown in the example above.
Btw. you don't have to assign contract member in constructors of PaymentA and PaymentB since base class does it for you.

Interface Bloated with Callbacks

Imagine the following class hierarchy:
interface IRules
{
void NotifyPickup(object pickedUp);
void NotifyDeath();
void NotifyDamage();
}
class CaptureTheFlag : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
if(pickedUp is Flag)
GameOver();
}
public void NotifyDeath()
{
}
public void NotifyDamage()
{
}
}
class DeathMatch : IRules
{
public void NotifyPickup(Pickup pickedUp)
{
points++;
}
public void NotifyDeath()
{
lives--;
}
public void NotifyDamage()
{
}
}
class GameWorld
{
IRules gameMode;
public Main(IRules gameMode)
{
this.gameMode = gameMode;
}
object[] worldObjects;
public void GameLoop()
{
foreach(object obj in worldObjects)
{
// This call may have a bunch of sideeffects, like getting a pickup
// Or a player dying
// Or damage being taken
// Different game modes are interested in different events / statistics.
obj.Update();
// Stuff happens...
gameMode.NotifyDamage();
// Stuff happens...
gameMode.NotifyDeath();
}
}
}
So here I've got an interface which contains Notify* functions. These are callbacks. Different game modes are interested in different events of the game. It's not really possible to access the concrete objects creating these events because they're buried in the worldObjects array. Imagine we are adding new game modes to our game. The IRules interface will get hugely bloated, containing all the possible things a game mode may be interested in, and most calls will be stubbed! How can I prevent this?
Edit 2: Concrete example
Seems like your Process logic sends out a lot of events. If you would give these events a name, you could subscribe your observers to them.
Then it would even be possible to create a 'filtering' observer that can forward the events to any other observer (a decorator pattern):
struct Event {
enum e { A, B, /*...*/ };
e name;
};
class IEventListener {
public:
virtual void event( Event e ) = 0;
};
// an event dispatcher implementation:
using namespace std;
class EventDispatcher {
public:
typedef std::shared_ptr<IEventListener> IEventListenerPtr;
map<Event::e,vector<IEventListenerPtr>> listeners;
void event(Event e){
const vector<IEventListenerPtr> e_listeners=listeners[e.name].second;
//foreach(begin(e_listeners)
// ,end(e_listeners)
// ,bind(IEventListener::event,_1,e));
for(vector<IEventListenerPtr>::const_iterator it=e_listeners.begin()
; it!=e_listeners.end()
; ++it)
{
(*it)->event(e);
}
}
};
You program could look like this:
Main main;
EventEventDispatcher f1;
f1.listeners[Event::A].push_back(listener1);
main.listener=f1;
Note: code untested - grab the idea.
If you really want to decouple the sender from the sink, you put an event system in between. The example given here is very dedicated and lightweight, but do sure take a look at various existing implementations: Signals and Slots implemented in Qt and in Boost, the delegates from C#, ...
Apologizes if I missed something but why not use event? Basically let IController expose void Callback() method, then Main would be able subscribe any callback to own event:
class Main
{
private event EventHandler SomeEvent;
public Main(IController controller)
{
// use weak events to avoid memory leaks or
// implement IDisposable here and unsubscribe explicitly
this.SomeEvent += controller.Callback;
}
public void ProcessStuff()
{
// invoke event here
SomeEvent();
}
}
EDIT:
This is what I would do: extract each rule action into the separate interface so you just implement what you need in concrete classes, for instance CaptureTheFlag class does only PickupFlag action for now so does not need Damage/Death methods, so just mark by IPickupable and that's it. Then just check whether concrete instance supports concrete actions and proceed with execute.
interface IPickupable
{
void NotifyPickup(object pickedUp);
}
interface IDeathable
{
void NotifyDeath();
}
interface IDamagable
{
void NotifyDamage();
}
class CaptureTheFlag : IPickupable
{
public void NotifyPickup(Pickup pickedUp)
{
if (pickedUp is Flag)
GameOver();
}
}
class DeathMatch : IPickupable, IDeathable
{
public void NotifyPickup(Pickup pickedUp)
{
points++;
}
public void NotifyDeath()
{
lives--;
}
}
class GameWorld
{
public void GameLoop()
{
foreach(object obj in worldObjects)
{
obj.Update();
IPickupable pickupable = gameMode as IPickupable;
IDeathable deathable = gameMode as IDeathable;
IDamagable damagable = gameMode as IDamagable;
if (pickupable != null)
{
pickupable.NotifyPickup();
}
if (deathable != null)
{
deathable.NotifyDeath();
}
if (damagable != null)
{
damagable.NotifyDamage();
}
}
}
}
My final solution was the C# equivalent of what xtofl posted. I created a class which stored a bunch of delegates in it. These delegates started off with default values (so they would never be null) and the different concrete IRules classes could choose to overwrite them or not. This worked better than abstract or stubbed methods because it doesn't clog the interface with unrelated methods.
class GameEvents
{
public Action<Player> PlayerKilled = p => {};
public Func<Entity, bool> EntityValid = e => true;
public Action ItemPickedUp = () => {};
public Action FlagPickedUp = () => {};
}
class IRules
{
GameEvents Events { get; }
}
class CaptureTheFlag : IRules
{
GameEvents events = new GameEvents();
public GameEvents Events
{
get { return events; }
}
public CaptureTheFlag()
{
events.FlagPickedUp = FlagPickedUp;
}
public void FlagPickedUp()
{
score++;
}
}
Each rule set can choose which events it wants to listen to. The game simply calls then by doing Rules.Events.ItemPickedUp();. It's guaranteed never to be null.
Thanks to xtofl for the idea!

Refactoring Switching On Types Code Smell When Adding Method to Type Seems Inappropriate

Let's say I have the following method that, given a PaymentType, sends an appropriate payment request to each facility from which the payment needs to be withdrawn:
public void SendRequestToPaymentFacility(PaymentType payment) {
if(payment is CreditCard) {
SendRequestToCreditCardProcessingCenter();
} else if(payment is BankAccount) {
SendRequestToBank();
} else if(payment is PawnTicket) {
SendRequestToPawnShop();
}
}
Obviously this is a code smell, but when looking for an appropriate refactoring, the only examples I have seen involve cases where the code executed within the conditionals are clearly the responsibility of the class itself, e.g. with the standard example given:
public double GetArea(Shape shape) {
if(shape is Circle) {
Circle circle = shape As Circle;
return circle.PI * (circle.radius * circle.radius);
} else if(shape is Square) {
Square square = shape as Square;
return square.length * square.width;
}
}
GetArea() seems like a pretty reasonable responsibility for each Shape subclass, and can of course be refactored nicely:
public class Shape
{
/* ... */
public abstract double GetArea();
}
public class Circle
{
public override double GetArea()
{
return PI * (radius * radius);
}
}
However, SendRequestToPaymentFacility() does not seem like an appropriate responsibility for a PaymentType to have. (and would seem to violate the Single Responsibility Principle). And yet I need to send a request to an appropriate PaymentFacility based on the type of PaymentType - what is the best way to do this?
You could consider adding a property or method to your CandyBar class which indicates whether or not the CandyBar contains nuts. Now your GetProcessingPlant() method does not have to have knowledge of the different types of CandyBars.
public ProcessingPlant GetProcessingPlant(CandyBar candyBar) {
if(candyBar.ContainsNuts) {
return new NutProcessingPlant();
} else {
return new RegularProcessingPlant();
}
}
One option would be to add an IPaymentFacility interface parameter to the constructors for the individual PaymentType descendants. The base PaymentType could have an abstract PaymentFacility property; SendRequestToPaymentFacility on the base type would delegate:
public abstract class PaymentType
{
protected abstract IPaymentFacility PaymentFacility { get; }
public void SendRequestToPaymentFacility()
{
PaymentFacility.Process(this);
}
}
public interface IPaymentFacility
{
void Process(PaymentType paymentType);
}
public class BankAccount : PaymentType
{
public BankAccount(IPaymentFacility paymentFacility)
{
_paymentFacility = paymentFacility;
}
protected override IPaymentFacility PaymentFacility
{
get { return _paymentFacility; }
}
private readonly IPaymentFacility _paymentFacility;
}
Rather than wiring up the dependency injection manually, you could use a DI/IoC Container library. Configure it so that a BankAccount got a Bank, etc.
The downside is that the payment facilities would only have access to the public (or possibly internal) members of the base-class PaymentType.
Edit:
You can actually get at the descendant class members by using generics. Either make SendRequestToPaymentFacility abstract (getting rid of the abstract property), or get fancy:
public abstract class PaymentType<TPaymentType>
where TPaymentType : PaymentType<TPaymentType>
{
protected abstract IPaymentFacility<TPaymentType> PaymentFacility { get; }
public void SendRequestToPaymentFacility()
{
PaymentFacility.Process((TPaymentType) this);
}
}
public class BankAccount : PaymentType<BankAccount>
{
public BankAccount(IPaymentFacility<BankAccount> paymentFacility)
{
_paymentFacility = paymentFacility;
}
protected override IPaymentFacility<BankAccount> PaymentFacility
{
get { return _paymentFacility; }
}
private readonly IPaymentFacility<BankAccount> _paymentFacility;
}
public interface IPaymentFacility<TPaymentType>
where TPaymentType : PaymentType<TPaymentType>
{
void Process(TPaymentType paymentType);
}
public class Bank : IPaymentFacility<BankAccount>
{
public void Process(BankAccount paymentType)
{
}
}
The downside here is coupling the Bank to the BankAccount class.
Also, Eric Lippert discourages this, and he makes some excellent points.
One approach you can take here is to use the Command pattern. In this case, you would create and queue up the appropriate command (e.g. Credit Card, Bank Account, Pawn Ticket) rather than calling a particular method. Then you could have separate command processors for each command that would take the appropriate action.
If you don't want the conditional complexity here, you could raise a single type of command that included the payment type as a property, and then a command processor could be responsible for figuring out how to handle that request (with the appropriate payment processor).
Either of these could help your class follow Single Responsibility Principle by moving details of payment processing out of it.

Where to put the save/pre save methods in a domain object?

I want to enforce some rules every time a domain object is saved but i don't know the best way to achieve this. As, i see it, i have two options: add a save method to the domain object, or handle the rules before saving in the application layer. See code sample below:
using System;
namespace Test
{
public interface IEmployeeDAL
{
void Save(Employee employee);
Employee GetById(int id);
}
public class EmployeeDALStub : IEmployeeDAL
{
public void Save(Employee employee)
{
}
public Employee GetById(int id)
{
return new Employee();
}
}
public interface IPermissionChecker
{
bool IsAllowedToSave(string user);
}
public class PermissionCheckerStub : IPermissionChecker
{
public bool IsAllowedToSave(string user)
{
return false;
}
}
public class Employee
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public void Save()
{
if (PermissionChecker.IsAllowedToSave("the user")) // Should this be called within EmployeeDAL?
EmployeeDAL.Save(this);
else
throw new Exception("User not permitted to save.");
}
}
public class ApplicationLayerOption1
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public ApplicationLayerOption1()
{
//set dependencies
EmployeeDAL = new EmployeeDALStub();
PermissionChecker = new PermissionCheckerStub();
}
public void UnitOfWork()
{
Employee employee = EmployeeDAL.GetById(1);
//set employee dependencies (it doesn't seem correct to set these in the DAL);
employee.EmployeeDAL = EmployeeDAL;
employee.PermissionChecker = PermissionChecker;
//do something with the employee object
//.....
employee.Save();
}
}
public class ApplicationLayerOption2
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public ApplicationLayerOption2()
{
//set dependencies
EmployeeDAL = new EmployeeDALStub();
PermissionChecker = new PermissionCheckerStub();
}
public void UnitOfWork()
{
Employee employee = EmployeeDAL.GetById(1);
//do something with the employee object
//.....
SaveEmployee(employee);
}
public void SaveEmployee(Employee employee)
{
if (PermissionChecker.IsAllowedToSave("the user")) // Should this be called within EmployeeDAL?
EmployeeDAL.Save(employee);
else
throw new Exception("User not permitted to save.");
}
}
}
What do you do in this situation?
I would prefer the second approach where there's a clear separation between concerns. There's a class responsible for the DAL, there's another one responsible for validation and yet another one for orchestrating these.
In your first approach you inject the DAL and the validation into the business entity. Where I could argue if injecting a validator into the entity could be a good practice, injecting the DAL into the business entity is is definitely not a good practive IMHO (but I understand that this is only a demonstration and in a real project you would at least use a service locator for this).
If I had to choose, I'd choose the second option so that my entities were not associated to any DAL infrastructure and purely focused on the domain logic.
However, I don't really like either approach. I prefer taking more of an AOP approach to security & roles by adding attributes to my application service methods.
The other thing I'd change is moving away from the 'CRUD' mindset. You can provide much granular security options if you secure against specific commands/use cases. For example, I'd make it:
public class MyApplicationService
{
[RequiredCommand(EmployeeCommandNames.MakeEmployeeRedundant)]
public MakeEmployeeRedundant(MakeEmployeeRedundantCommand command)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
{
Employee employee = _employeeRepository.GetById(command.EmployeeId);
employee.MakeRedundant();
_employeeRepository.Save();
}
}
}
public void AssertUserHasCorrectPermission(string requiredCommandName)
{
if (!Thread.CurrentPrincipal.IsInRole(requiredCommandName))
throw new SecurityException(string.Format("User does not have {0} command in their role", requiredCommandName));
}
Where you'd intercept the call to the first method and invoke the second method passing the thing that they must have in their role.
Here's a link on how to use unity for intercepting: http://litemedia.info/aop-in-net-with-unity-interception-model
Where to put the save/pre save methods in a domain object?
Domain objects are persistent-ignorant in DDD. They are unaware of the fact that sometimes they get 'frozen' transported to some storage and then restored. They do not notice that. In other words, domain objects are always in a 'valid' and savable state.
Permission should also be persistent-ignorant and based on domain and Ubiquitous Language, for example:
Only users from Sales group can add OrderLines to an Order in a
Pending state
As opposed to:
Only users from Sales group can save Order.
The code can look like this:
internal class MyApplication {
private IUserContext _userContext;
private ICanCheckPermissions _permissionChecker;
public void AddOrderLine(Product p, int quantity, Money price, ...) {
if(!_permissionChecker.IsAllowedToAddOrderLines(_userContext.CurrentUser)) {
throw new InvalidOperationException(
"User X is not allowed to add order lines to an existing order");
}
// add order lines
}
}