OCLint的部分规则(Size 部分)

对OCLint的部分规则进行简单翻译解释,有部分进行了验证以及进一步分析、测试。OCLint其他相关内容如下:

1、high cyclomatic complexity

Cyclomatic complexity is determined by the number of linearly independent paths through a program’s source code. In other words, cyclomatic complexity of a method is measured by the number of decision points, like if, while, and for statements, plus one for the method entry.
简单解释:圈复杂度过高。统计一个函数有多少个分支(if, while,for,等等),没有的话复杂度为一,每增加一个分支复杂度加一。简单计算的话V(G)=e-n+2。其中,e表示控制流图中边的数量,n表示控制流图中节点的数量,或者V(G)=区域数=判定节点数+1。当然可以数一数。

 void example(int a, int b, int c) { // 1
        if (a == b) {                   // 2
            if (b == c) {               // 3 
            } else if (a == c){          // 3
            }
            else {
            }
        }
        for (int i = 0; i < c; i++)  {  // 4
        }
        switch(c)  {
            case 1:                   // 5
                break;
            case 2:                   // 6
                break;
            default:                  // 7
                break;
        }
    }

Thresholds:
CYCLOMATIC_COMPLEXITY The cyclomatic complexity reporting threshold, default value is 10. Suppress:
Suppress:
__attribute__((annotate("oclint:suppress[high cyclomatic complexity]")))
References:
McCabe (December 1976). “A Complexity Measure”. IEEE Transactions on Software Engineering: 308–320

2、long class

Since:0.6 定义类传送门~点击

Long class generally indicates that this class tries to do many things. Each class should do one thing and that one thing well.
简单解释:类行数太多。

class Foo {
        void bar() {
            // 1001 lines of code
        }
    }

Thresholds:
LONG_CLASS The class size reporting threshold, default value is 1000.

3、 long line

When the number of characters for one line of code is very high, it largely harms the readability. Break long lines of code into multiple lines.
简单解释:单行代码太长,影响可读性。

void example()
    {
        int a012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789;
    }

Thresholds:
LONG_LINE The long line reporting threshold, default value is 100.

4、long method

Long method generally indicates that this method tries to do many things. Each method should do one thing and that one thing well.
简单解释:方法太长,影响阅读,应该实现单一职责。

void example() {
        cout << "hello world";
        cout << "hello world";
        // repeat 48 times
    }

Thresholds:
LONG_METHOD The long method reporting threshold, default value is 50.

5、 high ncss method

This rule counts number of lines for a method by counting Non Commenting Source Statements (NCSS). NCSS only takes actual statements into consideration, in other words, ignores empty statements, empty blocks, closing brackets or semicolons after closing brackets. Meanwhile, a statement that is broken into multiple lines contribute only one count.
简单解释:其实是指某个代码块中代码行数过多(只统计有效的语句),查看代码块中代码是否能拆分,公共功能能否提供一个公共接口。空语句,空块,右括号或分号后的右括号会被忽略。

void example()          // 1
    {
        if (1)              // 2
        {
        }  else                // 3
        {
        }
    }

6、deep nested block

This rule indicates blocks nested more deeply than the upper limit.
简单解释:嵌套块是否超过指定的深度值.

if (1) {               // 1
        {           // 2
            {       // 3
            }
        }
    }

7、high npath complexity

NPath complexity is determined by the number of execution paths through that method. Compared to cyclomatic complexity, NPath complexity has two outstanding characteristics: first, it distinguishes between different kinds of control flow structures; second, it takes the various type of acyclic paths in a flow graph into consideration.
Based on studies done by the original author in AT&T Bell Lab, an NPath threshold value of 200 has been established for a method.
简单解释:NPath复杂度是一个方法中各种可能的执行路径总和,一般把200作为考虑降低复杂度的临界点,这里提示NPath复杂度过高。

void example() {
        // complicated code that is hard to understand
    }

Thresholds:
NPATH_COMPLEXITY The NPath complexity reporting threshold, default value is 200.
Suppress:
__attribute__((annotate("oclint:suppress[high npath complexity]")))
References:
Brian A. Nejmeh (1988). “NPATH: a measure of execution path complexity and its applications”. Communications of the ACM 31 (2) p. 188-200

8、too many fields

A class with too many fields indicates it does too many things and lacks proper abstraction. It can be redesigned to have fewer fields.
简单解释:一个类中有定义太多东西,需要进行适当的抽象、设计。

 class c {
        int a, b;
        int c;
        // ...
        int l;
        int m, n;
        // ...
        int x, y, z;
        void m() {}
    };

9、too many methods

A class with too many methods indicates it does too many things and is hard to read and understand. It usually contains complicated code, and should be refactored.
简单解释:一个类有太多的方法,证明他做了太多的事儿,不利于理解。应该考虑重构。考虑单一职责。

class c {
        int a();
        int b();
        int c();
        // ...
        int l();
        int m();
        int n();
        // ...
        int x();
        int y();
        int z();
        int aa();
        int ab();
        int ac();
        int ad();
        int ae();
    };

10、too many parameters

Methods with too many parameters are hard to understand and maintain, and are thirsty for refactorings, like Replace Parameter With method, Introduce Parameter Object, or Preserve Whole Object.
简单解释: 一个方法中参数过多。

 void example(int a, int b, int c, int d, int e, int f,
        int g, int h, int i, int j, int k, int l) {
    }

TOO_MANY_PARAMETERS The reporting threshold for too many parameters, default value is 10.
References:
Fowler, Martin (1999). Refactoring: Improving the design of existing code. Addison Wesley.

Basic(基本)

BitWiseOperationInConditional (在条件语句中查找按位操作的条件、虽然这些操作都很“聪明”,但太聪明的语法很难理解 like:if (a | b))
BrokenNilCheck (nil检查 在某些情况会返回相反的结果 like:if (!obj1))
BrokenNullCheck (null检查会导致程序crash like:if (a == NULL)
BrokenOddnessCheck (x % 2 == 1 对于负数不起作用、使用 x & 1 == 1 or x % 2 != 0 代替)
CollapsibleIfStatements(检查是否两个情况可以合在一个条件中

 if (x)              // these two if statements can be
    {
        if (y)          // combined to if (x && y)
        {
            foo();
        }
    }`

ConstantConditionalOperator(是否条件永远true或者永远false like:int a = 1== 1 ? 1:0)
ConstantIfExpression(条件恒true like:if(true))
DeadCode (永远不会执行的代码 like:if(a = 1) return 1; return 2;//deadcode)
DoubleNegative(双重否定 like:if(!!a))
ForLoopShouldBeWhileLoop (在应该使用while的时候是用来for)
GotoStatement (使用goto 语句 like:goto a)
JumbledIncrementer 乱七八糟的增量 like:

for (int i = 0; i < a; i++) {
        for (int j = 0; j < a; i++) { // references both 'i' and 'j'
        }
    }

MisplacedNilCheck (nil 检查被放错了地方、在OC中、向一个nil对象发送消息、什么也不会发生、但是代码读起来会很让人费解 like:if ([obj1 isEqualTo:obj2] && obj1))
MisplacedNullCheck (null check被放错了地方、在C 和C++中、想一个null 指针发送消息会导致crash like:if (a->bar(b) && a != NULL))
MultipleUnaryOperator (多重一元操作很难理解 like:int b = -(+(!(~1)));)
ReturnFromFinallyBlock(在finallyBlock 中return 是不推荐的)

@try
    {
        foo();
    }
    @catch(id ex)
    {
        bar();
    }
    @finally
    {
        return;         // this can discard exceptions.
    }

ThrowExceptionFromFinallyBlock()

@try {;}
    @catch(id ex) {;}
    @finally {
        id ex1;
        @throw ex1;                              // this throws an exception
        NSException *ex2 = [NSException new];
        [ex2 raise];                             // this throws an exception, too
    }

Cocoa(objc)

ObjCVerifyIsEqualHash(重写isEqual 一定要重写 hash)
ObjCVerifyIsEqualHash(必须call super的情况 比如 layoutSubViews)
ObjCVerifyProtectedMethod(因为在OC中是没有protected,所以有的时候希望强制某个方法只能被它自己或者子类才能调用)

@interface A : NSObject
- (void)foo __attribute__((annotate("oclint:enforce[protected method]")));
@end

@interface B : NSObject
@property (strong, nonatomic) A* a;
@end

@implementation B
- (void)bar {
    [self.a foo]; // calling protected method foo from outside A and its subclasses
}
@end

ObjCVerifySubclassMustImplement (子类必须实现的方法)

@interface Parent

- (void)anAbstractMethod __attribute__((annotate("oclint:enforce[subclass must implement]")));

@end

@interface Child : Parent
@end

@implementation Child

/*
// Child, as a subclass of Parent, must implement anAbstractMethod
- (void)anAbstractMethod {}
*/

@end

Convention(惯例)

AvoidBranchingStatementAsLastInLoop (在一个循环的最后语句中使用break非常让人疑惑)

 for (int i = 0; i < 10; i++)
    {
        if (foo(i))
        {
            continue;
        }
        break;      // this break is confusing
    }

CoveredSwitchStatementsDontNeedDefault (switch中如果case覆盖了所有的情况、那么defaul 是不需要的)

typedef enum {
    value1 = 0,
    value2 = 1
} eValues;

void aMethod(eValues a)
{
    switch(a)
    {
        case value1:
            break;
        case value2:
            break;
        default:          // this break is obsolete because all
            break;        // values of variable a are already covered.
    }
}

DefaultLabelNotLastInSwitchStatement(default没有在最后一个)

void example(int a)
{
    switch (a) {
        case 1:
            break;
        default:  // the default case should be last
            break;
        case 2:
            break;
    }
}

DestructorOfVirtualClass(虚类的子数的解析函数也要是虚函数)

class Base { // class Base should have a virtual destructor ~Base()
    public: virtual void f();
};
class Child : public Base {
    public: ~Child();  // destructor ~Child() should be virtual
};

InvertedLogic(反转逻辑很难理解)

if (a != 0)             // if (a == 0)
    {                       // {
        i = 1;              //      i = 0;
    }                       // }
    else                    // else
    {                       // {
        i = 0;              //      i = 1;
    }                       // }

    return !i ? -1 : 1;     // return i ? 1 : -1;

MissingBreakInSwitchStatement (switch中缺少break)
NonCaseLabelInSwitchStatement (switch中缺少case)
ObjCAssignIvarOutsideAccessors (禁止在setter、getter、和init之外定义变量)

@interface Foo : NSObject
{
    int _bar;
}
@property (assign, nonatomic) int bar;
@end
@implementation Foo
@synthesize bar = _bar;
- (void)doSomething {
    _bar = 3; // access _bar outside its getter, setter or init
}
@end

ParameterReassignment(参数再赋值在大部分情况下是有问题的 like:if (a < 0){a = 0; // reassign parameter a to 0})
PreferEarlyExit (不期望的结果先判断)

int *doSomething(int a) {
  if (!foo(a) && bar(a) && doOtherThing(a)) {
    // ... some really long code ....
  }

  return 0;
}

// is preferred as

int *doSomething(int a) {
  if (foo(a)) {
    return 0;
  }

  if (!bar(a)) {
    return 0;
  }

  if (!doOtherThing(a)) {
    return 0;
  }

  // ... some long code ....
}

SwitchStatementsShouldHaveDefault
TooFewBranchesInSwitchStatement(如果swtich的case很少、建议使用if)

Empty(空)

EmpthCatchStatement (一个exception 被catch、但是什么也没做)

  try
    {
        int* m= new int[1000];
    }
    catch(...)                  // empty catch statement, this swallows an exception
    {
    }

EmptyDoWhileStatement

do
    {                           // empty do-while statement
    } while(1);

EmptyElseBlock

if (1)
    {
        return a + 1;
    }
    else                // empty else statement, can be safely removed
    {
    }

EmptyFinallyStatement

Foo *foo;
    @try
    {
        [foo bar];
    }
    @catch(NSException *e)
    {
        NSLog(@"Exception occurred: %@", [e description]);
    }
    @finally            // empty finally statement, probably forget to clean up?
    {
    }

EmptyForStatement

for (;;)                // empty for statement
    {
    }

    for (id it in array)    // empty for-each statement
    {
    }

EmptyIfStatement

if (a == 1)                  // empty if statement
    {
    }

EmptySwitchStatement

switch (i)              // empty switch statement
    {
    }

EmptyTryStatement
EmptyWhileStatement

Migration(移植、感觉叫最佳实践更好理解)

ObjCBoxedExpressions(可以使用简单的写法、 就尽量不要太繁琐)

void aMethod()
{
    NSNumber *fortyTwo = [NSNumber numberWithInt:(43 - 1)];
    // NSNumber *fortyTwo = @(43 - 1);

    NSString *env = [NSString stringWithUTF8String:getenv("PATH")];
    // NSString *env = @(getenv("PATH"));
}

ObjCContainerLiterals

void aMethod()
{
    NSArray *a = [NSArray arrayWithObjects:@1, @2, @3, nil];
    // NSArray *a = @[ @1, @2, @3 ];

    NSDictionary *d = [NSDictionary dictionaryWithObjects:@[@2,@4] forKeys:@[@1,@3]];
    // NSDictionary *d = @{ @1 : @2, @3 : @4 };
}

ObjCNSNumberLiterals

void aMethod()
{
    NSNumber *fortyTwo = [NSNumber numberWithInt:42];
    // NSNumber *fortyTwo = @42;

    NSNumber *yesBool = [NSNumber numberWithBool:YES];
    // NSNumber *yesBool = @YES;
}

ObjCObjectSubscripting

void aMethod(NSArray *a, NSDictionary *d)
{
    id item = [a objectAtIndex:0];
    // id item = a[0];

    id item = [d objectForKey:@1];
    // id item = d[@1];
}

Naming(命名)

LongVariableName (太长的变量名称)
LongVariableName (过短的变量名称)

Redundant(多余的)

RedundantConditionalOperator

void example(int a, int b, int c)
{
    bool b1 = a > b ? true : false;     // true/false: bool b1 = a > b;
    bool b2 = a > b ? false : true;     // false/true: bool b2 = !(a > b);
    int i1 = a > b ? 1 : 1;             // same constant: int i1 = 1;
    float f1 = a > b ? 1.0 : 1.00;      // equally constant: float f1 = 1.0;
    int i2 = a > b ? c : c;             // same variable: int i2 = c;
}

RedundantIfStatement

bool example(int a, int b)
{
    if (a == b)             // this if statement is redundant
    {
        return true;
    }
    else
    {
        return false;
    }                       // the entire method can be simplified to return a == b;
}

RedundantLocalVariable

int example(int a)
{
    int b = a * 2;
    return b;   // variable b is returned immediately after its declaration,
}               // can be simplified to return a * 2;

RedundantNilCheck

+ (void)compare:(A *)obj1 withOther:(A *)obj2
{
    if (obj1 && [obj1 isEqualTo:obj2]) // if ([obj1 isEqualTo:obj2]) is okay
    {
    }
}

UnnecessaryElseStatement

bool example(int a)
{
    if (a == 1)                 // if (a == 1)
    {                           // {
        cout << "a is 1.";      //     cout << "a is 1.";
        return true;            //     return true;
    }                           // }
    else                        //
    {                           //
        cout << "a is not 1."   // cout << "a is not 1."
    }                           //
}

UnnecessaryNullCheckForCXXDealloc

void m(char* c) {
    if (c != nullptr) { // and be simplified to delete c;
        delete c;
    }

UselessParentheses

int example(int a)
{
    int y = (a + 1);    // int y = a + 1;
    if ((y > 0))        // if (y > 0)
    {
        return a;
    }
    return (0);         // return 0;
}

Size(尺寸)

CyclomaticComplexity(圈复杂度)
LongClass(过大的类)
LongLine (每行过长)
LongMethod (方法过长)
NcssMethodCount(Ncss:Non Commenting Source Statements 没有说明的代码的数量 方法数量)
NestedBlockDepth (层次过大)
NPathComplexity (NPath 复杂度)
TooManyFields (太多的域)

class c
{
    int a, b;
    int c;
    // ...
    int l;
    int m, n;
    // ...
    int x, y, z;

    void m() {}
};

TooManyMethods

class c
{
    int a();
    int b();
    int c();
    // ...
    int l();
    int m();
    int n();
    // ...
    int x();
    int y();
    int z();
    int aa();
    int ab();
    int ac();
    int ad();
    int ae();
};

TooManyParameters

void example(int a, int b, int c, int d, int e, int f,
    int g, int h, int i, int j, int k, int l)
{
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容

  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,451评论 0 13
  • 看了奶奶和外婆 奶奶的身体恢复得还不错 外婆却越发记不得事儿了 记不得早上妈妈刚去看望过她 和舅舅争执自己是否已经...
    Alicewhale_阅读 90评论 0 0
  • 就如芊蓁女王所说 自己买花给自己的女人 才是真爱 充分满足自己 是一种能力的体现 我有一个梦想 拥有一座花园的梦想...
    Cy_f233阅读 101评论 1 2
  • 今天的科研还是没有啥进展嘞~嗯,早上上了两节课,打游戏打到整个人心态都崩了~也不晓得是我太菜还是对面太强,下午和晚...
    Yanic阅读 204评论 0 0
  • 今天依旧是js学习。首先是发现虽然带java,但是和java本身的各种类之间的继承并没有太大的关系,有了较为初步的...
    姬汉斯阅读 146评论 0 2