M通用版代码规范 - 持续更新
Posted yaoxin521123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了M通用版代码规范 - 持续更新相关的知识,希望对你有一定的参考价值。
文章目录
M通用版代码规范 - 持续更新
变量
- 代码中的命名均不能
$
、#
等特殊符号开始或结束,因为$
、#
等是系统方法、变量,禁止混淆。
反例:
$name
_name
正例:
name
- 严禁代码中使用拼音与英文混合方式命名,更不允许直接使用中文。
反例:
Dazhe
getDZname
[打折]
正例:
discount
getDiscountName
- 参数名、成员变量、局部变量都统一使用
lowerCamelCase
风格。
反例:
Params
正例:
params
- 常量命名全部大写。力求完整语义表达清楚,不要嫌长。
反例:
MaxCount = 10
正例:
MAXCOUNT = 10
- 杜绝不规范缩写,避免词不达意。
反例:
com
condi
正例:
complete
condition
- 长度为7个以内单词不需要缩写,当变量长度过长时需考虑缩写,且缩写应为常用正规缩写,避免无意义缩写。
反例:
st
nb
正例:
start
number
num
- 避免无意义变量。
反例:
s a = "1"
s b = "2"
s c = a * b
正例:
s fitstNum = "1"
s secondNum = "2"
s sum = firstNum * secondNum
- 临时
global
、进程global
命名严格使用^TMP
、^||TMP
,且携带pid
。格式为领域名 + 类名 + 方法 + pid + 标识
。
- 提前把
TMP
开头的global
名称配置到临时TEMP
命名空间,配置不写日志。
反例:
s ^||YX("TMP", pid, "Login")
正例:
s ^||TMP("IRIS", "IRIS.MOB.Base", "Login", pid)
- 布尔变量不要用
is
开头,因为其他框架引用的话会解析错误。例如Java
的Getter
的方法也叫isDisp()
。
反例:
isDisp
正例:
dispFlag
- 所有表的
ID
,都用表的前缀。
反例:
BS_IRIS_Student
:ID
CF_IRIS_Config
:configID
正例:
BS_IRIS_Student
:bis
CF_IRIS_Config
:cic
- 所有引用
global
数据的变量,用表ID + data
方式命名,多节点用ID + 节点 + Data
方式。
反例:
s data=^BS.IRIS.StudentD(inci)
正例:
s bisData = ^BS.IRIS.StudentD(inci)
- 方法中仅出现一次
dataStr
分割字符串分割索引均为i
长度均为len
。
反例:
s prescNolen=$l(prescNoStr, ",")
f index = 1 : 1 : len q:ret'=0 d
.s prescNo = $p(prescNoStr, ",", index)
正例:
s len = $l(prescNoStr, ",")
for i = 1 : 1 : len
s prescNo = $p(prescNoStr, ",", i)
- 创建的私有对象可以加
m
,例如有Execute
类的初始化对象。
反例:
s execute = ##(IRIS.Execute).%New()
正例:
s mExecute = ##(IRIS.Execute).%New()
- 不要将系统保留字或
SQL
保留字做为变量。
反例:
s SQLCODE="0"
正例:
s code = "0"
- 对于调用其他方法获取返回值的变量,禁止使用
err
的名称,推荐ret
。
反例:
s errRet=##class(XXX).Save()
s retErr=##class(XXX).Save()
正例:
s ret = ##class(XXX).Save()
- 禁止变量超过
31
个字符。(局部变量名称限制为31
个字符。可以指定长度超过31
个字符的名称,但仅使用前31
个字符。)
示例:
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
结果:
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
- 百分比变量命名要以
%z
开头,避免与系统变量冲突。
反例:
s %msg = ""
正例:
s %zXX("XX") = ""
.inc
文件里的通用变量,为了防止与系统变量重复。加上前缀标识。
反例:
#define Error "XX"
正例:
#define XXError "XX"
方法
- 类名、方法名使用
UpperCamelCase
风格。
反例:
BS.iris.student
getname()
正例:
BS.IRIS.Student
GetName()
- 返回布尔类型方法以
Is
开头,例如是否存在。ture
为$$$YES
,false
为$$$NO
,方法后面加上As %Boolean
。
反例:
GetExistFlag()
正例:
ClassMethod IsExist(name) As %Boolean
s bis = $o(^BS.IRIS.StudentD("Student", name, ""))
q:(bis '= "") $$$YES
q $$$NO
调用:
if(..IsExist(name))
// todo
q:..IsExist(name)
q:'..IsExist(name)
- 推荐使用动宾结构,函数名应清晰反应函数的用途和功能。
反例:
ObtainName()
正例:
GetName()
- 函数,方法名最长不超过
30
个字符。
反例:
DefineDeliveryProcessEvent()
正例:
SetDispEvent()
- 每个方法对应一个词
retrieve
、fetch
、find
、query
都有查询意思,manager
、handler
、controller
都有管理之意。我们只规定一种。查询就Query
,获取数据就Get
。
反例:
ObtaionSomething()
RetrieveSomething()
正例:
GetSomething()
QuerySomething()
- 一个方法尽量控制在
50
行(一屏)。如果过于庞大,就该重构。庞大的方法容易引起阅读疲劳,让人抓不住重点。代码逻辑要分主次,个性,共性。
反例:
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 .....)
正例:
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 .....)
- 方法内传递参数过多。考虑用对象方式来重构。
反例:
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
正例:
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
//各种属性
- 禁止在循环里直接写
sql
语句即&sql()
,应把sql
单独提出成方法。
- 禁止在公共查询里写涉及存储
sql
方法。 sql
语句应当单独建立类来保存,给予其他类调用。
反例:
ClassMethod Login(params)
s info =""
f s info = $o(^IRIS("info", info)) q:info="" d
.s flag = $p(^IRIS("info", info), "^", 1)
.sql(insert .....)
正例:
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 .....)
- 非普通字符串的入参或返回值需要进行声明,以明确数据类型,如数组、对象、流、引用,
%Status
等数据类型。
反例:
/// desc: 入参为引用,返回为数组
classmethod Test(Param)
正例:
/// desc: 入参为引用,返回为数组
classmethod Test(ByRef param) As %ArrayOfDataTypes
- 当遇错误信息时,返回值不能单纯的返回负数,不能使用大于等于0的数值作为错误信息的标识。
- 字符串形式:负数^错误信息的格式
q "-1^代码重复"
json
形式:
q ..RetFail("代码重复")
/// 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
形式:
q $$$ERROR($$$GeneralError,"代码重复")
/// 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,"代码重复")
类
- 全部类以
IRIS.XX
开头。
反例:
Class XXX.XXX.XX
正例:
Class IRIS.XXX.XX
- 所有类里的方法,方法顺序按照常用顺序排序,最常用的最在上,依次。
- 类默认均为
ProcedureBlock
,禁止Not ProcedureBlock
,如需使用特殊字符@
等,单独建类或方法并定义Not ProcedureBlock
。
反例:
Class IRIS.Login Extends %RegisteredObject [not ProcedureBlock]
正例:
Class IRIS.Login Extends %RegisteredObject
锁
- 禁止直接锁表结构的
Global
。
反例:
l +^BS.IRIS.StudentD
- 加解锁必须加
+
、-
严格控制,必须成对出现。
反例:
l +^BS.IRIS.Student(1)
l +^BS.IRIS.Student(1)
l -^BS.IRIS.Student(1)
正例:
l +^BS.IRIS.Student(1):3
l -^BS.IRIS.Student(1):3
l +^BS.IRIS.Student(1):3
l -^BS.IRIS.Student(1):3
- 加锁必须要带
+
,否则导致解锁进程内所有锁。
反例:
l +^BS.IRIS.Student1(1)
l +^BS.IRIS.Student2(1)
l ^BS.IRIS.Student3(1)
正例:
l +^BS.IRIS.Student1(1):3
l +^BS.IRIS.Student2(1):3
l +^BS.IRIS.Student3(1):3
- 加锁必须写超时的退出,避免死锁,造成进程无限期阻塞。
正例:
l +^BS.IRIS.Student:3
- 自定义功能锁:
^产品组代码(产品线,规范代码:唯一标识)
(例如:单号)。
反例:
l ^TMPOP(lockName)
正例:
l +^IRIS("BIZ", "BOXNO:" _ boxNo):5
- 私有进程全局变量名不能用作锁名。
反例:
l +^||BS.IRIS.Student(1):3
正例:
l +^BS.IRIS.Student(1):3
- 禁止单独在程序中使用无参数锁。
反例:
lock
- 使用锁时一定要下标节点。
反例:
l +^BS.IRIS.Student
正例:
l +^BS.IRIS.Student(1):3
事务
- 严格禁止开放性事务。
反例:
ClassMethod Save()
tstart
正例:
ClassMethod Save()
ts
tc //或 tro
- 事务
ts
、tc
、tro
的位置应保持近距离,在一屏幕范围内,避免位置过远。代码过多应当提取成方法,让事务看起来简洁、语义明朗。
反例:
ClassMethod Save()
ts
/* 添加主表信息 */
// todo 50行代码
/* 添加明细信息 */
// todo 100行代码
tc
正例:
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
- 严格禁止跨方法提交事务。
反例:
ClassMethod Save()
ts
s sc = ..InsMain()
ClassMethod InsMain()
// todo
tc
正例:
ClassMethod Save()
ts
s sc = ..InsMain()
tc
q sc
ClassMethod InsMain() as %Status
// todo
- 为明确显示事务,事务命令需要简写并且小写。
反例:
ClassMethod Save()
TSTART
...
TCOMMIT
正例:
ClassMethod Save()
ts
... // todo
tc
- 同一个方法内不应该出现事务嵌套的现象。
反例:
ClassMethod Save()
ts
ts
... // todo
tro
tc
... // todo
ts
tc
数据结构(C语言版)严蔚敏(线性表队列栈数组树图等数据结构参考代码,持续更新中。。。)
前言:本篇文章主要提供相关数据结构的实现的参考代码
1. 线性表
线性表的顺序存储(顺序表)和链式存储(链表)
1.1 顺序表
头文件:SqList.h
#ifndef SQLIST_H_INCLUDED
#define SQLIST_H_INCLUDED
#define LIST_INIT_SIZE 100
// 顺序表初始大小
#define LISTINCREMENT 10
// 超出当前顺序表容量时增加的容量大小
typedef int ElemType;
typedef struct
ElemType *data;
// 动态分配数组指针
int length,MaxSize;
SqList;
void InitList_Sq(SqList &L);
// 构造一个空的顺序表L
void DestroyList_Sq(SqList &L);
// 销毁顺序表L
void ClearList_Sq(SqList &L);
// 将顺序表L重置为空
bool ListEmpty_Sq(SqList L);
// 判断顺序表L是否为空
int ListLength_Sq(SqList L);
// 返回顺序表L中数据元素的个数
bool GetElem_Sq(SqList L,int pos,int &e);
// 用e返回顺序表L中第pos个数据元素的值
bool ListInsert_Sq(SqList &L,int pos,int e);
// 在顺序表L中第pos个位置之前插入新的元素e
bool ListDelete_Sq(SqList &L,int pos,int &e);
// 删除顺序表L的第pos个数据元素,并用e返回
int LocateElem_Sq(SqList L,int e);
// 返回顺序表L中第一个与e相等的数据元素的位序
#endif // SQLIST_H_INCLUDED
其他文件:SqList.cpp
#include "SqList.h"
#include <stdlib.h>
void InitList_Sq(SqList &L)
L.data = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if(!L.data)
exit(-1);
L.length = 0;
L.MaxSize = LIST_INIT_SIZE;
void DestroyList_Sq(SqList &L)
free(L.data);
// 释放data所指向的内存空间
L.data = NULL;
L.length = 0;
L.MaxSize = 0;
void ClearList_Sq(SqList &L)
L.length = 0;
bool ListEmpty_Sq(SqList L)
return L.length == 0;
int ListLength_Sq(SqList L)
return L.length;
bool GetElem_Sq(SqList L,int pos,int &e)
if(pos<1 || pos>L.length)
return false;
e = L.data[pos-1];
return true;
bool ListInsert_Sq(SqList &L,int pos,int e)
if(pos<1 || pos >L.length + 1)
return false;
if(L.length >= L.MaxSize)
ElemType *newbase = (ElemType *)realloc(L.data,(L.MaxSize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase)
exit(-1);
L.MaxSize += LISTINCREMENT;
ElemType *p = &(L.data[pos-1]);
for(ElemType *p1 = &(L.data[L.length-1]);p1>=p;p1--)
*(p1+1) = *p1;
*p = e;
// 用指针实现
/*for(int i = L.length-1;i>=pos;i--)
L.data[i+1] = L.data[i];
L.[pos-1] = e;*/
++ L.length;
return true;
bool ListDelete_Sq(SqList &L,int pos,int &e)
if(pos<1 || pos>L.length)
return false;
ElemType *p = &(L.data[pos-1]);
e = *p;
/*for(int i = pos;i<L.length;i++)
L.data[i-1] = L.data[i];*/
for(;p<&(L.data[L.length-1]);p++)
*p = *(p+1);
-- L.length;
return true;
int LocateElem_Sq(SqList L,int e)
for(int i=0;i<L.length;i++)
if(L.data[i] == e)
return i+1;
return -1;
主文件:main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "SqList.h"
void Print_SqList(SqList L)
ElemType e;
for(int i=0;i<L.length;i++)
GetElem_Sq(L,i+1,e);
printf("%d ",e);
int main()
SqList Sq;
InitList_Sq(Sq);
for(int i=0;i<200;i++)
ListInsert_Sq(Sq,i+1,i+1);
ListInsert_Sq(Sq,100,300);
Print_SqList(Sq);
ElemType e;
e = LocateElem_Sq(Sq,300);
printf("\\n%d\\n",e);
Print_SqList(Sq);
ListDelete_Sq(Sq,100,e);
printf("\\n%d\\n",e);
Print_SqList(Sq);
return 0;
运行结果:
关于运行结果的解释:先在顺序表中插入1-200这些数,然后在顺序表下标为100处插入数据元素300,最后将顺序表下标为100的数据元素删除。
1.2 链表
以上是关于M通用版代码规范 - 持续更新的主要内容,如果未能解决你的问题,请参考以下文章
Markdown 和 LaTeX 写作规范(持续更新,建议收藏)
Markdown 和 LaTeX 写作规范(持续更新,建议收藏)