shell编程之DRY&KISS

社区广播:运维派(Yunweipai.com)是国内最早成立的IT运维社区,欢迎大家投稿,让运维人不再孤寂的成长!

用BASH编程已有些时间了,参与过大型项目的开发。当初的摸石子过河,项目越来越大了,代码开始腐朽了。

也许,从新开始是件好事,如同老板所说,背上太多的包袱,你如何前行!

下面,我从DRY(Dont’t Repeat Yourself)和KISS(Keep it Simple & Smart),这两条
最重要的编程原则来展示一下我在新项目中的实践。

1. assert
及时发现错误,C代码中assert就是这样一个用处,很多时间,我们的程序员并不对命
令的执行进行返回码检查,其主要原因是,怕麻烦,且使用大量的if判断增加了代码
的冗余,如下所示。
[code lang=”shell”]function fn_main() {
cp $src $dst
if [ $? -ne 0 ]; then
echo "cp fail"
return 1
fi
}[/code]

我们可以构造一个BASH版的assert,称其为xt(assert的缩写)
[code lang=”shell”]PS8="eval echo \${BASH_SOURCE##*/}\|\$LINENO\|: "
function xt() {
[ "${1}" -eq 0 ] && return ${1}
echo ${@:2} || return $?
return ${1}
}[/code]

那么上面的代码改写如下:
[code lang=”shell”]function fn_main() {
cp $src $dst
xt $? `$PS8` "cp fail" || return $?
}[/code]

使用xt有两个明显的好处:
a. 大大减少检查代码的行数
b. 函数调用层次较多时,如果出错了,可以打印出调用栈

2. 关于日志
当前的代码现状:
a. 写代码时不写日志
b. 只有自己的提示信息,没有错误输出,往往命令的错误输出才是查错的关键

[code lang=”shell”]function fn_main() {
fn_cp $src1 $dst1 # 没有日志
fn_cp $src2 $dst2 || echo "cp fail" > $logfile # 不小心把日志清空了
fn_cp $src3 $dst3 || echo "cp fail" >> $logfile # 无错误输出
fn_cp $src4 $dst4 || echo "cp fail" >> $logfile 2>&1 # 写得太多,麻烦
}[/code]

结合xt,我们可以给出更好的方案
[code lang=”shell”]function fn_main() {
fn_cp $src1 $dst1
xt $? `$PS8` "cp fail" || return $?
}
fn_main $@ | tee -a $logfile
ret=$PIPESTATUS[0]
exit $ret[/code]

3. KISS,我们可以使用全局变量
先看一下老代码:
[code lang=”shell”]function fn_get_keys_from_conf() {
key1=`fn_get_val key1`
key2=`fn_get_val key2`
key3=`fn_get_val key3`
}
function fn_proc1() {
local key1=$1
local key2=$2
local key3=$3
}
.
.
.
function fn_procn() {
local key1=$1
local key2=$2
local key3=$3
}
function fn_main() {
fn_get_keys_from_conf

fn_proc1 $key1 $key2 $key3
fn_proc2 $key1 $key2 $key3
fn_proc3 $key1 $key2 $key3
}
fn_main[/code]

变量如果没有local限定词,其属性默认为全局的,使用local局部变量可以使变量
使用更加安全,但是带来大量冗余与重复,导致失误操作增加。

大多时候,从配置文件中读取的配置都是只读的,为了安全,我们只要使用关键字
readonly就可以保证其安全了。而且我们可以把所有全局变量放在一起管理。
那么上面的代码这样就可以了:
[code lang=”shell”]function fn_get_keys_from_conf()
{
readonly key1=`fn_get_val key1`
readonly key2=`fn_get_val key2`
readonly key3=`fn_get_val key3`
}
function fn_main()
{
fn_get_keys_from_conf

fn_proc1
fn_proc2
fn_proc3
}
fn_main[/code]

后记:使用已有特性DIY解决应用过程中的问题,不断优化,如此才有进步。不断的重复自己,只会让人变懒变傻。

网友评论comments

发表评论

电子邮件地址不会被公开。 必填项已用*标注

  1. Guang说道:

    终于看到小魔的大作了,DRY(Dont’t Repeat Yourself)和KISS(Keep it Simple & Smart)的这个解释很经典啊,但在实际开发过程中,一旦有进度压力的情况下,大部分人都会妥协的。。。

    PS:1)文章中代码的排版我帮你调整了下,后续我再发篇文章介绍下如何在文章中通过标签实现代码格式的排版。2)方便的话,准备下你的自我介绍吧,我们会在顶部的“关于”页面增加上。

  2. Simon说道:

    全局变量,还是少用哦。当你项目中文件多了的时候,全局变量容易冲突的。。。

  3. ibusybox说道:

    小魔终于冒泡了 哈
    贴代码的时候要注意编码转换的特殊字符,有好几个地方都需要编辑一下

  4. 捣乱说道:

    接触过点bash编程,但这篇高级了点,没看懂。

  5. XiaoMing说道:

    什么时候开始支持关键字高亮了,这个好,
    对于内容表示压力很大,
    ibusybox也是shell高手啊,

Copyright © 2012-2017 YUNWEIPAI.COM - 运维派 - 粤ICP备14090526号-3
扫二维码
扫二维码
返回顶部