在iOS移动银行应用程序中使用SwiftLint静态代码分析器

远程服务渠道能力中心主管Oleg Ivanov



大家好!正如“ ICD的移动银行:发展历史”一文中所承诺的那样,今天我想谈谈静态代码分析器及其在银行iOS移动应用程序中的应用经验。

让我们设置使用此工具箱要实现的目标:

  • 及早发现错误和缺点;
  • Code Style ( — , ).

实现我们目标的一种常见方法是手动检查代码- 代码审查

测试人员或一组测试人员仔细研究要测试的代码,然后确定将来可能变得错误的错误或代码部分,并通过对代码的注释提出改进建议,开发人员将在一段时间后(!)对其进行分析和纠正。如我们所见,一个漫长而昂贵的代码验证过程正在兴起。另外,总有一个人为因素-评论者可以跳过一些错误。

在这里,静态代码分析器将为我们提供帮助。

静态代码分析器-启动一个自动化过程,以检测程序源代码中的错误和不足。

静态代码分析器不是灵丹妙药,也不是手动代码检查的替代品,但它们是减少执行检查和快速发现模式错误所需时间的出色工具。使用静态分析仪的相关性只会随着时间而增长。

作为iOS项目中的静态代码分析器,我们使用SwiftLint。

SwiftLint是一个Swift代码自动检查实用程序,可在项目的构建阶段运行。该实用程序包含一组规则,可以用您的自定义规则来补充这组规则。该工具还用于遵守代码样式。

为什么在应用程序中遵循代码样式很重要?
当您是一个项目的开发人员时,一切都会变得很简单:您以自己的风格编写代码,并且可以以这种方式买得起代码:



但是当您在一个大型开发团队中工作时。一个重要的因素是理解和找到在其他人的代码中插入改进的地方的速度。
在这里,所有团队成员都必须接受编写代码的约定和规则。但是,如何检查其合规性呢?再一次,SwiftLint静态代码分析器将为我们提供帮助。而且我们的代码将使团队的每个成员都能理解它的愉悦外观:



要熟悉该工具,我建议您阅读官方文档

安装SwiftLint很简​​单:

  1. 将pod'SwiftLint'添加到项目podfile
  2. 在项目中添加一个新的“运行脚本阶段”。

    "${PODS_ROOT}/SwiftLint/swiftlint"
  3. SwiftLint .swiftlint.yml
  4. .swiftlint.yml , SwiftLint

如果SwiftLint嵌入项目已经包含代码,则您必须耐心并且系统地修复所有SwiftLint建议。他通过常见的错误和警告显示以及有关建议的全面提示来形成它们。



同样在括号中,它显示发起建议的规则的名称(operator_usage_whitespace)

在这种情况下,它们是:

运算符用法空白
运算符必须由单个空格包围。

正确的代码:




推荐的代码:



每个规则都有一组属性:

标识符operator_usage_whitespace
默认情况下启用禁用
由自动更正支持
类型style
Analyzer规则
Swift编译器的最低版本3.0.0
默认配置警告请

注意“ Swift编译器的最低版本” -将规则的使用与此属性以及项目设置相关联。“默认配置”

属性显示了如何感知具有此属性的规则:常规警告或编译错误,例如强制强制转换规则(默认配置:错误) 所有规则都可以在非常方便且有说明的文档中找到



下面,我将介绍我们在团队中选择的规则,您可以将其用作创建项目的示例。

我们将所有规则分为功能性和风格性 -是,是,是和每个花括号内有一个空格,并且闭合参数应与左括号和... :)在同一行。我没有绘制规则,您可以使用上面的链接轻松找到有关规则的信息。

功能

- private_outlet
- force_unwrapping
- force_cast
- force_try
- strong_iboutlet
- private_action
- block_based_kvo
- contains_over_first_not_nil
- discarded_notification_center_observer
- discouraged_direct_init
- discouraged_object_literal
- discouraged_optional_boolean
- discouraged_optional_collection
- duplicate_imports
- dynamic_inline
- empty_count
- empty_parameters
- empty_parentheses_with_trailing_closure
- empty_string
- explicit_enum_raw_value
- function_default_parameter_at_end
- generic_type_name
- identical_operands
- implicit_getter
- is_disjoint
- notification_center_detachment
- nsobject_prefer_isequal
- redundant_set_access_control
- unused_capture_list

的风格

- unneeded_pa​​rentheses_in_closure_argument
- let_var_whitespace
- yoda_condition
-结肠
-逗号
- closure_parameter_position
- closure_spacing
- collection_alignment
- leading_whitespace
-标记
- opening_brace
- operator_usage_whitespace
- operator_whitespace
- protocol_property_accessors_order
- return_arrow_whitespace
- switch_case_alignment
- statement_position
- trailing_comma
- trailing_newline
- unneeded_break_in_switch
- custom_rules
- closure_end_indentation
- file_name_no_space
- unowned_variable_capture
- no_space_in_method_call
- contains_over_filter_count
- contains_over_filter_is_empty
- contains_over_range_nil_comparison
- duplicate_enum_cases
- empty_collection_literal

也将SwiftLint的,我们通过增加配置文件.swiftlint.yml适当的设置我们的代码库只选目录的目标:

包括:

- <代码库目录>


我们已经创建了不予受理的规则打印功能。打印是一项非常艰巨的操作。通过配置.swiftlint.yml文件:

custom_rules:
  disable_print:
    included: ".*\\.swift"
    name: "print usage"
    regex: "((\\bprint)|(Swift\\.print))\\s*\\("
    message: "Prefer os_log over print"
    severity: error

此规则促使我们编写日志记录功能(具有日志记录级别)。开发人员使用此日志记录来进行快速调试,例如,对于错误的任何分析和开发,都需要带有参数,请求/响应主体的日志。对于Release,我们的.none版​​本中的日志级别。其余使用打印功能将导致项目的生成错误。

func logApp(level: Constants.LogLevel, items: Any...) {
    if Constants.logLevel == .none {
        return
    }
    
    if level.rawValue <= Constants.logLevel.rawValue {
        // swiftlint:disable disable_print
        if let strings = items as? [String] {
            for string in strings {
                print(string)
            }
        } else {
            print(items)
        }
        // swiftlunt:enable disable_print
    }

但是要使用print函数,我们必须使用SwiftLint在日志记录函数中关闭其调用,以忽略在带有特殊指令标记的代码块上自己的规则。

// swiftlint:disable disable_print
// swiftlunt:enable disable_print

SwiftLint可以忽略自己的规则:

// swiftlint:disable <rule1 [rule2 rule3…]>
<,   SwiftLint   rule1 [rule2 rule3…]>
// swiftlunt:enable <rule1 [rule2 rule3…]>

要么

// swiftlint:disable all
<,   SwiftLint   >
// swiftlint:enable all

利用这个机会,充分意识到这是必要的!

最后,我注意到:在我们的团队中使用SwiftLint可使手动代码审查的成本降低了20%。现在,我们的审阅者无需关注典型错误(强制转换等),代码样式,而可以完全专注于检查新代码。这显着提高了团队的整体效率(无需修复此类错误检查,这些都是合格的员工,他们的时间非常重要)。

所有!现在SwiftLint永远与您同在:)


All Articles