状态机适合处理促销系统中的状态变化吗?
我正在开发促销系统,我刚刚踩到了一些可能可以用状态机模式处理的东西,但我还没有状态机的经验。 也许状态机在这种情况下完全没用:) 所以我有一个促销活动,它有一定的持续时间,一些指定的客户,产品,折扣等。每个促销活动也有它的状态。 大约有5个州。 状态之间的转换是严格定义的 - 不可能直接将状态 1 更改为状态 3 - 用户必须首先将状态更改为状态 2。 有一些限制,例如“促销处于状态 3-5 时无法添加更多产品”。 或者诸如“只有超级用户才能在状态 3-5 时编辑促销费用”之类的限制。
我刚刚读到 http://www.codeplex.com/SimpleStateMachine ,但我不确定如果对于这种情况来说不是太复杂的话。 我可以使用以下内容处理服务层中的状态逻辑:
if (promotion.state == statesRepository.GetState3() && false == loggedUser.IsInRole("superUser")){
throw new PromotionStateException("user not allowed to edit promotion in this status");
}
...
或
public void ChangePromotionStatus(promotion, newStatus){
if (promotion.Status == status1 && newStatus != statesRepo.GetState2()){
throw new StateTransitionException("unable to change from status 1 to " + newStatus);
}
}
但我不喜欢这种代码 - 必须有更好的方法:) 有人有建议吗? 当然,我可以分离关注点并开发诸如 PromotionStatusChangeReviewService、PromotionEditPermissionService 等服务来减少代码的耦合,但目前可能有一些更好的解决方案。
I'm developing sales promotion system and I just stepped on something that could be probably handled with state machine pattern, but I have no experiences with state machines yet. Maybe the state machine is totally useless in this situation :)
So I have a sales promotion which has some duration, some assigned customers, products, discounts etc. Each promotion also has it's state. There's about 5 states. The transitions between states are strictly defined - it's not possible to change state 1 to state 3 directly - user has to change state to 2 first. There're some limitations like "it's not possible to add more products when promotion is in state 3-5". Or limitations like "only super-users can edit promotion costs when it's in state 3-5".
I just read about http://www.codeplex.com/SimpleStateMachine , but I'm not sure if it isn't too complex for this case. I could handle the state logic in my service layer using things like:
if (promotion.state == statesRepository.GetState3() && false == loggedUser.IsInRole("superUser")){
throw new PromotionStateException("user not allowed to edit promotion in this status");
}
...
or
public void ChangePromotionStatus(promotion, newStatus){
if (promotion.Status == status1 && newStatus != statesRepo.GetState2()){
throw new StateTransitionException("unable to change from status 1 to " + newStatus);
}
}
But I don't like this kind of code - there must be some better approach :) Does anybody have an advice? I could separate the concerns of course and develop services like PromotionStatusChangeReviewService, PromotionEditPermissionService etc to make the code less coupled, but there's probably some better solution I can't see at the moment.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于状态机来说,五个状态并不太复杂,但我认为通过尝试特殊或显式处理一些转换,您会遇到一些问题。 以下是一些提示:
除非您能够以有意义的方式标记状态,否则状态机没有任何帮助。 “状态3”没有任何意义; 您需要将其命名为有用的名称,例如“Promoted”、“Active”、“Completed”等。
状态机模式的一部分假设您有一个独立的实体,它了解状态以及如何在状态之间进行转换。 例如,您不应该在示例中使用像
ChangePromotionStatus()
这样的方法,如果不允许该状态,该方法就会崩溃。 状态机应该简单地防止无法发生的转换。状态
如果可能的转换数量很少且定义明确,并且对它们进行标记是有意义的,那么我还建议对转换进行命名。 如果所有转换都执行相同的操作但方式略有不同,这可能特别有用。
如果
Five states isn't too complex for a state machine, but I think you're running into some problems by trying to make a few of the transitions be handled specially or explicitly. Here's some tips:
State machines aren't helpful unless you can label the states in a meaningful way. "status 3" means nothing; you need to call it something useful like "Promoted", "Active", "Completed", et cetera.
Part of the State Machine pattern assumes that you have a detached entity that understands the states and how to transition between them. You shouldn't have a method like the
ChangePromotionStatus()
in your example, for instance, where it blows up if the state shouldn't be allowed. The state machine should simply prevent transitions that can't occur.If the number of possible transitions is small and well-defined, and it makes sense to label them, I'd also recommend naming the transitions as well. This is probably especially useful if the transitions all do the same thing but in slightly different ways.
约翰击中了要害 - 您希望使用状态机建模的流程与域实体解耦。 您的域实体可能不应该直接知道它们正在状态机中使用,状态机将根据某些事件管理将它们从一个状态转换到另一个状态的工作,但它们将了解业务他们所处的每个状态的含义,并且能够执行或应用与这些状态相关的业务规则。
理想情况下,适合由状态机管理的域实体将具有某种充当状态机状态的状态,并将引发可由状态机使用的事件来确定何时适合转换。
但是,如果您的状态确实是完全顺序的 - 即它们总是 abcde 或向后和向前恰好前进一步,我不确定状态机是否有意义,因为没有特殊的选择下一个状态所需的上下文 - 您只能向后或向前移动,因此任何有序的状态列表(例如枚举)与下一个/上一个逻辑相结合就足够了 - 但现实世界的过程很少那么严格线性,即使它们乍一看似乎是这样。
John hit the nail on the head - you want your process, as modeled using a state machine, to be decoupled from your domain entities. Your domain entities probably shouldn't have direct knowledge that they are being used in a state machine, which will manage the job of transitioning them from state to state based upon certain events, but they will understanding the business meaning of each state they are in, and be able to enforce or apply business rules related to those states.
Ideally, your domain entities that are appropriate for being managed by a state machine will have some kind of status that acts as a state for the state machine, and will raise events which can be used by the state machine to determine when a transition is appropriate.
However, if it is indeed true that your states are completely sequential - i.e. they always go a-b-c-d-e or backwards and forwards exactly one step, I'm not sure a state machine does make sense because there is no special context needed to choose the next state - you can only go backwards or forwards, so any ordered list of states (such as an Enum) coupled with Next/Previous logic should suffice - but real world processes are rarely that strictly linear, even though they may appear to be at first blush.