猪懂傻改之《powershell 代码规范》
脚本程序员或许都经历过这样的场景:
接手别人的代码时,因为没有注释,变量名五花八门,模块之间逻辑关系如麻,
弄得满头雾水,一脸茫然,痛定思痛之后不得不推倒重来,这些都是不注重编程规范造成的,事倍功半。
国内的开发者大多重技能,轻规范。
此前有这么一个段子,程序员A和B,
A每天只写100行代码,字里行间规范清晰,其余大部分时间都在整理文档,备注的非常详细,
B每天写50000行代码,却很少写注释,天马行空,为此还嘲笑A不够高效。
随着业务越来越复杂,客户需求随时可变,两个人都开始组建团队,这个时候,功夫不负苦心人,A之前的努力都派上了用场,B只能佩服加惭愧。
此前有这么一个段子,程序员A和B,
A每天只写100行代码,字里行间规范清晰,其余大部分时间都在整理文档,备注的非常详细,
B每天写50000行代码,却很少写注释,天马行空,为此还嘲笑A不够高效。
随着业务越来越复杂,客户需求随时可变,两个人都开始组建团队,这个时候,功夫不负苦心人,A之前的努力都派上了用场,B只能佩服加惭愧。
可见,编程规范,对于程序员而言,不是要靠强制约束,更关键的还是要让其从认知,思想觉悟上提高,骨子里意识到规范也是一种生产力。
powershell 传教士 原创文章。始于 2015-11-08 允许转载,但必须保留名字和出处,否则追究法律责任
欢迎斧正 补充
---【原则】---
powershell属于脚本范畴。脚本是由运维人员,用户,技术员编写的小程序。
这些个人,不是专业开发人员,没有系统学习过开发,只能说是散兵游勇小程序员。
一个运维/用户级别的写代码者,他的逻辑思维,他对语言、架构都熟悉度,都不如专业码农的。
而脚本小程序员的代码规范,是比c,c++,java宽松多的。
爱powershell,就写让别人能读懂的代码,爱powershell,就写【猪懂傻改】代码!
最求直观,容易理解,而不追求短小。
大数据追求节省空间(即不浪费内存),
cpu密集型追求快(即节省cpu),
行列整齐数据尽量用excel表,sqlite,access,mysql,sql server这些数据库存。
---【经验】---
尽量只做搬运工。2.1写脚本或函数前,先搜。或者估计是否有前人写好了。
2.2写数据结构前,先搜对象。基本上我们需要的所有的数据结构,已经有人写好了,并封装成类和对象了,而且其代码已历经多年的测试和再测试。
菜鸟问:如何写脚本?
老鸟答:
1 必须搞清楚问题细节。这是最重要的。
2 解题思路也基本完成。
前两条不透彻,不应该开始写脚本。
3 先粗写,写个大概。
4 调试通过。
5 详细写。考虑出错情况,加上错误代码,错误信息。去掉容易出错,不容易兼容的代码。改写性能不佳的代码。
6 精雕细琢。重构,把重复使用的代码段,写成函数。重写变量名,使人能一眼看懂。格式化好代码,搞好缩进。
---【第一章 为了容易读懂,容易分享】---
1.1 脚本文件名用中文写上功能。或脚本前几行,用中文写上注释,写上功能,和程序大致逻辑。
1.2 脚本中用命令全写,不用简写,不用alias,用$true而不是‘1’。
1.3 拒绝注释,尽量用变量名代替注释。如果你正在试图写一段注释,从某种角度来看,你正在试图写一段别人无法理解的代码。
有些人以为写很多注释就可以让代码更加可读,然而却发现事与愿违。注释不但没能让代码变得可读,反而由于大量的注释充斥在代码中间,让程序变得障眼难读。
而且代码的逻辑一旦修改,就会有很多的注释变得过时,需要更新。修改注释是相当大的负担,所以大量的注释,反而成为了妨碍改进代码的绊脚石。
有些人以为写很多注释就可以让代码更加可读,然而却发现事与愿违。注释不但没能让代码变得可读,反而由于大量的注释充斥在代码中间,让程序变得障眼难读。
而且代码的逻辑一旦修改,就会有很多的注释变得过时,需要更新。修改注释是相当大的负担,所以大量的注释,反而成为了妨碍改进代码的绊脚石。
1.4 避免茴香豆,尽量不搞幺蛾子。
---【茴香豆】又称【幺蛾子】---可以运行,但不容易理解的,n种语法变体。
本人新发明格言:【语法糖】让语言更好,【幺蛾子】【语法屎】【茴香豆】让语言更糟!
孔乙己道:“茴香豆的‘茴’字,共有4万种写法,来来来,让我给你一一道来。。。”---实际上孔乙己是为了骗指甲盖中的酒。
powershell传教士道:“滚!我没有必要浪费脑筋学4万种雷同语法,我只需要一种最简单最直接,大家都能看懂的写法。”
---【茴香豆】又称【幺蛾子】---可以运行,但不容易理解的,n种语法变体。
本人新发明格言:【语法糖】让语言更好,【幺蛾子】【语法屎】【茴香豆】让语言更糟!
孔乙己道:“茴香豆的‘茴’字,共有4万种写法,来来来,让我给你一一道来。。。”---实际上孔乙己是为了骗指甲盖中的酒。
powershell传教士道:“滚!我没有必要浪费脑筋学4万种雷同语法,我只需要一种最简单最直接,大家都能看懂的写法。”
腾讯云技术社区,10年开发经验大牛道“不要炫技,老老实实写代码”
http://www.cnblogs.com/qcloud1001/p/6606060.html
http://www.cnblogs.com/qcloud1001/p/6606060.html
话说任何语言,都有n种可以运行,但复杂难以理解的,语句、语法变体,简称“茴香豆”。
茴香豆除了绕脑袋,费时间,害人之外没有任何好处。不利于砸场子!
茴香豆就是,你进步路上的坑!坑里还有水,水中还有雷!
要知道perl很强,但perl人最爱玩“天书代码”,perl被评为开发者最讨厌的语言之一。用perl的人越来越少。
而python代码简单,用的人越来越多。简单的py代码,你敢说不强?
崇尚解决一个小+简单问题,有一万种“茴香豆”代码写法的,perl为啥被淘汰了?
崇尚解决一个小+简单问题,只有一种最简单代码写法,的python为啥如日中天了?
茴香豆除了绕脑袋,费时间,害人之外没有任何好处。不利于砸场子!
茴香豆就是,你进步路上的坑!坑里还有水,水中还有雷!
要知道perl很强,但perl人最爱玩“天书代码”,perl被评为开发者最讨厌的语言之一。用perl的人越来越少。
而python代码简单,用的人越来越多。简单的py代码,你敢说不强?
崇尚解决一个小+简单问题,有一万种“茴香豆”代码写法的,perl为啥被淘汰了?
崇尚解决一个小+简单问题,只有一种最简单代码写法,的python为啥如日中天了?
你爱powershell的话,就为菜鸟铺一条直达powershell高手的康庄大道,而不是在菜鸟学习powershell的路上,挖上坑,埋上雷!
从我做起,不写“茴香豆”语句,不给菜鸟埋雷!
谁要写“茴香豆”语句,你也不用研究,直接把他写的代码扔进垃圾桶!
从我做起,不写“茴香豆”语句,不给菜鸟埋雷!
谁要写“茴香豆”语句,你也不用研究,直接把他写的代码扔进垃圾桶!
---------------
1.5 尽量不用elseif,而要用else {if(){} }。或者单用if。
1.5 尽量不用elseif,而要用else {if(){} }。或者单用if。
1.6 代码尽量对齐,如:
$robert_age = 32
$annalouise_age = 25
$bob_age = 250
$dorothy_age = 56
1.7 代码尽量有好的缩进,和格式化。
---【3英文变量名的坑】---
null,print,computername,count 这些个,是非常容易和我们自定义的变量名,重复的。自己手机没电了,拿同事无波的安卓机调试,很简单的获取用户微信昵称,结果死活获取不到,一直显示为null。应该是跨平台问题,因为之前在自己iPhone上是没有bug的,拼命看api文档,但是都没提到这方面。急死我了。
刚刚无波告诉我他的昵称就是null。
A:“听说无波昨天被同事打死了。”
B:“哎。前天还发朋友圈呢。”
A:“是啊,年纪轻轻的,挺可惜的。”
前面夸张修辞,无波最后当然没死,腿打断了而已。
2016年11月11日凌晨。买家在天猫和淘宝客户端下单之后,支付发生问题,之后跳出英文显示“UnionPay is error,build UnionPay order fail ……”其中,“UnionPay”是中国银联注册商标。
众所周知,支付宝是与银行直连,并没有用银联的通道,因此支付宝再支付中遇到问题,与银联无关。
其实,支付宝跳出的英文意思是“合并支付失败,创建合并支付订单失败……”
11月11日早晨,有中国银联人士在朋友圈贴出昨晚支付发生问题的截图,对此事表示愤怒。
有银联人士表示,“合并支付”可以用英文“jointpayment”,unionpay是“合并订单”的意思,而且支付宝弹出的英文中大小写都和银联商标一致,“哪有那么凑巧的。”
今天中午,蚂蚁金服在微博“蚂自达”(微博认证:蚂蚁金服品牌与公众沟通部总经理)上郑重道歉。
“蚂自达”在微博中解释,“合并支付”的英文是“combined payment”,出现这个问题是因为淘宝工程师不认识combined这个单词,“但不管怎么说,这个无心的错误还是给银联造成了不好的影响,我们全体同事深表歉意。
这口乌漆嘛黑的锅我们不会甩给任何人,请牢牢地扣在我们头上,提醒我们以后不要再有这么令人难堪的错误。”
众所周知,支付宝是与银行直连,并没有用银联的通道,因此支付宝再支付中遇到问题,与银联无关。
其实,支付宝跳出的英文意思是“合并支付失败,创建合并支付订单失败……”
11月11日早晨,有中国银联人士在朋友圈贴出昨晚支付发生问题的截图,对此事表示愤怒。
有银联人士表示,“合并支付”可以用英文“jointpayment”,unionpay是“合并订单”的意思,而且支付宝弹出的英文中大小写都和银联商标一致,“哪有那么凑巧的。”
今天中午,蚂蚁金服在微博“蚂自达”(微博认证:蚂蚁金服品牌与公众沟通部总经理)上郑重道歉。
“蚂自达”在微博中解释,“合并支付”的英文是“combined payment”,出现这个问题是因为淘宝工程师不认识combined这个单词,“但不管怎么说,这个无心的错误还是给银联造成了不好的影响,我们全体同事深表歉意。
这口乌漆嘛黑的锅我们不会甩给任何人,请牢牢地扣在我们头上,提醒我们以后不要再有这么令人难堪的错误。”
---【4中文变量名,中文输出信息的好处】---
4.1 让菜鸟看懂代码,让猪能看懂代码!!!4.2 让英文不行的人看懂代码,或脚本原理。------无需争论,英文不行但想写脚本的人,比专业程序员多!我想让他们看懂。
4.3 中文变量名,中文属性,可以避免和【英文硬编码项目】混淆。
我们知道有常量、变量。编程时用常量就叫做硬编码,即写死,固定。比如写日志,我们永远打算写在一个固定的文件中。
再比如(获取)带路径的文件名,永远要用$_.fullname,但是我们如果要是有个文件名叫fullname,很容易弄混。
再比如,我们的属性叫做name,我们的值也叫name。而用中文变量名,属性名,甚至方法名,则极大地避免了这些。
我们知道有常量、变量。编程时用常量就叫做硬编码,即写死,固定。比如写日志,我们永远打算写在一个固定的文件中。
再比如(获取)带路径的文件名,永远要用$_.fullname,但是我们如果要是有个文件名叫fullname,很容易弄混。
再比如,我们的属性叫做name,我们的值也叫name。而用中文变量名,属性名,甚至方法名,则极大地避免了这些。
4.4 有些英文项目是区别大小写的,如xml的路径,如果我们用汉字作为xml元素,“/节点1/节点2”这样,则不易出现问题。
4.5 linux中有的,中文不兼容劣势,其他语言中有的,中文不兼容劣势。请不要带到win,powershell中来。
你还质疑中文进程名么?---请打开win10的任务管理器,你就会看到“系统空闲进程”这个中文进程名。
你还质疑中文计算机名么?---请把你的机子名改名为“张三”,重启后,ping 张三。
你还质疑中文用户名么?---请新建“李四”这个用户,然后登录。
你还质疑中文进程名么?---请打开win10的任务管理器,你就会看到“系统空闲进程”这个中文进程名。
你还质疑中文计算机名么?---请把你的机子名改名为“张三”,重启后,ping 张三。
你还质疑中文用户名么?---请新建“李四”这个用户,然后登录。
4.6 你觉得自己英文牛x么?请给我翻一个单词【芈月传】,就算你能翻译出来,但猪能看懂么?
请翻译:$国资委,$活雷锋,$第十八届三中全会第二次常务会议,$朱庄,$牛村,$苏家屯,$马家合子,$双泉堡
请翻译:$国资委,$活雷锋,$第十八届三中全会第二次常务会议,$朱庄,$牛村,$苏家屯,$马家合子,$双泉堡
4.7 随便打开简历,全都是大学本科生。随便看提问,全都中国话说不明白。它们起出来的变量名,不论中文英文都很随意,都让人看不懂。我只祈
求猪能写出稍微让我能懂点的,母语变量名。
求猪能写出稍微让我能懂点的,母语变量名。
---【5为了更好地调试】---
5.1 不要重用变量名。函数内外使用同一个变量名,脚本工作起来是毫无问题的。但为了好理解和调试,绝不在整个powershell.exe进程内使用相同的变量名。即$global:变量作用域内,不重用相同变量名。不建议这样【$var=3 function aaaa {$var=4}】,但不排斥这样【$global:var=3 function aaaa {$global:var + 2}】
5.1.1 实际上这是不要重名的问题。这个问题不仅仅存在于变量,还存在于程序名,函数名,属性名等。
脚本名叫ping,函数名也叫ping的这种坏习惯是很常有的,还有个外部命令ping,所以我们要注意避免。
通俗来讲这玩意是有层次的:
神仙>皇帝>大臣>你>你下属。即神仙叫《大禹》皇帝就不能叫;皇帝叫《秦始皇》你就不能叫;你名叫《狗剩》你儿子就不能叫;都叫狗剩不乱了?
脚本的层次是:
外部命令>ps内置模块名,命令名,函数名,变量名,属性名>你编写的脚本的,脚本名,函数名,变量名,属性名>2层函数名,变量名等。
脚本名叫ping,函数名也叫ping的这种坏习惯是很常有的,还有个外部命令ping,所以我们要注意避免。
通俗来讲这玩意是有层次的:
神仙>皇帝>大臣>你>你下属。即神仙叫《大禹》皇帝就不能叫;皇帝叫《秦始皇》你就不能叫;你名叫《狗剩》你儿子就不能叫;都叫狗剩不乱了?
脚本的层次是:
外部命令>ps内置模块名,命令名,函数名,变量名,属性名>你编写的脚本的,脚本名,函数名,变量名,属性名>2层函数名,变量名等。
5.2 避免一行写入太多代码。这样容易看懂,也容易调试。建议一行只给一个变量赋值,并且值中没有不需要的数据。建议把复杂的表达式提取出去,做成中间变量。
5.3 不用$i++,$i--,--$i,++$i,而用 $i=$i + 1。非要用的话,它们单独在一行中。for循环中的i除外。
5.4 管道符“|”是好东西。powershell的管道,是世界上唯一的支持面向对象的管道,但用了不利于调试,一行中管道越多,越不利调试。所以:
一行代码中,尽量不要用2个或更多管道。
一行代码中,尽量不要用2个或更多管道。
5.5 易出错的代码用try{}括起来,但不要在try{}中放入过多的代码,和不必要的代码。
---【5为了防止出错】---
1 在关键变量后,放置【防止出错防御代码】,如:if ($某关键变量 -eq $null) #或大于某个值
{
write-error '出错信息'
exit 一个数字
}
这段代码或许永远不能运行到,但可以防止程序出现逻辑错误,而导致的混乱。
永远告别乱码真经:
编写字符串输入输出函数时,读写文本函数时,
一次必须传2个参数,不可分割。【raw字符串值】和【此字符串,文档的编码类型】
编写字符串输入输出函数时,读写文本函数时,
一次必须传2个参数,不可分割。【raw字符串值】和【此字符串,文档的编码类型】
---【第六章 为了更好地性能】---
管道符“|”是好东西。powershell的管道,是世界上唯一的支持面向对象的管道,但用了性能很差。所以:6.1 能不用一定不要用管道,尽量用【命令 -inputobject xxx】
6.1.1 命令帮助上说sort-object -inputobject $xxx是不行的,你只能用$xxx | sort-object,但为了性能,你就是不应该用。
要用就用[system.array]::sort($xxx)
6.2 非要用管道,管道左面的输出,数量尽量少。最好500以内。
6.3循环。循环内,尽量不要用耗时的指令,而必须用省时的指令。
6.3.1 用数组或哈希表时,尽量用用foreach ($a in $b) { },而不用xxx|foreach-object { }。非要用管道,最好500以内。
6.3.2 循环内时间很短,不要在循环内获取随机数。用[System.Random]::netx()除外。
6.3.3 听说过大长今,大长庄,大长脸,大长循环么?不要搞大长循环,大长的循环就做成函数。
6.3.1 用数组或哈希表时,尽量用用foreach ($a in $b) { },而不用xxx|foreach-object { }。非要用管道,最好500以内。
6.3.2 循环内时间很短,不要在循环内获取随机数。用[System.Random]::netx()除外。
6.3.3 听说过大长今,大长庄,大长脸,大长循环么?不要搞大长循环,大长的循环就做成函数。
一到函数外,变量自动销毁,内存也会吐出。脚本外也是如此。
6.4减少返回对象个数,只需要99个对象,绝不返回100个。
同理,如果在意性能,就用select-object筛选需要的属性,除掉不需要的属性。
6.5 多线程,多进程。
必须考虑脚本中进程切换,线程切换的耗时。尽量给线程(进程)一次性传入多任务,而不是每次一个任务,来减少切换时间。
这跟送快递一样,线程(进程)就是快递员。
一次只送一件货,然后告诉经理结果。结果虽然能及时返回,但必然空跑。
必然比,一次送一百件货,然后返回一百个结果,要消耗更多【空跑时间】。这个【空跑时间】就是线程(进程)切换耗时。
也就是说你要根据任务总数,工作cpu核心数,来规划每线程任务数。
假设你有一万个任务,有一个8核心服务器,但你只想用7核心。
如果你想尽量减少线程(进程)切换耗费的时间。那么你应该建立7个线程,每个线程分配给(1万/7)个任务。
但是呢,假如你想【立马得到单个任务的结果】,就要【每个线程只给一个任务,任务结束后立马返回结果】。
那么问题来了,你到底是想要鱼呢?还是熊掌?你到底是想让任务尽快跑完?还是实时返回单个任务的结果?
假设每个任务消耗cpu时间很短,但任务数量很多,每次一个任务这种方式,【 空跑时间 / 总任务耗时 】占比将很大。
假设你有一万个任务,有一个8核心服务器,但你只想用7核心。
如果你想尽量减少线程(进程)切换耗费的时间。那么你应该建立7个线程,每个线程分配给(1万/7)个任务。
但是呢,假如你想【立马得到单个任务的结果】,就要【每个线程只给一个任务,任务结束后立马返回结果】。
那么问题来了,你到底是想要鱼呢?还是熊掌?你到底是想让任务尽快跑完?还是实时返回单个任务的结果?
假设每个任务消耗cpu时间很短,但任务数量很多,每次一个任务这种方式,【 空跑时间 / 总任务耗时 】占比将很大。
---【第七章 为了标准化,兼容性】---
7.1 只用return打断函数,只用exit打断脚本。虽然可以用break和return打断函数,但尽量不要用break打断函数,而只用return。其他也如此。7.2 函数或方法,只做一件简单的事情。。当你无法为你的方法起一个准确的名称时,很可能你的方法不止做了一件事,违反了(Do one thing)。
避免写太长的函数。如果发现函数太大了,就应该把它拆分成几个更小的。
避免写太长的函数。如果发现函数太大了,就应该把它拆分成几个更小的。
7.3 linux下保存文件只用带bom的utf-8。win下保存文件可以用带bom的utf-8,或带bom的utf-8。
7.4 尽量多使用标准ps命令,参数,方法,属性。这样做,ps升级之后,你的旧代码兼容性,才能比较好。
尽量少用wmi,.net方法。除非标准ps命令,没有提供你要的功能,没有提供你要的性能。
尽量少用wmi,.net方法。除非标准ps命令,没有提供你要的功能,没有提供你要的性能。
---【参考资料】---
部分参考了 王垠 代码规范中的观点,在此表示感谢。其他欢迎各位给与补充。
---【后记】---
【编程语言中】,比较小的不好的特性叫什么?答:苍蝇,幺蛾子,坑。
大的呢?
答:癌症!
答:癌症!
茴香豆是什么?
答:
孔乙己道:“茴香豆的‘茴’字,共有4万种写法,来来来,让我给你一一道来。。。”
孔乙己道:“去你家楼下小卖部的路,有8万种方法,每一种方法都绕10万8千里。”
最惨的是什么?
答:n多癌症,n多苍蝇。语法屎。
答:n多癌症,n多苍蝇。语法屎。
在6星级【编程语言】酒店中,你喊道:“老板,来份编程语言套餐,要简单易懂性能好的,
多加语法糖,多库,多框架。少加幺蛾子,不要茴香豆!不要坑!不要语法屎!绝不要癌症!不要不可控的未知数”
多加语法糖,多库,多框架。少加幺蛾子,不要茴香豆!不要坑!不要语法屎!绝不要癌症!不要不可控的未知数”
编码严谨不是错!!!
若编程语言中全都是坑和幺蛾子,未知数的话。编程者也是猪,将制造更多坑。
坑多了,代码运行中,蹦~叭~,乱跳错误,总给用户造成损失,那谁还敢用你的代码呀?
坑多了,代码运行中,蹦~叭~,乱跳错误,总给用户造成损失,那谁还敢用你的代码呀?
编程的人应该严谨,你选择的编程语言也必须是严谨,少幺蛾子的,否则请看:
http://news.cnblogs.com/n/541717/
日本鬼子证劵公司因bug损失27亿人民币!官司打了10年!
不严谨的编程语言,不严谨的人,是不是应该滚粗代码界啊?