shipfi

Add Rules

## 数据库和表设计规范
### 1. 数据库设计规范
#### 1.1 命名规范
* 对象名(表、列、函数、视图、序列),一律只使用小写字母,下划线、数字。不以数字开头,不使用保留字。对象名不体现复数的概念,所以名字不以s/es结尾。
> 表定义示例: ev_return_good / ev_user
* 表的字段列名,一律只使用小写字母、下划线、数字。
* 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint
( 1 表示是,0 表示否)。
* 删除标志字段,统一使用 del_flag。
* 命名禁止两个下划线中间只出现数字
* 创建索引以idx_开头,创建唯一索引以uk_开头.
* 临时表以tmp_开头。
* 数据库名以应用或者部门简写为前缀,例如qi_,ev_等
#### 1.2 SQL设计规约
* 表默认使用InnoDB,表字符集默认使用utf-8
* 所有表必备三字段: xx_id | created_at | updated_at字段。其中created_at/updated_at字段的nullable=yes
* 所有的表必须定义主键,主键定义规则如下:
> ev_site => site_id
>
> ev_site_brand => sb_id
>
> ev_spc_discount => sd_id
>
> ev_spc_delay => sd_id
* 外键的关联字段设计,关联的字段一定要相同,以group和site为例:
> ev_group => **group_id** | group_name | ...
>
> ev_site => site_id | **group_id** | site_name | ...
* 表字段被索引列必须定义为not null,并设置default值
* 除非特殊需要,才将字段定义为null, 否则,将字段定义为非null, 并设置默认值。
* 所有表主键都是int并自增性,禁止使用varchar类型作为主键。
* 小数类型为 decimal,禁止使用 float 和 double。
* varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长
度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索
引效率。
* 每个表字段都需要有注释。如果是枚举类型的字段,必须存在每种枚举的注释。
* 表修改时必须有修改日志记录。
* 业务上具有唯一特性的字段,即使是组合字段,也**必须**建成唯一索引。
* 超过三个表禁止 join
* 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据
实际文本区分度决定索引长度即可。
* 以下设计规约来自阿里:
* 不要使用 count(列名)或 count(常量)来替代 count(\*)。count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
* 使用 ISNULL()来判断是否为 NULL 值。注意:NULL 与任何值的直接比较都为 NULL
* 不得使用外键与级联,一切外键概念必须在应用层解决。
* 禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
* in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控
制在 1000 个之内
#### 1.4 Model定义规约
* Model继承自自定义的BaseModel.
* Model的命名是表名去除前缀和下划线的大驼峰写法
```php
// 表名 : ev_group_discount
class GroupDiscount extends BaseMode { }
```
* 除了作为基类的Model如BaseModel, 其它表映射的Model都需要定义\$table\$primaryKey 变量
```php
class APIManager extends BaseModel {
protected $table = 'api_manager';
protected $primaryKey = 'am_id';
}
```
* 所有的插入操作,必须更新created_at / updated_at 字段
* 所有的更新操作,必须更新updated_at字段.
* 在应用的查询中,一律不使用 * 作为查询的字段列表。有哪些字段必须明确写明。
\ No newline at end of file
## GIT FLOW规范
### 1. GIT FLOW 规范
项目永远存在两个分支
* 主分支master
* 开发分支 develop
对于master分支,任何时候这个分支拿到的,都是稳定发布版。
而develop分支,存放的是最新的开发版。
其中,项目中存在四种短期分支
* 功能分支 (feature branch)
* 补丁分支(hotfix branch)
* 测试bug分支(bug branch)
* 预发分支(release branch)
一旦开发完成,以上分支会被合并到develop/master,然后删除
对于版本发布的项目,每有一个稳定的版本,都要从master上打出一个版本,版本号按产品进行定义。
在master分支上,在新的功能增加前,只有hotfix,才允许将代码合并到这个分支,合并后,要更新小版本号。
### 2. 提交Commit
提交commit,一定要给出完整扼要的提交信息。项目经理需要检查提交的信息是否足够。每个成员也需要确保自己的提交信息完整。提交信息如下所示:
```
Present-tense summary under 50 characters
* More information about commit (under 72 characters).
* More information about commit (under 72 characters).
http://project.management-system.com/ticket/123
```
一个正式的提交功能的注释:
```
HOTFIX3001(UserController|CacheListener) : 解决了头部Cache没有引入的问题
1. UserController头部没有引入Cache包导致异常
2. CacheListener Log去除
http://chandao.runsa.cn:8604/pro/bug-view-3001.html
```
不建议通过git commit命令提交,而是建议通过SourceTree或者git cz命令进行提交。
关于git cz命令,查看: [Git Commit](https://mp.weixin.qq.com/s?__biz=MzAwNDYwNzU2MQ==&mid=401622986&idx=1&sn=470717939914b956ac372667ed23863c&scene=2&srcid=0114ZcTNyAMH8CLwTKlj6CTN&from=timeline&isappinstalled=0#wechat_redirect)
### 3. 使用git rebase代替git merge
当多个分支并行发展,需要合并时,使用rebase功能进行合并,这样在SourceTree跟踪代码变更时,会更清晰易懂。
### 4. 其它
git分支管理流程可以查看:
[Git flow 開發流程](https://ihower.tw/blog/archives/5140)
[GIT分支管理策略](http://www.ruanyifeng.com/blog/2012/07/git.html)
## LUMEN+API Service规范
这里的Service其实包含了两层意义,一种表示的是业务逻辑处理(Service)层,一种是表示通用处理(Manager)层。
应用层之间的关系如下:
![](http://of2xnjf2g.bkt.clouddn.com/20170330154524.png)
### 1. Service规范
......@@ -8,14 +13,16 @@
* Service一般实现包括以下几个方面:
* 封装用户的权限验证
* 封装一些基本操作,如通过curl实现HttpGet,HttpPost、通过Cache实现CacheManager、通过Log实现LogService等。
* 封装一些基本操作,如通过curl实现HttpGet,HttpPost、通过Cache实现CacheManager、通过Log实现LogManager等。
* 封装了与其它系统交互的细节,如CRMService, PortalService, SCService等。
* 一般简单的工具类,文件存放在app\Libraray中。
* 其它具体的提供服务类,文件存放在app\Service中。
* 服务不依赖于上层Controller/Model类,按照约定,服务可以在不同项目中复用。
* 通用处理不依赖于上层Controller/Model类,按照约定,通用处理可以在不同项目中复用。
* 设计服务层时,避免层和层之间互相依赖的关系。一般来说层次结构是 Controller -> Model -> Service,或者Controller -> Service -> Model
* 在应用中,服务的日志需要独立。
......
......@@ -12,8 +12,6 @@
### 1. 代码规范
##### 1.1 文件夹命名
* 如果有框架定义,则文件夹命名统一按照框架制定的规则,如果框架不定义,则统一使用小写字母。
......@@ -21,7 +19,6 @@
> 以Lumen为例,项目下的第一级目录全部以小写字母命名。除app文件夹外,其它目录也是全部使用小写字母命名。 app目录下文件夹统一使用首字符大写命名。
---
......@@ -79,18 +76,17 @@
```
---
##### 1.3 变量命名
* 全局变量命名使用大驼峰,前缀加上_,所有单词首字母大写。
* 全局变量命名使用大驼峰,前缀加上G_, 所有单词首字母大写。
* 常量统一使用大写,中间分隔使用_
* 常量统一使用大写,中间分隔使用_,力求语义表达完整清楚,不要嫌名字长。
* 私有变量命名小驼峰,前缀加上_
* 私有变量命名小驼峰
* 变量命名确认以英文名词为主。
......@@ -102,16 +98,16 @@
```php
// 全局变量
$_System_Config = config('myconfig');
$_Root_Path = '/';
$G_System_Config = config('myconfig');
$G_Root_Path = '/';
// 常量
define('CURRENT_SCRIPT','index_php');
const TRANSCATION_TYPE = 'income';
// 私有变量(protected不在此列)
private $_orderCnt = 0;
protected $_salaryAmount = 0;
private $orderCnt = 0;
protected $salaryAmount = 0;
/**
* 我的订单列表
......@@ -127,24 +123,24 @@
```
---
##### 1.4 类、方法、对象命名
##### 1.4 类、方法、对象
* 类统一使用大驼峰形式命名,与文件名必须保持一致。
* 自编写的类一般遵循名词或名词短语来进行命名。
* 框架中的一些类的命名参考 ()
* 类的动作方法 ,一般使用【动词+名词】方式进行命名,例如 sendMessage / getAttr / setAttr / postLogin等
* 类的属性和变量字段,使用小写字母或者小写驼峰方式命名
* 类的private字段和方法,**必须**使用带_前缀的方式命名
* 常量值,统一使用大写。
* 如果方法为API由外部调用,不允许修改方法签名,避免对接口调用方产生影响。
* 所有继承的覆写方法,必须加@Override 注解
* 接口过时必须加@deprecated 注解,并清晰地说明采用的新接口或者新服务是什么
* [PHP自定义类示例参考](Samples/my_class_sample.md)
---
......@@ -155,6 +151,21 @@
* 所有的类、函数、方法定义都需要进行注释。
* 类、方法、函数统一使用/** 内容 */ 注释格式, 不得使用 //** 方式
* 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
* 与其“半吊子”英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可。
* 代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。
* 好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。
* 两个特殊注释标记的注释格式 : TODO / FIXME
* TODO : 待办事宜(TODO):( 标记人,标记时间,[预计处理时间]
* FIXME : 错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间]
* 一般php注释遵循phpdocumentor规范, [phpdocumentor](https://phpdoc.org/docs/latest/references/phpdoc/index.html)
* 如果是API的接口,则提供PHP APIDOC的相关注释 [APIDOC](https://github.com/calinrada/php-apidoc)
......@@ -215,13 +226,25 @@
```
---
##### 1.6 代码和语句
* if/else/for/while/do 语句中必须使用大括号,即使只有一行代码.
* 大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行.
* 左括号和后一个字符之间不出现空格;同样,右括号和前一个字符之间也不出现空格
```php
($age > 18)
```
* 任何运算符左右必须加一个空格。运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号、三目运算符等
* 两元运算符,前后使用空格
```php
......@@ -248,6 +271,14 @@
* 每行代码长度应控制在80个字符以内,最长不超过120个字符, 如超过则另起一行
> 运算符与下文一起换行。
>
> 方法调用的 -> 符号与下文一起换行。
>
> 在多个参数超长,逗号后进行换行。
>
> 在括号前不要换行, 如 append \n ("---");
```php
$qyAuthAppGrpIns = (new QyAuthAppGrp())->getInstanceBySuiteNameCorpId(
$suiteName,
......@@ -257,6 +288,14 @@
* 每行结尾不允许有多余空格
* 方法参数在定义和传入时,多个参数逗号后边必须加空格。
```php
method('a', 'b', 'c');
```
?
* 在类中(尤其是在Model),对于每个属性的访问, 统一使用get/set方法
```php
......@@ -312,7 +351,7 @@
* 每个 php 文件只允许声明一个类。
* 任何类变量的声明都**必须**放在类顶部,先于任何函数的声明。
* 任何类变量的声明都**必须**放在类顶部,先于任何函数的声明。
* 类中的方法必须总是用 private,protected 或者 public 来声明其作用域。
......@@ -324,13 +363,28 @@
}
```
* 代码做到复用,对于相同听代码逻辑,严禁出现在两个函数或者两个文件内,如果逻辑相同,使用重构提取共用性。
* 代码做到复用,对于相同听代码逻辑,严禁出现在两个函数或者两个文件内,如果逻辑相同,使用重构提取共用性。必要时抽取共性方法,或者抽象公共类,甚至是共用模块。
* 一个函数的逻辑实现**严禁**超过一屏(非常特殊或者逻辑简单可理解的除外)。如果业务复杂,使用多个函数实现。
* 一个函数中**不能**出现以下复杂的if/else逻辑判断, 简单规则,每个函数只允许一个if/elseif/else嵌套层。
* 不要在条件判断中执行其它复杂的语句
```php
if ((file.open(fileName, "w") != null) && (...) || (...)) { } // ERROR
// RIGHT
$existed = (file.open(fileName, "w") != null) && (...) || (...);
if ($existed) { /*...*/ }
```
?
* 一个函数中**不能**出现以下复杂的if/else逻辑判断, 一个规则,每个函数只if/elseif/else嵌套不超过三层。
* 逻辑上超过 3 层的 if-else 代码可以使用卫语句或状态模式来实现,关于 [卫语句](http://blog.csdn.net/jw903/article/details/45506777)。
```php
if($condition1) {
if($condition2) {
// do sth
......@@ -346,7 +400,6 @@
```
---
......@@ -399,9 +452,42 @@
---
##### 1.8 日志
* 需要提供统一的日志SDK,作日志API的调用,(现暂时没有)
* 日志 命名方式:appName_logType_logName.log。
logType : 推荐的分类有 : stats / desc / monitor /visit , 通过这些类型命名,有利于归类查找。
* 对日志进行分类,错误日志和业务日志尽量分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控。
* 生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题
* 以使用 warn 日志级别来记录Request请求时用户输入参数错误的情况。
* 注意日志输出的级别,error 级别只记录系统逻辑出错、异常等重要的错误信息。
---
##### 1.9 异常
* 异常不要用来做流程控制,条件控制.
* 不想处理异常,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
* 不能在 finally 块中使用 return。finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句。
* 在应用代码中使用“抛异常”代替“返回错误码”,应用如果是API,则对异常作出处理,返回匹配的Result结果信息。
##### 1.8 其它
---
##### 1.10 其它
* 对API接口和复杂的返回数据,必须进行注释。以能够在代码中准确的了解接口所实现的功能、接口所接收的数据、接口所返回的数据。
![](http://of2xnjf2g.bkt.clouddn.com/20170329172557.png)
......@@ -409,4 +495,5 @@
![](http://of2xnjf2g.bkt.clouddn.com/20170329172345.png)
* 未完成的功能使用TODO标记,如果函数接口层已经定义好,则在函数体内抛出暂时无法实现的异常
![](http://of2xnjf2g.bkt.clouddn.com/20170329172942.png)
* ?
\ No newline at end of file
?
\ No newline at end of file
......