Skill: yaoxin521123/iris-code-formatter (version 3.1.0)

--- name: iris-code-formatter description: | 对InterSystems IRIS/Cache ObjectScript代码进行格式化检查、审查和自动修正。 当用户需要格式化IRIS代码、检查代码规范合规性、审查代码质量或修正不符合规范的代码时触发此技能。 支持变量命名、方法命名、锁、事务、陷阱、格式、空行、注释等多个维度的规范检查。 author: 姚鑫 email: [REDACTED_SECRET] version: 3.1 --- # IRIS 代码格式化规范 ## 概述 本技能基于作者总结的IRIS代码规范，提供ObjectScript代码的格式化、审查和修正能力。涵盖变量命名、方法命名、锁、事务、陷阱、格式、空行、注释等多个维度，确保代码风格统一、可读性强、维护性高。 > **该技能的作者**: 姚鑫 > **作者邮箱**: [REDACTED_SECRET] ## 触发条件 当用户提出以下请求时激活此技能： - "格式化这段IRIS代码" - "检查这段代码是否符合规范" - "审查ObjectScript代码" - "修正代码风格问题" - "按照IRIS规范格式化" - 任何涉及IRIS/Cache/ObjectScript代码格式化的需求 ## 核心能力 ### 1. 变量命名规范 #### 1.1 基本原则 - 禁止使用`$`、`#`等特殊符号开始或结束 - 严禁拼音与英文混合，不允许直接使用中文 - 参数名、成员变量、局部变量统一使用`lowerCamelCase` - 常量命名全部大写 - 杜绝不规范缩写，长度为7个以内单词不需要缩写 - 避免无意义变量（如a, b, c） #### 1.2 Global命名 - 临时global：对于临时Global，命名规范以^CacheTemp开头`^CacheTemp*`，不允许有其它的命名。旧命名方式以^`TEMP*、^Temp*、^temp*、^TMP*、^Tmp*、^tmp*`、开头的均不合法。 - 进程global：`^||TMP`，节点必须携带pid #### 1.3 特殊变量 - 布尔变量不要用`is`开头，使用`Flag`后缀（如`dispFlag`） - 引用global数据的变量用`表ID + Data`方式（如`bisData`） - 分割字符串索引统一用`i`，长度用`len` - 私有对象加`m`前缀（如`mExecute`） - 禁止使用系统保留字或SQL保留字（如`SQLCODE`） - 调用其他方法返回值用`ret`，禁止使用`err` - 变量不超过31个字符 - 百分比变量以`%z`开头 - `.inc`文件通用变量加前缀标识 ### 2. 方法命名规范 #### 2.1 基本规则 - 类名、方法名使用`UpperCamelCase` - 返回布尔类型方法以`Is`开头，加`As %Boolean`，正向描述（存在返回$$$YES） - 推荐使用动宾结构（Get, Set, Query等） - 函数/方法名最长不超过30个字符 - 查询统一用`Query`，获取数据用`Get` #### 2.2 方法组织 - 一个方法控制在50行以内 - 方法内传递参数过多时考虑用对象方式重构 - 禁止在循环里直接写SQL语句（`&sql()`），SQL语句应当单独建立类来保存 - 非普通字符串的入参或返回值需要声明类型（数组、对象、流、%Status等） #### 2.3 错误处理 - 返回值不能单纯返回负数 - 字符串形式：`负数^错误信息` - JSON形式：`..RetFail("错误信息")` - %Status形式：`$$$ERROR($$$GeneralError,"错误信息")` ### 3. 锁规范 - 禁止直接锁表结构的Global - 加解锁必须加`+`、`-`严格控制，必须成对出现 - 加锁必须带`+`，否则导致解锁进程内所有锁 - 加锁必须写超时退出（如`:3`），避免死锁 - 自定义功能锁格式：`^产品组代码(产品线,规范代码:唯一标识)` - 私有进程全局变量名不能用作锁名 - 禁止单独使用无参数锁 - 使用锁时一定要下标节点 ### 4. 事务规范 - 严格禁止开放性事务（必须有tc或tro） - 事务`ts`、`tc`、`tro`位置保持近距离，在一屏幕范围内 - 严格禁止跨方法提交事务 - 事务命令简写并且小写（`ts`、`tc`、`tro`） - 同一个方法内不应该出现事务嵌套 - 事务应在保存程序的最外层 - 单条SQL语句的数据保存不需要事务 - `ts`、`tc`首尾添加空行或注释 ### 5. 陷阱规范 - 严格禁止陷阱内部报错导致死进程 - `Not ProcedureBlock`类陷阱名称统一为`Err + 方法名` - 默认类陷阱名称统一为`Error` - 通用陷阱写法： - 设置`$zt = ""`避免死循环 - `$tl > 0`时执行`tro`避免开放性事务 - 执行`lock`避免开放锁 ### 6. 格式规范 #### 6.1 基本格式 - 方法大括号一律换行显示 - 运算符（`=`、`+`、`-`、`*`、`/`、`_`、`:`）左右加空格 - 逗号后加空格 - 方法内命令行采用一个Tab缩进（4空格宽度） - 禁止命令大小写混用，统一小写 - 系统命令使用缩写（除`for`、`while`外） - 系统函数使用缩写（`$e`, `$p`, `$l`, `$o`等） #### 6.2 SQL格式 - SQL语句一行5个字段 - 换行后3个Tab缩进 - 逗号在行末，不带入下行 - 每行不超过120字符 - SQL命令全部统一小写 #### 6.3 字符串格式 - 单行字符串拼写最多5个字段 - 禁止用同一变量后加数字累加 - 获取多返回值用`%ArrayOfDataTypes`或JSON，不建议字符串拼接 #### 6.4 命令与函数缩写规范 **系统命令缩写规则**： - `for`、`while` 、`if` 、`elseif`、`else`、`continue` 命令使用全拼（语义明确，表示循环结构） - 其他系统命令使用缩写形式 | 全拼 | 缩写 | 说明 | |------|------|------| | set | s | 赋值 | | do | d | 执行 | | quit | q | 退出/返回 | | break | b | 跳出循环 | | kill | k | 删除变量 | | new | n | 新建变量 | | write | w | 输出 | | read | r | 读取 | | tstart | ts | 事务开始 | | tcommit | tc | 事务提交 | | trollback | tro | 事务回滚 | | lock | l | 加锁 | | open | o | 打开设备 | | close | c | 关闭设备 | | use | u | 使用设备 | | hang | h | 暂停 | | job | j | 启动作业 | | merge | m | 合并 | **系统函数缩写规则**： - 所有系统函数使用缩写形式 | 全拼 | 缩写 | 说明 | |------|------|------| | $extract | $e | 提取子串 | | $piece | $p | 按分隔符提取 | | $length | $l | 获取长度 | | $order | $o | 遍历global | | $get | $g | 安全获取值 | | $data | $d | 判断变量是否存在 | | $find | $f | 查找子串 | | $ascii | $a | 获取ASCII码 | | $char | $c | ASCII转字符 | | $translate | $tr | 字符替换 | | $justify | $j | 格式化对齐 | | $zboolean | $zb | 位运算 | | $zconvert | $zcvt | 编码转换 | | $zhex | $zh | 十六进制转换 | | $zdate | $zd | 日期格式化 | | $ztime | $zt | 时间格式化 | | $ztimestamp | $zts | 时间戳 | | $increment | $i | 自增 | | $random | $r | 随机数 | | $stack | $st | 堆栈信息 | #### 6.5 控制结构 - 尽量使用对仗词（add/remove, get/set等） - 禁止`{}`和`.`同时出现，推荐使用块级语法 - 所有`if`语句都要换行写 - `if`嵌套不宜过多，建议不超过3层 - 多级`if else`考虑用`$case`替换 - 与或逻辑运算统一使用`&&`、`||` - 块级语法命令要全拼（`for`、`while`而非`f`、`w`） - 后置表达式要加括号，等号两侧加空格 - **多条件后置表达式**（如 `continue:` `q:` 后的条件）：括号**内部**的条件运算符两侧**加空格**，括号与`&&`/`||`之间**不加空格**。例如： - 正确：`q:(inci = "")&&(arcim = "")&&(phcdf = "")` - 括号内`=`两侧有空格，括号与`&&`之间无空格 - 错误：`q:(inci = "") && (arcim = "") && (phcdf = "")` - 括号与`&&`之间有空格，会导致编译错误 - `} else {` 不换行，写在同一行 ### 7. 空行规范 - 方法与方法之间空行隔断（1个空行） - 空行分割功能相似、逻辑内容相近的代码片段 - 空行之前添加行注释`#; 规则` - 事务首尾一定要加空行或注释 ### 8. 注释规范 #### 8.1 注释格式 - 单行注释用`#;`，句尾注释用`//` - 类、方法头注释用`///` - 各类注释后应跟空格 #### 8.2 注释原则 - 避免无意义注释，用规范代码命名描述 - 简明扼要，不要啰嗦 - 避免错误注释误导 #### 8.3 类注释 ```objectscript /// desc: 类用途描述 /// author：姓名全拼 /// date：YYYY-MM-DD Class XXX.XXX ``` #### 8.4 方法注释 ```objectscript /// desc: 方法描述 /// author: 姓名 /// createDate: YYYY-MM-DD /// params: 参数说明 /// return: 返回值说明 /// version: 版本 /// modify: 修改记录 /// debug: 调试方法 ``` ## 使用方法 ### 代码审查流程 执行以下步骤审查和修正代码： 1. **读取代码**：获取用户提供的ObjectScript代码 2. **逐条检查**：按照上述规范逐项检查 3. **标记问题**：识别不符合规范的代码位置 4. **提供修正**：给出符合规范的修正版本 5. **说明原因**：解释每项修正的依据 6. **输出完整代码**：**必须**输出完整的修正后代码，包含所有类定义、方法、注释，不得省略任何部分 ### 关键修正规则（强制执行） #### 1. 后置表达式处理（关键！） 多条件后置表达式必须严格遵守以下格式： ```objectscript ; 正确格式 - 括号内运算符两侧加空格，括号与&&之间不加空格 continue:(hospId '= "")&&(hospId '= ($p(^CTLOC(locId),"^",22))) q:(inci = "")&&(arcim = "")&&(phcdf = "") ; 错误格式 - 会导致IRIS编译错误 continue:(hospId '= "") && (hospId '= ($p(^CTLOC(locId),"^",22))) q:(inci = "") && (arcim = "") && (phcdf = "") ``` **修正逻辑：** - 识别后置表达式（`q:` `continue:` `b:` 等命令后的条件） - 确保每个条件用括号包裹：`(条件)` - 括号内运算符两侧加空格：`(a = "")` `(b <= 0)` - 括号与`&&`/`||`之间**绝对不能**加空格：`)&&(` 不是 `) && (` - 这是IRIS编译器的硬性要求，必须严格遵守 #### 2. 命令缩写规则 - `for`、`while`、`if`、`elseif`、`else`、`continue` 使用全拼 - 其他命令使用缩写：`s`/`d`/`q`/`b`/`k`/`n`/`w`/`r`/`ts`/`tc`/`tro`/`l`/`o`/`u`/`h`/`j`/`m` #### 3. 系统函数缩写 使用缩写形式：`$e`/`$p`/`$l`/`$o`/`$g`/`$d`/`$a`/`$c`/`$tr`/`$j`/`$zb`/`$zcvt`/`$zh` ### 输出格式 审查结果应包含： ``` ## 代码审查报告 ### 问题汇总 - [严重] 问题1描述（行号） - [警告] 问题2描述（行号） ### 详细说明 #### 1. 变量命名问题 **位置**：第X行 **问题**：描述 **规范依据**：引用具体规则 **建议修正**： // 修正后的代码 #### 2. 方法命名问题 ... ### 修正后完整代码 **IMPORTANT**: 必须输出完整的修正后代码，不要省略任何部分。将用户提供的完整代码按照规范修正后全部输出。 // 完整修正后的代码（必须包含所有方法，不得省略） ``` ## 规范速查表 | 类别 | 规则 | 正确示例 | 错误示例 | |------|------|----------|----------| | 变量名 | lowerCamelCase | `startDate` | `startdate` | | 常量 | 全大写 | `MAXCOUNT` | `MaxCount` | | 布尔变量 | Flag后缀 | `dispFlag` | `isDisp` | | 方法名 | UpperCamelCase, 动宾结构 | `GetName()` | `getname()` | | 布尔方法 | Is开头 | `IsExist() As %Boolean` | `GetExistFlag()` | | 事务 | 简写小写 | `ts` / `tc` | `TSTART` | | 锁 | 带+/-和超时 | `l +^XXX:3` | `l ^XXX` | | 注释符 | #; 或 // | `#; 说明 ` | `; 说明` | | 空格 | 运算符两侧 | `a = b` | `a=b` | | 命令 | 除for/while外使用缩写 | `s`, `d`, `q`, `for` | `set`, `do`, `quit`, `f` | | 系统函数 | 使用缩写 | `$e`, `$p`, `$l`, `$o` | `$extract`, `$piece`, `$length`, `$order` | | 逻辑运算 | && \|\| | `(a)&&(b)` | `a,b` | | 后置表达式 | 括号内空格，括号外无空格 | `q:(a = "")&&(b = "")` | `q:(a = "") && (b = "")` | ## 参考资源 - `references/代码规范 - 变量.md` - `references/代码规范 - 方法.md` - `references/代码规范 - 格式.md` - `references/代码规范 - 空行.md` - `references/代码规范 - 事务.md` - `references/代码规范 - 锁.md` - `references/代码规范 - 陷阱.md` - `references/代码规范 - 注释.md`

path: CHANGELOG.md
content: # 更新日志

## v3.1 (2026-04-18)

### 优化
- 优化 SKILL.md frontmatter，添加版本号
- 改进描述使用第三人称格式
- 重构使用方法部分，增加关键修正规则说明
- 创建 references/README.md 索引文件
- 添加 CHANGELOG.md 记录版本历史

## v3.0 (2026-04-16)

### 新增
- 完善后置表达式规则
- 添加使用手册
- 明确 `} else {` 不换行规则

### 修复
- 修复多条件后置表达式 `&&` 两侧空格问题
- 修复后置表达式括号内运算符空格规则

## v2.0 (2026-04-15)

### 重构
- 重构为 Markdown 格式
- 8章73条规则完整覆盖
- 添加详细示例

## v1.0 (2026-04-15)

### 初始版本
- 基于RIS代码规范
- 基础格式化规则


path: IRIS 代码格式化 Skill 使用说明.md
content: [toc]

# IRIS 代码格式化 Skill 使用说明

> **作者**: 姚鑫  
> **邮箱**: [REDACTED_SECRET]  
> **版本**: v3.0

---

## 一、安装方法

### 方式1：通过 WorkBuddy 安装（推荐）

1. 将 `iris-code-formatter` 文件夹复制到 WorkBuddy skills 目录：
   ```
   Windows: C:\Users\<用户名>\.workbuddy\skills\
   ```
   
2. 重启 WorkBuddy 或重新加载技能

### 方式2：通过 OpenClaw/ClawHub 安装

```bash
npx clawhub install iris-code-formatter --workdir <目标路径> --no-input
```

### 方式3：clawhub 下载

- https://clawhub.ai/yaoxin521123/iris-code-formatter



---

## 二、使用方法

### 触发方式

在对话中直接提供 IRIS ObjectScript 代码，Skill 会自动激活并执行代码审查。

**触发关键词：**
- "格式化这段IRIS代码"
- "检查这段代码是否符合规范"
- "审查ObjectScript代码"
- "修正代码风格问题"
- "按照IRIS规范格式化"

### 使用示例

**输入：**
```
Class Util.Encryption.SM3 Extends %RegisteredObject
{
ClassMethod HMAC(key As %Stream.GlobalCharacter, text As %Stream.GlobalCharacter)
{
    s keyStream=..UTF8(key)
    s keyPadding=..KeyPadding(keyStream)
    q ..Str2Hex(hmacByte)
}
...
}
使用iris-code-formatter技能
```

**输出：**

- 修正前代码

![image-20260416165210524](C:\Users\yaoxin521123\AppData\Roaming\Typora\typora-user-images\image-20260416165210524.png)

- 修正后代码

![image-20260416165150802](C:\Users\yaoxin521123\AppData\Roaming\Typora\typora-user-images\image-20260416165150802.png)

---

**以下是输出内容：**



---

---

## 代码审查报告

### 问题汇总

| 类别           | 问题                         | 严重程度 |
| -------------- | ---------------------------- | -------- |
| 方法大括号     | 方法大括号应换行显示         | ⚠️ 警告   |
| 空格规范       | 运算符两侧缺少空格           | ⚠️ 警告   |
| 注释格式       | 方法头注释不规范             | ⚠️ 警告   |
| 变量命名       | 参数命名未使用lowerCamelCase | ⚠️ 警告   |
| 条件后置表达式 | 括号内空格使用错误           | ⚠️ 警告   |
| 字符串拼接     | 单行字段数超过限制           | ⚠️ 警告   |

### 详细问题分析

#### 1. 方法大括号格式问题

**位置**: 所有方法 **问题**: ObjectScript方法大括号应换行显示

```objectscript
// 错误
ClassMethod OrderDetailGrpExecute(...) As %Status {
    s repid=$I(^CacheTemp)
    
// 正确  
ClassMethod OrderDetailGrpExecute(...) As %Status
{
    s repid = $I(^CacheTemp)
```

#### 2. 运算符空格问题

**位置**: 全局 **问题**: `=`、`+`、`-`等运算符左右应加空格

```objectscript
// 错误
s repid=$I(^CacheTemp)
s qHandle=$lb(0,repid,0)
s ind=1

// 正确
s repid = $I(^CacheTemp)
s qHandle = $lb(0, repid, 0)
s ind = 1
```

#### 3. 参数命名问题

**位置**: 所有Query参数**问题**: 参数应使用lowerCamelCase



```objectscript
// 错误
Query OrderDetailGrp(Oeori = "", Oeore = "", DspId = "", ProCode = "")

// 正确
Query OrderDetailGrp(oeori = "", oeore = "", dspId = "", proCode = "")
```

#### 4. 条件后置表达式空格问题

**位置**: OrderDetailGrpExecute, TimeLineExecute等 **问题**: 括号内部条件运算符两侧有空格，但括号与逻辑运算符之间不应有空格

```objectscript
// 错误
i Oeore'="" s Oeori=$p(Oeore,"||",1,2)
e  i DspId'="" s Oeori=$p($g(^DHCOEDISQTY(DspId)),"^",1)
q:Oeori="" $$$OK

// 正确
i (oeore '= "") s oeori = $p(oeore, "||", 1, 2)
e  i (dspId '= "") s oeori = $p($g(^DHCOEDISQTY(dspId)), "^", 1)
q:(oeori = "") $$$OK
```

#### 5. 字符串拼接字段数超限

**位置**: 多处 **问题**: 单行字符串拼接超过5个字段

```objectscript
// 错误
s data = $lb(locDesc, qtyWithUom)

// 建议保持现状（$lb函数本身是内置函数调用）
```

#### 6. 方法头注释不规范

**位置**: 所有方法 **问题**: 缺少规范的docstring注释

```objectscript
// 错误
Query OrderDetailGrp(Oeori = "", ...) As websys.Query(...)

// 正确
/// Desc: 医嘱明细,注意区分门诊住院
/// Output: 两列属性以及值
/// w ##class(%ResultSet).RunQuery("PHA.COM.Query","OrderDetailGrp","41||77")
Query OrderDetailGrp(oeori = "", ...) As websys.Query(...)
```

### 修正后完整代码

以下是按照IRIS代码规范修正后的完整代码：

```
/// Desc: 医嘱明细,注意区分门诊住院
/// Output: 两列属性以及值
/// w ##class(%ResultSet).RunQuery("PHA.COM.Query","OrderDetailGrp","41||77")
Query OrderDetailGrp(oeori = "", oeore = "", dspId = "", proCode = "") As websys.Query(ROWSPEC = "group,field1,value1,field2,value2") [ SqlProc ]
{
}

ClassMethod OrderDetailGrpExecute(ByRef qHandle As %Binary, oeori = "", oeore = "", dspId = "", proCode = "") As %Status
{
    s repid = $I(^CacheTemp)
    s qHandle = $lb(0, repid, 0)
    s ind = 1
    
    #; 处理入参转换
    i (oeore '= "") s oeori = $p(oeore, "||", 1, 2)
    e  i (dspId '= "") s oeori = $p($g(^DHCOEDISQTY(dspId)), "^", 1)
    q:(oeori = "") $$$OK
    
    s ordId = +oeori
    s ordItm = $p(oeori, "||", 2)
    s dspId = $o(^DHCOEDISQTY(0, "OEORI", oeori, ""))
    s admId = $p($g(^OEORD(ordId)), "^", 1)
    q:(admId = "") $$$OK
    s patId = $p(^PAADM(admId), "^", 1)
    s admType = $p(^PAADM(admId), "^", 2)
    s OEORDI1 = $g(^OEORD(ordId, "I", ordItm, 1))
    s OEORDI2 = $g(^OEORD(ordId, "I", ordItm, 2))
    s OEORDI3 = $g(^OEORD(ordId, "I", ordItm, 3))
    s OEORDI5 = $g(^OEORD(ordId, "I", ordItm, 5))
    s OEORDI6 = $g(^OEORD(ordId, "I", ordItm, 6))
    s OEORDI9 = $g(^OEORD(ordId, "I", ordItm, 9))
    s OEORDI11 = $g(^OEORD(ordId, "I", ordItm, 11))
    s OEORDIDHC = $g(^OEORD(ordId, "I", ordItm, "DHC"))
   
...
```

---

---





## 三、规范速查表

### 命名规范

| 类型 | 规则 | 正确示例 | 错误示例 |
|------|------|----------|----------|
| 变量名 | lowerCamelCase | `startDate` | `startdate` |
| 常量 | 全大写 | `MAXCOUNT` | `MaxCount` |
| 布尔变量 | Flag后缀 | `dispFlag` | `isDisp` |
| 方法名 | UpperCamelCase | `GetName()` | `getname()` |
| 布尔方法 | Is开头 | `IsExist()` | `GetExistFlag()` |

### 命令/函数缩写

| 类型 | 全拼 | 缩写 |
|------|------|------|
| 命令 | set/do/quit | s/d/q |
| 命令 | for/while | for/while（全拼） |
| 函数 | $extract/$piece/$length | $e/$p/$l |
| 函数 | $zconvert/$zhex | $zcvt/$zh |

### 格式规范

| 场景 | 正确 | 错误 |
|------|------|------|
| 运算符空格 | `a = b` | `a=b` |
| 后置表达式 | `q:(info = "")` | `q:info=""` |
| 多条件后置 | `q:(a = "")&&(b = "")` | `q:(a = "") && (b = "")` |
| else格式 | `} else {` | `}\nelse {` |

---

## 四、输出说明

### 审查报告结构

```
## 代码审查报告

### 问题汇总
- [严重] 问题1描述（行号）
- [警告] 问题2描述（行号）

### 详细说明
#### 1. 变量命名问题
**位置**：第X行
**问题**：描述
**规范依据**：引用具体规则
**建议修正**：代码示例

### 修正后完整代码
```objectscript
// 完整的修正后代码
```


path: references/README.md
content: # IRIS 代码规范参考文档索引

本目录包含 IRIS ObjectScript 代码规范的详细文档。

## 文档列表

| 文件 | 内容 |
|------|------|
| [代码规范 - 变量.md](./代码规范%20-%20变量.md) | 变量命名规范（18条规则） |
| [代码规范 - 方法.md](./代码规范%20-%20方法.md) | 方法命名规范（10条规则） |
| [代码规范 - 格式.md](./代码规范%20-%20格式.md) | 代码格式规范（19条规则） |
| [代码规范 - 锁.md](./代码规范%20-%20锁.md) | 锁规范（8条规则） |
| [代码规范 - 事务.md](./代码规范%20-%20事务.md) | 事务规范（8条规则） |
| [代码规范 - 陷阱.md](./代码规范%20-%20陷阱.md) | 陷阱规范（3条规则） |
| [代码规范 - 空行.md](./代码规范%20-%20空行.md) | 空行规范（4条规则） |
| [代码规范 - 注释.md](./代码规范%20-%20注释.md) | 注释规范（4条规则） |

## 快速参考

### 命名规范
- 变量：`lowerCamelCase`
- 常量：`UPPER_CASE`
- 方法：`UpperCamelCase`
- 布尔方法：`IsXxx()`

### 命令缩写
- 全拼：`for`、`while`、`if`、`elseif`、`else`、`continue`
- 缩写：`s`、`d`、`q`、`b`、`k`、`n`、`w`、`r`、`ts`、`tc`、`tro`、`l`、`o`、`u`、`h`、`j`、`m`

### 系统函数缩写
`$e`、`$p`、`$l`、`$o`、`$g`、`$d`、`$a`、`$c`、`$tr`、`$j`、`$zb`、`$zcvt`、`$zh`

### 后置表达式格式
```objectscript
; 正确
q:(a = "")&&(b = "")
continue:(hospId '= "")&&(hospId '= $p(...))

; 错误
q:(a = "") && (b = "")
```

## 总计

共 8 个规范文件，74 条规则。


path: references/代码规范 - 事务.md
content: # 代码规范 - 事务

# 事务

1. 严格禁止开放性事务。

反例：

```java
ClassMethod Save()
{
	tstart
}
```

正例：

```java
ClassMethod Save()
{
	ts
	
	tc //或 tro 
}
```

2. 事务`ts`、`tc`、`tro`的位置应保持近距离，在一屏幕范围内，避免位置过远。代码过多应当提取成方法，让事务看起来简洁、语义明朗。

反例：

```java
ClassMethod Save()
{
	ts
	
	#; 添加主表信息
	// todo 50行代码

	
	#; 添加明细信息
	// todo 100行代码

	tc
}
```

正例：

```java
ClassMethod Save()
{
	ts
	
	#; 添加主表信息
	s sc = ..InsMain()
	i $$$ISERR(sc) tro
	q:($$$ISERR(sc)) sc
	
	#; 添加明细信息
	s sc = ..InsDetail()
	i $$$ISERR(sc) tro
	q:($$$ISERR(sc)) sc
	
	tc
	
	q sc
	
}
```


3. 严格禁止**跨方法**提交事务。

反例：

```java
ClassMethod Save()
{
	ts
	s sc = ..InsMain()

}
ClassMethod InsMain()
{
	// todo
	tc
}

```

正例：

```java
ClassMethod Save()
{
	ts
	
	s sc = ..InsMain()

	tc
	
	q sc
}

ClassMethod InsMain() as %Status
{
	// todo
}

```

4. 为明确显示事务，事务命令需要**简写并且小写**。

反例：

```java
ClassMethod Save()
{
	TSTART
	...
	TCOMMIT
}
```

正例：

```java
ClassMethod Save()
{
	ts
	
	... // todo
	
	tc
}
```

5. 同一个方法内不应该出现事务嵌套的现象。

反例：

```java
ClassMethod Save()
{
	ts
    ts
    ... // todo
    tro
    
	tc
	
	... // todo
	ts
	
	tc
}

```

正例：

```java
ClassMethod Save()
{
	ts
	
	... // todo
	
	tc
}


```

6. 事务应在保存程序的最外层。

反例：

```java
ClassMethod Save()
{
	ts
	
    s sc = ..InsMain()
    
    s sc = ..InsDetail()
    
	tc
}

ClassMethod InsMain() as %Status
{
    ts
	// todo
	tc
}

ClassMethod InsDetail() as %Status
{
    ts
	// todo
	tc
}
```

正例：

```java
ClassMethod Save()
{
	ts
	
    s sc = ..InsMain()
	i $$$ISERR(sc) tro
	q:($$$ISERR(sc)) sc
    
    s sc = ..InsDetail()
	i $$$ISERR(sc) tro
	q:($$$ISERR(sc)) sc
	
	tc
}

ClassMethod InsMain() as %Status
{
	// todo
	q sc
}

ClassMethod InsDetail() as %Status
{
	// todo
	q sc
}
```

7. 单条`SQL`语句的数据保存不需要事务。

反例：

```java
ClassMethod Save()
{
	ts
    
    &&sql()
	
	tc
}

```

正例：

```java
ClassMethod Save()
{
    &&sql()
}


```


8. `ts`,`tc` 首尾添加`空行`，或者`注释`.。

反例：

```java
ClassMethod Save()
{
	TSTART
	s ret=..SaveMain()
	...
	s retItm=..SaveDetail()
	...
	TCOMMIT	
}

ClassMethod SaveMain()
{
	TSTART
	...
	TCOMMIT
}

ClassMethod SaveDetail()
{
	TSTART
	...
	TCOMMIT
}
```

正例：

```java
ClassMethod Save()
{
	ts
	
	#; 注释
	s ret = ..SaveMain()
	i ret < 0 tro q
	...
	
	#; 注释
	s ret = ..SaveDetail()
	i ret < 0 tro q
	...
	
	tc	
}

ClassMethod SaveMain()
{
	...
}

ClassMethod SaveDetail()
{
	...
}

```


path: references/代码规范 - 变量.md
content: # 代码规范 - 变量

# 变量

1. 代码中的命名均不能`$`、`#`等特殊符号开始或结束，因为`$`、`#`等是系统方法、变量，禁止混淆。

反例：

```java
$name
_name
```

正例：

```java
name
```

2. 严禁代码中使用拼音与英文混合方式命名，更不允许直接使用中文。

反例：

```java
Dazhe 
getDZname
[打折]
```

正例：

```java
discount
getDiscountName
```

3. 参数名、成员变量、局部变量都统一使用`lowerCamelCase`风格。

反例：

```java
Params
```

正例：

```java
params
```

4. 常量命名全部大写。力求完整语义表达清楚，不要嫌长。

反例：

```java
MaxCount = 10
```

正例：

```java
MAXCOUNT = 10
```

5. 杜绝不规范缩写，避免词不达意。

反例：

```java
com
condi
```

正例：

```java
complete
condition
```

6. 长度为7个以内单词不需要缩写，当变量长度过长时需考虑缩写，且缩写应为常用正规缩写，避免无意义缩写。

反例：

```java
st
nb
```

正例：

```java
start
number
num
```

7. 避免无意义变量。

反例：

```java
s a = "1"
s b = "2"
s c = a * b
```

正例：

```java
s fitstNum = "1"
s secondNum = "2"
s sum = firstNum * secondNum
```

8. 临时`global`、进程`global`命名严格使用`^CacheTemp`开头，且携带`pid`。格式为`领域名 + 类名 + 方法 + pid + 标识`。

反例：

```java
s ^||YX("TMP", pid, "Login")
```

正例：

```java
s ^||CacheTemp("IRIS", "IRIS.MOB.Base", "Login", pid)
```

9. 布尔变量不要用`is`开头，因为其他框架引用的话会解析错误。例如`Java`的`Getter`的方法也叫`isDisp()`。

反例：

```java
isDisp
```

正例：

```java
dispFlag
```

10. 所有表的`ID`，都用表的前缀。

反例：

- `BS_IRIS_Student`：`ID`
- `CF_IRIS_Config`：`configID`

正例：

- `BS_IRIS_Student`：`bis`
- `CF_IRIS_Config`：`cic`

11. 所有引用`global`数据的变量，用表`ID + data`方式命名，多节点用`ID + 节点 + Data`方式。

反例：

```java
s data=^BS.IRIS.StudentD(inci)
```

正例：

```java
s bisData = ^BS.IRIS.StudentD(inci)
```

12. 方法中仅出现一次`dataStr`分割字符串分割索引均为`i`长度均为`len`。

反例：

```java
s prescNolen=$l(prescNoStr, ",")
f index = 1 : 1 : len q:ret'=0  d
.s prescNo = $p(prescNoStr, ",", index)
```

正例：

```java
s len = $l(prescNoStr, ",")
for i = 1 : 1 : len {
	s prescNo = $p(prescNoStr, ",", i)
}
```

13. 创建的私有对象可以加`m`，例如有`Execute`类的初始化对象。

反例：

```java
s execute = ##(IRIS.Execute).%New()
```

正例：

```java
s mExecute = ##(IRIS.Execute).%New()
```

14. 不要将系统保留字或`SQL`保留字做为变量。

反例：

```java
s SQLCODE="0"
```

正例：

```java
s code = "0"
```

15. 对于调用其他方法获取返回值的变量，禁止使用`err`的名称，推荐`ret`。

反例：

```java
s errRet=##class(XXX).Save()
s retErr=##class(XXX).Save()
```

正例：

```java
s ret = ##class(XXX).Save()
```

16. 禁止变量超过`31`个字符。（局部变量名称限制为`31`个字符。可以指定长度超过`31`个字符的名称，但仅使用前`31`个字符。）

示例：

```java
ClassMethod Var()
{
	s abcdefghiklmnopqrstuvwxzy123456789 = "1"
	w abcdefghiklmnopqrstuvwxzy123456789,!
	
	s fitst = 1
	s fitstSum = fitst +abcdefghiklmnopqrstuvwxzy123456789
	w fitstSum,!
        
	s second = 2
	s abcdefghiklmnopqrstuvwxzy1234567891 = "2"
	w abcdefghiklmnopqrstuvwxzy1234567891,!
	
	s secondSum = second + abcdefghiklmnopqrstuvwxzy123456789
	w secondSum,!
	b
}
```

结果：

```java
DHC-APP>d ##class(M82).Var()
1
2
2
4
 
 b }
 ^
<BREAK>zVar+11^M82.1
DHC-APP 2d1>w
 
<Private variables>
abcdefghiklmnopqrstuvwxzy123456=2
fitst=1
fitstSum=2
second=2
secondSum=4
```

17. 百分比变量命名要以`%z`开头，避免与系统变量冲突。

反例：

```java
s %msg = ""
```

正例：

```java
s %zXX("XX") = ""
```

18. `.inc`文件里的通用变量，为了防止与系统变量重复。加上前缀标识。

反例：

```java
#define Error "XX"
```

正例：

```java
#define XXError "XX"
```

path: references/代码规范 - 方法.md
content: # 代码规范 - 方法

1. 类名、方法名使用`UpperCamelCase`风格。

反例：

```java
BS.iris.student
getname()
```

正例：

```java
BS.IRIS.Student
GetName()
```


2. 返回布尔类型方法以`Is`开头,例如是否存在。`ture`为`$$$YES`,`false`为`$$$NO`,方法后面加上 `As %Boolean`。

反例：

```java
GetExistFlag()
```

正例：

```java
ClassMethod IsExist(name) As %Boolean
{
	s bis = $o(^BS.IRIS.StudentD("Student", name, ""))
	q:(bis '= "") $$$YES	
	q $$$NO
}
```

调用：

```java
if(..IsExist(name)){
    // todo
}

```

```java
q:..IsExist(name)
```

```java
q:'..IsExist(name)
```

3. 推荐使用动宾结构，函数名应清晰反应函数的用途和功能。

反例：

```java
ObtainName()
```

正例：

```java
GetName()
```

4. 函数，方法名最长不超过`30`个字符。

反例：

```java
DefineDeliveryProcessEvent()
```

正例：

```java
SetDispEvent()
```

5. 每个方法对应一个词 `retrieve` 、`fetch`、  `find`、 `query` 都有查询意思，`manager`、`handler`、`controller`都有管理之意。我们只规定一种。查询就`Query`，获取数据就`Get`。

反例：

```java
ObtaionSomething()
RetrieveSomething()
```

正例：

```java
GetSomething()
QuerySomething()
```

6. 一个方法尽量控制在`50`行（一屏）。如果过于庞大，就该重构。庞大的方法容易引起阅读疲劳，让人抓不住重点。代码逻辑要分主次，个性，共性。

反例：

```java
ClassMethod Login(params)
{
    s info =""
	f  s info = $o(^IRIS("info", info)) q:info="" d
	.s flag = $p(^IRIS("info", info), "^", 1)
	.i flag = "Y" d
	.sql(insert .....)
}

```

正例：

```java
ClassMethod Login(params)
{
	s info =""
	for {
		s info = $o(^IRIS("info", info))
		q:(info = "")
		s flag = $p(^IRIS("info", info), "^", 1)
		s ret = ..IsFlag(flag)
		continue:(ret)
	}
}
ClassMethod IsFlag(flag) as %Boolean
{
	if flag = "Y" {
		s ret = ..InsSomeThing()
		q:(ret '= 0) $$$NO
	}
	q $$$YES
}
ClassMethod InsSomeThing(flag)
{
    sql(insert .....)
}
```

7. 方法内传递参数过多。考虑用对象方式来重构。

反例：

```java
ClassMethod Login(params)
{
    s startDate = $p(params, "^" ,1)
    s endDate = $p(params, "^" ,2)
    s locID = $p(params, "^" ,3)
    s userID = $p(params, "^" ,4)
    s groupID = $p(params, "^" ,5)
    s ret = ..DoSomeThing(startDate, endDate, locID, userID , groupID)
}
ClassMethod DoSomeThing(startDate, endDate, locID, userID , groupID)
{
    s status = $o(^IRIS("Flag",flag,""))
    s other = $o(^IRIS("userID",userID,""))
    s flag = $o(^IRIS("flag","")
  
    s ret = ..DoSomeThingSub(startDate, endDate, locID, userID , groupID, flag , status, other)
}
ClassMethod DoSomeThingSub(startDate, endDate, locID, userID , groupID, flag , status, other)
{
    //to do
}
```

正例：

```java
ClassMethod Login(params)
{
    s mLogin = ##class(PHA.OP.MOB.Login).%New()
    s mLogin.startDate = startDate
    s mLogin.endDate = endDate
    s mLogin.locID = locID
    s mLogin.userID = startDate
    s mLogin.groupID = groupID
    d mLogin.Login()
}
Class IRIS.Login
{
    //各种属性
}
```

9. 禁止在循环里直接写`sql`语句即`&sql()`，应把`sql`单独提出成方法。
- 禁止在公共查询里写涉及存储`sql`方法。
- `sql`语句应当单独建立类来保存，给予其他类调用。

反例：

```java
ClassMethod Login(params)
{
    s info =""
	f  s info = $o(^IRIS("info", info)) q:info="" d
	.s flag = $p(^IRIS("info", info), "^", 1)
	.sql(insert .....)
}

```

正例：

```java
ClassMethod Login(params)
{
    s info =""
	for {
		s info = $o(^IRIS("info", info))
		q:(info = "")
		s flag = $p(^IRIS("info", info), "^", 1)
		s ret = ..InsSomeThing(flag)
	}
}
ClassMethod InsSomeThing(flag)
{
    sql(insert .....)
}
```

10. 非普通字符串的入参或返回值需要进行声明，以明确数据类型，如数组、对象、流、引用，`%Status`等数据类型。

反例：

```java
/// desc: 入参为引用,返回为数组
classmethod Test(Param)
{
}
```

正例：

```java
/// desc: 入参为引用,返回为数组
classmethod Test(ByRef param) As %ArrayOfDataTypes
{
}
```

11. 当遇错误信息时，返回值不能单纯的返回负数，不能使用大于等于0的数值作为错误信息的标识。
- 字符串形式：负数^错误信息的格式

```java
q "-1^代码重复"
```
- `json`形式:

```java
q ..RetFail("代码重复")
```

```java
/// w ##class(M.M83).Save()
ClassMethod Save()
{
	s ret = ..InsData()
	q:(ret.code < 0 ) ret.msg
	q $$$OK
}

ClassMethod InsData()
{

	q ..RetFail("代码重复")
}

ClassMethod RetFail(msg)
{
	s obj = {}
	s obj.code = -1
	s obj.msg = msg
	q obj
}
```

- `%Status`形式：

```java
q $$$ERROR($$$GeneralError,"代码重复")
```

```java
/// w ##class(M.M83).SaveStauts()
ClassMethod SaveStauts() As %Status
{
	s sc = ..InsDataStauts()
	q:$$$ISERR(sc) $System.Status.GetOneStatusText(sc)
	q $$$OK
}

ClassMethod InsDataStauts() As %Status
{

	q $$$ERROR($$$GeneralError,"代码重复")
}

```




path: references/代码规范 - 格式.md
content: # 代码规范 - 格式

1.  方法大括号一律换行显示。

反例：

```java
SetDispEvent(){
    
}
```

正例：

```java
SetDispEvent()
{
    
}
```

1.  以下符号添加空格，美观代码，`=`、 `+`、 `-`、 `*`、 `/`、 `_`、 `:` 左右加空格，`,`之后加空格 。

反例：

```java
GetName(hour,number,year)
{
    s name=“yaoxin”
    s day=hour*number
    s sub=$o(^IRIS("DATE",day,hour,""))
}
```

正例：

```java
GetName(hour, number, year)
{
    s name = “yaoxin”
    s day = hour * number
    s sub = $o(^IRIS("DATE", day, hour, ""))
}
```

1.  方法内命令行均采用一个制表符`tab`缩进，宽度为四个空格宽度。**注意**是一个`tab`键，而不是按四次空格，可在`studio`设置（默认为4）

反例：

```java
GetName(hour,number)
{   
 s name=“yaoxin”
 s day=hour*number
 s sub=$o(^IRIS("DATE",day,hour,""))
}
```

正例：

```java
GetName(hour, number)
{
    s name = “yaoxin”
    s day = hour * number
    s sub = $o(^IRIS("DATE", day, hour, ""))
}
```

1.  `SQL`语句一行`5`个字段。并且换行后`3`个`tab`键为准。逗号在每行行末，不要带入下行开始。因为一行字符书不超过`120`个，即一屏。

注意：`sql`命令全部统一小写。

反例：

```java
ClassMethod InsBox(str As %String) As %Library.String
{
	&SQL(Insert Into DHC_PHBox (
			PHB_No, PHB_Num, PHB_Status, PHB_FLoc_Dr,PHB_TLoc_Dr,PHB_UserCreate_Dr,PHB_DateCreate, PHB_TimeCreate, PHB_PrintFlag, PHB_Remark) 
		values(
			:boxNo, 1, :status, :fromLocID, :toLocID,:userID, :date, :time, "Y", :remark))
	q SQLCODE
}
```

正例 `insert`：

```java
ClassMethod InsBox(str As %String) As %Library.String
{
	&SQL(
		insert into DHC_PHBox 
		(
			PHB_No, PHB_Num, PHB_Status, PHB_FLoc_Dr, PHB_TLoc_Dr,
			PHB_UserCreate_Dr, PHB_DateCreate, PHB_TimeCreate, PHB_PrintFlag, PHB_Remark
		) 
		values
		(
			:boxNo, 1, :status, :fromLocID, :toLocID,
			:userID, :date, :time, "Y", :remark
		)
	)
	q SQLCODE
}
```

正例 `update`：

```java
ClassMethod UpdMenu(arg...) As %Library.String
{
	&sql(
		update CT.IMP.Menu 
         set 
			CIM_Name = :name, CIM_Path = :path, CIM_Component = :component, CIM_Icon = :icon, CIM_OrderNum = :num
        	CIM_Status = :status,
		where 
			ID = :ID
    )
	q SQLCODE
}
```

正例 `delete`：

```java
ClassMethod DelMenu(arg...) As %Library.String
{
	&sql(
		delete BS_PHA_IN.BarCode 
		where 
        	 ID = :ID
	)
	q SQLCODE
}
```

1.  单行字符串拼写最多`5`个字段。因为一行字符书不超过`120`个，即一屏。

反例：

```java
ClassMethod GetString(str As %String) As %Library.String
{
	s str = first _ second _third _ fourth _ fifth _six
}
```

正例：

```java
ClassMethod InsBox(str As %String) As %Library.String
{
	s str = $lb("first", "second", "other", 4, "71")
	s str = str _ $lb("y", "x", "what", "apple", "sum")
	s str = $lts(str, "^")
	w str
}
```

1.  禁止用同一变量后加数字累加。

反例：

```java
ClassMethod GetString(str As %String) As %Library.String
{
    s str1 = first _ second _ third _ fourth _ fifth 
    s str2 = six
    s str = str1 _ str2
}
```

正例：

```java
ClassMethod GetString(str As %String) As %Library.String
{
   s str = first _ second _ third _ fourth _ fifth 
   s str = str _ six
}
```

1.  获取多返回值用数组`%ArrayOfDataTypes`或`JSON`点语法或其他对象数组，不建议使用字符串拼接形式。

反例：

```java
ClassMethod GetPatLocDesc(prescNo)
{
    s str = wardID _ "^" _ wardLocDR _ "^" _ patLocDesc 
	q str
}
```

正例：

```java
ClassMethod GetPatLocDesc(prescNo)
{
    s array = ##class(%ArrayOfDataTypes).%New()
	d array.SetAt(wardID, "wardID")
	d array.SetAt(wardLocDR, "wardLocDR")
	d array.SetAt(patLocDesc, "patLocDesc")
	q array
}
```

正例：

```java
ClassMethod GetPatLocDesc(prescNo)
{
    s obj = {}
    s obj.wardID = wardID
    s obj.wardLocDR = wardLocDR
    s obj.patLocDesc = patLocDesc
	q obj
}
```

1.  禁止系统命名混搭方法中出现`s`和 `set` 统一用命名缩写方式。

反例：

```java
ClassMethod GetPatLocDesc(prescNo)
{
    s str = “wardID”
    set patLocDesc = “病区”
    do ..GetName()
	q str
}
```

正例：

```java
ClassMethod GetPatLocDesc(prescNo)
{
    s str = “wardID”
    s patLocDesc = “病区”
    d ..GetName()
	q str
}
```

1.  禁止命令出现大小写，统一小写。

反例：

```java
ClassMethod GetName(userID)
{
    s name=“yaoxin”
    S age=30
}
```

正例：

```java
ClassMethod GetName(userID)
{
    s name = “yaoxin”
    s age = 30
}
```

1.  尽量使用对仗词。

```java
add/remove
open/close
get/set
start/end
insert/delete
show/hide
lock/unlock
first/last
next/previous
old/new
```

1.  禁止`{}`和`.`同时出现,推荐用使用块级语法，抛弃使用点语法。并且括号要对齐。

反例：

```java
ClassMethod GetName(userID)
{
    i flag="yx" d
    .i other = "other"{
        s name = “other” 
    }
    .s name = "yx"
}
```

正例：

```java
ClassMethod GetName(userID)
{
    if flag="yx" {
        if other = "other" {
            s name = “other” 
        }
        s name = "yx"
    }
}
```

1.  如果`if`语句只有一行，建议使用三元运算符。所有`if`语句都要换行写，即使只有一行。

反例：

```java
i name="yx" s age=30
e s age=0
```

正例：1

```java
i name = "yx" {
    s age = 30
} else {
    s age = 0
}
```

正例：2

```java
s age = $s(name = "yx" , 1 : 0)
```

1.  `if` 嵌套不宜过多，建议不超过3层。

反例：

```java
i name = "yx" d
.s state = 30
.i gender = "男" d
..s state = 20
..i age = "年轻人"
...s state = 10
e  d
.s state =0
```

正例：[用策略模式或状态模式封装](https://www.processon.com/view/5dd7deebe4b0d8a683f3e4aa#map)。

1.  多级`if else` 考虑用`$case`替换。

反例：

```java
i day =1 d
.s desc = "Monday"
e  i day =2 d
.s desc = "Tuesday"
e  i day =3 d
.s desc = "Wednesday"
```

正例：

```java
$CASE(day,
	1:"Monday",
	2:"Tuesday",
	3:"Wednesday",
	4:"Thursday",
	5:"Friday",
	6:"Saturday",
	7:"Sunday",
	:"entry error"
)
```

1.  与或逻辑运算统一使用`&&`、`||`，禁止使用其他`&`、`!`、`,`。

反例：

```java
s firstName = "Yao"
s lastNmae = "Xin"
if firstName = "Yao",lastNmae = "Xin" 
.w "true",!
e  d
.w "false",!
```

正例：

```java
	s firstName = "Yao"
	s lastNmae = "Xin"
	if (firstName = "Yao")&&(lastNmae = "Xin") {
		w "true",!
	} else {
		w "false",!
	}
```

1.  块级语法命令要全拼。例如`for`，`if`命令在块语法中不要缩写，这样语义更强。

反例：

```java
ClassMethod Login()
{
    s info =""
	f  s info = $o(^IRIS("info", info)) q:info="" d
	.s flag = $p(^IRIS("info", info), "^", 1)
	.i flag = "1" d
	..// todo 
}
```

正例：

```java
ClassMethod Login()
{
    s info = ""
	for {
		s info = $o(^IRIS("info", info))
		q:(info = "")
		s flag = $p(^IRIS("info", info), "^", 1)
		if (flag) {
			//to do 
		}
	}
}
```

1.  后置表达式要加括号,并且等号两侧加上空格。保持风格统一。

反例：

```java
q:info=""
```

正例：

```java
q:(info = "")
```

1.  **多条件后置表达式**（如 `continue:` `q:` `b:` 后的条件）：括号**内部**的条件运算符两侧**加空格**，括号与`&&`/`||`之间**不加空格**。例如：正例`)&&(`，反例`) && (`

反例：

```java
continue:(hospId'="") && (hospId'=($p(^CTLOC(locId),"^",22)))
q:(inci = "") && (arcim = "") && (phcdf = "")
```

正例：

```java
continue:(hospId '= "")&&(hospId '= ($p(^CTLOC(locId), "^", 22)))
q:(inci = "")&&(arcim = "")&&(phcdf = "")
```

**说明**：括号内的`=` `'=` 等运算符两侧加空格，但`)`与`&&`之间、`&&`与`(`之间不加空格。


path: references/代码规范 - 注释.md
content: # 代码规范 - 注释

1. 句首注释用`#; ` ，句尾注释用`//  ` ，头注释用`///` ，注意各类注释后应跟`空格`。

反例：

```java
// desc: 获取名称
///Input:	     用户ID
ClassMethod GetName(userID)
{
    //获取参数
    s userID = $p(params, "#", 1)  ;用户ID
}
```

正例：

```java
/// desc: 获取名称
ClassMethod GetName(params)
{
    #; 获取参数
    s userID = $p(params, "#", 1) // 用户ID
}
```


2. 避免无意义注释，尽量用规范的代码命名语言去描述。不要浪费大量时间在毫无意义的注释上。**简明扼要，不要啰嗦，注释应当画龙点睛。**

反例：

```java
/// Description: 获取名称
/// Input:	     用户ID
ClassMethod GetName(userID)
{
}
```

正例：无须注释。

```java
ClassMethod GetName(userID)
{
}
```

3. 所有类加上创建者和日期，创建者应为姓名的全拼，避免出现`yx`等简写或其他英文名，并简易说明类用途。

反例：

```java
Class IRIS.MOB.API Extends IRIS.MOB.Biz
```

正例：

```java
/// desc: 煎药室接口
/// author：yaoxin
/// date：2022-08-12
Class IRIS.MOB.API Extends IRIS.MOB.Biz
```

4. 避免错误注释误导。可能由于复制过来方法，没有改注释。这样的注释后期开发人员困惑性极大。

反例：

```java
/// Description: 获取年龄
/// Input:	     科室ID
ClassMethod GetName(userID)
{
}
```

正例：

```java
ClassMethod GetName(userID)
{
}
```

6. 方法的完整注释，关于接口中的方法以及存储数据核心方法(如门诊发药)，应给与完整注释以及修改记录等。

```java
/// desc: 住院是否存在未退药,提前退费已退
/// author: name
/// date: 2022-09-12
/// params: name - 姓名, age - 年轻
/// retrun: 输出说明
/// version: V7~V8.3+
/// caller: 医生，护士，计费
/// modify: 增加急诊留观判断, 2020-02-01, name
/// debug:w ##class(XXX).XX(xxx)
```


path: references/代码规范 - 空行.md
content: # 代码规范 - 空行

1.  方法与方法之间进行空行隔断。(1个空行)

反例：

```java
Method GetName()
{
	...
}
Method GetAge()
{
	...
}
```

正例：

```java

Method GetName()
{
	...
}

Method GetAge()
{
	...
}

```

1.  空行用来分割功能相似，逻辑内容，意思相近的代码片段，使程序布局更加清晰。

反例：

```java
ClassMethod Execute(params)
{
	s $zt="ErrExecute"
	s prescNo = $p(params, ..#Del, 1)
	s exeCode = $p(params, ..#Del, 2)	
	s userID = $p(params, ..#Del, 3)
	s locID = $p(params, ..#Del, 4)
	TSTART
	s mExecute = ##class(PHA.DEC.MOB.Execute).%New(prescNo, exeCode, userID, locID)
	s ret = mExecute.Execute()
	i ret '= 0 TROLLBACK
	q:(ret '= 0) ..RetFail(ret)
	TCOMMIT
	s rows = ..GetPrescDetail(prescNo)
	s objectJson = ..GetPrescData(prescNo)
	s objectJson.rows = rows
	q ..RetObject(objectJson)
ErrExecute
	q ..RetFail($ze)
}
```

正例：

```java
ClassMethod Execute(params)
{
	s $zt="Error"
	
	s prescNo = $p(params, ..#Del, 1)
	s exeCode = $p(params, ..#Del, 2)	
	s userID = $p(params, ..#Del, 3)
	s locID = $p(params, ..#Del, 4)
	
	ts
	s mExecute = ##class(PHA.DEC.MOB.Execute).%New(prescNo, exeCode, userID, locID)
	s ret = mExecute.Execute()
	i ret '= 0 TROLLBACK
	q:(ret '= 0) ..RetFail(ret)
	tc
	
	s rows = ..GetPrescDetail(prescNo)
	s objectJson = ..GetPrescData(prescNo)
	s objectJson.rows = rows
	
	q ..RetObject(objectJson)
	
Error
	q ..RetFail($ze)
}

```

1.  基于第2点，空行之前添加行注释也要空行，并且行注释`#; 说明`。

*   注意：`*`空格的位置。

反例：

```java
ClassMethod Execute(params)
{
	s $zt="ErrExecute"
	s prescNo = $p(params, ..#Del, 1)
	s exeCode = $p(params, ..#Del, 2)	
	s userID = $p(params, ..#Del, 3)
	s locID = $p(params, ..#Del, 4)
	TSTART
	s mExecute = ##class(PHA.DEC.MOB.Execute).%New(prescNo, exeCode, userID, locID)
	s ret = mExecute.Execute()
	i ret '= 0 TROLLBACK
	q:(ret '= 0) ..RetFail(ret)
	TCOMMIT
	s rows = ..GetPrescDetail(prescNo)
	s objectJson = ..GetPrescData(prescNo)
	s objectJson.rows = rows
	q ..RetObject(objectJson)
ErrExecute
	q ..RetFail($ze)
}
```

正例：

```java
ClassMethod Execute(params)
{
	s $zt="Error"
	
	#; 获取入参
	s prescNo = $p(params, ..#Del, 1)
	s exeCode = $p(params, ..#Del, 2)	
	s userID = $p(params, ..#Del, 3)
	s locID = $p(params, ..#Del, 4)
	
	#; 执行方法
	ts
	s mExecute = ##class(PHA.DEC.MOB.Execute).%New(prescNo, exeCode, userID, locID)
	s ret = mExecute.Execute()
	i ret '= 0 TROLLBACK
	q:(ret '= 0） ..RetFail(ret)
	tc
	
	#; 获取json
	s rows = ..GetPrescDetail(prescNo)
	s objectJson = ..GetPrescData(prescNo)
	s objectJson.rows = rows
	
	#; 返回json
	q ..RetObject(objectJson)
	
Error
	q ..RetFail($ze)
}

```

1.  事务首尾先后一定要加空行或注释，代表强调。



path: references/代码规范 - 锁.md
content: # 代码规范 - 锁

# 锁

1. 禁止直接锁表结构的`Global`。

反例：

```java

l +^BS.IRIS.StudentD

```


2. 加解锁必须加`+`、`-`严格控制，必须成对出现。

反例：

```java

l +^BS.IRIS.Student(1)
l +^BS.IRIS.Student(1)

l -^BS.IRIS.Student(1)

```

正例：

```java
l +^BS.IRIS.Student(1):3
l -^BS.IRIS.Student(1):3

l +^BS.IRIS.Student(1):3
l -^BS.IRIS.Student(1):3
```

3. 加锁必须要带`+`，否则导致解锁进程内所有锁。

反例：

```java

l +^BS.IRIS.Student1(1)
l +^BS.IRIS.Student2(1)
l ^BS.IRIS.Student3(1)


```

正例：

```java
l +^BS.IRIS.Student1(1):3
l +^BS.IRIS.Student2(1):3
l +^BS.IRIS.Student3(1):3
```

4. 加锁必须写超时的退出，避免死锁，造成进程无限期阻塞。

正例：

```java
l +^BS.IRIS.Student:3
```

5. 自定义功能锁：`^产品组代码(产品线,规范代码:唯一标识)`（例如：单号）。

反例：

```java
l ^TMPOP(lockName)
```

正例：

```java
l +^IRIS("BIZ", "BOXNO:" _ boxNo):5 
```

6. 私有进程全局变量名不能用作锁名。

反例：

```java
l +^||BS.IRIS.Student(1):3
```

正例：

```java
l +^BS.IRIS.Student(1):3
```

7. 禁止单独在程序中使用无参数锁。


反例：

```java
lock
```

8. 使用锁时一定要下标节点。


反例：

```java

l +^BS.IRIS.Student

```

正例：

```java
l +^BS.IRIS.Student(1):3
```

path: references/代码规范 - 陷阱.md
content: # 代码规范 - 陷阱

1. **严格禁止**陷阱内部报错导致死进程。

反例：

```java
/// d ##class(M.M87).Save()
ClassMethod Save()
{
	s $zt = "Error"
	
Error
	s color = red
	q $ze
}

```

正例：

```java
/// d ##class(M.M87).Save()
ClassMethod Save()
{
	s $zt = "Error"
	
Error
    // 禁止写业务逻辑
	q $ze
}
```



2. 如果类为`Not ProcedureBlock` ,陷阱名称统一为 `Err + 方法名`。

反例：

```java
ClassMethod Save()
{
	s $zt="Save"
	...
Save
	...
}
```

正例：

```java
ClassMethod Save()
{
	s $zt="ErrSave"
	...
ErrSave
	...
}
```

3. 默认类陷阱名称统一为`Error`，**注意通用陷阱写法。**

```java
ClassMethod CommonZtrap() As %String
{
	s $zt = "Error"

	// todo	

	q ""
Error
	s $zt = ""	/* 避免死循环 */
	i $tl >0 tro	/* 避免开放性事务 */
	lock	/* 避免开放锁 */
	q $ze
}
```

Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)