CLeanCode -- 第三章 -- 函数

本文介绍了编写高效函数的八个关键原则:保持函数短小,每次只做一件事,使用描述性名称,理想参数数量为零,避免过多参数,区分指令与询问,使用异常处理,以及避免重复。通过实例解析了如何重构函数以提高代码可读性和可维护性。
摘要由CSDN通过智能技术生成

part03 - 函数

  • 函数是所有程序中的第一组代码;

1. 短小

  • 函数的第一条规则就是短小;
  • 代码块和缩进:
    • if 语句、else 语句、while语句,其中的代码块应该只占一行;
    • 该行应该是一个函数调用的语句;
    • 所以,函数的缩进层级不应该多于一层或两层;

2. 只做一件事

  • 编写函数是为了把较大的函数拆分为另一抽象层上的一系列步骤;
  • 判断函数是否只做了一件事,可以通过它是否能再拆出一个函数;
  • 栗子:对一个列表进行排序和求和:
def sum_and_sort(test_list):
    sum = 0
    for element in test_list:
        sum += element

    for index_i in range(len(test_list) - 1):
        for index_j in range(index_i + 1, len(test_list)):
            if test_list[index_i] > test_list[index_j]:
                test_list[index_i], test_list[index_j] = test_list[index_j], test_list[index_i]
    
    return sum, test_list
  • 重构后:
def sum_list(test_list):
    sum = 0
    for element in test_list:
        sum += element
    return sum


def sort_list(test_list):
    for index_i in range(len(test_list) - 1):
        for index_j in range(index_i + 1, len(test_list)):
            if test_list[index_i] > test_list[index_j]:
                test_list[index_i], test_list[index_j] = test_list[index_j], test_list[index_i]
    return test_list


def sum_and_sort(test_list):
    sum_list(test_list)
    sort_list(test_list)

3. 使用具有描述性的名称

  • 长而具有描述性的名称,要比短而令人费解的名称好;
  • 命名方式保持一致;
    • 使用与模块名一脉相承的短语、名词和动词给函数命名;
    • includeSetupAndTeardownPages、includeSetupPages、includeSuiteSetupPage、includeSetupPage 等;

4. 函数参数

  • 最理想的参数数量是 0;(零参数函数)
  • 尽量避免 3
    • includeSetupPage() 要比 includeSetupPageInto(newPageContent) 易于理解;
  • 可以从测试角度来看问题:
    • 没有参数的测试用例,就是小菜一碟;
    • 一个参数的测试用例,也不困难;
    • 两个参数的测试用例,就很麻烦了;
    • 三个以上,测试索要覆盖的组合简直无法无天;

4.1 标识参数

  • 向函数传入布尔值简直就是骇人听闻的做法;
    • 因为会传递函数不止一个操作的消息,若为 True 我该怎么做,若为 False 我该怎么做;

4.2 参数对象

  • 如果说函数需要 2 个、3 个或者 3 个以上的参数,就说明其中一些参数应该封装为类了;
  • 栗子:
Circle makeCircle(double x, double y, double radius)
Circle makeCircle(Point center, double radius)
  • 从参数创建对象,从而减少参数数量;

5. 分隔指令与询问

  • 函数要么做什么事,要么回答什么事;
  • 即函数要么修改某对象的状态,或返回该对象的有关信息;
  • 还是说明一件事,一个函数只做一件事;

6. 使用异常替代返回错误码

  • 使用异常替代返回错误码,错误处理代码就能从主路径代码中分离出来,从而得到简化;

6.1 抽离 try/catch 代码块

  • try/catch 代码块把错误处理与正常流程混为一谈;
  • 最好把 try 和 catch 代码块的主体部分抽离出来,形成另外的函数;
  • 栗子:(书本是 Java 的,Python 这一块异常不是很了解,可能会有语法错误,大概理解一下思想就行;)
  • 原代码:
try:
    deletePage(page)
    registry.deleteReference(page.name)
    configKeys.deleteKey(page.name.makeKey())
except(Exception):
    logger.log(Exception.message)
  • 抽离后:
try:
    deletePageAndAllReferences(page)
except(Exception):
    logError(Exception)
    

def deletePageAndAllReferences(page):
    deletePage(page)
    registry.deleteReference(page.name)
    configKeys.deleteKey(page.name.makeKey())
    

def logError(Exception):
    logger.log(Exception.message)

7. 别重复

  • 重复是软件中一切邪恶的根源

8. 如何写出这样的函数

  • 没有人一开始可以写出这样的函数;
  • 刚开始写的函数都是冗长而复杂的;
  • 写完之后,需要打磨这些代码:
    • 分解函数、修改名称、消除重复;最重要的是保持测试通过
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值