﻿/*
	© 2009-2014 FrankHB.

	This file is part of the YSLib project, and may only be used,
	modified, and distributed under the terms of the YSLib project
	license, LICENSE.TXT.  By continuing to use, modify, or distribute
	this file you indicate that you have read the license and
	understand and accept it fully.
*/

/*!	\file YFramework.txt
\ingroup Documentation
\brief YFramework 设计和实现说明。
\version r742
\author FrankHB <frankhb1989@gmail.com>
\since 早于 build 132
\par 创建时间:
	2009-12-02 05:14:30 +0800
\par 修改时间:
	2014-05-18 21:23 +0800
\par 文本编码:
	UTF-8
\par 模块名称:
	Documentation::YFramework
*/


/*

@0 体例和适用范围：
引用标记参见 [Documentation::CommonRules @@0.1] 。
项目范围参见 [Documentation::ProjectRules @@1.1] 。
本文档适用于 YFramework 。
部分编码细节和其它规范和 YBase 共享，参见 [Documentation::Designation] 。

@1 设计：
基本内容参见 [Documentation::Designation @@1] 。

@1.1 设计的基本原理和表达形式：
 YSLib 项目的框架容器。

@1.2 理论背景、工具和依据：
基本内容参见 [Documentation::CommonRules @@2.1] 。

@1.3 构建原则：
基本内容参见 [Documentation::CommonRules @@2.2] 。
其它见 [Documentation::Designation @@1.3] 。

@1.4 通用语义：
基本内容参见 [Documentation::CommonRules @@2.3] 。

@1.4.1 运行时程序模型：
除以下部分外由具体项目定义。

@1.4.1.1 运行时程序结构和部署模型：
 YSLib 中讨论可部署的程序的基本单位是 Shell(@1.4.4.2) 。
 YSLib 基于单一进程和单一线程的运行时程序结构，类似于单内核操作系统；但内部实现是微内核至无内核的，除了主循环，任意一个 Shell 都可以独立部署。
在适当的平台上通过扩充能实现多个独立的二进制实体并行运行的多进程程序。

@1.4.1.2 并发模型：
基于可移植性和易用性的考虑， YSLib 并发语义的表达不包括作为机器模型的语言和库特性提供的线程模型的直接使用，而以角色模型进行并发抽象的问题模型。
对于 Shell 内部的操作，不存在共享状态的竞争条件，无需进行加锁操作，避免死锁、活锁和优先级反转等问题。即 Shell 本身使用单线程。
由于语言的限制，无法直接表达任意的并行语义，从而无法有效实现真并发行为。真并发行为可能由平台相关的扩展 API 实现。
 YSLib 仅提供有限的调度设施保证，通过加入线程模型相关的设计和实现，进程内的控制流实体保持是可扩充的和自洽的。

@1.4.1.3 消息机制：
基本内容参见 [Documentation::CommonRules @@2.5.3] 。
 YSLib 支持消息队列。
 YSLib 的消息被用于在 Shell 之间传递状态，称为 Shell 消息。
默认 Shell 消息列表参见 [Documentation::YSLib @@2] 。
消息、消息队列、消息分派和消息循环的实现参见 [Documentation::YSLib @@2.5.10] 。

@1.4.1.4 可重入性和线程安全性：
除本条外， YSLib 及其部分依赖项的可重入性和线程安全性参见 @2.8 、 [Documentation::Designation @@5.2] 、 [Documentation::YSLib @@1.3] 和 [Documentation::CHRLib] 。

@1.4.1.4.1 一般准则：
中断服务例程应保证可重入性。
可重入和线程安全无必然联系。
对于单线程实现环境，不对线程安全性另行说明。

@1.4.1.4.2 例程和包含的可调用对象(callable object) 的调用：
仅包含可调用对象的调用时，此例程的可重入性和线程安全性等价于包含的所有调用：
包含可调用对象的调用时，此例程可重入，仅当包含的所有调用可重入。
包含可调用对象的调用时，此例程线程安全，仅当包含的所有调用线程安全。

@1.4.1.5 全局初始化：
除另有说明，仅保证可重入的调用可用于全局初始化。

@1.4.2 资源分类：
基本内容参见 [Documentation::CommonRules @@2.3.2.2] 。
 YSLib 对于资源的直接使用仅限软件资源（硬件资源通过语言抽象和 YCLib 等平台兼容层包装后间接使用）。

@1.4.3 资源管理：
基本内容参见 [Documentation::CommonRules @@2.3.2.3] 。
 RAII 在异常安全和可维护性等方面具有其它方法不可替代的优势，因此是 YSLib 中最主要使用的资源管理惯用法。

@1.4.4 Shell ：
在 YFramework/YSLib 中， Shell 有多种含义。
如无特殊说明一般指 @1.5.1.1 。

@1.4.4.1 组织分类：
参见 @1.2.1.1 。

@1.4.4.2 程序实体：
 Shell 实体（简称 Shell ）是一种包含状态的有限片段控制流抽象，是动态映像(@1.5.1.1) 或静态映像(@1.5.1.2) 之一。

@1.4.5 会话(session) ：
会话是用于在一段连续的时间间隔内访问连接(@2.6.4) 且所有权不属于此连接的实体，其中的连接称为会话连接。
会话通常用于在一段连续的时间间隔内跟踪连接的客户端([Documentation::CommonRules @@2.5.4.1]) 的操作。会话连接一般包含于客户端中，由客户端控制。

@1.4.5.1 网络通信会话：
网络通信会话是半持久化的数据交换的抽象。
会话的连接用于网络通信。
它可能被基于特定的协议上实现。

@1.4.5.2 用户登录会话：
保存特定用户使用计算机的状态的抽象。

@1.4.5.3 用户界面会话：
用户界面会话是对用户在特定界面操作状态集合的抽象。
会话的连接用于在界面逻辑状态和输入/输出缓冲区之间通信。

@1.4.5.4 会话的实例：
桌面会话是典型的用户界面会话。
浏览器会话包含客户端的网络通信会话和用户界面会话。

@1.4.5.5 会话管理：
会话管理是人机交互中对抽象为若干会话的用户活动的追踪。它能重置或还原特定用户行为和操作下的状态。

@1.5 YSLib 模型抽象：
本节讨论具体的基本特性相关的模型抽象。

@1.5.1 框架抽象：
本节描述框架组成成分的抽象。

@1.5.1.1 Shell 动态映像：
 Shell 作为被执行的程序称为 Shell 的动态映像。一个 Shell 动态映像的实例称为 Shell 对象，是运行时控制流映像，用于表示一段时间间隔（称为生存期）内计算机系统当前处理的任务。
 Shell 对象是程序的基本调度单位之一。不同于进程/线程等具体的任务实体，它仅是表示可执行的程序的高层抽象，并不限定环境(@1.2.1.2) 对共享资源的分配方式。
实现形式上 Shell 对象，可以是进程/线程等和体系结构关联更彻底的方式，但这并非其内涵。

@1.5.1.2 Shell 静态映像：
储存 Shell 动态映像中执行的代码的非运行时映像实体称为 Shell 静态映像。
实现形式上， Shell 静态映像可以是可执行文件中的代码片段或内存中的流，但这并非其内涵。
它可以作为构建程序时复用的单位。因此可以用于组织分类(@1.4.4.1) 。
注意 YSLib 中的实现 Shell 实体的基类 Shell 属于组织意义上的 Core 而非 Shell ，位于 "/Core" 。

@1.5.1.3 Shell 对象的执行状态：
一个 Shell 对象被调度的时间间隔不一定等于它的生存期，可能是其中的一部分。
因此， Shell 对象不仅表示活动的（当前正在运行的）运行时状态，还可以储存非活动的运行时状态。
在某个确定的时刻，一个 Shell 对象具有以下执行状态之一：不处于可被有效调度时的非活动态和处于可被有效调度时的活动态。
新建的 Shell 对象默认具有非活动态。
对于单线程的实现，同一时刻有且仅有一个 Shell 对象处于活动态。

@1.5.1.4 Shell 状态切换：
 Shell 对象由非活动态至活动态的转换过程称为激活(activation) ；活动态至非活动态的转换过程称为停用(deactivation) 。激活和停用合称为 Shell 状态的切换(switching) ，简称 Shell 切换。
 Shell 切换要求 Shell 具有完整的存储和正常的生存期。

@1.5.1.5 Shell 通信：
 Shell 的必要的基本通信机制是消息机制(@1.4.1.3) 。
使用消息机制， Shell 切换是用户程序可知的(@2.6.11) 。
用户可以自定义具体 Shell 的特定机制。
 Shell 可能是连接对象([Documentation::CommonRules @@2.5.4]) 。

@1.5.1.6 Shell 类和 Shell 对象生存期导致的限制：
 Shell 被设计为一个 C++ 多态类。
默认不在 Shell 内部保存激活或停用状态，而由外部控制。
在 C++ 中应注意以下几点：
一个类类型对象的生存期起始于构造调用结束后，构造函数中的操作是受限的（例如无法正确地调用虚函数）；
构造函数允许抛出异常。
因此：
 Shell 切换(@1.5.1.2) 时无法新建 Shell 对象且是无异常抛出保证([Documentation::CommonRules @@5.20.5.4]) 的；
激活和停用有必要明确地区分于构造和析构。
特定的 Shell 可作为 ISO C++11 30.2.5.1/1 定义的执行代理(execution agent) 。

@1.5.1.7 Shell 的应用场景：
 Shell 表示一类任务，可作为程序中的可复用组件存在。
 Shell 可在一段时间间隔内作为保存程序执行中公共状态的实体，类似于 Microsoft Windows 的会话(session) 或窗口站(window station) 。
 Shell 可以是会话(@1.4.5) 。

@1.5.2 显示模型：
本节描述显示特性相关的抽象。

@1.5.2.1 二维输出设备参照坐标系：
表示输出平面，使用二维欧几里得空间的视图坐标系。
逻辑上，坐标值是纯量，是实数或其子集的元素。对于实现而言也可能包括非数学量（如浮点数的无穷值）。
若无额外说明，同一个坐标系内的两个坐标值的取值范围相等。
若无额外说明，以输出设备相对于用户的最左上角为原点 (0, 0) ，横坐标正方向向右，纵坐标正方向向下。

@1.5.2.2 屏幕坐标系：
屏幕坐标系是以屏幕为输出设备的二维输出设备参照坐标系的基准实例。
若无额外说明，屏幕坐标系的单位为像素。

@1.5.2.3 屏幕平移坐标系：
相对于输出所在屏幕的屏幕坐标系直接平移变换得到的坐标系。
注意原点相对于屏幕坐标系的坐标分量可以有负值。

@1.5.2.4 标准矩形(canonical rectangle) ：
边和二维输出设备坐标系共线的矩形。
一般地，可以使用四个纯量表示，如表示左上角的点坐标和长、宽，或表示对角线端点的两个点坐标。

@1.6 组件和界面设计概述：

@1.6.1 UI（User Interface ，用户界面）设计：
为了适应不确定数量的输出设备，特定的 Shell(@1.2.1.1) 可以用于实现程序中处理 UI（User Interface ，用户界面）行为，称为 UI Shell 。
输出特性依赖于屏幕平移坐标系(@1.5.2.2) 。
用于实现 UI 的 Shell 一般也包括实现相关消息处理。
和 Shell 相对的 Core 不直接参与实现 UI 。

@1.6.2 GUI（Graphical UI ，图形用户界面）设计概述：
界面实现使用称为 Shell-Widget 的模式，是精简的主动模型-视图-控制器模式的变体，参照窗体-控件模式。但架构模式无本质变化。
界面实现解决的三个问题：安排状态(state) 、逻辑(logic) 和同步(synchronization) ，都可以在运行期配置。
为了方便复用，这些属性有如下分类：
根据是否依赖于具体的 Widget 实例分为实例的和公共的；
根据是否能被所有 Widget 类共用分为公用的和专用的。
这些属性也适用于用于实现的构件。
强化了编译期可配置性。
基于性能考虑，仅在少数必要处实现观察者模式。
默认公共 UI 状态通过 YGUI 单元的 GUIState 类实现。

@1.6.2.1 模型(model) ：
模型表示数据模型(data model) ，保证和领域逻辑(domain logic)/业务逻辑(business logic) 具有合理的关联。
模型和其它部分是适当分离的，模型不被依赖，或仅被专用视图或控制器依赖。

@1.6.2.2 视图(view) ：
视图用于向用户呈现数据，保持用户界面状态。
视图在 GUI 响应（如具体实现 [Documentation::YSLib @@5.3] 和 [Documentation::YSLib @@5.5] ）中不会修改模型，但可以向控制器提交状态。
部件类实现了基本的视图。通过派生或修饰这些类可以得到扩展的视图。
通常约定视图在显示设备上呈现矩形区域。

@1.6.2.2.1 视图组织：
构件对象的视图之间的联系组成的抽象整体（是一个图）称为视图组织。
为了便于实现中以遍历为基础的算法能可靠结束，视图组织一般应是受限的、带层次的有向树（约定相邻层次的节点由父节点指向子节点），称为视图树。
一旦存在环路，对视图的某些操作可能导致未定义行为。
视图树的节点之间表示的显示范围存在约束。子节点可表示的区域是父节点的子集。

@1.6.2.2.2 包围盒(bounding box) ：
视图在屏幕上的可以用一个标准矩形(@1.5.2.4) 表示的逻辑区域称为包围盒。
包围盒在逻辑上具有连续边界，但在坐标(@1.5.2.1) 表示时仅在较小端满足封闭性。
包围盒定义了视图在屏幕上的位置，是作为视图绘制的参照依据之一。

@1.6.2.2.3 视图坐标系：
以视图包围盒(@1.6.2.2.2) 的左上角作为原点的屏幕平移坐标系(@1.5.2.3) 称为视图坐标系。

@1.6.2.3 控制器(controller) ：
控制器完成界面状态和模型状态的同步，保持根据用户在视图中的行为更新模型的逻辑。
若有必要，控制器可以保持状态。模型和视图不能直接修改控制器的状态，但可以提交状态等待控制器自行更新。

@1.6.2.3.1 公用控制器：
公用控制器用于实现公用输入逻辑，并储存了相关状态，是 UI Shell(@1.6.1) 的重要组成部分。
用户输入由公用控制器而不是视图进行直接处理。公用控制器转发处理的结果到专用控制器(@1.6.2.3.2) 中以便被进一步处理。
公用控制器是公共的，不依赖于实例。
专用控制器依赖于公用控制器的行为，但不依赖其实现。

@1.6.2.3.2 专用控制器：
专用控制器用于实现特定 Widget 的较高层 UI 行为。

@1.6.2.3.2.1 专用公共控制器：
专用公共控制器用于实现 Widget 类特定的较高层 UI 行为。

@1.6.2.3.2.2 专用实例控制器：
专用实例控制器用于实现 Widget 实例特定的较高层 UI 行为。一般位于部件(@1.6.2.5) 中。

@1.6.2.4 Shell-Widget 模式：

@1.6.2.4.1 Shell 状态和控制器：
 Shell 负责保存所有 GUI 之间的公用状态（如拖曳位置），并集成保存公用逻辑的公用控制器。它们都是公共的，不依赖于 Widget 实例。

@1.6.2.4.2 Widget 状态、控制器和视图：
 Widget 负责保存单一的 GUI 非公用状态、视图的直接实现，并集成保存专用逻辑的专用控制器用于在一定范围内动态配置 UI 的行为。
专用公共逻辑可能是多个 Widget 中相同的。
专用公共状态可能是多个 Widget 之间共享的([Documentation::CommonRules @@2.3.4.6]) 。
视图总是实例的，它自身有且仅有两种状态：已经被同步或未被同步。

@1.6.2.4.3 数据流和响应流程：
输入数据流首先被 Shell 的公用控制器响应；若有必要，更新公用状态。然后，转发至 Widget 。
 Widget 的专用控制器对输入进行响应；若有必要，更新非公用状态。（通常是公共的）专用控制器可能更新公用状态。根据此状态同步视图，并决定对输入数据的修饰以及是否转发至下一层次的 Widget 。
因为 Widget 之间的视图组织是有限的，所以当不存在环路时，以上流程应在有限时间内完成。
 Shell 的其它部分实现使视图更新至显示设备的输出调用。

@1.6.2.5 构件实体(part entities) ：
实现中 Shell-Widget 模式中作为 Widget 的角色。相较于典型的窗体-控件模式， GUI 控件(controls) 退化为部件(widgets) ，部件退化为组件(components) ，进而分离可视属性，抽象出独立于这些构件的部件特征，细分功能以实现高度可配置性。
一般的组件、部件和控件等实体在此统称为构件(parts) 。
 YSLib 本身不提供大量成熟的控件，而是着重提供可供组装为控件的基本 GUI 类（部件模块类）、部件类、在部件基础上衍生的构件以及部件简单组合的组件。这些用户界面元素(UI elements) 不一定具有消息处理或事件响应的功能，因此可以不是控件；参见 @1.6.2.6 。
控件主要由用户通过组装以上的构件定制。

@1.6.2.5.1 组合构件(compound parts) ：
可以自定义任意的模型类来组装部件、控件或其它用户界面元素。
但是，并非每一个成分都是必须的。某些成分可能在具体的类的外部实现。
若组合的结果能处理消息或响应事件，同时能够呈现界面数据，那么就是控件。

@1.6.2.5.2 构件容器(containers) ：
构件容器是能以引用等方式在逻辑上包含构件的构件实体。被包含的构件称为包含构件的子构件。
组件容器是组件。部件容器是部件。控件容器是控件。

@1.6.2.6 构件组织(parts construct) ：
和视图组织(@1.6.2.2.1) 类似，部件之间存在的联系组成的抽象整体（是一个图）称为构件组织。
类似地，构件组织一般应是受限的、带层次的有向树（约定相邻层次的节点由父节点指向子节点），称为构件树。
部件的构件组织的节点默认和视图组织的节点一一对应，用于视图组织的实现。
其它构件组织可以由用户按需抽象。
其它非部件的构件组织同样可具有树形结构，但（默认）不具有类似的实现。

@1.6.2.7 场景(scenes) ：
场景是任意两个节点(@1.6.2.6) 具有至少一个直接依赖的构件组织的非空子集。
由定义，场景是非空连通图。

@1.6.2.8 焦点(focuses) 概述：
焦点在部件容器（称为焦点上下文）中对 GUI 对象的标识。
控制器根据焦点选择当前操作（通常是输入）作用的对象。
由于在一个焦点上下文中可能包含多个子上下文（参见 @1.6.2.6 ），因此可能有多个焦点。
对于视图树而言，通过迭代访问焦点对象可以得到唯一的路径，称为焦点活动路径；其中的焦点称为活动路径焦点。末端的活动路径焦点称为活动焦点，在确定状态下若存在，则是唯一的。

@1.6.3 目标风格与最佳实践：
本节概述基于 [Documentation::Designation @@1.1] 和 @1.3 的约束下，组件和 UI 库接口设计的总体风格和对用户代码的影响。

@1.6.3.1 引用参照：
 Ultimate++ ： http://www.ultimatepp.org/www$uppweb$overview$en-us.html 。

@1.6.3.2 库依赖策略：
除非必要，尽量使用标准库。例外情况下应该提供充足理由，并对用户自行替换底层接口和实现提供一定的便利性。

@1.6.3.3 资源管理：
基于对象所有权，方法参见 [Documentation::YSLib @@2.2.2] 。
基于和 Ultimate++ 相同的理由，接口不使用智能指针，且用户代码而不是被依赖的组件决定部件对象的所有权从属。
但总体风格上没有限定作用域和所有权的严格对应关系，也因此能够自然地使用部件指针的标准库容器。这点同时简化基于迭代器模式的实现。
此外， YSLib 不排斥在部件实现([Documentation::YSLib @3.3]) 中提供（有限的）复制和转移支持以保证值语义。

@1.6.3.4 泛型值类型：
适当使用 YBase([Documentation::YBase]) 提供的基于类型擦除的泛型值语义对象 ystdex::any([Documentation::YBase @@2.4.6.4]) 等类型实现。允许空值。

@2 框架概览：
本章描述 YSLib 项目中的 YFramework 框架库。外部依赖项和 YSLib 项目整体配置参见 [Documentation::Designation @@5] 。
模块化设计原则参见 [Documentation::CommonRules @@3.7.1] 。
一个模块目录([Documentation::ProjectRules @@3.2]) 中的模块组成一个系统。
名称使用前提约束：参见 [Documentation::CommonRules @@7.2] 。
关于源代码组织，参见 [Documentation::ProjectRules @@3.3] 。
关于文件名和目录名，参见 [Documentation::ProjectRules @@3.4] 。
使用嵌套命名空间，避免过长的标识符命名。
关于一些文件的文件名的额外约定参见 @2.2 。

@2.1 框架组成和依赖项规则：
基本目录和文件组织规则以及原始目录的概念参见 [Documentation::ProjectRules @@3.3] 。
 YFramework 可分为几个目录表示具有特定功能集合的库的子集。在讨论具体目录下的库时，路径表示以此库的根目录。
除非另有说明，仅保证非成员函数（排除声明紧随于某个类之后，首个参数为该类类型引用的人本接口）和静态成员函数的可重入性和线程安全性。
关于 YBase 的文件依赖性参见 [Documentation::YBase @@2.2] 。

@2.1.1 组成概述：
 YFramework 最核心的部分是 YSLib 库，除了本文档描述外，参见 [Documentation::YSLib] 。
 YFramework 集成的第三方库([Documentation::Designation @@5]) ，位于 "/3rdparty/" 目录下。其它部分的原始目录为 "/YFramework" 。例如 YSLib 位于 "/YFramework/YSLib/" 目录下。
当前第三方库和 YFramework 其它部分编译为单独的目标（静态库或动态库）。
关于 YFramework 依赖的外部项目（包括平台支持和基础库 YBase([Documentation::YBase]) ）的关联和配置参见 [Documentation::Designation @@5] 。

@2.1.2 附加库：
除了 YSLib 和第三方库 YFramework 也集成了一些附加的库作为非第三方次级子项目。这些库不直接在 YSLib 命名空间中添加声明（参见 @2.2.4 ）。
其中一部分除了平台扩展([ProjectRules @@3.3]) 外不依赖于 YSLib ，称为基础附加库，包括 CHRLib(@2.7) 和 YCLib([Documentation::Designation @@5.2.2]) 。
另一部分依赖于 YSLib ，包括 NPL(@2.9) 和 Helper(@2.8) 。其它具体说明参见 [Documentation::Designation @@5] 。
综上所述， YFramework 有以下非第三方次级子项目： CHRLib 、 YCLib 、 YSLib 、 NPL 和 Helper 。

@2.1.2.1 组织和依赖准则：
每个附加库都有相对独立的功能，且与框架程序实现相关但相对独立，因此不作为 YSLib 库(@2.1.1) 的组成部分。
基础附加库总是被 YSLib 库的 Adaptor 或 Core 直接或间接依赖。
 YCLib 和 Helper 不保证接口或实现平台中立。其中 YCLib 不依赖于 YSLib ，被作为 YSLib 平台中立接口和实现的基础适配层； Helper 依赖于 YSLib 。
其它附加库没有平台扩展且保证平台中立，只依赖于 YSLib 库的 Core 和 Service ，但当前不确定适合作为框架实现。（以后可能被合并至 YSLib 库中或独立于 YFramework 外）。

@2.1.3 平台相关性：
除平台扩展外的 YFramework 公开接口是平台中立的（但 YCLib 和 Helper 接口可能会限定平台集合，如宿主实现环境）；
 YSLib 没有平台扩展。对 YSLib 的平台特定的功能扩展由 Helper 提供。
平台扩展一般直接作为目标平台的接口，但也可以包括仅供实际目标平台模拟的接口。使用 YCL/Platform.h 中定义的平台宏([Documentation Designation @@5.2.2.4.1]) 确定程序实际运行的目标平台。

@2.1.4 YSLib Adaptor 和本体：
 YSLib 中，目录 "/YFramework/Adaptor/" 下的部分称为 Adaptor [Documentation::YSLib @@2] ，其它部分总称为本体。
除了标准库和 YBase 的公开接口外，本体的接口和实现以及 Adaptor 的公开接口没有 YSLib 以外的依赖项。
而 Adaptor 非公开接口除此之外还可能有其它外部依赖项（第三方库），但这些依赖项的公开接口是平台中立的。
 Adaptor 被 YSLib 的几乎所有其它部分依赖。 Adaptor 的改变很可能导致整个本体中的很一大部分翻译单元需要重新编译，因此除非是用来实现基本功能、有必要被足够多模块依赖的的外部依赖项，新增的部分应尽量放在外部的 Helper 库(@2.7) 而不是 Adaptor 中。

@2.2 文件依赖性：
以下部分指定 YFramework 中明确或明确禁止依赖的文件，排除构建的中间文件。非公开头文件的适用规则同非头文件。以下头文件指公开头文件。

@2.2.1 基本文件依赖性（适用于 YFramework ）：
 YSLib 和 Helper(@2.8) 文件中，文件名以 y 或 Y 起始且非限定模块名以 Y 起始的文件为必要文件，其它为非必要文件。作为稳定的公开接口，必要文件必须被 YFramework 内的至少一个其它文件依赖。
关于 ISO C++11 直接指定的依赖项，参见 [Documentation::CommonRules @@5.25.2] ；其它基本代码依赖性规则如下（以优先级顺序排列，即后者不满足前者的部分以前者为准）：
禁止依赖于（包括包含）非头文件。
除非另有说明，禁止显式重复包含同一文件或循环依赖；头文件应具有守护宏([Documentation::ProjectRules @@2.2.6]) 。
除非以下显式说明，禁止平台中立文件依赖于平台扩展；例外的被依赖项视为具体实现，不应作为公开接口。
 YFramework/YBaseMacro.h 仅依赖 YBase 的 ydef.h 。
 YSLib/Adaptor 中的 config.h 不依赖 YCLib/Platform.h 以外的其它文件，仅可被 YSLib/Adaptor 中的头文件直接包含。
必要文件不依赖非必要文件。
任意 YFramework 文件可依赖 @2.2 以下部分指定的标准库头文件以及 YBase 头文件。
 YCLib 和 Helper 文件可依赖具体平台相关的外部依赖项。关于 Helper 的文件附加依赖规则参见 @2.8 。

@2.2.2 YCLib 文件依赖性：
 YCLib 的实现可依赖 YCLib 的对应平台扩展。
 YCLib 非平台扩展头文件不依赖 YSLib 文件和 YCLib::NativeAPI 。
 YCLib 平台扩展可依赖 YSLib/Core 的必要头文件。
 YCLib 平台扩展的实现文件可依赖 YSLib/Core 或 YSLib/Service 的公开头文件。
 YCLib 中除 YCLib/Platform.h 外的文件仅可被 YCLib 、 YSLib 和 Helper 依赖。

@2.2.3 YSLib 文件依赖性：
除 @2.1.1 和本节另有约定的外， YSLib 不依赖 CHRLib 、 YCLib 和 YSLib 以外的文件。
除 YSLib/Adaptor/yadaptor.h 外， YSLib/Adaptor 头文件不依赖 YCLib/ycommon.h 以外的 YCLib 文件。
 YSLib/Adaptor 头文件可依赖 YFramework 平台中立文件或 ISO C++ 标准库实现的非标准的公开头文件（如 libstdc++ 的 "ext/" 目录下的头文件）。
本体的必要文件不依赖 YSLib 以外的文件。
本体的非必要非头文件可依赖除 YSLib 和 Helper 外的 YFramework 其它平台中立文件。
对于公开的头文件包含依赖关系，在 #include 指令中使用 YFM_* 宏而不是文件名；之前需要包含对应的 "YModules.h" （若在当前头文件中存在则使用直接相对路径，否则使用相对于 YFramework/include 的路径）。
 Adaptor 的头文件依赖于 YFramework 的 YFM_YBaseMacro 。
实现源文件依赖于同名头文件，应保证包含此头文件，但不重复包含此头文件已经包含的其它头文件。
下层的 <YModules.h> 包含 "../YModules.h" 。除此之外，以下包含关系是确定的：
 <CHRLib/YModules.h> 包含 "../YCLib/YModules.h" ；
 <YSLib/Core/YModules.h> 包含 "../Adaptor/YModules.h" ；
 <YSLib/Service/YModules.h> 包含 "../Core/YModules.h" ；
 <YSLib/UI/YModules.h> 和 <NPL/YModules.h> 包含 "../Service/YModules.h" ；
 <YSLib/Helper/YModules.h> 包含 "../YSLib/UI/YModules.h" 和 "../NPL/YModules.h" 。
关于 YSLib 内部的具体头文件依赖性，参见 [Documentation::YSLib @@1.2] 。

@2.3 名称：

@2.3.1 标识符限制：
公开头文件不使用保留标识符([Documentation::CommonRules @@5.15.1]) ，包括使用实现扩展提供的宏。使用 ydef.h([Documentation::YBase @@2.3]) 包装的宏代替。

@2.3.2 YFramework 引入的命名空间：
 YCLib 在全局命名空间内引入命名空间 platform 、 platform_ex 和 platform_replace ，称为顶级平台命名空间。顶级平台命名空间以下按需引入独立平台([Documentation::ProjectRules @@1.2]) 对应的命名空间，其中抽象平台使用内联命名空间。
 除 YCLib 外， YFramework 引入的主要命名空间唯一且和次级子项目的模块名称一致。
 platform ：平台中立：接口平台无关但实现平台相关的公共接口。 YSLib 本体间接依赖（可配置 using 声明的名称）于此命名空间。
 platform_ex ：平台扩展：接口和实现都平台相关的公共接口。 YSLib 本体不依赖于此命名空间。
 platform_replace ：平台替换：接口和实现都平台相关的特定接口，专用于包括替换平台接口实现。 YSLib 本体不依赖于此命名空间，但可能依赖于该命名空间中成员包装的宏。
 CHRLib ：子库 CHRLib 的命名空间。 YSLib 本体直接依赖（固定使用 using 声明的名称）于此命名空间。
 NPL ：子库 NPL(@2.9) 的命名空间。
 YSLib ： YSLib 库命名空间。

@2.4 实体实现规则：

@2.4.1 对象准则：
局部对象在声明时同时初始化。
函数内变量尽可能置于最小作用域内——除非效率原因，尽可能使用语句块级对象代替函数级局部对象。
避免在嵌套类中定义被嵌套类的定义，除非能够确保此定义的实现无关性。
有依赖关系的全局对象应置于同一编译单元内。
禁止使用函数返回值初始化全局对象。
除非程序明确为单线程的，禁止使用非 POD(plain-old data) 类型的全局对象。若非必要，用内建 (built-in) 类型代替 POD 结构体全局对象。
多线程程序中，禁止使用非 const 全局对象。

@2.4.2 对象引用和所有权管理：
基本概念参见 [Documentation::CommonRules @@2.3.4] 。
注意基于非透明引用计数实现的非侵入式智能指针（如 boost::shared_ptr/std::tr1::shared_ptr 以及 C++11 的 std::shared_ptr ）具有以下固有的缺点：
无法修改引用计数并直接转移所有权，资源实例的生存期依赖于至少一个具体智能指针对象的生存期；
资源实例对智能指针对象的上述依赖性导致智能指针类型入侵用户程序接口；
并非完全的非侵入式实现（例如可能依赖于 enable_shared_from_this 等），可能入侵客户资源实现，导致耦合扩散；
用户程序无法显式指定引用计数操作而造成不必要的性能负担（特别是异步流程中，无法进行基于调用栈的引用计数优化）。
为了克服前三个缺点，可以使用侵入式方案代替，但可能会引起额外的编码复杂度。最后一个缺点所在的场景一般不适合使用引用计数策略（尽管改用侵入式引用计数方案可能减小开销）。
因此 YSLib 仅在必要时使用基于此类智能指针实现的句柄，如跨 Shell 资源传递（包括 Shell 类实例本身）。
注意此时尽管和非句柄意义下的智能指针类型相同，但意义不同，除特殊情况外（如和内建指针直接比较；需在对应实现处注释）应避免通过 get 成员或 ystdex::raw 等直接使用对应的内建指针值。
对于需要保持所有权但又要避免重复引用计数的开销的情况，使用 std::unique_ptr 。
其它情况下，使用不含所有权的内建指针，以保持用户程序对资源管理的选择自由和灵活性。若没有在注释或文档注明所有权关系，均应视为由用户程序对象具有指针参数指向对象的所有权。

@2.4.2.1 所有权标签：
以下独占所有权关系中，被托管对象类不是直接的成员或明确具有所有权语义的指针指向的对象。使用 OwnershipTag 模板标识这些类型。
所有者（基类）中 private 继承了 OwnershipTag<_type> 。被托管对象的实际类型可能是 _type 的派生类（需要是虚析构的多态类）。除了 Helper 外的实例包括：
 Drawing::FontCache 具有 Drawing::Typeface 和 Drawing::FontFamily 的所有权；
 UI::MenuHost 具有 UI::Menu 的所有权；
 Text::TextMap 及其派生类 Text::TextFileBuffer 具有 Text::TextBlock 的所有权。
可以使用 HasOwnership<_tOwner, _type> 判断 _tOwner 是否具有 _type 成员的所有权。

@2.5 语言特性和扩展支持：
除了 YBaseMacro(@2.5.1) 外，主要位于 YBase[Documentation::YBase] 、 YFramework::YCLib 和 YFrameowrk::YSLib::Core[Documentation::YSLib @@3] 中。
 YFramework 直接通用基础设施 YBaseMacro ：定义了各种基础平台无关的宏，用于简化代码。具体使用参见 @6.2.1 。

@2.5.1 接口

@2.5.2 断言

@2.5.3 成员函数简写（代码生成器）

@2.6 类型构建：

@2.6.1 基本约束：
命名必须和标识符命名规约(@4) 兼容。

@2.6.2 类型特性：
除了 I 和 A 前缀的类，都不含有纯虚函数。
命名中按以下列出的顺序确定分类。

@2.6.3 I 前缀类名的类：
接口类型([Documentation::CommonRules @@2.4.1]) 或纯虚类。

@2.6.4 A 前缀类名的类：
抽象类。
成员函数中至少存在一个纯虚函数；不能被实例化。

@2.6.5 S 前缀类名的类：
静态类。
除了类型定义外，应仅包含静态成员。但编译时不作检查。
可参与多重继承，例如作为特征类(traits class) 。

@2.6.6 M 前缀类名的类：
模块类。
具有 public 或 protected 的无参数（或所有参数都有默认参数）的构造函数。不一定能够被复制构造（可能显式地被禁止）。
用于提供实现而非规范接口，可定义人本接口成员。
作为混入(mixin) 类的实现：强调可以参与多重继承组合为其它模块类和一般构件类，也包括被参数化（作为模板类型参数）以构建这些类。
当作为非多态类时析构函数应为 protected （除非它的所有派生类都没有在它的基础上扩展域，或都满足析构函数为 protected ），且不可作为类的成员或被实例化。
其它情况下可实例化，但通常仅用于作为类实例的子对象（混入实例）。此时应尽可能减少虚表体积，并降低额外的运行时效率开销（例如，不使用引用类型的成员）。

@2.6.7 H 前缀类名的类型：
从属于相近但不同的两类：
句柄(handles) ：具有间接访问语义的类型（例如指针、引用或迭代器）。
处理器(handlers) ：具有回调功能的类型（例如事件处理器或 std::function 的实例）。

@2.6.8 无前缀类名的类型：
一般类型。
其它类型。无其它限制和特性保证。

@2.6.9 异常类总览：
专用于被 C++ 异常机制捕获的类称为异常类。
异常类不一定在特定的命名空间中定义，但 YSLib 集中使用某些异常，参见 [Documentation::YSLib @@3.5] 。

@2.7 字符表示结构支持库 CHRLib ：
位于 "/CHRLib" 。非外部依赖项。
支持字符相关构造（编码和字符集等）的抽象。
支持特定编码字符串的转换。
参见 [Documentation::CHRLib] 。

@2.8 助手(Helper) 库：
位于 "/Helper" 。非外部依赖项。
除 @2.2.1 的限制， Helper 可以依赖其它所有非 Helper 的 YFramework 文件，不被非 Helper 的 YFramework 文件依赖。
可能平台相关的外部库，可以提供宿主实现、加入插件等，一般由库用户自行配置。
除非另有说明，仅保证必要文件(@2.1.1) 提供接口中的可重入性和线程安全性同本体(@2.1) 。其它文件的例程仅当明确说明时可具有可重入性和线程安全性。
 YGlobal 是不可缺少的，它封装了必要的全局对象。
 main 函数由 Helper 的其它源文件封装，或由用户提供。
 Helper 定义的类型若适用于不同平台，不保证二进制兼容性，除非另有说明。

@2.8.1 YGlobal 单元：
平台相关的全局对象和函数定义。
除了以下接口，其它都是不确定的：
const SDst MainScreenWidth, MainScreenHeight;

unspecified-class-type&
FetchGlobalInstance() ynothrow;

bool
InitConsole(Devices::Screen&, Drawing::PixelType, Drawing::PixelType);

这里 FetchGlobalInstance 返回类型为平台相关的应用程序类的引用。
 YSLib 不依赖这些接口以外的特性。

@2.8.2 Application 派生类：
适应于具体平台的应用程序实例抽象。
包含默认消息循环等。

@2.8.3 初始化 Initialization ：
关于配置文件格式和内容参见 [Documentation::YSLib @@8] 。
初始化的重要策略之一是在程序启动时减少不必要的初始化，以达到以下的优势：
减少可能的外部依赖（如不需要使用文字的程序就不初始化字体缓存，也不需要依赖外部字体文件和字体配置等）；
减少可能的资源占用；
保留静态链接时优化去除没有调用的代码以减少二进制可执行文件体积的可能性。
因此，对于一些全局资源使用静态函数内 static 对象实现单态(monostate) 模式，保存全局状态。当前取得单态状态的接口包括：
 FetchRoot ：取值类型根节点；
 FetchDefaultFontCache ：取默认字体缓存。
其它如 ImageCodec 因为未包含复杂副作用，当前不提供接口。用户可以自行初始化这些对象。

@2.9 NPL 库：
实现基于 S 表达式的名称协议语言，当前仅用于用户配置设置。

@3 API 设计和风格概述：
基本内容参见 [Documentation::Designation @@3] 。

@3.1 异常使用规则：
尽量保持异常中立。
除了接口和实现非平台中立的部分（参见 @2.1.3 ），或保证重新抛出，避免 catch(...) 以避免错误地捕获非 C++ 异常，参见 [Documentation::CommonRules @@5.10.5.6] 。
所有平台中立的内部的异常类型继承 std::exception ，使用 catch(std::exception&) 满足无异常抛出保证([Documentation::CommonRules @@5.10.5.1.3]) 。

@3.2 字符编码：
 YFramework 使用 UTF-8 作为外部文本编码。
除非显式指定表示编码的参数或另有说明，以 char 作为字符类型的 C 风格字符串使用外部文本编码。
关于 YSLib 使用的内部文本编码参见 [Documentation::YSLib @@3.6] 。

@4 编码风格导引：
基本内容参见 [Documentation::Designation @@6] 。

@4.1 YFramework 宏使用：
 YLSib 和 YFramework 中依赖 YSLib 的项目尽量使用 YFramework::YBaseMacro(@2.4) 定义的宏，而不是其展开形式。
使用宏 YSL_BEGIN 和 YSL_END 标识 YSLib 命名空间；
使用宏 YSL_BEGIN_NAMESPACE 和 YSL_END 标识 YSLib 命名空间下的子命名空间；
使用宏声明接口类型([Documentation::CommonRules @@2.4.1]) 。

@4.1.1 函数实现：
除非无法用宏简单表示定义或需要隐藏实现，总是使用以下的宏实现类定义中的成员函数或函数模板或紧随类定义的扩展接口：
使用宏 DefDe* 声明默认的特殊成员函数；
使用宏 DefDel* 声明删除的特殊成员函数；
使用宏 Impl* 表示公开实现（提供定义）的非模板成员函数的函数体；
使用宏 DefEmptyDtor 在类定义内定义空析构函数，除非需要显式的异常规范；
使用宏 PDefH 和 Impl* 在类定义中实现成员函数（模版）、友元函数（模版）或在类定义后实现类的扩展接口。
注意为了简便，模板一般总是在类定义内实现，不一定使用以上宏。非成员函数或函数模板若无法使用以上宏表示，可以显式在头文件中使用 inline 或分离定义。
除构造函数、构造模板和成员 operator= 外，类定义中若无法使用以上函数表示成员定义，则该成员不在类定义中定义（可以在类定义后使用 inline 定义，或在另外的源文件中分离定义）。

@4.2 类类型规则：

@4.2.1 接口类型实现规则：
接口类型的实现应在基类列表中连续结尾，和其它基类之间半紧缩分行([Documentation::CommonRules @@6.4.3.3]) 。

@4.2.2 成员声明顺序规则：
一般规则参见 [Documentation::CommonRules @@6.9.6] 。
访问器[Documentation::CommonRules @@3.11.3] （以谓词([Documentation::CommonRules @@3.11.2]) 、其它获取器([Documentation::CommonRules @@3.11.4]) 、设置器([Documentation::CommonRules @@3.11.4]) 排列）在转换操作符后和其它函数或函数模板前声明。

@4.3 附加规则：
对于 YDefinition([Documentation::YBase @@2.3]) 中的每个表达式宏([Documentation::CommonRules @@6.10]) M ，使用特定的以下规则：
删除 M( 和对应的 ) 、删除原紧接 ) 之后的 ; 之前的空白符并去除多余的空行后应保证余下的代码遵循其它规则。
这避免表达式宏参数内的多行代码使用过多的缩进而影响可读性，且可能减少重构需要修改的代码。

*/
////

