资讯专栏INFORMATION COLUMN

重构 - 保持函数的单一职责

haitiancoder / 784人阅读

摘要:学习的步伐不能就此停止,今天的文章,将会提及开发的另一个原则单一职责原则。通俗点说就是一个函数只做一件事,下面将会通过几个实例,探究单一职责原则。遵守单一职责的实例太多了,下面简单列举一下。在市面上,也有是违反单一职责的。

1.前言

上篇文章写了添加扩展性方面的重构,讲到了开放封闭原则。学习的步伐不能就此停止,今天的文章,将会提及开发的另一个原则:单一职责原则。通俗点说就是一个函数只做一件事,下面将会通过几个实例,探究单一职责原则。

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{
        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{
        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{
            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{
                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 元素的某一个属性。

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

5.小结

今天的例子就到这里了,这个例子,解释降解函数单一原则会有什么好处。这个例子比上篇文章的例子还要简单。大家看不明白,把代码拷贝在浏览器上运行,就很好理解。如果大家对这个例子有什么更好的建议,或者代码上有什么问题,欢迎在评论区留言,大家多交流,相互学习。

---------------------华丽的分割线---------------------

想了解更多,关注关注我的微信公众号:守候书阁

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94949.html

相关文章

  • 读懂 SOLID 单一职责」原则

    摘要:同时,在方法命名上也投入一精力,尽可能地使方法名保持简单,它将帮助你在重构代码时,更好的达到单一职责。 这是理解SOLID原则中,关于单一职责原则如何帮助我们编写低耦合和高内聚的第二篇文章。 单一职责原则是什么 之前的第一篇文章阐述了依赖倒置原则(DIP)能够使我们编写的代码变得低耦合,同时具有很好的可测试性,接下来我们来简单了解下单一职责原则的基本概念: Every module o...

    Magicer 评论0 收藏0
  • 重构 - 改善代码各方面问题

    摘要:暴露接口如果是函数,就扩展,否则就是验证数据使用金额校验规则这样运行能正常,也有扩展性性,但是对于代码洁癖的来说,这样写法不优雅。 重构不是对以前代码的全盘否定,而是利用更好的方式,写出更好,更有维护性代码。不断的追求与学习,才有更多的进步。 1.前言 做前端开发有一段时间了,在这段时间里面,对于自己的要求,不仅仅是项目能完成,功能正常使用这一层面上。还尽力的研究怎么写出优雅的代码,性...

    AlphaWallet 评论0 收藏0
  • 深入理解JavaScript系列6:S.O.L.I.D五大原则之单一职责

    摘要:,开始我们的第一篇单一职责。通过解耦可以让每个职责工更加有弹性地变化。关于本文本文转自大叔的深入理解系列。深入理解系列文章,包括了原创,翻译,转载,整理等各类型文章,原文是大叔的一个非常不错的专题,现将其重新整理发布。 前言 Bob大叔提出并发扬了S.O.L.I.D五大原则,用来更好地进行面向对象编程,五大原则分别是: The Single Responsibility Princi...

    walterrwu 评论0 收藏0
  • 可靠React组件设计7个准则之终篇

    摘要:单元测试不仅涉及早期错误检测。当组件的架构设计很脆弱时,就会变得难以测试,而当组件难以测试的时候,你大概念会跳过编写单元测试的过程,最终的结果就是组件未测试。可测试性是确定组件结构良好程度的实用标准。可复用的组件是精心设计的系统的结果。 翻译:刘小夕原文链接:https://dmitripavlutin.com/7-... 本篇文章重点阐述可测试和富有意义。因水平有限,文中部分翻译可...

    jasperyang 评论0 收藏0
  • 读懂 SOLID 「接口隔离」原则

    摘要:接口隔离原则是什么客户端代码不应当被迫依赖于它们不需要的方法。 这是理解SOLID原则,关于接口隔离原则如何帮助我们创建简单的抽象接口,并使客户端代与接口之间存在的更少的依赖关系。 接口隔离原则是什么 Clients should not be forced to depend on methods that they do not use.客户端代码不应当被迫依赖于它们不需要的方法。...

    wing324 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<