M通用版代码规范 - 持续更新

Posted yaoxin521123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了M通用版代码规范 - 持续更新相关的知识,希望对你有一定的参考价值。

文章目录

M通用版代码规范 - 持续更新

变量

  1. 代码中的命名均不能$#等特殊符号开始或结束,因为$#等是系统方法、变量,禁止混淆。

反例:

$name
_name

正例:

name
  1. 严禁代码中使用拼音与英文混合方式命名,更不允许直接使用中文。

反例:

Dazhe 
getDZname
[打折]

正例:

discount
getDiscountName
  1. 参数名、成员变量、局部变量都统一使用lowerCamelCase风格。

反例:

Params

正例:

params
  1. 常量命名全部大写。力求完整语义表达清楚,不要嫌长。

反例:

MaxCount = 10

正例:

MAXCOUNT = 10
  1. 杜绝不规范缩写,避免词不达意。

反例:

com
condi

正例:

complete
condition
  1. 长度为7个以内单词不需要缩写,当变量长度过长时需考虑缩写,且缩写应为常用正规缩写,避免无意义缩写。

反例:

st
nb

正例:

start
number
num
  1. 避免无意义变量。

反例:

s a = "1"
s b = "2"
s c = a * b

正例:

s fitstNum = "1"
s secondNum = "2"
s sum = firstNum * secondNum
  1. 临时global、进程global命名严格使用^TMP^||TMP,且携带pid。格式为领域名 + 类名 + 方法 + pid + 标识
  • 提前把TMP开头的global名称配置到临时TEMP命名空间,配置不写日志。

反例:

s ^||YX("TMP", pid, "Login")

正例:

s ^||TMP("IRIS", "IRIS.MOB.Base", "Login", pid)
  1. 布尔变量不要用is开头,因为其他框架引用的话会解析错误。例如JavaGetter的方法也叫isDisp()

反例:

isDisp

正例:

dispFlag
  1. 所有表的ID,都用表的前缀。

反例:

  • BS_IRIS_StudentID
  • CF_IRIS_ConfigconfigID

正例:

  • BS_IRIS_Studentbis
  • CF_IRIS_Configcic
  1. 所有引用global数据的变量,用表ID + data方式命名,多节点用ID + 节点 + Data方式。

反例:

s data=^BS.IRIS.StudentD(inci)

正例:

s bisData = ^BS.IRIS.StudentD(inci)
  1. 方法中仅出现一次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)

  1. 创建的私有对象可以加m,例如有Execute类的初始化对象。

反例:

s execute = ##(IRIS.Execute).%New()

正例:

s mExecute = ##(IRIS.Execute).%New()
  1. 不要将系统保留字或SQL保留字做为变量。

反例:

s SQLCODE="0"

正例:

s code = "0"
  1. 对于调用其他方法获取返回值的变量,禁止使用err的名称,推荐ret

反例:

s errRet=##class(XXX).Save()
s retErr=##class(XXX).Save()

正例:

s ret = ##class(XXX).Save()
  1. 禁止变量超过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
  1. 百分比变量命名要以%z开头,避免与系统变量冲突。

反例:

s %msg = ""

正例:

s %zXX("XX") = ""
  1. .inc文件里的通用变量,为了防止与系统变量重复。加上前缀标识。

反例:

#define Error "XX"

正例:

#define XXError "XX"

方法

  1. 类名、方法名使用UpperCamelCase风格。

反例:

BS.iris.student
getname()

正例:

BS.IRIS.Student
GetName()
  1. 返回布尔类型方法以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)
  1. 推荐使用动宾结构,函数名应清晰反应函数的用途和功能。

反例:

ObtainName()

正例:

GetName()
  1. 函数,方法名最长不超过30个字符。

反例:

DefineDeliveryProcessEvent()

正例:

SetDispEvent()
  1. 每个方法对应一个词 retrievefetchfindquery 都有查询意思,managerhandlercontroller都有管理之意。我们只规定一种。查询就Query,获取数据就Get

反例:

ObtaionSomething()
RetrieveSomething()

正例:

GetSomething()
QuerySomething()
  1. 一个方法尽量控制在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 .....)

  1. 方法内传递参数过多。考虑用对象方式来重构。

反例:

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

    //各种属性

  1. 禁止在循环里直接写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 .....)

  1. 非普通字符串的入参或返回值需要进行声明,以明确数据类型,如数组、对象、流、引用,%Status等数据类型。

反例:

/// desc: 入参为引用,返回为数组
classmethod Test(Param)


正例:

/// desc: 入参为引用,返回为数组
classmethod Test(ByRef param) As %ArrayOfDataTypes


  1. 当遇错误信息时,返回值不能单纯的返回负数,不能使用大于等于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,"代码重复")


  1. 全部类以IRIS.XX开头。

反例:

Class XXX.XXX.XX

正例:

Class IRIS.XXX.XX
  1. 所有类里的方法,方法顺序按照常用顺序排序,最常用的最在上,依次。
  2. 类默认均为ProcedureBlock,禁止Not ProcedureBlock,如需使用特殊字符@等,单独建类或方法并定义Not ProcedureBlock

反例:

Class IRIS.Login Extends %RegisteredObject  [not ProcedureBlock]

正例:

Class IRIS.Login Extends %RegisteredObject

  1. 禁止直接锁表结构的Global

反例:


l +^BS.IRIS.StudentD

  1. 加解锁必须加+-严格控制,必须成对出现。

反例:


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
  1. 加锁必须要带+,否则导致解锁进程内所有锁。

反例:


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
  1. 加锁必须写超时的退出,避免死锁,造成进程无限期阻塞。

正例:

l +^BS.IRIS.Student:3
  1. 自定义功能锁:^产品组代码(产品线,规范代码:唯一标识)(例如:单号)。

反例:

l ^TMPOP(lockName)

正例:

l +^IRIS("BIZ", "BOXNO:" _ boxNo):5 
  1. 私有进程全局变量名不能用作锁名。

反例:

l +^||BS.IRIS.Student(1):3

正例:

l +^BS.IRIS.Student(1):3
  1. 禁止单独在程序中使用无参数锁。

反例:

lock
  1. 使用锁时一定要下标节点。

反例:


l +^BS.IRIS.Student

正例:

l +^BS.IRIS.Student(1):3

事务

  1. 严格禁止开放性事务。

反例:

ClassMethod Save()

	tstart

正例:

ClassMethod Save()

	ts
	
	tc //或 tro 

  1. 事务tstctro的位置应保持近距离,在一屏幕范围内,避免位置过远。代码过多应当提取成方法,让事务看起来简洁、语义明朗。

反例:

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
	

  1. 严格禁止跨方法提交事务。

反例:

ClassMethod Save()

	ts
	s sc = ..InsMain()


ClassMethod InsMain()

	// todo
	tc


正例:

ClassMethod Save()

	ts
	
	s sc = ..InsMain()

	tc
	
	q sc


ClassMethod InsMain() as %Status

	// todo


  1. 为明确显示事务,事务命令需要简写并且小写

反例:

ClassMethod Save()

	TSTART
	...
	TCOMMIT

正例:

ClassMethod Save()

	ts
	
	... // todo
	
	tc

  1. 同一个方法内不应该出现事务嵌套的现象。

反例:

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通用版代码规范 - 持续更新的主要内容,如果未能解决你的问题,请参考以下文章

Verilog代码规范(持续更新)

Markdown 和 LaTeX 写作规范(持续更新,建议收藏)

Markdown 和 LaTeX 写作规范(持续更新,建议收藏)

Markdown 和 LaTeX 写作规范(持续更新,建议收藏)

代码规范

《通用规范汉字表》2013版