加入社区

订阅:www.yunweipai.com/feed

QQ群:
1群:201777608 - 运维综合
2群:526871767 - 运维综合
3群:1689067 - Linux Shell脚本

微博:weibo.com/tektea

微信:yunweipai(或扫描以下二维码)

合作伙伴

小猪动图 - GIF动图素材库_GIF在线工具

shell编程之DRY&KISS

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

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

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

1. assert
及时发现错误,C代码中assert就是这样一个用处,很多时间,我们的程序员并不对命
令的执行进行返回码检查,其主要原因是,怕麻烦,且使用大量的if判断增加了代码
的冗余,如下所示。

function fn_main() {
    cp $src $dst
    if [ $? -ne 0 ]; then
        echo "cp fail"
        return 1
    fi
}


我们可以构造一个BASH版的assert,称其为xt(assert的缩写)

PS8="eval echo \${BASH_SOURCE##*/}\|\$LINENO\|: "
function xt() {
    [ "${1}" -eq 0 ] && return ${1}
    echo ${@:2} || return $?
    return ${1}
}

那么上面的代码改写如下:

function fn_main() {
    cp $src $dst
    xt $? `$PS8` "cp fail" || return $?
}

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

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

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 # 写得太多,麻烦
}

结合xt,我们可以给出更好的方案

function fn_main() {
    fn_cp $src1 $dst1
    xt $? `$PS8` "cp fail" || return $?
}
fn_main $@ | tee -a $logfile
ret=$PIPESTATUS[0]
exit $ret

3. KISS,我们可以使用全局变量
先看一下老代码:

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

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

大多时候,从配置文件中读取的配置都是只读的,为了安全,我们只要使用关键字
readonly就可以保证其安全了。而且我们可以把所有全局变量放在一起管理。
那么上面的代码这样就可以了:

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

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

转载请注明:运维派 » shell编程之DRY&KISS

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

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

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

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

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