《编写可读代码的艺术》---拆分超长的表达式

关键思想

把你超长的表达式,拆分成更容易理解的小模块;使其不成为读者阅读上的“减速带”

1 “解释型”变量 

拆分表达式最简单的方法是引入一个额外的变量,让它来表达一个小一点的子表达式。

这个额外变量有时候被称作“解释”变量,因为它可以帮助解释子表达式的含义。

来个判断用户名称的例子

BAD

            string userInput = "kimmy:1989/4/11:male";
            
            if (userInput.Split(':').FirstOrDefault().Trim() == "kimmy")
            {
                Console.WriteLine("是kimmy");
            }

GOOD  引入“解释”变量

            string userInput = "kimmy:1989/4/11:male";
            string userName = userInput.Split(':').FirstOrDefault().Trim();

            if (userName == "kimmy")
            {
                Console.WriteLine("是kimmy");
            }

此处,我们使用userName,来解释该行对userInput进行一系列操作的目的。

在if判断的时候,我们清晰的明白:判断的对象,是用户输入的用户名。

2 “总结型”变量

你可以一眼看出作用的代码块,不需要引入额外的“解释型”变量,但是把它装入一个“总结型”变量仍然有用。

使用“总结型”变量的目的是:用一个短很多的名字来代替一大块代码 来更加直接地向读者传递编码意图。

来个权限判断的例子

BAD

            int userRights = 7;
            int editRights = 1;

            //如果用户有编辑的权限
            if ((userRights & editRights) == editRights)
            {
                
            }

            //如果用户没有编辑权限,文档是只读的
            if ((userRights & editRights) != editRights)
            {

            }

GOOD 引入“总结型”变量

            int userRights = 7;
            int editRights = 1;

            bool isUserHasEditRights = (userRights & editRights) == editRights;

            //如果用户有编辑的权限
            if (isUserHasEditRights)
            {
                
            }

            //如果用户没有编辑权限,文档是只读的
            if (isUserHasEditRights==false)
            {

            }

3 善用“摩根定理”  简化逻辑判断

如果你学过“电路”或者“逻辑课”,就记得有个叫“摩根定理”,把它应用于布尔表达式,可以得出两个等价的写法。

  • not (a or b or c)      <=>  (not a) and (not b) and (not c)
  • not (a and b and c)  <=>  (not a) or (not b) or (not c)

如果记不住这个写法,一个口诀就是(分别取反,转换与或)

比如判断文件是否可以操作

BAD 最外层还有反转,易读性差

            if ((isFileExist && !isFileProtected)==false)
            //文件无法写入

GOOD 简化了外层反转的逻辑

现在我们就用"摩根定理",去掉外面的逻辑反转;    谨记口诀(分别取反,转换与或)

是不是看起来代码的逻辑简单多了:如果文件不存在,或者文件存在保护,则无法写入。

            if (!isFileExist || isFileProtected)
            //文件无法写入

4:警惕被滥用的短路逻辑

在javascript里,短路逻辑用来初始化参数很方便,比如

 function showUserName(userName) {
            //如果没指定用户名称,则默认使用游客
            userName = userName || "游客";
            alert(userName);
        }

使用短路逻辑很方便,但是有时可能被滥用,以实现复杂逻辑

比如 我们要检查是否找到了桶

assert(!(bucket = FindBucket())

现在需求变更了,还要检查桶有没有被占用,另外接手的程序员见缝插针,写了个短路逻辑进去

 assert((!(bucket = FindBucket())) || !bucket.isOccupied());

尽管它只用一行代码就实现了两个检查的点,但是付出的代价是,我们在阅读的时候需要停下来想一想这个代码的意思--得不偿失。

改进的方法有很多,最简单的方法是分成两个语句:

//确保找到篮子
assert(!bucket = FindBucket());
//确保篮子没被占用
assert(!bucket.isOccupied());

5 拆分巨大的语句

还记得DRY原则吗?(don‘t repeat yourself)

把重复使用的变量提取成公用变量(不是全局变量,生命周期只局限在函数内。滥用全局变量会导致可读性变差)。

把重复使用的代码块提取成公用方法。

c/c++里面还可以使用“宏”来替你做重复的事情。

原文地址:https://www.cnblogs.com/kimmy/p/3695608.html