<读书笔记>(代码单元层面)BMS-1: 写小的代码
1 写人能够理解的代码, 而非计算机能够理解的
1.1 指导原则:
将一个代码单元(函数或方法)的长度限制在 15 行(这个经验值在大部分时候都适用: 95% 以上)以内. 这就要求在写的时候就要仔细规划, �满足这样的条件. 或者是将以前代码中的不满足要求的内容再进行分解.
这样的代码满足: 易于理解, 易于测试, 易于重用.
这里的重用并非是复制代码那样的重用, 这种重用是在一开始就该极力避免的.
1.2 如何运用这个原则
在实际工作中, 一个是写新的代码单元, 一个是修改老的代码单元. 这两种场景都需要�遵守上面的原则. 而为了保持原则不变, 则需要利用好一些在代码重构时候可以用到的方法:
-
方法展开(Extract Method): 即将之前超限方法中的若干种功能再次分解到多个单独的方法中. 这个方法的主要想法是将方法功能进行再次分解.
-
方法替换为方法对象(Replace Method with Method Object): 将方法替换为方法对象的思路就是如果这个方法的功能在分解的时候会导致过多的参数传入, 则可以将参数全部封装到一个新的类中, 然后用这个类来完成以前方法的某个功能.
1.3 针对这个原则的不同声音:
原则说起来容易, 但实际运用的时候却十分困难, 主要的反对声音集中在如下:
-
反对者说: 过多的代码单元会影响性能.
他们的原因是: 这样导致更多的方法调用, 上下文切换, 从而造成更多的性能影响.
实际上编译器会对这样的情况进行优化, 所以担心是无谓的.
故: 不要因为性能而去损害可维护性.
-
反对者说: 代码单元变小后, 变得更加分散, 所以更加难以阅读.
实际上这个是不存在的. 长代码更加难以阅读和理解.
-
反对者说: 某些单元的分解是不可能的.
有时分解一个单元的确比较困难, 但是并非不可能�.
若这个时候重构看似可能, 但实际却没有道理, 这时就该思考一下架构问题了.
-
反对者说: 没有看到功能分解带来的任何好处.
由于每个代码单元都是一个完整的功能单元, 故这个时候就可以思考一下命名上的问题了. 因为从理解上和�可重用上都是好处大于坏处的.
1.4 总结
多思考架构上的问题, 或者是命名上的问题, 对代码进行合理的分解.
在 SIG 的评分中有针对行数的判断. 大的代码单元的出现一般都对代码质量有很大影响.
在 swift 中可以使用 swift-lint 来控制代码行数.
附录
附上使用的 .swiftlint.yml 配置文件(隐藏文件):
disabled_rules: # 在运行时不执行如下检查规则
# - colon
# - comma
# - control_statement
# - for_where
# - force_unwrapping
opt_in_rules: # 在运行时加入的可选检查规则
- empty_count
- missing_docs
- closure_end_indentation
- closure_spacing
- force_unwrapping
- implicitly_unwrapped_optional
- operator_usage_whitespace
- redundant_nil_coalescing
# 可以使用如下命令查看所有可用规则: swiftlint rules
included: # 包含目录
- ./
excluded: # 排除目录, 这个是在包含目录之前进行排除的
- Carthage
- Pods
force_cast: warning # implicitly
force_try:
severity: warning # explicitly
# 行宽
line_length: 120
# 类型体的长度
type_body_length:
- 300 # warning
- 400 # error
# 方法或函数体的长度
function_body_length: 30
# 方法或函数的参数个数限制
function_parameter_count: 6
# 文件的长度限制
file_length:
warning: 500
error: 1200
# 类型名称的长度规定
type_name:
min_length: 2 # only warning
max_length: # warning and error
warning: 40
error: 50
excluded: iPhone # excluded via string
# 标识符长度规定
identifier_name:
min_length: # only min_length
error: 2 # only error
excluded: # excluded via string array
- id
- vm
- URL
- GlobalAPIKey
reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji)