﻿/*
	© 2013-2016 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 ProjectRules.txt
\ingroup Documentation
\brief 项目组织和管理规则。
\version r895
\author FrankHB <frankhb1989@gmail.com>
\since build 381
\par 创建时间:
	2013-02-14 17:59:49 +0800
\par 修改时间:
	2016-06-03 12:44 +0800
\par 文本编码:
	UTF-8
\par 模块名称:
	Documentation::ProjectRules
*/


/*

@0 体例和适用范围：
引用标记参见 [Documentation::CommonRules @@0.1] 。
本文档适用范围为项目范围， 参见 @1 。

@1 项目范围：
YSLib 项目(the YSLib project) 是以程序库(@3) 为主要产出的项目。
除非另行约定，本文档在任意修订后对同一项目构建版本(@2.2) 及之后的版本生效；本条规则适用追溯无限制。

@1.1 依赖管理：
基本内容参见 https://bitbucket.org/FrankHB/yslib/wiki/Terminology.zh-CN.md 。
依赖项作为对象([Documentation::CommonRules @@2.3.3.3]) ，之间具有的引用关系称为依赖关系([Documentation::CommonRules @@2.3.6]) 。
关于当前 YSLib 的具体外部依赖，参见 [Documentation::Dependencies] 。

@1.2 平台(platform) 环境：
基本概念和约定参见 https://bitbucket.org/FrankHB/yslib/wiki/Terminology.zh-CN.md 。
YSLib 项目中使用的概念和一般规则参见 https://bitbucket.org/FrankHB/yslib/wiki/Development.zh-CN.md 有关平台环境的说明。
配置管理(@2.1) 需另行约定，其它由 YFramework 特定部分的实现定义。其它部分除另行约定(@3.3) 外，都保持平台中立。
使用的语言和具体环境（语言版本和语言实现等）参见 @1.2.1 。

@1.2.1 语言使用和实现要求：
基本规则及适用性参见 https://bitbucket.org/FrankHB/yslib/wiki/Development.zh-CN.md ，其中依赖项的概念适用 @1 。
在 YBase([Documentation::YBase]) 中有约定的部分，适用相应规则；项目中的其它部分适用本节以下规则。
标识符使用参见 [CommonRules @@4] 。

@1.3 顶级子项目：
对完全支持的平台，所有生成二进制文件的基本项目(@1.3.1) 应能构建至单一的二进制文件。
独立实现和至少一个宿主实现的平台中，此文件是可执行映像。

@1.3.1 基本项目：
YBase ： YSLib 基础库。
YFramework ： YSLib 框架库。
YSTest ： YSTest 测试项目，是包含测试代码的应用程序项目，包含示例（当前为 YReader ）。

@1.3.2 附属项目：
Data ：运行时数据。
Test ：测试框架。
Tools ：开发工具集合。
YDE ：桌面环境工具集，当前仅用于测试。

@1.3.3 YSLib 顶级子项目依赖结构：
YFramework 依赖 YBase 。
YSTest 依赖 YBase 和 YFramework 。
具体的框架依赖架构见 "/doc/vsd" 。
文件组织依赖见 @3.3 。

@1.4 项目组和项目边界：
本项目和附属 wiki https://bitbucket.org/FrankHB/yslib/wiki/ 属于共享项目过程的项目组。
本项目内的 Documentation 顶级子项目提供维护本项目的开发者文档，使用 Doxygen 生成 API 文档。
维护本项目组的公共文档以及其它面向一般用户的文档由 wiki 提供。

@2 项目管理：
默认使用迭代增量式开发。
除非另行约定，不修改外部依赖项(@1.1.2) 。
以下是非外部依赖项设计和管理约定。
注意具体的 IDE （集成开发环境）等工具不一定支持以下所有项。
关于开发阶段的定义，参见 https://bitbucket.org/FrankHB/yslib/wiki/Releases.zh-CN.md 。

@2.1 配置管理：
适用于各个子项目。
各目标平台统一包含的基本配置为 debug 和 release （注意大小写），分别对应调试和发布。
对有其它生成目标的平台可以追加配置。

@2.1.1 支持等级：
项目中对程序构建和运行的支持基于平台([Documentation::CommonRules @@2.2.2]) 上的具体配置。
通过特定于更改相关范围内的现有的可构建、示例项目的可运行及测试项目的正确性测试(@3.3.2) ，对应提供可构建、可运行和正确性支持。
支持的配置可能在开发过程中被计划性地验证，据此按支持程度从高到低划分为以下验证支持等级：
第一类支持：每个提交版本(@2.2.1.2) 提供可构建、可运行和正确性支持，且构建版本(@2.2.1.1) 对此造成的影响应立刻解决；
第二类支持：每个构建版本提供可构建和可运行支持，但除非涉及此配置的代码被修改，不要求在构建版本进行验证；
第三类支持：每个构建版本提供可构建和可运行支持，但除非涉及此配置的代码被修改，不要求在非发布版本(@2.2.1.5) 进行验证；
第四类支持：已验证存在可构建和正常运行的程序，但不保证构建和指定的功能在运行时可用，也不要求在任意版本进行验证。
第五类支持：未被完整实现或当前明确不支持，未测试，但在代码中保留已知平台的占位符（如条件分支选项）。
第一类至第三类支持是正式支持。
基于支持涵盖项目内容和功能范围的不完整性，非第一类的正式支持可明确提供为待定(pending) 支持。
待定支持和非正式支持可用于正在移植中的目标。
具体配置的支持等级可能会在项目中变更。
整个项目声明周期中应保证存在至少一个第一类支持的配置。

@2.2 版本控制：
项目的特定部分或整体在同一连续阶段的操作具有的共同属性称为版本标识。
版本标识可在代码和文档中被标示。具有确定格式的版本标示称为版本号。
指定相同的意义时，版本标识和标示统称版本。
版本控制规则指定项目过程中指派标识和标示的方法，为项目修订和发布提供的有限的内容分类，适用于任意非外部依赖项。
被版本库识别并归档的文件称为托管文件。
作为权威发行者的中心版本库对托管的版本提供顺序保证，在此之上顺序同构的抽象版本集合。
任意托管文件的被版本库识别的改动都是项目的修订。除此之外，存档与临时文件的临时版本记录区域不视为文件修订。
项目构建版本号独立于文件版本号。

@2.2.1 项目构建：
自 build 132 起使用版本控制工具。

@2.2.1.1 构建版本：
以 (release) rev （缩写 r ）加整数序号表示用于在构建之间迭代的构建版本。
一个编译版本具有一次或多次修订后对特定构建目标的的一个或多个配置的一次构建。

@2.2.1.2 提交版本：
以 build （缩写 b ）加整数序号表示经过完整构建的公开提交版本。一个提交版本应至少具有目标项目的一次（各个平台）的所有第一类支持(@2.1.1) 的配置的全部重新构建。
原则上一个提交版本具有至少 X = min{8, ∑A(i) + ∑B(i)} 个编译版本，其中最后的连续几个构建版本作为各个配置的提交发布版本，参数含义如下：
i 表示被正式支持(@2.1.1) 的配置的具体平台数。
A 是 i 的函数；对独立实现， A(i) = 4 ；对宿主环境（操作系统内核及应用虚拟机等运行时环境其中任一）和已被相同或更高支持等级支持的宿主平台不共享实现的新的宿主实现， A(i) = 3 ；否则 A(i) = 2 。
B 是 i 的函数，表示平台上被支持的第一类支持的配置数。
当前状态的具体值详见测试说明([Documentation::Test @@1.4.2]) 。

@2.2.1.3 库提交版本：
包含库源代码的文件的修改，构建目标项目包括库重新构建的提交版本称为库提交版本。
大部分提交版本应为库提交版本。
库提交版本应尽量避免回退。

@2.2.1.4 主分支版本：
在主要开发路径分支（主分支）上的库提交版本称为主分支版本。
除此之外，主分支版本也可以仅包含库的文档改进，但应在提交记录说明。
主分支版本应保证所有程序（非文档）目标能在所有完整支持(@2.1.1) 的平台上成功构建，且变更日志(@2.2.7) 和当前进度保持同步，否则为工程缺陷(@2.3.3) 。
仅包含库的程序或文档以外修订的版本，不是主分支版本。
主分支版本需要保证通过版本库的所有现有的可构建和正确性测试。
主分支版本禁止回退。

@2.2.1.5 发布版本：
在主分支的基础上的特定版本或分支打包发布的版本。
除主分支版本要求(@2.2.1.4) 外，同时要求正式支持的移植版本能成功构建且更新日志(@2.2.8.1) 当前进度保持同步，否则为工程缺陷(@2.3.3) 。

@2.2.2 独立元数据：
项目内应以独立于外部存储系统元数据的、在不同宿主开发环境之间可移植的形式记录特定文件的元数据，称为独立元数据。
不限制外部存储系统（如文件系统、版本库或数据库）和独立元数据的关联（不要求严格同步）。
独立元数据不应用于基于外部依赖(@1.1.2) 的文件。
独立元数据应用于程序代码和正式开发者文档的文件。

@2.2.2.1 存储形式：
除非另行约定，当前位于文件内容之中。

@2.2.2.2 基本内容规则：
当前包括文件创建时间和文件修改时间。
文件创建时间应不晚于最早的提交时间。
分支版本使用新的文件创建时间，但父文件不再存在时都继承父文件创建时间。
文件修改时间应保证和对应提交时间一致，除非最近一次修订是回滚前一次操作。
当从其它分支合并或提交未在版本库中的文件时，文件创建时间可早于提交时间。

@2.2.3 文件版本号：
文件版本号表示特定文件的历史版本的修订行数，即增加、删除、修改或移动的行的有效计数。
有多种计数时以较小者为准（如移动优先于修改）。
版本说明（版本号）、修改时间的修改不列入计数。
注意修订的版本不一定提交，因此相邻提交版本之间版本号的变动可以大于（但不得小于）直接比较提交版本之间的差异得到的计数。
除非一次修订仅涉及空行（这里指仅含空白符的行，以及不可见行如 BOM 的修改），对空行的修改不列入计数。

@2.2.3.1 代码标示：
文件版本号在代码中以 Doxygen 指令 \version 标示。
自 build 334 起严格执行（之前大部分文件版本号在新增时加入偏移而偏大）。

@2.2.4 实体和实体版本：
实体包括源代码（文本）文件实体和程序实体（ ISO C++ 定义的实体，参见 ISO/IEC 14882 Clause 3 ）以及宏（名称为和 ISO C++ 宏名通用的标识符，包括 ISO C++ 的宏）。
实体版本是表示抽象的实体被引入时和文件版本关联的版本，适用范围较文件版本号更广。
特定的实体及其实体版本组合为抽象的标识。
实体版本标识首要用于跟踪实体的修订，其次关注公开接口的可使用性，和接口的设计目的和具体含义并无直接的关联。
实体修订时接口兼容性可能发生变化但版本不变；或补充兼容接口后，兼容接口使用新的版本标识。
更新实体版本标识的充分必要条件是存在名称变更或以下约定的其它变更的修订。
当从其它分支合并或提交未在版本库中的文件时，实体版本标识可早于提交版本。

@2.2.4.1 实体同一性(identity) ：
同一性是连续构建版本之间接口使用的名义上的(nominal) 等价关系。
通过新的构建版本中的实体替换旧版本的同一接口（如正向闭合变更(@2.2.4.2) ），能保证演进意义上的不变性(invariant) 。
在某个声明中，被声明的实体以确定的名称标识，即不同名的实体不视为同一实体。
实体的名称优先基于源代码推断，因此同一实体允许在不同构建版本之间具有不同的目标代码表示，而不保证二进制兼容([Documentation::CommonRules @@2.2.4.2]) 。
对 C++ 实体，在某个代码位置上，若不同记号序列组成的名称根据声明和名称查找规则确定同一实体的指称，则这些名称在这个位置上等价；但除了仅声明而不被定义的名称（如 typedef 名称），不用于版本标识目的。
	推论：同一声明中重命名（被声明或使用其它声明的）标识符，标识符对应的名称在这个位置上不等价。
等价的名称之间的替换称为等价名称变换。
同一性决定了实体版本标识：同一的实体共享实体版本标识(@2.2.4) ，不同的实体之间的版本标识不同。
注意名称和实体之间不保证一一对应，即同名实体可能包括不同的非同一实体，虽然实体版本标识不同，之间可能共享版本标示(@2.2.4.8) 。
同名且同参数列表的形式（接受相同位置的标识符或 ... ）的宏视为同一实体。
不同的重载以及不同模板参数的模板特化不视为同一实体。
同一个 C++ 声明可能引入不同的实体，如 using 声明可以引入不同的重载函数/函数模板或构造函数/模板。

@2.2.4.2 一般实体变更：
实体上的基元变更是使邻接项目构建版本之间的实体保持关联性的引起预处理记号或记号序列改变的变换操作。
实体变更是一个或多个连续基元变更的有序组合。其中旧版本变换到新版本的变更是正向变更，反之为逆向变更。
实体变更是闭合的(closed) ，当且仅当变更保持作为外部接口的实体的同一性。添加和移除实体的变更是非闭合的。
实体变更是原子的(atomic) ，当且仅当未被约定拆分为多于一个的变更操作（如移除后添加）。原子变更实质蕴含基元变更。
基元变更的实体版本标识(@2.2.4) 保持不变，当且仅当变更是闭合的原子变更。
注意实体变更的顺序不影响等价名称变换（即变换仍然是自反的），尽管某个代码位置上的名称等价性可能依赖（其中可能仅一个版本满足的）其它声明的存在以及出现的顺序。

@2.2.4.3 同名实体变更：
同名实体变更不保证是闭合或原子的，因此可能导致其版本标识(@2.2.4) 及指派的单一标示(@2.2.4.8) 需要变更(@2.2.4.2) 。
此时，之前共享的标示被指派标示的实体的旧版本标示。
例如，构成重载的一组函数可用相同的函数名指称，在此之上的变更可能包括添加或移除重载函数，闭合性和原子性取决于具体的变更内容。若变更都是平凡的，可以指定变更是闭合和原子的，沿用之前的版本标示。

@2.2.4.4 平凡(trivial) 变更：
实体变更是平凡的，当且仅当实体公开接口在变更后被保证且实现和变更之前兼容（对正向变更即向后兼容）。
除非另行约定，使用经过平凡变更的接口的代码具有在预处理阶段后不可分辨的行为。
private 成员的变更、隐式指定语义（如隐式指定的枚举值、类型推断、没有 trailing-return-type 的隐式返回类型）、标注为实现细节（由文档约定，在特定命名空间中或以宏标注的代码）的变更是平凡的。
除非涉及 C++ 实体（如参数类型）变更或另行约定，所有变更直接通过预处理记号序列比较，即宏的替换序列改变是宏定义的平凡的变更；但这不包括被替换的实例。
	推论：宏名不变但宏的替换序列改变导致的实体的 C++ 名称变化是非平凡变更。
在确定上下文中语言构造之间的意义完全一致的变换是平凡变更，包括别名声明和 typedef 之间的等价变换以及初始化指针的 nullptr 修改为 {} 等。
除以上规则外具有链接的名称变更和程序实体类型变更是非平凡的；除非另行约定(@2.2.4.7) ，同时是非闭合的。

@2.2.4.5 组合变更：
特定部分的变更可能对外部整体变更的起可推断的作用，称为相对于外部整体的组合变更。
组合变更性质是合取变更性质(@2.2.4.5.1) 和析取变更性质(@2.2.4.5.2) 的统称。

@2.2.4.5.1 合取变更性质：
实体满足合取变更性质，当且仅当若干变更构成关于这个实体的组合变更时，后者闭合的充分必要条件是前者中的每个非平凡变更闭合。
声明符对被声明的标识符满足合取变更性质。
类型名对组成类型名的声明符满足合取变更性质。
宏、函数和模板对宏参数、函数参数和模板参数列表对应满足合取变更性质，参数列表的非平凡变更为所有参数的变更的以及添加参数、移除参数或更改参数位置的组合。
	推论：对宏、函数和模板的参数的变更中，等效的参数重命名以及模板参数中关键字 typename 和 class 之间的置换是闭合的。
非别名声明对声明符和 ISO C++ 或具体实现的方言提供的属性(attribute) 满足合取变更性质。
参与决定静态类型（如作为数组大小或类模板的实际参数）或其它常量表达式的值的常量表达式对其经过标准转换后的值对应的实体满足合取变更性质。
函数的默认参数对默认参数的类型、参数值改变的形式（字面量、字面量和非字面量之间的变更）和其中名称的链接和可见性满足合取变更性质。
通过宏替换得到的多个声明对其中所有替换前的声明（此时宏可能不存在）满足合取变更性质。

@2.2.4.5.2 析取变更性质：
实体满足析取变更性质，当且仅当若干变更构成关于这个实体的组合变更时，后者闭合的充分必要条件是前者中存在闭合的非平凡变更。
同名非同一实体(@2.2.4.3) 的声明满足析取变更性质。
在不同的条件编译指令下至少一个条件分支下存在的同一实体，每一个分支的变更（包括增加及减少）对参与这些分支的条件编译的实体满足析取变更性质。
变更后被和其它声明/新增声明符合并，或拆分为其它声明/删减部分声明符对变更前的声明（如类类型和对象声明合并为同时声明类类型的对象声明）满足析取变更性质。
因模板参数引起被声明的实体的静态类型变更对模板的所有实例满足析取变更性质。

@2.2.4.5.3 非组合变更性质：
非组合实体的整体变更和其中的部分变更相对独立。
命名空间对其中的成员、类和类模板对类的成员以及枚举对枚举器不满足组合变更性质。
模板对模板默认参数的变更不满足组合变更性质。

@2.2.4.5.4 非实体组合变更：
非实体构造导致其中的实体的闭合性不会组合到外部实体。
函数或函数模板对函数体的变更（不包括导致函数体外的隐式变更）不满足组合变更性质。
复合语句对语句不满足组合变更性质。

@2.2.4.6 实体转移：
实体转移是在邻接项目构建版本之间，仅包括导致实体或引入实体的代码出现在项目中的不同位置的闭合实体变更，在代码中的实例包括：
	项目中（包括在相同或不同的作用域之间）移动的完全相同的唯一实体声明，名称的链接/符号可见性以及可访问性（若存在）都不变的，是实体的转移；
	对声明完全相同的存在定义的实体，定义在同一个顶级子项目内移动（包括在类和类之间、命名空间和命名空间之间以及类和命名空间之间），且名称的链接/符号可见性以及可访问性（对命名空间成员视为等效于 public ）都不变的，是实体的转移。
顶级子项目(@1.2) 内部的实体转移是原子的，包括以下变更：
	对文件，仅包括目录路径和作为非公开接口（非公开头文件）的文件名的变更（注意虽然 YFramework 使用 YFM_* 代替包含头文件路径，但公开供用户包含的头文件名和目录名仍属于公开接口）；
	对代码中的宏和其它实体，参照以上实例，仅包括所在命名空间（若存在）、文件名、模块名称(@3.2) 及头文件公开性(@3.3) 变更。
其它转移不是原子的；若在同一项目中，按移除后添加处理。

@2.2.4.7 其它实体变更的闭合性：
不满足析取变更性质(@2.2.4.5) 的声明的实体类别变更（如类模板替换为别名模板、 using 声明和非 using 声明之间的变更）非闭合。
所有导致实体名称的链接或对应目标代码中的符号(symbol) 可见性(visibility) 变更的非平凡变更非闭合，除了以下例外：
	显式 = delete 之间的变换；
	预处理记号序列不变，仅由宏定义替换序列导致的相同含义的接口的 C++ 名称变更。
注意针对源代码而不是生成的代码，仅变换 inline 或 constexpr 而省略指定符号可见性（接口不保证符号可见）是平凡变更。
除符号可见性变更以外所有 ISO C++ 或实现扩展的属性(attribute) 变更是闭合的。
对宏，对象宏/函数宏之间的变更以及参数列表变更非闭合。
仅包含替换列表外空白符变更的宏定义是闭合的。
typedef 名称和别名声明中被声明标识符以外的变更是闭合的；别名模板除了模板参数列表的部分中，被声明标识符以外的变更是闭合的。
对所有被声明的实体，不等价的类型（类型等价性参见 [Documentation::LanguageConvention @@5.12.1] ）和存储类限定符（ static 、 extern 、 mutable 等）变更非闭合。
	推论：对同标记的类类型， struct 与 class 的变更闭合，但 struct 和 class 与 union 之间的变更非闭合。
	推论：对同标记的枚举， enum struct 与 enum class 的变更闭合，但 enum struct 和 enum class 与 enum 之间的变更非闭合。
对相同类型的特殊成员函数，任意声明使用或不使用 = default 是闭合的；此外，对函数、函数模板和函数模板特化，闭合变更仅包括：
	在声明的记号序列差异仅包含等价名称变换时，仅由 typedef 名称和别名声明中名称以外部分的变更导致的间接变更；
	函数限定符（ inline 、 virtual 、explicit ）和 constexpr 的变更；
	推论：对函数、函数模板和函数模板特化，非闭合变更包括：
		是否在任意声明上使用或不使用 = delete ；
		声明中等价名称变换以外的 typedef 名称的记号替换（即使保持类型等价）；
		成员和非成员之间的转移及 friend 的变更；
		添加、移除和修改显式指定的异常规范（不论修改前后是否总是保持等效）；
		非平凡的函数默认参数变更；
		其它没有被上述规则排除的变更。
对枚举，在枚举器上添加、移除或修改显式指定的常量表达式的变更非闭合，而调换枚举器顺序等导致的隐式值的变更是闭合的。
	注意调换枚举器顺序等导致的隐式值的变更是平凡的(@2.2.4.4) 。
对类的成员，访问权限变更非闭合。
对类作用域的 using 声明（注意不是 typedef 声明、 using 指示、友元声明或别名声明），保持最终指称同一个类的同一个相同可访问性的实体不变时闭合。
在类定义内初始化的类的数据成员和首次声明时初始化的命名空间作用域变量的不等效的初值符变更非闭合。

@2.2.4.8 代码标示：
实体版本标识(@2.2.4) 在代码中以 Doxygen 指令 \since 标示。
不同实体的不同版本标识可以具有相同的版本标识。
对类或命名空间的成员，若和所在的类或命名空间同时创建，可省略版本标示。
所在的类或命名空间因重命名导致版本变更的成员不从属于新版本，但仍可省略版本标示。对此类实体可查看版本历史确定版本。
若同名实体由不同的声明或宏定义引入，版本号在逻辑上最早引入的语言构造上标示；
否则，多个实体共享版本号，仅对指称的所有实体都变更时对版本标示进行变更。
实体变更的组合即使和变更前等效仍然是变更；被视为非变更的修改的组合不是变更。

@2.2.5 非定义声明独立版本标识：
直接位于块作用域内的声明不加注版本。
typedef 声明、 using 声明、 using 指示 、友元声明和别名声明可独立加注版本，以声明的名称确定版本一致性。
static_assert 声明可独立加注版本，以记号序列等价性确定版本一致性。

@2.2.6 头文件包含：
基本规则参见 [Documentation::CommonRules @@3.13.2.1] 。
头文件包含守护宏名可能包含模块命名空间(@3.2) 的名称。
不使用实现相关的方式如 #pragma([LanguageConvention @@5.3.9]) 等代替头文件包含守护宏，以避免影响可移植性。
注意 #pragma once 无法保证可移植，因为无法确定代码所在的文件在不同实现环境（操作系统和文件系统等）中唯一性的精确含义。

@2.2.7 变更日志：
主分支版本的变更活动应保留到变更日志，保存为 [Documentation::ChangeLog] 。
其中，公开接口的修改是必要内容，非公开接口和实现是可选内容。
当前每个新增的发布版本之间的主分支版本保持独立的日志文件。

@2.2.7.1 标记规则：
具体变更操作可附加 [Documentation::Meta] 声明的标识。
具体顶级子项目可附加指定要求标识为必须的规则。

@2.2.8 发布(releasing) 和发行(publishing) ：
目前为 PreAlpha 测试阶段。自 build 600 起进入 Alpha 阶段。无其它发布和发行计划。

@2.2.8.1 更新日志：
更新日志表明和上一发布版本之间的差异，面向库维护者以外的用户。
所有同一阶段、同一语言的日志使用同一文件。

@2.3 问题跟踪(issue tracking) 和管理：

@2.3.1 问题记录：
和项目运行和质量直接相关的问题应被记录。记录内容参见 [Documentation::Meta] 。
间接的问题和备忘可记录在汇总的年度报告(annual report) 中。

@2.3.2 工程描述文档(enginerring description document) ：
以工程方式控制项目运行和质量的规则描述文档称为工程描述文档，包括本文档和 [Documentation::Designation] 。

@2.3.3 缺陷(defect) ：
不符合且明显有碍于项目目标的问题是缺陷，包括错误(error) 和故障(fault) 。
错误是被证明对预期目的或结果不合适的计划导致的缺陷。错误以外的缺陷是故障。
工程描述文档(@2.3.2) 的规则描述是确认缺陷的充分非必要条件。
违反工程文档的缺陷、错误和故障依次为工程缺陷(engineering defect) 、工程故障(engineering fault) 和工程错误(engineering error) 。
工程缺陷应在提交版本(@2.2.1.2) 中标注。

@2.4 文档管理：
除了正式发布的版本，允许文档落后于实际项目中其它部分的进度。

@2.5 质量保证：
静态验证优先于测试。
默认使用部分整体回归测试代替所有单元测试，以避免过大的测试维护的开销。

@2.6 版本库(repository) 规则：
除了版本控制(@2.2) 外版本库管理根据本节约定。
本节文件限制仅作用于被版本控制系统跟踪的文件，不包括未被跟踪的版本控制自身的数据（如 Mercurial 的 /.hg 和 Git 的 /.git）或其它文件。
注意一些专版本控制的文件（如 Mercurial 的 .hgignore 和 .hgtags 和 Git 的 .gitignore）一般属于被跟踪的文件。

@2.6.1 版本管理工具：
当前使用 Mercurial(hg) 管理版本库，使用 hg-git 制作 Git 镜像。
不使用未被分布式版本控制程序广泛实现的特性。
若需使用 hook ，需要在文档中约定。

@2.6.1.1 书签(bookmark) ：
使用书签(bookmark) 标记指定版本的工程缺陷(@2.3.3) ，标记至引入缺陷的起始提交版本(@2.2.1.2) 。
为避免重名冲突，在书签名称中标记缺陷确认存在的最后截止公开提交版本(@2.2.1.2) ，必要时添加后缀。

@2.6.2 文件系统限制：
注意版本控制工具可能只跟踪文件。避免可能无法实现的操作，例如跟踪空目录。
不使用没有被普遍移植的文件系统特性，包括 NTFS 备选流、加密、目录链接(junction) 等。
不使用文件系统支持的硬链接(hard link) ，避免对特定文件系统和路径的限制。
不使用文件系统支持的符号链接(symbolic link) ，避免对特定文件的限制。若有必要且可实现，在文档中约定后可以通过其它方式模拟。
不在文件系统层次使用元数据（如权限设置，包括 POSIX ACL 和 NTFS ACL ）。若需要此类配置，保存为元数据文件。

@2.6.3 内容转换特性限制：
对文本文件限制内容转换特性以保证不同版本库之间的一致性。
不使用自动行末字符(EOL) 转换（主要是 LF/CR+LF ）。注意 Windows 上的 Git 可能自动使用 autocrlf 配置，应予关闭（配置为 false ）。
不使用自动编码转换。

@2.7 版权(copyright) ：
具有所有权(ownership) 的正式的文件，除了许可证文档外(license documents) ，应予以指定版权从属和使用的许可证授权。
版权约定应尽量明确使用字符 © 和年限标识以取得对适用于不同管辖之下的法律兼容性。若无法使用字符 © （如文件编码限制），使用字符序列 (C) 代替。
注意文件创建时间不同于内容创建时间，内容创建时间可以早于文件创建时间。版权声明的时间上限使用内容创建时间。
另见 [Documentation::CommonRules @@5.7.4] 。

@3 组织约定：
软件包括程序和非程序的软件资源（基本和一般概念参见 [Documentation::CommonRules @@2.3.2] ）。
软件划分为组件(components) ，其粒度由具体程序的设计决定。
组件确定粒度的模块(@3.2) 组织。
一个组件是一个库(library) ，当其被设计为可被复用且提供便于复用的形式独立地进行部署。
库设计为程序的组件时是程序库。
一个组件的实现以外的实现是外部实现。对于程序库，其主要形式为用户代码。

@3.1 单元(unit) ：
编译单元简称单元，是一组包含源代码的文本文件，包含一个不作为头文件包含的源文件（默认后缀名 .cpp ）和若干个被这个源文件直接或间接包含的头文件，经过预处理后成为翻译单元(translation unit) 。
编译单元可以包含类/结构体等类型，以及 API（Application Programing Interface ，应用程序编程接口）的实现。
单元可以作为测试的基本单位之一，即进行单元测试(unit testing) 。

@3.2 模块和模块命名空间：
此处模块特指静态的组织构成单位。注意和一般意义的模块（参见 [Documentation::CommonRules @@3.7.1] ）之间的区别与联系。
一个单元或无源文件对应的头文件称为模块(module) 。一个模块目录是某个抽象路径中的模块的集合。
一个模块仅可属于一个模块目录。
模块和模块目录以类 C++ qualified-id 语法组成的名称表示，形式定义如下：
name-expression:
	identifier
	identifier ( name-expression )
simple-module-name:
	name-expression
module-namespace-name:
	name-expression
	module-namespace-name :: name-expression
module-namespace-qualifier:
	module-namespace-name ::
nested-module-name:
	module-namespace-qualifier simple-module-name
module-path:
	simple-module-name
	module-namespace-name
	nested-module-name
 identifier 规则同 ISO C++ 标识符。
:: 、 ( 和 ) 两边的空白仅作区分记号的示意，实际使用时和标识符之间不保留空格。
此处语法使用 :: 而不使用 . 或其它分隔符并非语义上必要，而是为了便于和一般文件名相区分。

@3.2.1 简单模块名称约定：
除非另行约定，以下使用的模块名称都是简单模块名 simple-module-name 。
对清晰的上下文，可以使用部分的模块名称。特别地，在标识库的组件时顶级的标识符（表示库的名称）通常省略。
顶级子项目(@1.3) 不作为模块命名空间；其并集作为全局模块命名空间。

@3.2.2 内联模块(inlined module)
包含 () 指定的模块名称为内联模块名称，是参数化的模块名称，其中 () 内的表达式是参数。
内联模块名称指称内联模块。对应的非参数化名称指称的称为主模块。
内联模块名称参数用于一般用于表示特定的模块依赖项，如作为修饰符指定独立于主模块的默认配置，在安装或部署时复制或覆盖主模块中对应的子模块。
一般约定内联模块名称参数为平台名时，内联模块的内容被用于参数指定的平台的接口。目标平台(@1.2) 可能和此平台相同（原生支持）或不同（模拟支持）。

@3.3 文件组织：
和模块目录对应的用于存储源文件的文件系统中的一组目录称为模块目录。模块对应其中的文件。
除非另行指定，模块命名空间的名称和对应的主要模块目录（在文件系统的对应称为原始目录）名称相同。对模块不限制名称一致。
每个次级子项目中关于特定独立平台(@1.2) 配置适用的部分称为平台扩展，在原始目录下存储为单独的子目录，目录名称为平台配置名称，项目文件名称一般为项目名称加后缀 "_平台配置名称" 。
相同或不同顶级子项目中，平台特定的目录中的文件可依赖对应的原始目录，原始目录的文件不依赖这些目录中的文件。这保证顶级子项目可以在不更改依赖性的前提下直接被拆分为独立项目。
顶级子项目之间内部的文件仅存在单向依赖，具体依赖和项目相关，参见 [Documentation::YFramework @@2] 和 [Documentation::Designation @@5.2.1.2]。
此外，第三方依赖项项目独占顶级子项目并列的文件系统目录 "/3rdparty" 。

@3.3.1 源文件组织：
典型情况下，每个顶级子项目的根模块目录包含存储公开头文件 "/include" 和存储其它源文件的 "/source"，以下分别按模块命名空间组织为文件系统的目录。
"/include" 中的头文件是公开头文件，它的内容是公开的接口。公开头文件和 "/source" 中的不作为头文件包含的源文件对应组成的模块，称为公开模块。
"/source" 包含的头文件不是公开头文件，它的内容不是公开的接口。非公开头文件可能和同一个目录下的其它源文件组成模块，称为非公开模块。
命名参见 @3.4 。

@3.3.2 测试模块：
适用于每个目录下的测试作为一个模块，使用 "test" 目录，可以作为直接包含源文件和测试脚本的独立项目。
测试项目包含若干测试单元。每个单元包含若干用例。
每个用例用于在特定条件下对可构建、正确性或性能等方面进行验证。

@3.4 文件名和目录名：
本节适用于代码和相关目录，不适用于文档和相关目录。

@3.4.1 长度和可包含的字符：
除 @3.4.2 列出的例外，同 Boost 限制，参见 http://www.boost.org/development/requirements.html#Directory_structure 。
build 275 前在此之上有更强的保证：支持 8.3 文件名兼容性，文件名不使用大写字母，目录名不超过 8 个字符）。
考虑可移植性，在每一个目录下，保证其中所有文件名和目录名中的所有字符使用 std::tolower 转换后得到的文件名不重复。

@3.4.2 可包含字符例外：
除了 YBase([Documentation::Designation @@5.2.1]) ，在文件名（但对存在扩展名的文件名，不包含扩展名部分）和目录名中允许使用大写字母。

@3.4.3 头文件扩展名：
一般使用 h ，但设计时即确定不需要作为独立翻译单元的实现文件（如仅包含模板的实现或元编程设施）的头文件使用 hpp 。

@3.4.4 文件包含：
本节约定 #include 等使用的字符序列。
不使用文件系统中的绝对路径。
统一使用 "/" 作为文件路径分隔符。
实现搜索的根路径为顶级子项目(@1.3) 所在的各个目录(@3.3) 。
本节约定的完整路径是指实现搜索的根路径起始的相对路径；最简相对路径指不包含自指 "." ，以尽量少的 ".." 跳转表示的相对路径。
对包含当前项目外的文件（包括外部的库文件），使用 <完整路径> 。
对包含当前项目中的相同子项目文件，使用 "最简相对路径" 。注意对同一个项目的不同平台配置指定原始目录(@3.3) 时路径会较原始目录内部的包含路径复杂。
对其它文件，使用 "完整路径" 。

@3.4.5 基础文件依赖规则：
关于 ISO C++11 直接指定的依赖项，参见 [Documentation::LanguageConvention @@5.25.2] 。
禁止依赖（包括包含）头文件以外的文件。
除非另行约定（如 [Documentation::YBase @@2.5.7.4] ），禁止显式重复包含同一文件或循环依赖；头文件应具有守护宏([Documentation::ProjectRules @@2.2.6]) 。
实现源文件依赖同名头文件，应保证包含此头文件，但不重复包含此头文件已经包含的其它头文件。

@3.5 命名空间：
库和用户程序的代码在逻辑上最终属于一定的命名空间([Documentation::NPL @@4.3.4]) ，对应 C++ 等语言的命名空间特性。（对没有命名空间特性的语言如 C ，则相当于使用全局命名空间，或另行约定以标识符中的前缀等方式作为替代）。
语言支持的命名空间特性通常具有单一根（一般称为全局命名空间）的树形层次体系。直接从属于全局命名空间的子命名空间称为顶层命名空间。
和模块名称(@3.2) 或源文件的目录名(@3.4) 不同，命名空间的组织方式更多对用户公开不同层次的接口，而不是主要供库维护者组织代码的持久储存形式。注意语言可以只提供命名空间特性，而源文件及目录的组织由环境实现，可能另行约定。
此外，C++ 命名空间对库以外的代码也是开放的，不限制用户添加内容。若需要限制，则需另行约定，如 ISO C++ 标准库中 std 不得随意添加声明。
因此，顶层命名空间不需要和库或程序组件的模块或目录名严格对应。但使用一致的对应名称往往有利于简化设计，便于维护和使用。
YSLib 项目中各个库对命名空间的使用由库约定。

@4 项目过程(process) ：
项目过程是项目生存期中计划和被经历的工程学意义上的明确阶段。
具有顺序约束的过程的总体称为流程。不包含于任何其它流程的流程是完整流程。
流程中的过程可能非必须，由具体流程定义。
对项目过程的实现参见 https://bitbucket.org/FrankHB/yslib/wiki/Development.zh-CN.md 。

@4.1 抽象规则：
使用过程式语言的语义，项目过程被抽象为程序过程(procedure) 。
项目过程使用指令式语言的语义，除了具有输入和输出，允许产生副作用(side effects) ；同时，使用控制流(control flow) 抽象，区分正常路径和异常路径。
控制流抽象项目过程实际被执行的顺序。正常控制流约定为顺序地执行流程中的过程。其它控制流是异常控制流，由具体项目流程约定是否被允许。
项目的操作作为抽象机的行为，可以具有被并发执行的一个和多个完整流程。
在抽象机的意义上，过程的执行不交错(interleaving) ，但实际操作允许在保证输入、输出和副作用等效时的内联，即合并不同过程的边界：可以仅对若干连续项目过程要求输入、输出和副作用具有的规范形式。

@4.2 基本流程（正向工程）：
除非另行约定，每个顶级子项目的开发和维护默认使用以下流程：
需求分析(requirement analysis) ；
可行性研究(feasibility study) ；
设计(designing) ；
实现(implementation) ，可包括局部质量保证（如单元测试）；
前期整体质量保证，可包括形式验证和测试等；
维护(maintenance) ，包括后期整体质量保证（如回归测试）。
所有其它非默认过程需要由文档指定明确的项目过程边界。

@4.2.1 必要性：
除了以下例外，以上任意一个过程在正常控制流都是必须的：
一个流程的实现结束后可直接跳转到需求分析并接受新的流程外部输入，称为一次迭代。

@4.2.2 输入和输出：
需求分析的输入是流程外部的非形式需求，或由其它过程回溯提供的内部需求。所有其它过程的默认输入是上一个过程的文档以及其它产品（若存在）。
所有阶段的默认输出包括文档和可选的其它产品。
这里的其它产品默认是软件，包括程序和可选的使用时必须的其它资源(@3) 。

@4.2.3 异常控制流：
当必要时，所有过程都可以回溯到前一过程（若存在）。
经过质量保证无法确认满足规格要求时可直接回溯到实现或之前的过程。

@4.3 内容约束：
任何正式的设计必须保证实现上的可行性，否则为工程缺陷(@2.3.3) 。
除非存在文档明确例外，任何设计都是正式的。
已实际被实现并经过验证的设计总是可行的。

@4.4 项目角色(role) ：
依据项目过程中起到的作用，对项目涉众(skateholder) 实行一些附加归类，称为角色(role) 。
项目角色同时可用于项目阶段的描述中。
独立为项目过程的用户角色为最终用户(end user) 。最终用户可以不参与提前(ahead-of-time) 构建的项目过程，基于认知需求的差异可能需要从一般用户中单独区分。

@5 程序部署：
使用 YFramework 和 YBase 需要维持目录结构。其它暂略。
关于 YReader 的部署配置参见 [Documentation::YSLib @@10] 。

@6 用户配置：
暂略。

*/
////

