关于《重构—改善即有代码的设计》一书“代码的坏味道”章节的知识分享

322 阅读3分钟

一. 代码命名

开局一张图,后面全靠编

对于前端代码中命名的问题,最麻烦的无非是以下两点:

  1. Class类的命名
  2. JavaScript方法的命名

1. Class类的命名应该遵循可读性高的原理

坏味道:

<div class="alert_btn flex">
    <button type="button" class="red_btn">提交</button>
</div>

好味道:

<div class="submit_btn_wrapper flex">
    <!-- "red_btn"有可能是全局样式 -->
    <button type="button" class="submit_btn red_btn">提交</button>
</div>

2. JS方法使用驼峰命名,尽管单词长但保证能读懂

坏味道:

<!-- 获取URL中的参数 -->
function getparameter(param) {
  var queryString = window.location.search.substring(1); // 获取浏览器"?"后的url值
  var queryArray = queryString.split("&");
  for (var i = 0; i < queryArray.length; i++) {
    var item = queryArray[i].split("=");
    if (item[0] === param) {
        return item[1];
    }
  }
  return false;
}

好味道:

<!-- 获取URL中的参数 -->
function getUrlParams(param) {
  var queryString = window.location.search.substring(1); // 获取浏览器"?"后的url值
  var queryArray = queryString.split("&");
  for (var i = 0; i < queryArray.length; i++) {
    var item = queryArray[i].split("=");
    if (item[0] === param) {
        return item[1];
    }
  }
  return false;
}

二. 重复代码

坏味道行列中首当其冲的就是Duplicated Code。如果你在一个以上的地点看到相同的程序结构,那么可以肯定:设法将它们合二为一,程序会变得更好。

其实对于我们现在这个商城,最为突出的问题就是重复代码,很多时候为了赶项目进度,大家都会选择复制代码,而不是去精简代码,短时间内可能不会有啥影响,但是时间一长尤其是后面再加功能时,再去编辑那些代码就会感觉痛不欲生,鄙人深有体会。

就拿商城手机端下单页的代码来说,两千行,HTMLCSS还有JS,错综复杂交织环绕,维护该页面其实是个很费神的差事。

坏味道:

// 跳转选择地址页面(选择收货地址)
$('.address_wrapper').bind('click', function() {
    // 保存已上传图片的base64
    if ($('.imgShow').length > 0) {
        const base64Array = [];
        $('.imgShow').each(function() {
            base64Array.push($(this).attr('src'));
        });
        const data = { array: base64Array, status: 1 }
        localStorage.setItem('base64Array', JSON.stringify(data))
    }
    // 保证已选择的发票不受影响
    var ch_addr_json = JSON.parse(localStorage.getItem('ch_addr'));
    if (ch_addr_json && ch_addr_json.status == 2) {
        ch_addr_json.status = 1;
    };
    localStorage.setItem('ch_addr', JSON.stringify(ch_addr_json));
    // 保证已选择的发票寄送地址不受影响
    var send_addr_json = JSON.parse(localStorage.getItem('send_addr_id'));
    if (send_addr_json && send_addr_json.status == 2) {
        send_addr_json.status = 1;
    };
    localStorage.setItem('send_addr_id', JSON.stringify(send_addr_json));
    // 保证已选择的抵扣券不受影响
    var coupon_id_json = JSON.parse(localStorage.getItem('coupon_id'));
    if (coupon_id_json && coupon_id_json.status == 2) {
        coupon_id_json.status = 1;
    }
    localStorage.setItem('coupon_id', JSON.stringify(coupon_id_json));
    // 判断是请购单还是普通下单
    var order_or_pr = '{$order_or_pr}';
    if (order_or_pr == 'pr') { // 请购单
        location.href = 'index.php?app=order&act=get_addr';
    } else { // 普通下单
        location.href = 'index.php?app=my_address';
    }
    // 修改addr_id的值
    localStorage.setItem('addr_id', '1');
});

好味道:

// 跳转选择地址页面(选择收货地址)
$('.address_wrapper').bind('click', function() {
    saveImgData('.imgShow'); // 保存已上传图片不受跳转页面的影响
    saveOtherData('ch_addr'); // 保证其他数据不受跳转页面的影响
    saveOtherData('send_addr_id');
    saveOtherData('coupon_id');
    // 判断是请购单还是普通下单
    var order_or_pr = '{$order_or_pr}';
    if (order_or_pr == 'pr') {
        location.href = 'index.php?app=order&act=get_addr';
    } else {
        location.href = 'index.php?app=my_address';
    }
    // 修改addr_id的值
    localStorage.setItem('addr_id', '1');
});
// 保存已上传图片base64数据的方法
function saveImgData(selector) {
    if ($(selector).length > 0) {
        const base64Array = [];
        $(selector).each(function() {
            base64Array.push($(this).attr('src'));
        });
        const data = { array: base64Array, status: 1 }
        localStorage.setItem('base64Array', JSON.stringify(data))
    } else {
        return false;
    }
}
// 保证其它已选择值不受跳转页面的影响(不刷新页面的情况)
function saveOtherData(localStorageName) {
    var localStorage_json = JSON.parse(localStorage.getItem(localStorageName));
    if (localStorage_json && localStorage_json.status == 2) {
        localStorage_json.status = 1;
        localStorage.setItem(localStorageName, JSON.stringify(localStorage_json));
    } else {
        return false;
    }
}

封装独立方法,单独使用单独调用,后期维护起来将变得比较轻松。

三. 过长参数列

太长的参数列难以理解,太多参数会造成前后不一致、不易使用,而且一旦你需要更多的数据,就不得不修改它。

如果函数需要传递的参数太多,那么请尽量传递对象或者以函数取代参数

坏味道:

// 调用方法
layuiPage('table', 'get_bill_goods', [], 1, '1a2b3c', 1)
// 定义获取分页方法
function layuiPage(elem, act, data, count, bill_id, current_page) {
    layui.use('laypage', function(){
        var laypage = layui.laypage;
        // 调用表格的分页
        laypage.render({
            elem: elem,
            theme: '{$theme.wd_theme_color}' // 页码颜色
            limit: 10, // 每页限制条数
            curr: current_page, // 当前页码
            count: count,
            jump: function(obj, first) {
                if (act === 'get_bill_goods') {
                    console.log(data, bill_id);
                } else {
                    return false;
                }
            }
        });
    });
}

好味道:

// 定义参数对象
var paramObject = {
    elem: 'table',
    act: 'get_bill_goods',
    data: [],
    count: 1,
    bill_id: '1a2b3c',
    current_page: 1
}
// 定义获取分页方法
function layuiPage(paramObject) {
    // 解构取值
    const { elem, act, data, count, bill_id, current_page  } = paramObject;
    // 分页功能
    layui.use('laypage', function(){
        var laypage = layui.laypage;
        // 调用表格的分页
        laypage.render({
            elem: elem,
            theme: '{$theme.wd_theme_color}' // 页码颜色
            limit: 10, // 每页限制条数
            curr: current_page, // 当前页码
            count: count,
            jump: function(obj, first) {
                if (act === 'get_bill_goods') {
                    console.log(data, bill_id);
                } else {
                    return false;
                }
            }
        });
    });
}