第172章 StateService
172.1 提出背景
在前面的ICAI对象体系中,State已经多次出现。
Individual具有State:
Individual→StateIndividual \rightarrow State
Object具有State:
Object→StateObject \rightarrow State
Behavior、Action、Execution、Result、Service等运行对象同样具有不同生命周期状态。
因此,State并不是某一个具体类的附属字段,而是整个WSaiOS-ICAI运行体系中用于描述对象当前状态的重要基础结构。
但是,如果每一个Domain Object都自行处理:
读取状态
判断状态
转换状态
保存状态
就会产生大量重复代码,同时不同对象的状态规则容易出现不一致。
因此建立:
StateService(状态服务)
StateService负责统一组织状态的读取、判断、转换和保存:
StateService=Read+Evaluate+Transition+SaveStateService = Read + Evaluate + Transition + Save
其核心问题是:
一个具体对象当前处于什么状态?在当前条件下能否进入目标状态?如果允许,状态如何完成合法转换并被保存?
172.2 State定义
State(状态) 是一个具体对象在特定时间、上下文和条件下所处的实际状态描述。
可以定义:
S=(O,V,T,C,R)S=(O,V,T,C,R)
其中:
- SS:State;
- OO:Object,状态所属对象;
- VV:Value,状态值;
- TT:Time,状态发生时间;
- CC:Context,状态上下文;
- RR:Reason,状态原因。
例如:
Individual = 1001
State = running
Time = 10:20:10
Reason = behavior_started
状态不是简单的:
$state = 'running';
因为真正的状态还需要知道:
谁的状态
是什么状态
什么时候发生
为什么发生
是否允许转换
因此State应该作为独立的领域对象理解。
172.3 StateService定义
StateService 是负责状态读取、状态判断、状态转换和状态持久化的应用服务。
可以定义:
SS=(O,S,R,E,T,P)SS=(O,S,R,E,T,P)
其中:
- OO:Object;
- SS:Current State;
- RR:State Rule;
- EE:State Engine;
- TT:Transition;
- PP:Persistence。
运行过程:
Object
↓
Read Current State
↓
Evaluate State
↓
Check Transition Rule
↓
Transition
↓
New State
↓
Save
因此:
StateService=State Process CoordinationStateService = State\ Process\ Coordination
而不是:
StateService=State StorageStateService = State\ Storage
数据库保存状态,但数据库本身不是StateService。
172.4 状态读取
172.4.1 状态读取定义
状态读取是从当前Domain Object或Persistence中取得某一对象当前有效状态的过程。
可以定义:
ReadState(O)→StReadState(O)\rightarrow S_t
其中:
- OO:对象;
- StS_t:对象在当前时间tt的状态。
例如:
Object ID = 2001
↓
StateService
↓
Current State = active
172.5 状态读取流程
基础读取过程:
State Request
↓
Object ID
↓
StateRepository
↓
Current State
↓
State Object
如果状态直接属于Object:
Object
└── State
则可以:
$object = $objectService->get($id);
$state = $object->getState();
如果系统需要独立状态历史,则可以进一步:
Object
↓
Current State
↓
State History
因此:
CurrentState≠StateHistoryCurrentState \neq StateHistory
当前状态回答:
现在是什么状态?
历史回答:
曾经经历过什么状态变化?
172.6 当前状态与历史状态
例如:
10:00 created
10:01 initialized
10:02 ready
10:05 running
10:06 completed
当前状态:
completed
状态历史:
created
→
initialized
→
ready
→
running
→
completed
因此:
Scurrent=completedS_{current}=completed
而:
HS={created,initialized,ready,running,completed}H_S= \{created,initialized,ready,running,completed\}
StateService可以同时提供:
getCurrentState($objectId)
getStateHistory($objectId)
但二者职责不同。
172.7 状态判断
172.7.1 状态判断定义
State Evaluation(状态判断) 是根据当前状态、对象事实、条件和规则确定对象当前状态是否满足某一要求的过程。
例如:
Current State = ready
Required State = ready
↓
Match
或者:
Current State = running
Required State = ready
↓
Not Match
可以定义:
Evaluate(S,C)→REvaluate(S,C)\rightarrow R
其中:
- SS:当前状态;
- CC:判断条件;
- RR:判断结果。
172.8 状态判断不是状态转换
必须严格区分:
状态判断
与:
状态转换
状态判断:
Current State = ready
↓
是否满足条件?
↓
Yes / No
状态转换:
ready
↓
Start
↓
running
因此:
Evaluate≠TransitionEvaluate \neq Transition
状态判断回答:
现在是不是这个状态,或者当前状态是否满足要求?
状态转换回答:
是否可以从当前状态进入另一个状态?
172.9 状态判断Engine
复杂状态判断应该交给StateEngine。
例如:
class StateEngine
{
public function evaluate(
$state,
$condition
) {
if ($state == $condition) {
return true;
}
return false;
}
}
Service负责调用:
$result = $this->stateEngine->evaluate(
$currentState,
$requiredState
);
形成:
StateService
↓
StateEngine
↓
State Evaluation
↓
Result
这样保持第169章建立的原则:
Service=ProcessService = Process Engine=Rule/CalculationEngine = Rule / Calculation
172.10 状态转换
172.10.1 状态转换定义
State Transition(状态转换) 是对象在满足规定条件时,从当前状态进入另一个合法状态的过程。
定义:
T(S1,E,C)→S2T(S_1,E,C)\rightarrow S_2
其中:
- S1S_1:当前状态;
- EE:触发事件;
- CC:转换条件;
- S2S_2:目标状态。
例如:
ready
↓
start
↓
running
这里:
Current State = ready
Event = start
Target State = running
172.11 状态转换规则
状态转换不能任意发生。
可以建立:
RT(S1,E,C)=S2R_T(S_1,E,C)=S_2
即只有满足规则:
CurrentState+Event+ConditionCurrentState + Event + Condition
才能得到:
NewStateNewState
例如:
created → initialized
initialized → ready
ready → running
running → completed
running → failed
而:
created → completed
如果没有对应规则,则应该被拒绝。
172.12 State Transition Matrix
可以使用状态转换矩阵表达状态规则。
例如:
| 当前状态 | 事件 | 目标状态 | 是否允许 |
|---|---|---|---|
| created | initialize | initialized | 是 |
| initialized | prepare | ready | 是 |
| ready | start | running | 是 |
| running | success | completed | 是 |
| running | failure | failed | 是 |
| running | cancel | cancelled | 是 |
| created | complete | completed | 否 |
| failed | success | completed | 否 |
该矩阵本质上是一组确定性规则。
因此:
Transition=Rule EvaluationTransition = Rule\ Evaluation
而不是随机选择。
172.13 状态转换PHP实现
可以建立:
class StateEngine
{
protected $rules;
public function __construct()
{
$this->rules = array(
'created' => array(
'initialize' => 'initialized'
),
'initialized' => array(
'prepare' => 'ready'
),
'ready' => array(
'start' => 'running'
),
'running' => array(
'success' => 'completed',
'failure' => 'failed',
'cancel' => 'cancelled'
)
);
}
public function transition(
$currentState,
$event
) {
if (!isset(
$this->rules[$currentState]
)) {
return false;
}
if (!isset(
$this->rules[$currentState][$event]
)) {
return false;
}
return $this->rules[
$currentState
][$event];
}
}
Engine只负责:
当前状态
+
事件
+
规则
↓
目标状态
不负责数据库保存。
172.14 StateService执行状态转换
StateService负责组织整个转换过程:
public function transition(
$objectId,
$event
) {
$object = $this->objectRepository
->find($objectId);
if (!$object) {
return false;
}
$currentState =
$object->getState();
$newState =
$this->stateEngine->transition(
$currentState,
$event
);
if (!$newState) {
return false;
}
$object->setState(
$newState
);
return $this->objectRepository
->save($object);
}
整个过程:
Object ID
↓
Read Object
↓
Read Current State
↓
State Engine
↓
Check Rule
↓
Generate New State
↓
Update Object
↓
Save
172.15 状态保存
172.15.1 状态保存定义
状态保存是将经过合法状态转换后的State持久化到Persistence层的过程。
可以定义:
Save(St)→PersistenceSave(S_t)\rightarrow Persistence
例如:
State
↓
StateRepository
↓
MySQL
StateService可以调用:
$this->stateRepository->save(
$state
);
或者由ObjectRepository统一保存Object及其当前State。
两种模式都可以存在,但必须保持一致的数据边界。
172.16 当前状态保存与状态历史保存
保存当前状态和保存状态历史是两个不同动作。
当前状态:
objects
state = running
状态历史:
state_history
ready
→
running
因此一次状态转换可能同时产生:
Current State Update
+
State History Record
完整过程:
Old State
↓
Transition
↓
New State
↓
Update Current State
↓
Create State History
↓
Save
可以定义:
StateUpdate=CurrentStateUpdate+HistoryRecordStateUpdate = CurrentStateUpdate + HistoryRecord
这样系统不仅知道“现在是什么”,也知道“为什么变成现在这样”。
172.17 状态原因
状态转换最好记录Reason。
例如:
ready
→
running
Reason = behavior_started
或者:
running
→
failed
Reason = execution_failed
因此状态历史可以包含:
id
object_id
from_state
to_state
event
reason
created_at
例如:
Object 2001
ready → running
event = start
reason = behavior_started
这使状态变化成为可追踪事实。
172.18 StateService与Domain Object
StateService并不拥有所有Object。
例如:
Individual
Object
Behavior
Action
Execution
Service
都可以具有State。
因此StateService应该面向:
State Owner
而不是只面向Object。
可以抽象:
StateOwner→StateStateOwner \rightarrow State
例如:
Individual → State
Object → State
Behavior → State
Action → State
Execution → State
Service → State
因此StateService可以处理:
getState($objectType, $objectId)
changeState($objectType, $objectId, $event)
这样可以避免为每一种对象重新建立完全重复的状态处理逻辑。
172.19 StateService与IndividualService
第170章建立了IndividualService。
IndividualService负责:
Individual Create
Individual Read
Individual Update
Individual Lifecycle
StateService负责:
State Read
State Evaluate
State Transition
State Save
因此:
IndividualService
↓
StateService
↓
StateEngine
例如:
IndividualService
↓
Individual 1001
↓
StateService
↓
ready → running
↓
Repository
IndividualService不应该重新实现完整State Transition规则。
172.20 StateService与ObjectService
第171章建立了ObjectService。
同样:
ObjectService
↓
StateService
↓
StateEngine
例如:
ObjectService
↓
Object 2001
↓
StateService
↓
active → inactive
↓
Persistence
因此ObjectService负责对象生命周期流程,而StateService负责状态专业处理。
172.21 StateService与Engine
二者职责边界可以进一步明确。
StateService
负责:
读取状态
组织判断
请求转换
组织保存
处理Result
StateEngine
负责:
状态规则
状态判断
状态转换
合法性计算
因此:
StateService→StateEngineStateService \rightarrow StateEngine
Service不直接复制Engine内部规则。
172.22 StateService与Repository
StateService不应该直接操作MySQL。
应该:
StateService
↓
StateRepository
↓
MySQL
或者:
StateService
↓
ObjectRepository
↓
MySQL
具体采用哪一种取决于系统的数据模型。
如果State具有独立Identity和History,则推荐建立:
StateRepository
StateHistoryRepository
如果State只是Domain Object的一部分,则可以由ObjectRepository负责保存。
关键原则不是必须只有一种Repository,而是:
StateService不能直接承担Persistence细节。
172.23 StateService PHP基础结构
可以建立:
class StateService
{
protected $stateRepository;
protected $stateEngine;
public function __construct(
$stateRepository,
$stateEngine
) {
$this->stateRepository =
$stateRepository;
$this->stateEngine =
$stateEngine;
}
public function getState($objectId)
{
return $this->stateRepository
->findCurrent($objectId);
}
public function evaluate(
$objectId,
$requiredState
) {
$state =
$this->getState($objectId);
if (!$state) {
return false;
}
return $this->stateEngine
->evaluate(
$state,
$requiredState
);
}
public function transition(
$objectId,
$event
) {
$state =
$this->getState($objectId);
if (!$state) {
return false;
}
$newState =
$this->stateEngine
->transition(
$state->getName(),
$event
);
if (!$newState) {
return false;
}
return $this->stateRepository
->change(
$objectId,
$state->getName(),
$newState,
$event
);
}
public function save($state)
{
return $this->stateRepository
->save($state);
}
}
该结构体现:
StateService
├── Read
├── Evaluate
├── Transition
└── Save
而:
StateEngine
保持独立。
172.24 StateService的完整状态流程
一次状态转换可以统一表示为:
ProcessState=Read→Evaluate→Transition→SaveProcessState = Read \rightarrow Evaluate \rightarrow Transition \rightarrow Save
展开:
Object
↓
Read State
↓
Current State
↓
Condition
↓
State Evaluation
↓
Transition Rule
↓
New State
↓
Save Current State
↓
Save History
↓
Result
172.25 状态转换失败
状态转换失败必须成为合法Result。
例如:
Current State = created
Event = complete
如果没有:
created + complete → completed
规则,则:
Transition = Failed
而不能强行:
created → completed
因此:
InvalidTransition→FailedInvalidTransition \rightarrow Failed
失败原因可以保存:
from_state
event
target_state
reason
例如:
created
+
complete
=
invalid_transition
这类失败事实可以进一步进入:
Feedback
↓
Memory
↓
Experience
172.26 状态与Result
State不能脱离实际Result随意变化。
例如:
running
↓
Execution
↓
Result = success
↓
completed
失败:
running
↓
Execution
↓
Result = failure
↓
failed
因此:
Execution→Result→StateTransitionExecution \rightarrow Result \rightarrow StateTransition
而不是:
Execution→State=CompletedExecution \rightarrow State=Completed
这与第163章Feedback、第165章Diagnosis以及第168章Runtime Object体系保持一致。
172.27 状态与Feedback
状态变化可以成为Feedback的重要输入。
例如:
Before State = ready
After State = running
形成:
ΔS=Safter−Sbefore\Delta S = S_{after} – S_{before}
即:
ready → running
StateService完成转换后,可以向FeedbackService提供:
State Before
State After
Event
Reason
Time
形成:
StateService
↓
State Change
↓
FeedbackService
↓
MemoryService
从而进入ICAI闭环。
172.28 状态与Memory、Experience
状态变化本身属于重要历史事实。
例如:
Object 2001
ready → running
保存为History后:
History
↓
Memory
多次状态变化经过比较后:
Memory
↓
Comparison
↓
Experience
因此:
StateHistory→Memory→ExperienceStateHistory \rightarrow Memory \rightarrow Experience
Experience又可能影响未来状态判断。
例如:
Experience
↓
Risk
↓
Protection
↓
State
因此StateService虽然专注于状态,但处于整个ICAI反馈和学习闭环的重要位置。
172.29 StateService统一状态模型
可以建立:
SS=(R,E,T,S,H,P)SS=(R,E,T,S,H,P)
其中:
- RR:Read;
- EE:Evaluate;
- TT:Transition;
- SS:Save;
- HH:History;
- PP:Persistence。
核心流程:
Read→Evaluate→Transition→Save→History\boxed{ Read \rightarrow Evaluate \rightarrow Transition \rightarrow Save \rightarrow History }
如果转换失败:
Read→Evaluate→Invalid→Failure\boxed{ Read \rightarrow Evaluate \rightarrow Invalid \rightarrow Failure }
172.30 StateService在整体架构中的位置
结合前面几章:
Controller
↓
Service
↓
Domain Object
↓
StateService
↓
StateEngine
↓
State
↓
Repository
↓
MySQL
对于Individual:
IndividualService
↓
Individual
↓
StateService
↓
StateEngine
对于Object:
ObjectService
↓
Object
↓
StateService
↓
StateEngine
对于Execution:
ExecutionService
↓
Execution
↓
StateService
↓
StateEngine
因此StateService可以成为整个ICAI系统共享的基础领域服务。
172.31 StateService与Runtime
第168章建立了:
RuntimeObject=(Object,State,Context,Relation,Time)RuntimeObject=(Object,State,Context,Relation,Time)
因此Runtime Object必须持续依赖State。
运行过程:
Runtime Object
↓
Current State
↓
Event
↓
StateService
↓
StateEngine
↓
New State
↓
Runtime Update
↓
Persistence
例如:
Runtime Individual
State = ready
↓
Start Behavior
↓
StateService
↓
StateEngine
↓
State = running
因此:
Runtime↔StateServiceRuntime \leftrightarrow StateService
StateService成为Runtime状态变化的重要基础服务。
172.32 StateService与MVC
在MVC架构中,StateService位于Controller与Domain/Repository之间。
Controller
↓
StateService
↓
StateEngine
↓
Domain Object
↓
Repository
↓
MySQL
Controller不应该直接:
UPDATE state
而应该:
Controller
↓
StateService
↓
Transition
↓
Save
这样能够保证所有状态变化经过统一规则。
172.33 StateService数据库设计
如果State采用独立数据模型,可以建立:
states
id
object_type
object_id
state
context
reason
created_at
updated_at
状态历史:
state_history
id
object_type
object_id
from_state
to_state
event
reason
created_at
如果需要状态规则数据库化,还可以建立:
state_transition_rules
id
object_type
from_state
event
to_state
condition
enabled
形成:
State
↓
State History
↓
Transition Rules
但是状态规则是否全部数据库化,应根据系统复杂度决定。
基础系统可以使用PHP配置和Engine规则;规则规模扩大后再进一步持久化。
172.34 状态保存的真实性原则
StateService必须遵循:
只保存真实发生或经过合法规则确认的状态。
不能为了程序流程方便而提前保存:
completed
例如:
Execution尚未完成
却保存:
State = completed
是不正确的。
正确流程:
Execution
↓
Actual Result
↓
Verification
↓
State Transition
↓
State Save
因此:
StateSave⇐ValidTransitionStateSave \Leftarrow ValidTransition
而不是:
StateSave⇐ProgramExpectationStateSave \Leftarrow ProgramExpectation
172.35 本章核心原则
StateService需要遵循以下原则。
第一,状态独立于对象类型
State描述当前情况,不描述Class Type。
第二,判断与转换分离
Evaluate ≠ Transition
第三,转换必须有规则
Current State
+
Event
+
Condition
→
New State
第四,Engine负责规则
StateEngine负责状态判断和转换规则。
第五,Service负责流程
StateService负责读取、调用、转换、保存和结果组织。
第六,Repository负责持久化
StateService不直接承担SQL。
第七,当前状态与历史状态分离
Current State ≠ State History
第八,状态必须来源于事实
真实Execution、Result、Feedback和Verification应当成为状态变化的重要依据。
172.36 本章小结
第172章建立了ICAI统一的StateService。
State定义:
S=(O,V,T,C,R)S=(O,V,T,C,R)
StateService定义:
SS=(R,E,T,S,H,P)SS=(R,E,T,S,H,P)
其中:
- RR:Read;
- EE:Evaluate;
- TT:Transition;
- SS:Save;
- HH:History;
- PP:Persistence。
核心流程:
Object
↓
State Read
↓
State Evaluation
↓
Transition Rule
↓
New State
↓
State Save
↓
State History
其核心工程关系为:
StateService→StateEngine→State→Repository→MySQL\boxed{ StateService \rightarrow StateEngine \rightarrow State \rightarrow Repository \rightarrow MySQL }
同时,它与前面的IndividualService、ObjectService形成统一关系:
IndividualService
↓
Individual
↓
StateService
↓
StateEngine
ObjectService
↓
Object
↓
StateService
↓
StateEngine
因此,StateService并不是一个简单的状态字段读写工具,而是ICAI运行系统中的 统一状态控制服务。
最终形成:
Read→Evaluate→Transition→Save→History→Feedback\boxed{ Read \rightarrow Evaluate \rightarrow Transition \rightarrow Save \rightarrow History \rightarrow Feedback }
再进入:
Feedback→Memory→Experience→Future State Evaluation\boxed{ Feedback \rightarrow Memory \rightarrow Experience \rightarrow Future\ State\ Evaluation }
至此,ICAI已经从“对象能够被创建和管理”,进一步进入“对象能够依据事实和规则发生合法状态变化”的运行阶段,为后续CapabilityService、MethodService、BehaviorService和ExecutionService提供统一的状态基础。