iOS第三方库OCLint

OCLint 规则查询 & 简单理解

2021-03-25  本文已影响0人  Aaron升

Rule Category

Rule Name Name 简单理解
BitwiseOperatorInConditional bitwise operator in conditional OCLint认为位运算符可读性不好,不建议用位运算
BrokenNilCheck broken nil check 无效的nil检查,结果往往存在问题
BrokenNullCheck broken null check 无效的null检查,可能会使程序崩溃
BrokenOddnessCheck broken oddness check 对奇数进行检查(x % 2 == 1)不适用于负数,应使用(x & 1 == 1)或者(x % 2 != 0)
CollapsibleIfStatements collapsible if statements 两个连续if语句的条件可以合并的应该合并,可以提高可读性,使代码整洁。
ConstantConditionalOperator constant conditional operator 条件运算符的条件永远为truefalse,令人困惑
ConstantIfExpression constant if expression if语句的条件始终为truefalse,令人困惑
DeadCode dead code 存在永远不会被执行的代码
DoubleNegative double negative 使用双重否定是没有意义的
ForLoopShouldBeWhileLoop for loop should be while loop 在某些情况下,可以将某些for循环简化为while循环,以使代码更简洁
GotoStatement goto statement goto语句被认为是有害的,慎重使用
JumbledIncrementer jumbled incrementer 混乱的增量器通常是错别字。如果不是笔误,那么代码阅读起来是非常混乱的
MisplacedNilCheck misplaced nil check nil 判断 放错位置,逻辑短路
MisplacedNullCheck misplaced null check null 判断 放错位置,可能会程序崩溃
MultipleUnaryOperator multiple unary operator 多重一元运算符不易理解,应简化
ReturnFromFinallyBlock return from finally block 不建议从finally代码块中return
ThrowExceptionFromFinallyBlock throw exception from finally block finally代码块中抛出异常,可能会掩盖其他异常或代码缺陷
Rule Name Name 简单理解
CallingProhibitedMethod calling prohibited method 当一个方法用__attribute__((annotate("oclint:enforce[prohibited method]")))标记时,禁止被调用(ps:不清楚使用场景)
CallingProtectedMethod calling protected method 当一个方法用__attribute__((annotate("oclint:enforce[protected method]")))标记时,它将是受保护的。在Objective-C中虽然没有protected这个概念,但是在设计的角度,我们有时希望一个方法只希望被它自己或者它的子类调用。这个方法可以模仿protected在有人调用的时候给一个警告
MissingAbstractMethodImplementation missing abstract method implementation 当一个方法用__attribute__((annotate("oclint:enforce[abstract method]")))标记时,如果该方法没有具体实现,可以检测出来
MissingCallToBaseMethod missing call to base method 当一个方法用__attribute__((annotate("oclint:enforce[base method]")))标记时,其实现都必须调用super类的该方法
MissingHashMethod missing hash method isEqual方法被重写时,hash方法也必须重写
Rule Name Name 简单理解
AssignIvarOutsideAccessors ivar assignment outside accessors or init 检查是否在gettersetterinit method以外的方法对成员进行赋值
AvoidBranchingStatementAsLastInLoop avoid branching statement as last in loop 在循环最后加入分支语句可能是个bug,负责理解起来比较困难,很大程度上会遗忘一些事情,导致一些错误
DestructorOfVirtualClass destructor of virtual class 虚拟类的析构函数必须是虚拟的(ps:不太理解)
InvertedLogic inverted logic 倒置逻辑难以理解(例如:(!i ? -1 : 1))应改为(i ? 1 : -1)
MisplacedDefaultLabel ill-placed default label in switch statement switch语句中,default应放在最后的位置,否则令人困惑
MissingBreakInSwitchStatement missing break in switch statement switch语句中缺少break,很可能导致错误
MissingDefaultStatement missing default in switch statements switch语句中缺少default的情况,当switch语句未覆盖所有可能得情况时,必须要有default标签
NonCaseLabelInSwitchStatement non case label in switch statement 标签成为switch语句中的一部分时,非常令人困惑
ParameterReassignment parameter reassignment 大多数情况下,对传入的参数进行重新赋值可能会造成问题
PreferEarlyExit prefer early exits and continue return时,尽量让return提前,可以更轻松地理解代码(ps:参考例子
ProblematicBaseClassDestructor base class destructor should be virtual or protected 基类的析构函数,要么是publicvirtual的,要不是protectednonvirtual
TooFewBranchesInSwitchStatement too few branches in switch statement switch语句中的分支太少,可以用if语句代替,提高可读性
UnnecessaryDefaultStatement unnecessary default statement in covered switch statement switch语句涵盖所有可能的情况时,不需要default标签,应将其删除
Rule Name Name 简单理解
AvoidDefaultArgumentsOnVirtualMethods avoid default arguments on virtual methods 避免给虚函数设置默认参数,给虚函数设置默认参数会破坏多样性和引起不必要的层次结构发杂性
AvoidPrivateStaticMembers avoid private static members 避免使用私有静态成员,静态成员很容易破换封装性
Rule Name Name 简单理解
EmptyCatchStatement empty catch statement 空的catch,捕获了异常,但在未进行任何处理
EmptyDoWhileStatement empty do/while statement 空的do-while语句
EmptyElseBlock empty else block 空的else语句
EmptyFinallyStatement empty finally statement 空的finally
EmptyForStatement empty for statement 空的for循环
EmptyIfStatement empty if statement 空的if语句
EmptySwitchStatement empty switch statement 空的switch语句
EmptyTryStatement empty try statement 空的try
EmptyWhileStatement empty while statement 空的while语句
Rule Name Name 简单理解
UseBoxedExpression use boxed expression 检测出可以使用框式表达式代替的地方,更加简单易读(例如:[NSNumber numberWithInt:(43 - 1)] 改为 @(43 - 1)
UseContainerLiteral use container literal 检测出可以使用容器字面量代替的地方(例如:[NSArray arrayWithObjects:@1, @2, @3, nil] 改为 @[ @1, @2, @3 ]
UseNumberLiteral use number literal 检测出可以使用数值字面量代替的地方(例如:[NSNumber numberWithInt:42] 改为 @42
UseObjectSubscripting use object subscripting 检测出可以使用下标访问代替的地方(例如:[arr objectAtIndex:0] 改为 arr[0]
Rule Name Name 默认 简单理解
LongVariableName long variable name LONG_VARIABLE_NAME=20 变量名称太长,影响可读性
ShortVariableName short variable name SHORT_VARIABLE_NAME=3 变量名称太短,难以理解其含义
Rule Name Name 简单理解
RedundantConditionalOperator redundant conditional operator 冗余的条件运算符,应简化
RedundantIfStatement redundant if statement 冗余的if语句,应简化
RedundantLocalVariable redundant local variable 多余的局部变量,可以省略
RedundantNilCheck redundant nil check 多余的nil 检查,因为在OC中向nil发送任何消息都会返回空值
UnnecessaryElseStatement unnecessary else statement 如果if中已经带有return,则不需要写else语句
UnnecessaryNullCheckForDealloc unnecessary null check for dealloc dealloc中不需要判空,就能删除元素(ps:不清楚发生场景)
UselessParentheses useless parentheses 无用的括号
Rule Name Name 默认 简单理解
DeepNestedBlock deep nested block NESTED_BLOCK_DEPTH=5 代码块嵌套层数太深
HighCyclomaticComplexity high cyclomatic complexity CYCLOMATIC_COMPLEXITY=10 高圈复杂度,由决策点数量来决定,例如if, while, for(ps:if内的多个判断组合都会计算个数)
HighNPathComplexity high npath complexity NPATH_COMPLEXITY=200 高npath复杂度,NPath的复杂性取决于各种可能的执行路径数
HighNcssMethod high ncss method NCSS_METHOD=30 方法有效代码行数太多(ps:block内的代码不算)
LongClass long class LONG_CLASS=1000 类的实现代码行数太多
LongLine long line LONG_LINE=100 单行太长,可读性差
LongMethod long method LONG_METHOD=50 方法行数太多(ps:空行也算在内)
TooManyFields too many fields TOO_MANY_FIELDS=20 字段太多
TooManyMethods too many methods TOO_MANY_METHODS=30 方法太多
TooManyParameters too many parameters TOO_MANY_PARAMETERS=10 参数过多
Rule Name Name 简单理解
UnusedLocalVariable unused local variable 已声明但未使用的局部变量
UnusedMethodParameter unused method parameter 未使用的方法参数(ps:代理方法的参数不一定用到,可以忽略掉此规则)

自定义阈值 & 理由

默认:LONG_VARIABLE_NAME=20

OC命名规范在于完整、清晰,因此很容易出现较长的命名,例如UIApplicationWillChangeStatusBarOrientationNotification(都55个字符了),OCLint的变量命名长度规范默认为20,在OC中显然很多命名都不符合OCLint的规范,可以将此规范阈值改高一写,当然自己在命名时也不要毫无保留地随意用特别长的命名。

PS:写一门语言,就按该语言的习惯来写代码,否则各种不同习惯的代码混杂在一起很难受,现状就是这样。很反感有些以前写其他开发语言的同学在写OC时带上其他语言的习惯,例如函数命名、变量命名都喜欢缩写,阅读他们的代码还得去猜这个函数、变量是干什么的。

默认:LONG_LINE=100

此规则初衷是不希望一行代码太长,正如前面所说,由于OC的命名习惯,很容易超出OCLint的默认限制,但是调用系统方法就很容易超出限制,因此可以将此规范阈值改高一些。

默认:LONG_METHOD=50

我们希望一个方法内不要做太多事,保证单一职责原则,因此OCLint添加了此规范限制,而这个限制连同空行也计算在内,50行的限制也太少了,在规范自己代码的同时,可以适当提高一下此限制。

默认:NCSS_METHOD=30

此规则是限制方法的有效行数,同样的,在规范自己代码的同时,可以适当提高一下此限制。

默认:CYCLOMATIC_COMPLEXITY=10

此规则为高权复杂度,由ifwhilefor等决策点来决定的,实际项目中业余逻辑复杂,各种判断的决策点太多,可以适当提高此规范限制的阈值,当然最重要还是拆分简化方法。

个人存在疑问的规则

不错,一般可以将return提前的尽量提前,阅读者可以更好地理解其中的逻辑,但这个规则会使很多getterinit方法报警告,此时还有必要将return提前吗?对于getterinit方法我是更倾向于苹果默认的写法。
但我又不想忽略此规则,因为其他方法,我更认可将return提前。
有什么优雅的处理方式吗?或OCLint的作者在这个问题上是否有什么想法?

对于Objective-C上,在方法内对入参进行重新赋值,并不会影响调用者传入的原数据,自己也做过测试验证。
可能此规则是针对其他语言而言的,但还是想确认一下,在Objective-C中是否有必要使用此规则?否则的话我将选择忽略此规则。希望有知道的大神不吝赐教!

根据官方文档和网友对此规则的解释,循环最后不能加分支语句(即 continue、break、return?)。
对此我不太理解,为什么不可以?有时候代码逻辑就必须那样写啊!还是说为了迎合着个逻辑,要用更复杂的代码来避免(例如增加BOOL变量,在循环外面判断后再return)?

上一篇下一篇

猜你喜欢

热点阅读