重构保持函数的单一职责

更新日期: 2019-09-25阅读: 2.3k标签: 重构

2.单一职责表现形式

单一职责的定义可以理解为:一个对象或者方法,只做一件事。

遵守单一职责的实例太多了,下面简单列举一下。

原生的api方面

trimRight()和trimLeft():trimRight 只负责去除右边的空白,其它地方一概不管。 trimLeft 只负责去除右边的空白,其它地方也一概不关。

concat(): concat 只负责连接两个或更多的数组,并返回结果。不会涉及删除数组的操作。

toFixed(): toFixed 只把 Number 类型的值四舍五入为指定小数位数的数字。不会执行其它操作。

jquery 的 API

$.each() 只负责遍历,要处理什么,自己再动手操作。

css() 只负责设置 dom 的 style ,不会设置 innerhtml

animate() 只负责执行 CSS 属性集的自定义动画,不会涉及其它操作。

说是这样说,但是大家看着可能会有点懵,看不出来遵守单一原则有什么好处,下面看一个实例。


3.实例-数组处理

如下例子:

现有一批的录入学生信息,但是数据有重复,需要把数据根据 id 进行去重。然后把为空的信息,改成'--'。

let students=[
    {
        id:5,
        name:'守候',
        sex:'男',
        age:'',
    },
    {
        id:2,
        name:'浪迹天涯',
        sex:'男',
        age:''
    },
    {
        id:5,
        name:'守候',
        sex:'',
        age:''
    },
    {
        id:3,
        name:'鸿雁',
        sex:'',
        age:'20'
    }
];

function handle(arr) {
    //数组去重
    let _arr=[],_arrIds=[];
    for(let i=0;i<arr.length;i++){
        if(_arrIds.indexOf(arr[i].id)===-1){
            _arrIds.push(arr[i].id);
            _arr.push(arr[i]);
        }
    }
    //遍历替换
    _arr.map(item=>{
        for(let key in item){
            if(item[key]===''){
                item[key]='--';
            }
        }
    });
    return _arr;
}
console.log(handle(students))


运行结果没有问题,但是大家想一下,

1.如果改了需求,比如,学生信息不会再有重复的记录,要求把去重的函数去掉,无论,就是整个函数都要改了,还影响到下面的操作。

2.如果项目另一个地方也是同样的操作,但是不需要去重。这样只能再写一个基本一样的函数,因为上面的函数无法复用。如下

function handle1(arr) {
    //数组深拷贝
    let _arr=JSON.parse(JSON.stringify(arr));
    //遍历替换
    _arr.map(item=>{
        for(let key in item){
            if(item[key]===''){
                item[key]='--';
            }
        }
    });
    return _arr;
}

3.如果项目有一个地方还需要根据 ID 排序。这样还是得写一个函数,因为在不能在上面的函数上面排序。

function handle2(arr) {
    //数组去重
    let _arr=[],_arrIds=[];
    for(let i=0;i<arr.length;i++){
        if(_arrIds.indexOf(arr[i].id)===-1){
            _arrIds.push(arr[i].id);
            _arr.push(arr[i]);
        }
    }
    //遍历替换
    _arr.map(item=>{
        for(let key in item){
            if(item[key]===''){
                item[key]='--';
            }
        }
    });
    //根据ID排序
    _arr.sort((item1,item2)=>item1.id-item2.id);
    return _arr;
}

这样的问题就是在于,面对需求的变化,不能灵活的处理。函数也基本没办法复用。

下面使用单一原则构造一下

let handle={
    //数组去重
    removeRepeat(arr){
        let _arr=[],_arrIds=[];
        for(let i=0;i<arr.length;i++){
            if(_arrIds.indexOf(arr[i].id)===-1){
                _arrIds.push(arr[i].id);
                _arr.push(arr[i]);
            }
        }
        return _arr;
    },
    //遍历替换
    setInfo(arr){
        arr.map(item=>{
            for(let key in item){
                if(item[key]===''){
                    item[key]='--';
                }
            }
        });
        return arr;
    },
    //根据id排序
    sortForId(arr){
        return arr.sort((item1,item2)=>item1.id-item2.id);
    }
};
//去重
students=handle.removeRepeat(students);
//设置信息
students=handle.setInfo(students);
console.log(students);


结果一样,而且这样的方式,可以使得方法可以组合使用,更加的灵活,也方便复用。

如果还需要根据ID排序,就在上面代码执行结果的基础上,再加一行代码即可。

//根据ID排序
students=handle.sortForId(students);
console.log(students);


如果原始数据不需要去重,设置完信息之后,直接排序

let students=[
    {
        id:5,
        name:'守候',
        sex:'男',
        age:'',
    },
    {
        id:2,
        name:'浪迹天涯',
        sex:'男',
        age:''
    },
    {
        id:5,
        name:'守候',
        sex:'',
        age:''
    },
    {
        id:3,
        name:'鸿雁',
        sex:'',
        age:'20'
    }
];
//设置信息
students=handle.setInfo(students);
//根据ID排序
students=handle.sortForId(students);


这样操作起来,即使以后需求有改动,在可控的范围内,可以灵活的组合使用,函数也可以复用。

如果觉得要让 students 连续赋值麻烦,可以借鉴 JQuery 的链式调用方式。

let ec=(function () {
    let handle=function (obj) {
        this.obj=JSON.parse(JSON.stringify(obj));
    };
    handle.prototype={
        /**
         * @description 去重
         */
        unique(){
            //根据id数组去重
            let _arr=[],_arrIds=[];
            for(let i=0;i<this.obj.length;i++){
                if(_arrIds.indexOf(this.obj[i].id)===-1){
                    _arrIds.push(this.obj[i].id);
                    _arr.push(this.obj[i]);
                }
            }
            this.obj=_arr;
            return this;
        },
        /**
         * @description 设置保密信息
         */
        setInfo(){
            this.obj.map(item=>{
                for(let key in item){
                    if(item[key]===''){
                        item[key]='--';
                    }
                }
            });
            return this;
        },
        sortForId(){
            this.obj.sort((item1,item2)=>item1.id-item2.id);
            return this;
        },
        /**
         * @description 返回处理结果
         * @return {Array|*}
         */
        end(){
            return this.obj;
        }
    }
    //暴露构造函数接口
    return function (obj) {
        return new handle(obj);
    }
})();
let students=[
    {
        id:5,
        name:'守候',
        sex:'男',
        age:'',
    },
    {
        id:2,
        name:'浪迹天涯',
        sex:'男',
        age:''
    },
    {
        id:5,
        name:'守候',
        sex:'',
        age:''
    },
    {
        id:3,
        name:'鸿雁',
        sex:'',
        age:'20'
    }
];
//根据id去重和设置'--'
students=ec(students).unique().setInfo().end();
console.log(students)


结果还是一样,只是增加了一个方法,方便链式调用。

关于实现链式调用,这个肯定是会增加代码的,如果调用的方法并不是一些常用,通用的方法的话,只是处理一些特殊格式的数据的方法(如上实例),不建议花费时间,实现链式调用,普通调用就好。如果是一些常用的函数的封装,就建议使用链式调用。


4.违反单一职责原则

在上面的实例里面,相信大家都看到了,遵守单一职责的好处,但是单一职责也有缺点,就是会增加代码的复杂程度。

在市面上,也有API是违反单一职责的。

JQuery 的 html() 方法,既可以获取 innerHTML ,也可以设置 innerHTML 。 attr ()既可以获取 DOM 元素的某一个属性,也可以设置 DOM 元素的某一个属性。

在维护上面,这样的代码,可能会给维护增加难度,但是对于使用者而言,这样简化了使用。这应该是一个取舍关系,取什么,舍什么。这个就是具体情况具体分析。


链接: https://fly63.com/article/detial/5537

web页面的重构和回流【转载】

在了解什么是重构和回流之前,我们应该先看看浏览器是怎么渲染的?浏览器的渲染过程;什么是重构和回流;什么操作会引起重绘、回流;浏览器对回流的优化;如何减少回流、重绘

web页面重构和前端性能优化

在不改变外部行为的前提下,简化结构、添加可读性,而在网站前端保持一致的行为;你有用过哪些前端性能优化的方法?减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适

代码重构!你敢吗?

我从基础架构部门,转调到业务部门。技术负责人想让我搞定业务系统的稳定性问题。当时的业务系统确实存在不少问题,不过我初来乍到,对整体系统不熟悉,就想在熟悉一段时间后再动手。

代码重构的基本认知

代码不可能在第一次就写得完美,这是一个持续修改的过程,那么应该怎么来进行呢?好代码的检验标准就是人们是否能轻而易举地修改它。

前端项目重构要点总结

项目是公司主打业务产品之一的可视化子项目,与其他子项目几乎没有耦合,所以可以单独拎出来重构。具体业务不作描述。技术主要用的是Vue2系列和JavaScript,还有一个自研的可视化工具库。第一个重构原因就是没有引入静态类型

指尖前端重构(React)技术调研分析

React是当前前端应用最广泛的框架。三大SPA框架 Angular、React、Vue比较。Angular出现最早,但其在原理上并没有React创新的性能优化,且自身相对来说显得笨重。Vue出现最晚,其核心原理学习了React

web前端代码重构

1. 整理一套vscode中格式化配置,在页面保存时自动格式化,团队成员格式统一(搭配eslint)。2. 整理项目中的命名(不要嫌长,但也不能过于冗长,尽量能让人一眼看明白)

JavaScript重构技巧-让函数简单明了

JavaScript 是一种易于学习的编程语言,编写运行并执行某些操作的程序很容易。然而,要编写一段干净的JavaScript 代码是很困难的。

代码重构的实战经验和那些坑

我在一家创业公司的小团队里搞软件开发。彼时我们有一位真实的企业客户,且软件的第一版也已发布。开发按进度完工,在发布时我欣喜若狂

前端的自动化重构

过去,我一直想着抽时间写一个小的前端工具,以对代码进行自动化的重构。但是呢,经过我再三的考虑,我暂时取消了这个打算 —— 主要是没时间

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!