大家好,我叫谢伟,是一名程序员。
上节从编程语言特性的角度讲述了编写可读代码的几个要点。
编写可读的代码的艺术
本节接着从编程语言的语言特性:流程控制和循环等角度,再次谈谈编写可读代码的要点。
还记得吗,编写可读代码的核心的要点是什么?
写易于理解的代码
编程语言关于流程控制的语句有哪些?
涉及流程控制的话,一般涉及条件判断,你有认真思考条件判断语句中的参数的顺序吗?
比如:
if (number < 10) {} // A
if (10 > number) {} // B
if (receivedNumber < expectedNumber) // C
if (expectNumber > receivedNumber) // D
上述实例,你会条件语句的参数顺序你会选择哪个?
A, C
那么应该准从什么样的尊则?
左边倾向于变量,右边倾向于常量;
其实这不是什么新的东西,在我们学习数学中的未知数的时候就是这么做的。
x < 2
可以参照下面的下面准则:
if createParam.Data.ShopType != RegionEntrances {
newShop.ShopUUID = tools.GenerateUUID(16, createParam.Data.Name, company.Name)
} else {
var tmpShop models.Shop
if notFound := database.POSTGRES.Where("company_id = ? AND shop_type = ?", company.ID, createParam.Data.ShopType).First(&tmpShop).RecordNotFound(); notFound {
newShop.ShopUUID = tools.GenerateUUID(16, createParam.Data.Name, company.Name)
} else {
newShop.ShopUUID = tmpShop.ShopUUID
}
}
上文根据输入的 ShopType 字段是否是 RegionEntrances;
上文没有一定的规范,搞的整个流程不容易理解。
根据:先处理正向逻辑,处理简单的,处理可疑或者有趣的准则,改善如下(仅仅只是调换顺序)
if createParam.Data.ShopType == RegionEntrances {
var tmpShop models.Shop
if notFound := database.POSTGRES.Where("company_id = ? AND shop_type = ?", company.ID, createParam.Data.ShopType).First(&tmpShop).RecordNotFound(); !notFound {
newShop.ShopUUID = tmpShop.ShopUUID
} else {
newShop.ShopUUID = tools.GenerateUUID(16, createParam.Data.Name, company.Name)
}
} else {
newShop.ShopUUID = tools.GenerateUUID(16, createParam.Data.Name, company.Name)
}
三目运算符一定程度上能够精简代码,减少代码的行数,但是却存在另外一个缺点,即:不容易理解(虽然大学教材总会考这类题目,判断执行的顺序和结果)
只在简单场景下使用三目运算符。
经常我们编写函数的时候,喜欢声明一个变量用来存储结果,到所有的逻辑结束后返回这个变量作为函数的返回值。
几个建议:
层级的增多,增加了认知的负担。而且容易出现不容易发现的 bug。
如何减少嵌套:
建议使用短表达式
如何做到短表达式:
如何拆分:
使用中间变量
中间变量的用途可以划分为:
比如:
if createParam.Data.ShopType == RegionEntrances {}
感觉表达式长了,怎么做:
var shopTypeEqual = createParam.Data.ShopType == RegionEntrances
if shopTypeEqual {}
编程语言支持显式申明,也支持自动识别变量类型,你觉得哪种好?
var number int
number = 10
numberMax := 100
显式的命名更好,强类型编程语言遇到的问题可能还不多,弱类型的编程语言,可能存在隐藏的 bug.
变量的申明区分:全局和局部
问:全局变量多点好?还是少点好? 问:局部变量是统一在函数下侧统一命名,还是靠近需要使用变量的语句处?
全局变量少用,随着项目越来越复杂,可能在某个角落,全局变量就进行了更改。这样引起的 异常处理很难进行追踪和分析。
局部变量在靠近使用该变量的地方声明并使用,这样,逻辑、思维不容易断。
比如:
var fetchMaxNumber = func( ) int {
var maxNumber int
var minNumber int
...
...
...
do...
return maxNumber
}
var fetchMaxNumber = func()int{
...
...
var (
maxNumber int
minNUmber int
)
do...
return maxNumber
}
第二种变量的组织方式优于第一种,而且更利于思维。像第一种,读到真正的处理逻辑,还需要回过头去看下变量的声明,给思维造成了额外的认知负担,尤其你还喜欢写大段代码的函数。
一个准则:全局变量的个数需要尽可能少,如果有可能,使用常量替代。局部变量最好在需要使用变量的地方进行申明。
好,那么我们的目的便是尽可能的减少变量。
如何减少?
软件架构有一种很流行的设计方法,叫:领域驱动设计,对持续迭代的微服务有很大的帮助。该领域驱动方法将项目划分为4个层级。
其中谈到领域,和我们之前变量的命名建议使用专业的词、领域内的词不谋而合。
同时,基础设施层是将一些辅助性的任务集合。比如文件处理、比如网络请求处理、比如字符串处理等
组织代码节也提倡这么做。
实现核心的业务需求时,尽量将这些工具类的功能规整在独立的基础设施里,专注于实现核心的业务。
代码的组织,一个是项目的组织,一个良好的项目组织方式,一定程度上能体现代码的逻辑性。
另外一个比较重要的是函数的组织。
有下面几条准则:
全文完,我是谢伟,再会。