首页 理论 架构 工程 文档 白皮书 著作 研究 案例 下载 博客 关于 开始使用 →

第172章 StateService

第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提供统一的状态基础。

Leave a Reply

Your email address will not be published. Required fields are marked *