mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
1050 lines
48 KiB
HTML
1050 lines
48 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
||
<head>
|
||
|
||
<head>
|
||
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
|
||
<link rel="icon" href="/static/favicon.png">
|
||
|
||
<title>097 设计概念的统一语言.md.html</title>
|
||
|
||
<!-- Spectre.css framework -->
|
||
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
|
||
<!-- theme css & js -->
|
||
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
|
||
<div class="book-sidebar">
|
||
|
||
<div class="book-brand">
|
||
|
||
<a href="/">
|
||
|
||
<img src="/static/favicon.png">
|
||
|
||
<span>技术文章摘抄</span>
|
||
|
||
</a>
|
||
|
||
</div>
|
||
|
||
<div class="book-menu uncollapsible">
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="../">上一级</a></li>
|
||
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/001 「战略篇」访谈 DDD 和微服务是什么关系?.md.html">001 「战略篇」访谈 DDD 和微服务是什么关系?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/002 「战略篇」开篇词:领域驱动设计,重焕青春的设计经典.md.html">002 「战略篇」开篇词:领域驱动设计,重焕青春的设计经典.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/003 领域驱动设计概览.md.html">003 领域驱动设计概览.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/004 深入分析软件的复杂度.md.html">004 深入分析软件的复杂度.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/005 控制软件复杂度的原则.md.html">005 控制软件复杂度的原则.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/006 领域驱动设计对软件复杂度的应对(上).md.html">006 领域驱动设计对软件复杂度的应对(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/007 领域驱动设计对软件复杂度的应对(下).md.html">007 领域驱动设计对软件复杂度的应对(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/008 软件开发团队的沟通与协作.md.html">008 软件开发团队的沟通与协作.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/009 运用领域场景分析提炼领域知识(上).md.html">009 运用领域场景分析提炼领域知识(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/010 运用领域场景分析提炼领域知识(下).md.html">010 运用领域场景分析提炼领域知识(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/011 建立统一语言.md.html">011 建立统一语言.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/012 理解限界上下文.md.html">012 理解限界上下文.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/013 限界上下文的控制力(上).md.html">013 限界上下文的控制力(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/014 限界上下文的控制力(下).md.html">014 限界上下文的控制力(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/015 识别限界上下文(上).md.html">015 识别限界上下文(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/016 识别限界上下文(下).md.html">016 识别限界上下文(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/017 理解上下文映射.md.html">017 理解上下文映射.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/018 上下文映射的团队协作模式.md.html">018 上下文映射的团队协作模式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/019 上下文映射的通信集成模式.md.html">019 上下文映射的通信集成模式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/020 辨别限界上下文的协作关系(上).md.html">020 辨别限界上下文的协作关系(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/021 辨别限界上下文的协作关系(下).md.html">021 辨别限界上下文的协作关系(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/022 认识分层架构.md.html">022 认识分层架构.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/023 分层架构的演化.md.html">023 分层架构的演化.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/024 领域驱动架构的演进.md.html">024 领域驱动架构的演进.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/025 案例 层次的职责与协作关系(图文篇).md.html">025 案例 层次的职责与协作关系(图文篇).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/026 限界上下文与架构.md.html">026 限界上下文与架构.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/027 限界上下文对架构的影响.md.html">027 限界上下文对架构的影响.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/028 领域驱动设计的代码模型.md.html">028 领域驱动设计的代码模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/029 代码模型的架构决策.md.html">029 代码模型的架构决策.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/030 实践 先启阶段的需求分析.md.html">030 实践 先启阶段的需求分析.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/031 实践 先启阶段的领域场景分析(上).md.html">031 实践 先启阶段的领域场景分析(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/032 实践 先启阶段的领域场景分析(下).md.html">032 实践 先启阶段的领域场景分析(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/033 实践 识别限界上下文.md.html">033 实践 识别限界上下文.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/034 实践 确定限界上下文的协作关系.md.html">034 实践 确定限界上下文的协作关系.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/035 实践 EAS 的整体架构.md.html">035 实践 EAS 的整体架构.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/036 「战术篇」访谈:DDD 能帮开发团队提高设计水平吗?.md.html">036 「战术篇」访谈:DDD 能帮开发团队提高设计水平吗?.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/037 「战术篇」开篇词:领域驱动设计的不确定性.md.html">037 「战术篇」开篇词:领域驱动设计的不确定性.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/038 什么是模型.md.html">038 什么是模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/039 数据分析模型.md.html">039 数据分析模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/040 数据设计模型.md.html">040 数据设计模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/041 数据模型与对象模型.md.html">041 数据模型与对象模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/042 数据实现模型.md.html">042 数据实现模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/043 案例 培训管理系统.md.html">043 案例 培训管理系统.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/044 服务资源模型.md.html">044 服务资源模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/045 服务行为模型.md.html">045 服务行为模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/046 服务设计模型.md.html">046 服务设计模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/047 领域模型驱动设计.md.html">047 领域模型驱动设计.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/048 领域实现模型.md.html">048 领域实现模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/049 理解领域模型.md.html">049 理解领域模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/050 领域模型与结构范式.md.html">050 领域模型与结构范式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/051 领域模型与对象范式(上).md.html">051 领域模型与对象范式(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/052 领域模型与对象范式(中).md.html">052 领域模型与对象范式(中).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/053 领域模型与对象范式(下).md.html">053 领域模型与对象范式(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/054 领域模型与函数范式.md.html">054 领域模型与函数范式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/055 领域驱动分层架构与对象模型.md.html">055 领域驱动分层架构与对象模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/056 统一语言与领域分析模型.md.html">056 统一语言与领域分析模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/057 精炼领域分析模型.md.html">057 精炼领域分析模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/058 彩色 UML 与彩色建模.md.html">058 彩色 UML 与彩色建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/059 四色建模法.md.html">059 四色建模法.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/060 案例 订单核心流程的四色建模.md.html">060 案例 订单核心流程的四色建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/061 事件风暴与业务全景探索.md.html">061 事件风暴与业务全景探索.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/062 事件风暴与领域分析建模.md.html">062 事件风暴与领域分析建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/063 案例 订单核心流程的事件风暴.md.html">063 案例 订单核心流程的事件风暴.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/064 表达领域设计模型.md.html">064 表达领域设计模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/065 实体.md.html">065 实体.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/066 值对象.md.html">066 值对象.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/067 对象图与聚合.md.html">067 对象图与聚合.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/068 聚合设计原则.md.html">068 聚合设计原则.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/069 聚合之间的关系.md.html">069 聚合之间的关系.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/070 聚合的设计过程.md.html">070 聚合的设计过程.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/071 案例 培训领域模型的聚合设计.md.html">071 案例 培训领域模型的聚合设计.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/072 领域模型对象的生命周期-工厂.md.html">072 领域模型对象的生命周期-工厂.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/073 领域模型对象的生命周期-资源库.md.html">073 领域模型对象的生命周期-资源库.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/074 领域服务.md.html">074 领域服务.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/075 案例 领域设计模型的价值.md.html">075 案例 领域设计模型的价值.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/076 应用服务.md.html">076 应用服务.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/077 场景的设计驱动力.md.html">077 场景的设计驱动力.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/078 案例 薪资管理系统的场景驱动设计.md.html">078 案例 薪资管理系统的场景驱动设计.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/079 场景驱动设计与 DCI 模式.md.html">079 场景驱动设计与 DCI 模式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/080 领域事件.md.html">080 领域事件.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/081 发布者—订阅者模式.md.html">081 发布者—订阅者模式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/082 事件溯源模式.md.html">082 事件溯源模式.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/083 测试优先的领域实现建模.md.html">083 测试优先的领域实现建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/084 深入理解简单设计.md.html">084 深入理解简单设计.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/085 案例 薪资管理系统的测试驱动开发(上).md.html">085 案例 薪资管理系统的测试驱动开发(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/086 案例 薪资管理系统的测试驱动开发(下).md.html">086 案例 薪资管理系统的测试驱动开发(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/087 对象关系映射(上).md.html">087 对象关系映射(上).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/088 对象关系映射(下).md.html">088 对象关系映射(下).md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/089 领域模型与数据模型.md.html">089 领域模型与数据模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/090 领域驱动设计对持久化的影响.md.html">090 领域驱动设计对持久化的影响.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/091 领域驱动设计体系.md.html">091 领域驱动设计体系.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/092 子领域与限界上下文.md.html">092 子领域与限界上下文.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/093 限界上下文的边界与协作.md.html">093 限界上下文的边界与协作.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/094 限界上下文之间的分布式通信.md.html">094 限界上下文之间的分布式通信.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/095 命令查询职责分离.md.html">095 命令查询职责分离.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/096 分布式柔性事务.md.html">096 分布式柔性事务.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
<a class="current-tab" href="/专栏/领域驱动设计实践(完)/097 设计概念的统一语言.md.html">097 设计概念的统一语言.md.html</a>
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/098 模型对象.md.html">098 模型对象.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/099 领域驱动设计参考过程模型.md.html">099 领域驱动设计参考过程模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/100 领域驱动设计的精髓.md.html">100 领域驱动设计的精髓.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/101 实践 员工上下文的领域建模.md.html">101 实践 员工上下文的领域建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/102 实践 考勤上下文的领域建模.md.html">102 实践 考勤上下文的领域建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/103 实践 项目上下文的领域建模.md.html">103 实践 项目上下文的领域建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/104 实践 培训上下文的业务需求.md.html">104 实践 培训上下文的业务需求.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/105 实践 培训上下文的领域分析建模.md.html">105 实践 培训上下文的领域分析建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/106 实践 培训上下文的领域设计建模.md.html">106 实践 培训上下文的领域设计建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/107 实践 培训上下文的领域实现建模.md.html">107 实践 培训上下文的领域实现建模.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/108 实践 EAS 系统的代码模型.md.html">108 实践 EAS 系统的代码模型.md.html</a>
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/109 后记:如何学习领域驱动设计.md.html">109 后记:如何学习领域驱动设计.md.html</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
|
||
<div class="sidebar-toggle-inner"></div>
|
||
|
||
</div>
|
||
<script>
|
||
|
||
function add_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.add('show')
|
||
|
||
}
|
||
function remove_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.remove('show')
|
||
|
||
}
|
||
function sidebar_toggle() {
|
||
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let content = document.querySelector('.off-canvas-content')
|
||
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
|
||
sidebar_toggle.classList.remove('extend')
|
||
|
||
sidebar.classList.remove('hide')
|
||
|
||
content.classList.remove('extend')
|
||
|
||
} else { // hide
|
||
|
||
sidebar_toggle.classList.add('extend')
|
||
|
||
sidebar.classList.add('hide')
|
||
|
||
content.classList.add('extend')
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
function open_sidebar() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.add('show')
|
||
|
||
overlay.classList.add('show')
|
||
|
||
}
|
||
|
||
function hide_canvas() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.remove('show')
|
||
|
||
overlay.classList.remove('show')
|
||
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
|
||
<div class="columns">
|
||
|
||
<div class="column col-12 col-lg-12">
|
||
|
||
<div class="book-navbar">
|
||
|
||
<!-- For Responsive Layout -->
|
||
|
||
<header class="navbar">
|
||
|
||
<section class="navbar-section">
|
||
|
||
<a onclick="open_sidebar()">
|
||
|
||
<i class="icon icon-menu"></i>
|
||
|
||
</a>
|
||
|
||
</section>
|
||
|
||
</header>
|
||
|
||
</div>
|
||
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
|
||
overflow-x: auto;
|
||
|
||
overflow-y: hidden;">
|
||
|
||
<div class="book-post">
|
||
|
||
<p id="tip" align="center"></p>
|
||
|
||
<div><h1>097 设计概念的统一语言</h1>
|
||
|
||
<p>毫无疑问,领域驱动设计引入了一套自成体系的设计概念:限界上下文、应用服务、领域服务、聚合、实体、值对象、领域事件以及资源库和工厂。这些设计概念又与其它设计方法的设计概念互为参考和引用,再糅合不同团队不同企业不同领域的设计实践,就产生了更多的设计概念。诸多概念纠缠不清,说法不一,理解不同,就会形成认知上的混乱,干扰整个团队对领域驱动设计的理解。既然领域驱动设计强调为领域逻辑建立统一语言,我们不妨也为这些设计概念定义一套“统一语言”,通过理解的一致保证交流的畅通,确保架构和设计方案的统一性。</p>
|
||
|
||
<h3>设计术语的统一</h3>
|
||
|
||
<p>当我们在讨论领域驱动设计时,不止要谈到领域驱动设计固有的设计概念,结合开发语言和开发平台的设计实践,又会有其他设计概念穿插其中,它们之间的关系并非正交的,解决的问题和思考的角度都不太一致,许多设计概念更有其历史渊源,却又在提出之后或者被滥用,或者被错用,到了最后已经失去了它本来的面目。因此,我们需要揭开这些设计术语的历史迷雾,理解其本真的概念,然后再确定它的统一语言。</p>
|
||
|
||
<h4>POJO对象</h4>
|
||
|
||
<p><a href="https://www.martinfowler.com/bliki/POJO.html">POJO(Plain Old Java Object)</a>的概念来自 Martin Fowler、Rebecca Parsons 和 Josh MacKenzie 在 2000 年一次大会的讨论。它的本质含义是指一个常规的 Java 对象,不受任何框架、平台的约束和限制。除了遵守 Java 语法之外,它不应该继承预先设定的类、实现预先设定的接口或者包含预先指定的注解。可以认为,如果一个模块定义的对象皆为 POJO,那么除了依赖 JDK 之外,它不会依赖任何框架或平台。在 .NET 框架中,借助这个概念,也提出了 POCO(Plain Old CLR Object)的概念。</p>
|
||
|
||
<p>Martin Fowler 等人之所以提出 POJO,是因为他们看到了<strong>使用 POJO 封装业务逻辑的益处</strong>,而在 2000 年那个时代,恰恰是 EJB 开始流行的时代,受到 EJB 规范的限制,Java 开发人员更愿意使用 Entity Bean,而 Entity Bean 却是与 EJB 强耦合的。</p>
|
||
|
||
<p>一些人错误地将 Entity Bean 理解为仅具有持久化能力的 Java 对象,实际并非如此。即使 EJB 规范也认为 Entity Bean 可以包含复杂的业务逻辑,例如 <a href="https://docs.oracle.com/cd/A91202_01/901_doc/java.901/a90188/entity.htm#1028116">Oracle 的官方网站</a>对 Entity Bean 的定义就包括:</p>
|
||
|
||
<ul>
|
||
|
||
<li>管理持久化数据</li>
|
||
|
||
<li>通过主键形成唯一标识</li>
|
||
|
||
<li>引入依赖对象执行复杂逻辑</li>
|
||
|
||
</ul>
|
||
|
||
<p>当 Entity Bean 还封装了复杂的业务逻辑时,带来的危害更多。由于定义一个 Entity Bean 类需要继承自 javax.ejb.EntityBean(基于 EJB 3.0 之前的规范),这就使得业务逻辑与 EJB 框架紧耦合,不利于对业务逻辑的测试、部署与运行。这也正是 Rod Johnson 要提出抛开 EJB 进行 J2EE 开发的原因。当然,Entity Bean 与 EJB 框架紧耦合的为人诟病,主要是针对 EJB 3.0 之前的版本,随着 Spring 与 Hibernate 等轻量级框架出来之后,EJB 也开始向轻量级方向发展,通过大量使用标注来降低 EJB 对 Java 类的侵入性。</p>
|
||
|
||
<p>既然 Entity Bean 也可以封装业务逻辑,针对它提出的 POJO 自然也可以封装业务逻辑。如前所述,Martin Fowler 等人看到的是“使用 POJO 封装业务逻辑的益处”,这就说明 <strong>POJO 对象并非只有 getter/setter 的贫血对象</strong>,它的主要特征不在于它究竟定义了什么样的成员,而在于它作为一个常规的 Java 对象,并不依赖于除语言之外的任何框架。当然,它的目的不在于数据传输,也不在于数据持久化,它其实是一种设计模式。</p>
|
||
|
||
<h4>Java Bean</h4>
|
||
|
||
<p>严格讲来,Java Bean 其实是一种 Java 开发规范。一个 Java Bean 类必须同时满足以下三个条件:</p>
|
||
|
||
<ul>
|
||
|
||
<li>类必须是具体的、公共的</li>
|
||
|
||
<li>具有无参构造函数</li>
|
||
|
||
<li>提供一致性设计模式的公共方法将内部字段暴露为成员属性,即为内部字段提供规范的 get 和 set 方法</li>
|
||
|
||
</ul>
|
||
|
||
<p>认真解读这三个条件,你会发现它们都是为支持反射访问类成员而准备的前置条件,包括创建 Java Bean 实例和操作内部字段。只要遵循 Java Bean 规范,就可以采用完全统一的一套代码实现对 Java Bean 的访问。这一规范并没有提及业务方法的定义,这是因为规范无法对公开的方法做出任何一致性的限制。这意味着框架使用 Java Bean,看重的其实是该对象携带的数据,并能通过反射访问对象的字段值。例如,JSP 对 Java Bean 的使用:</p>
|
||
|
||
<pre><code class="language-html"><jsp:useBean id="student" class="com.dddsample.javabeans.Student">
|
||
|
||
<jsp:setProperty name="student" property="firstName" value="Bill"/>
|
||
|
||
<jsp:setProperty name="student" property="lastName" value="Gates"/>
|
||
|
||
<jsp:setProperty name="student" property="age" value="20"/>
|
||
|
||
</jsp:useBean>
|
||
</code></pre>
|
||
|
||
<p>JSP 标签中使用的 Student 类就是一个 Java Bean。如果该类的定义没有遵循 Java Bean 规范,JSP 就可能无法实例化 Student 对象,无法设置 firstName 等字段值。</p>
|
||
|
||
<p>至于 Session Bean、Entity Bean 和 Message Driven Bean 则是 Enterprise Java Bean 的三个分类,它们都是 Java Bean,但 EJB 对它们又有框架的约束,例如 Session Bean 需要继承自 javax.ejb.SessionBean,Entity Bean 需要继承自 javax.ejb.EntityBean。</p>
|
||
|
||
<p>追本溯源,可发现 <strong>POJO 与 Java Bean 并没有任何关系</strong>。一个 POJO 如果遵循了 Java Bean 的设计规范,可以成为一个 Java Bean,但并不意味着 POJO 一定是 Java Bean。反过来,一个 Java Bean 如果没有依赖任何框架,也可以认为是一个 POJO。但是,Enterprise Java Bean 一定不是一个 POJO。POJO 可以封装业务逻辑,Java Bean 也没有限制它不能封装业务逻辑。一个提供了丰富领域逻辑的 Java 对象,如果它同时又遵循了 Java Bean 的设计规范,也可以认为是一个 Java Bean。</p>
|
||
|
||
<h4>贫血模型</h4>
|
||
|
||
<p>贫血模型准确地说,应该被称之为“<a href="https://www.martinfowler.com/bliki/AnemicDomainModel.html">贫血领域模型(Anemic Domain Model)</a>”,因为该术语主要用于领域模型这个语境,来自 Martin Fowler 的创造。从贫血这个词可知,这样的一种领域模型必然是不健康的,它违背了面向对象设计的关键原则,即“数据与行为应该封装在一起”。在领域驱动设计中,如果一个实体或值对象除了内部字段之外只有一系列的 getter/setter 方法,就成为了贫血对象。</p>
|
||
|
||
<p>关于贫血领域模型的坏处,我在本书已经阐述了很多,例如它会影响对象之间的协作方式,它违背了“迪米特法则”与“信息专家模式”,它会导致“特性依恋”坏味道的产生,最后,它其实破坏了封装,导致领域服务形成一种事务脚本的实现。</p>
|
||
|
||
<p>与贫血领域模型相对的是富领域模型(Rich Domain Model),也就是封装了领域逻辑的领域模型。这样的领域模型才符合面向对象设计思想。当我们采用对象范式进行领域设计建模时,实体与值对象都应该建立为富领域模型。富领域模型就是 Martin Fowler 在《企业应用架构模式》中定义的领域模型模式。作为一种<a href="https://martinfowler.com/eaaCatalog/index.html">领域逻辑模式(Domain Logic Pattern)</a>,它与事务脚本(Transaction Script)、表模块(Table Module)属于不同的表达领域逻辑的模式。倘若遵循这一模式的定义,即默认为<strong>领域模型就应该是富领域模型</strong>,而贫血领域模型会导致事务脚本,本不应该将这样的模型称为领域模型。</p>
|
||
|
||
<p>当我们在讨论领域模型时,发现更有好事者在贫血模型的基础上衍生出各种与“血”有关的各种模型,统计下来,除了 Martin Fowler 提出的贫血模型之外,还包括失血模型、充血模型与胀血模型。我将这些模型戏称为“X 血模型”。我个人并不赞成社区制造出这么多的模型,太多的概念反而为造成概念的混乱不清。实际上,造成贫血模型的原因是不恰当的职责分配。如果我们能够按照合理的职责分配原则来设计领域模型,就无所谓这些 X 血模型了。只要职责分配合理,有可能领域模型中的一个类确乎没有定义具有领域逻辑的行为,那也只能说明该领域概念确实不具有领域逻辑,不应当称之为贫血对象。</p>
|
||
|
||
<p>我还看到<a href="https://blog.csdn.net/Dancen/article/details/7270784">有的人错误的理解或者误用了“贫血模型”的定义</a>,将只有字段和 getter/setter 方法的类称之为“失血模型”,而将 Martin Fowler 提出的富领域模型称之为“贫血模型”。这一说法绝对是“谬种流传”。顾名思义,贫血(Anemic)这个词代表着不健康,贫血模型当然就意指不健康的模型。如果采用这篇文章的定义,Martin Fowler 所推崇的富领域模型反倒成了不健康的贫血模型(虽然该文作者未必认为贫血模型不健康),该何其无辜啊!因此,在这些“X 血模型”中,我们必须坚定果断地去掉失血模型,并让贫血模型回到本初的含义。</p>
|
||
|
||
<p>去掉错误的失血模型,一般认为充血模型其实就是 Martin Fowler 提出的富领域模型。我总觉得“充血”这个词仍然带有不健康的隐含意义,故而不愿意使用这一模式名称,更不用说更加惊悚的“胀血模型”了。这种胀血模型违背了单一职责原则,将与该领域概念相关的所有逻辑都放到了领域模型对象中,包括对数据访问对象或资源库的依赖以及对事务、授权等横切关注点的调用。在领域驱动设计的语境中,这相当于让一个实体类承担了聚合、领域服务以及应用服务的职责,明显有悖于领域驱动设计乃至面向对象的设计原则。</p>
|
||
|
||
<p>有的观点认为混入了持久化能力的领域模型属于充血模型,这更进一步混淆了 X 血模型的边界。实际上,Martin Fowler 将这种对象称之为“<a href="https://martinfowler.com/eaaCatalog/activeRecord.html">活动记录(Active Record)</a>”,它属于数据源架构模式(Data Source Architectural Patterns)中的一种。这种设计方式是领域驱动设计努力避免的,如果每个实体都混入了持久化能力,就会丢失聚合的边界保护作用,资源库也就失去了存在的价值。</p>
|
||
|
||
<p>还有人混淆了领域模型与 POJO 的概念,认为贫血模型对象就是一个 POJO,殊不知这二者根本就是两个迥然不同的维度。POJO 关注类的定义是否纯粹,领域模型关注对领域逻辑的表达与封装。即使是一个只有 getter/setter 方法的贫血模型对象,只要它依赖了任何外部框架,例如标记了 javax.persistence.Entity 标注,它也不属于一个 POJO。事实上,Dubbo 服务化最佳实践给出的建议——“服务参数及返回值建议使用 POJO 对象,即通过 setter、getter 方法表示属性的对象”,对 POJO 的描述是不正确的,因为 Dubbo 服务的输入参数与返回值需要支持序列化,不符合 POJO 的定义。</p>
|
||
|
||
<p>由此可以看出,定义种类繁多的模式会让人“乱花渐欲迷人眼”,随着信息的多次传递,就会迷失它们本来的面目。我们需要做减法,在领域驱动战术设计中,只要遵循领域驱动设计的原则定义了实体、值对象、领域服务和应用服务,就不用考虑这些模式,只需把握一条:避免设计出贫血领域模型!</p>
|
||
|
||
<h4>诸多 XO</h4>
|
||
|
||
<p>在分层架构的约束下,在职责分离的指引下,一个软件系统需要定义各种各样的对象,在分层架构中承担了不同的职责,又彼此协作,共同响应系统外部的各种请求,执行业务逻辑,并让整个软件系统能够真正地跑起来。然而,若没有真正理解这些对象在架构中扮演的角色和承担的职责,就会导致误用和滥用,效果反而适得其反。因此,有必要在领域驱动设计的方法体系下,将各式各样的对象进行一次梳理,形成一套统一语言。由于这些对象皆以 O 结尾,故而戏称为 XO 对象。</p>
|
||
|
||
<p>这些 XO 对象包括:</p>
|
||
|
||
<ul>
|
||
|
||
<li>DTO(Data Transfer Object,数据传输对象):DTO 用于进程间传递数据,远程服务接口的输入参数与返回值都可以认为是一个 DTO。我个人又根据调用者的不同,将其分为视图模型对象与消息契约对象。DTO 必须支持序列化,同时它通常应该设计为一个 Java Bean,即定义为公开的类,具有默认构造函数和 getter/setter 方法。这样就有利于一些框架通过反射来创建与组装 DTO 对象。DTO 还应该是一个贫血对象,因为它的目的是为了传输数据,没有必要定义封装逻辑的方法。</li>
|
||
|
||
<li>VO(View Object,视图对象):视图对象其实是 DTO 的一种,即我提到的视图模型对象。它遵循 MVC 模式,为前端视图提供数据,即 MVC 中的模型对象。视图对象可能仅传输视图需要呈现的数据,也可能为了满足前端UI的可配置,由后端传递与视图元素相关的属性值,如视图元素的位置、大小乃至颜色等样式信息。在微服务架构下,往往由 BFF(Backend For Frontend)层的控制器操作这样的 VO。注意,有人将领域驱动设计中的值对象(Value Object)也简称为 VO,注意不要混淆这两个概念。</li>
|
||
|
||
<li>BO(Business Object,业务对象):这是一个非常宽泛的定义,在软件系统中,它的定义来自于分层架构的定义,即数据访问层、业务逻辑层与 UI 呈现层,BO 属于定义在业务逻辑层中封装了业务逻辑的对象。在领域驱动设计中,可以认为就是领域层的领域对象。为避免混淆,我建议不要在领域驱动设计中使用该概念。</li>
|
||
|
||
<li>DO(Domain Object,领域对象):领域驱动设计将业务逻辑层分解为应用层和领域层,业务对象在领域层中就变成了领域对象。在领域驱动设计中,更准确的说法是领域模型对象。通常,领域模型对象包括实体、值对象、领域服务与领域事件。有时候,领域模型对象单指组成聚合的实体与值对象。宽泛地讲,只要表达了现实世界的领域概念,或者封装了领域行为逻辑,都可以认为是领域模型对象。</li>
|
||
|
||
<li>PO(Persistence Object,持久化对象):对象字段持有的数据需要被持久化到数据表中,但不要由此认为 PO 就只能定义字段以及对应的 getter/setter 方法,这回让 PO 变成一个贫血对象。前面讨论的富领域模型对象也可以成为 PO,二者并不矛盾。只要领域模型对象持有数据,就可以持久化,它拥有的领域行为方法并不影响持久化的实现。由于需要配置持久化框架对象与关系表之间的映射,往往需要以某种形式在 PO 中展现这种映射关系,由于这种映射关系是 ORM 框架定义的,因此一个 PO 往往不是一个 POJO。</li>
|
||
|
||
<li>DAO(Data Access Object,数据访问对象):DAO 对 PO 进行持久化,实现对数据的访问。由于领域驱动设计引入了聚合边界,并力求领域模型与数据模型之间的分离,且引入了资源库(Repository)来实现对聚合的生命周期管理,因此在领域驱动设计中,不再使用 DAO 这个概念。</li>
|
||
|
||
</ul>
|
||
|
||
<p>通过对以上概念的历史追寻与本质分析,我们基本上理清了这些概念的含义与用途。在归纳到领域驱动设计这个方法体系中,我们可以得出如下统一语言:</p>
|
||
|
||
<ul>
|
||
|
||
<li>领域模型对象包含实体、值对象、领域服务与领域事件,有时候也可以单指组成聚合的实体与值对象。</li>
|
||
|
||
<li>领域模型必须是富领域模型。</li>
|
||
|
||
<li>远程服务与应用服务接口的输入参数和返回值定义为 DTO,根据客户端的不同,可以分为视图模型对象与消息契约对象。</li>
|
||
|
||
<li>领域模型对象中的实体与值对象同时也可以作为 PO。</li>
|
||
|
||
<li>只有资源库对象,没有 DAO 对象。</li>
|
||
|
||
</ul>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/096 分布式柔性事务.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
<div style="float: right">
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/098 模型对象.md.html">下一页</a>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
|
||
</div>
|
||
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997ee1fe5a3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
|
||
</body>
|
||
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
|
||
<script>
|
||
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
|
||
dataLayer.push(arguments);
|
||
|
||
}
|
||
gtag('js', new Date());
|
||
|
||
gtag('config', 'G-NPSEEVD756');
|
||
|
||
var path = window.location.pathname
|
||
|
||
var cookie = getCookie("lastPath");
|
||
|
||
console.log(path)
|
||
|
||
if (path.replace("/", "") === "") {
|
||
|
||
if (cookie.replace("/", "") !== "") {
|
||
|
||
console.log(cookie)
|
||
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
setCookie("lastPath", path)
|
||
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
|
||
var d = new Date();
|
||
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
|
||
var expires = "expires=" + d.toGMTString();
|
||
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
|
||
}
|
||
function getCookie(cname) {
|
||
|
||
var name = cname + "=";
|
||
|
||
var ca = document.cookie.split(';');
|
||
|
||
for (var i = 0; i < ca.length; i++) {
|
||
|
||
var c = ca[i].trim();
|
||
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
|
||
}
|
||
|
||
return "";
|
||
|
||
}
|
||
</script>
|
||
</html>
|
||
|