首页 > 其他分享 >KISS 原则 (设计模式)

KISS 原则 (设计模式)

时间:2024-02-28 11:00:51浏览次数:26  
标签:return 原则 实现 代码 ipUnitIntValue KISS false 设计模式

KISS 定义

kiss 原则的英文描述又几个版本,计较下边的这几个

keep it simple and stupid.

keep it short and simple

keep it simple and straightforward

不过仔细看你会发现,他们表达的意思其实差不多,尽量保持简单。 它是一个万金油的设计原则,可以在很多场景中,它不仅仅经常用来指导软件开发,还经常指导更广泛的设计,比如冰箱,建筑,Iphone 手机的设计等等。

我们指导可读性和可维护性,是衡量代码质量的非常重要的两个标准。而kiss 原则是保持代码可读性和可维护性的重要手段。 代码足够简单,也就意味着很容易读懂,bug 比较难隐藏。即便出现bug ,修复起来也比较简单。 

不过这天原则告诉我们要保持“Simple and stupid”,但是并没有讲过,什么代码才是Simple and stupid ,更没有明确的方法论,来指导如何开发Simple and stupid 的代码。 所以看起来非常简单,但不能落地。 这有点像我们的心灵鸡汤,哦,我们这里应该叫技术鸡汤。 

代码行数越少就越简单吗? 

// 第一种实现方式: 使用正则表达式
    public boolean isValidIpAddressV1(String ipAddress) {
        if (StringUtils.isBlank(ipAddress)) return false;
        String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
                + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
                + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
                + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
        return ipAddress.matches(regex);
    }
    // 第二种实现方式: 使用现成的工具类
    public boolean isValidIpAddressV2(String ipAddress) {
        if (StringUtils.isBlank(ipAddress)) return false;
        String[] ipUnits = StringUtils.split(ipAddress, '.');
        if (ipUnits.length != 4) {
            return false;
        }
        for (int i = 0; i < 4; ++i) {
            int ipUnitIntValue;
            try {
                ipUnitIntValue = Integer.parseInt(ipUnits[i]);
            } catch (NumberFormatException e) {
                return false;
            }
            if (ipUnitIntValue < 0 || ipUnitIntValue > 255) {
                return false;
            }
            if (i == 0 && ipUnitIntValue == 0) {
                return false;
            }
        }
        return true;
    }
    // 第三种实现方式: 不使用任何工具类
    public boolean isValidIpAddressV3(String ipAddress) {
        char[] ipChars = ipAddress.toCharArray();
        int length = ipChars.length;
        int ipUnitIntValue = -1;
        boolean isFirstUnit = true;
        int unitsCount = 0;
        for (int i = 0; i < length; ++i) {
            char c = ipChars[i];
            if (c == '.') {
                if (ipUnitIntValue < 0 || ipUnitIntValue > 255) return false;
                if (isFirstUnit && ipUnitIntValue == 0) return false;
                if (isFirstUnit) isFirstUnit = false;
                ipUnitIntValue = -1;
                unitsCount++;
                continue;
            }
            if (c < '0' || c > '9') {
                return false;
            }
            if (ipUnitIntValue == -1) ipUnitIntValue = 0;
            ipUnitIntValue = ipUnitIntValue * 10 + (c - '0');
        }
        if (ipUnitIntValue < 0 || ipUnitIntValue > 255) return false;
        if (unitsCount != 3) return false;
        return true;

    }

  

第一种实现方式利用的是正则表达,只用三行就把问题搞定了。它的代码行数少,那是不是就是符合kiss 原则? 答案是否定的。 虽然代码行数少,看似简单,实际上却很复杂。这正是因为使用了正则表达

一方面,正则表达式本身是比较复杂的,写出完全没有 bug 的正则表达本身就比较有挑 战;另一方面,并不是每个程序员都精通正则表达式。对于不怎么懂正则表达式的同事来 说,看懂并且维护这段正则表达式是比较困难的。这种实现方式会导致代码的可读性和可维 护性变差,所以,从 KISS 原则的设计初衷上来讲,这种实现方式并不符合 KISS 原则

第二种实现方式使用了 StringUtils 类、Integer 类提供的一些现成的工具函数,来处理 IP 地址字符串。第三种实现方式,不使用任何工具函数,而是通过逐一处理 IP 地址中的字 符,来判断是否合法。从代码行数上来说,这两种方式差不多。但是,第三种要比第二种更 加有难度,更容易写出 bug。从可读性上来说,第二种实现方式的代码逻辑更清晰、更好 理解。所以,在这两种实现方式中,第二种实现方式更加“简单”,更加符合 KISS 原则。

不过,你可能会说,第三种实现方式虽然实现起来稍微有点复杂,但性能要比第二种实现方 式高一些啊。从性能的角度来说,选择第三种实现方式是不是更好些呢?

在回答这个问题之前,我先解释一下,为什么说第三种实现方式性能会更高一些。一般来 说,工具类的功能都比较通用和全面,所以,在代码实现上,需要考虑和处理更多的细节, 执行效率就会有所影响。而第三种实现方式,完全是自己操作底层字符,只针对 IP 地址这 一种格式的数据输入来做处理,没有太多多余的函数调用和其他不必要的处理逻辑,所以, 在执行效率上,这种类似定制化的处理代码方式肯定比通用的工具类要高些。

不过,尽管第三种实现方式性能更高些,但我还是更倾向于选择第二种实现方法。那是因为 第三种实现方式实际上是一种过度优化。除非 isValidIpAddress() 函数是影响系统性能的 瓶颈代码,否则,这样优化的投入产出比并不高,增加了代码实现的难度、牺牲了代码的可 读性,性能上的提升却并不明显。

如何写出满足KISS 原则的代码? 

不要使用同事可能不懂得技术来实现代码,比如前面例子中得正则表达式。还有一些编程语言中得过于高级的语法扽给。

不要重复造轮子,要善于使用已经有得工具类库,经验证明,自己去实现这些类库,出现bug 的概率会 更高,维护的成本也更高。 (但是你没有提高

不要过度优化,不要是公用一些奇技淫巧,比如位运算代替算数运算,复杂的条件代替if -else 

 

实施上,代码是否足够简单,式一个主观的评判,同样的而代码,有人觉得简单有人觉得不够简单。所以评判代码是否简单,还有一个有点的方法,那就是code review 。如果在code review 的时候,同事对你的代码有很多疑问,那就说明,你的代码可能不够简单。需要优化。 

这力我还要多说两句,我们在开发的时候,一定不要过度设计,不要觉得简单的东西没有技术含量,实际上越是呢个简单的方法解决复杂的问题,越能体现一个人的能力。 

YAGNI 原则,

不要设计当前用不到的功能,不要去编写用不到的代码, 实际上这条代码的原则是不要多读设计。 

比如,我们的系统暂时只用 Redis 存储配置信息,以后可能会用到 ZooKeeper。根据 YAGNI 原则,在未用到 ZooKeeper 之前,我们没必要提前编写这部分代码。当然,这并 不是说我们就不需要考虑代码的扩展性。我们还是要预留好扩展点,等到需要的时候,再去 实现 ZooKeeper 存储配置信息这部分。

在比如我们不要在项目中引入不需要的依赖开发包。 我们呢发现,有些同事为了避免library 包的确实频繁的修改和maven gradle 的配置,提前往项目中引入大量的常用的library 包,实际上也是违背了yangni 原则。 

KISS 原则讲的是如何做,YAGNI 原则是讲的要不要做。 

 

标签:return,原则,实现,代码,ipUnitIntValue,KISS,false,设计模式
From: https://www.cnblogs.com/dousil/p/18039312

相关文章

  • 设计模式--观察者(Observer)模式
    目录概念概念观察者模式(ObserverPattern)是C++中常用的一种设计模式,它定义了对象间的一种一对多的依赖关系。在这种模式中,当一个对象(被观察者,Subject)的状态发生改变时,所有依赖于它的对象(观察者,Observer)都会收到通知并自动更新。这种模式的结构通常包括四个部分:抽象主题(Subject......
  • 接口隔离原则(设计模式)
    定义“Clientsshouldnotbeforcedtodependuponinterfacesthattheydonotuse”个人认为接口隔离原则,和单一原则有点像。一个接口实现一个功能。 不过,你应该已经发现,接口隔离原则跟单一职责原则有点类似,不过稍微还是有点区别。单一职责原则针对的是模块、类、接口......
  • 里斯替换原则 (设计模式)
    定义IfSisasubtypeofT,thenobjectsoftypeTmaybereplacedwithobjectsoftypeS,withoutbreakingtheprogram。Functionsthatusepointersofreferencestobaseclassesmustbeabletouseobjectsofderivedclasseswithoutknowingit。子类能够替......
  • 单一职责 (设计模式)
    定义一个类或者模块只复杂完成一个职责。也就是说,不要设计大而全的类,要设计力度小,功能单一的类。一个类包含两个以上和业务不相干的功能,应该将他拆分多个功能更加单一,粒度更加细化的类。 比如一个类力既含有订单的一些操作,又包含用户的一些操作,而订单和用户是两个独立的业务领......
  • ImageList1控件的使用原则
    ImageList1的功能是设计时候,保存好一系列的图片。在设计加载后,绑定好使用控件,这里我们以TrayIcon1控件为例子 要更改 TrayIcon1控件的图标属性,  不能通过修改ImageList1,  要通过更改 TrayIcon1控件的相关属性,     TrayIcon1.IconIndex:=1;Imag......
  • 面向对象,到底是个什么鬼? (设计模式)
    什么才算是面向对象编程语言面向对象是支持类对性得语法机制,并有现成得语法机制,能方便得实现面向对象得封装,继承多态,抽象。 一般来讲,面型对象编程,是通过面向对像得编程语言来进行得,但是不用面型对象编程语言,我们照样可以进行面向对象编程,反过来讲,即使我们使用面向像得语言写出......
  • 那些维度评价代码的好坏?设计模式
    1.可维护性对于项目来说,维护代码的耗时,远远大于大于代码的编码。代码维护性非常关键主观评价标准:bug容易修复,添加功能比较简单。2.可读性代码的可读性,关乎代码的可维护性。 代码是否符合代码的命名规范。 命名是否规范,注释是否全面,函数是否长短合适,模块划分是否清......
  • 提升数据安全的五大原则
    PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。随着企业不断利用各类结构化和非结构化数据,包括快速流动、核心、边缘、人工生成、机器生成和机器人生成的数据,大多数企业继续构建信息孤岛。除......
  • 类变量和类方法、代码块、单例设计模式、final关键字、抽象类、接口、内部类
    类变量和类方法类变量-提出问题说:有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?,编写程序解决。传统的方法来解决思路在main方法中定义一个变量count当一个小孩加入游戏后count++,最后个count就记录有多少小孩玩游戏小孩是一个类,有名字属......
  • 依赖注入(Dependency Injection, DI)是一种设计模式,例如,在React中,父组件可以通过props向
    依赖注入renderprops其实就是React世界中的“依赖注入”(DependencyInjection)。所谓依赖注入,指的是解决这样一个问题:逻辑A依赖于逻辑B,如果让A直接依赖于B,当然可行,但是A就没法做得通用了。依赖注入就是把B的逻辑以函数形式传递给A,A和B之间只需要对这个函数......