Code Review
Code Review Developer Guide | eng-practices
Google Objective-C Style Guide | styleguide
设计
实现
不建议使用前置声明。原因:头文件没有 self-contain、引用来源无法确定、影响文件依赖分析结果。避免使用 @class
前向声明,前向声明只用来解决同一个文件中循环引用的问题,其他场景建议直接使用 import
。
头文件里写 static
函数,会让每一个引用的文件中都生成一份实现,会导致包大小增大。应该只写声明,在 .m
写实现。
父类不应该 import
子类。如果父类必须依赖子类则是设计上有问题。
就近原则:声明和使用尽量靠近;类似的声明分组放一起。
少抛异常,错误建议可以使用 NSError
传递。
重写 isEqual
方法时应该同时重写 hash
方法。
指针类型强转缺少背景信息,无法确认该实例是否一定实现了协议。建议接口使用泛型来传参,或增加断言判断。
基类不想让外部直接初始化来使用的话,应使用 NS_UNAVAILABLE
修饰、增加 NSAssert
断言等手段,防止直接初始化基类来使用。
优先使用标准库的能力。
防御性编程:变量都要初始化。
UIView
初始化的时候 frame
为 CGRectZero
且同时设置 cornerRadius
,一旦触发 renderLayerInContext
截图就会挂。
NSMutableArray
不能插入 nil
,会有崩溃,-[__NSArrayM insertObject:atIndex:]: object cannot be nil
类型
通知名称类型要用 NSNotificationName 而不是 NSString。
时间应该是使用 NSTimeInterval
。
完美透传视频相关的时间,应该使用 AVFoundation 定义的 CMTime
类型。
应该优先使用系统定义好的类型,对于此处来说应使用 AVLayerVideoGravity
。
NSError
错误类型应该用 NSErrorDomain
来声明。
某个 errorDomain 下的错误码定义,应该用 NS_ERROR_ENUM
。
错误码的定义一般会对外公开,建议放在头文件中。
错误命名风格应与系统保持一致,带命名空间前缀、以 Error 结束,如 SDWebImageError
。
正确示范:
FOUNDATION_EXPORT NSErrorDomain const SDWebImageErrorDomain;
typedef NS_ERROR_ENUM(SDWebImageErrorDomain, SDWebImageError) {
SDWebImageErrorInvalidURL = 1000,
// ...
};
规范
常量定义应该使用 FOUNDATION_EXPORT
,兼容 C++。
不用空行把紧密相关的代码分开。不插入没有价值的空行。无意义的空行,会降低信息密度,应该删除。
整个文件的缩进都应该使用空格而不是 tab,tab 在不同 IDE 看到的格式是不一致的。
可读性问题:同一行嵌套两个或以上三元运算符,应该拆成两个表达式。
宏定义中不应该定义外部变量,可以用参数传递。
建议避免使用宏生成类、属性、方法等。特别是会产生局部变量的宏,容易引起不必要的麻烦。
推荐使用 pragma mark -
分隔不同的代码模块。
不建议在同一个文件中声明多个不同的类,应该拆分至独立的文件中。
推荐使用轻量泛型:NSArray<NSString *> *userDescriptions;
优先使用字面量语法。
注释
注释格式不统一,同时存在两种风格的注释 /**/
和 //
,对于新版本 Xcode,可以统一用快捷键默认生成的注释格式。
使用 /**/
风格的注释时,注释内容与 *
之间需要留空格。
行注释 //
两边都要有空格,中英文之间应该有空格。
头文件里的公开属性、方法都需要加注释。
不要用注释删除代码,无用代码应直接删除。
关键的技术选择和业务逻辑等必要的背景信息,应该有文档注释。
公开接口的注释应该放在头文件,使用标准 ///
进行注释,不要只放在实现文件。
命名
使用驼峰命名。无拼写错误、单复数错误。
不要在名字上带类型。
命名应符合惯用法,getter 不以 get
开头,布尔值的方法通常用 can, is, should, has 这些开头。
布尔类型的属性在命名时不需要增加 is
开头,is
是属于 getter
需要增加的。属性带 is
前缀的话,会导致 getter
生成后变成 isIsPlaying
,引起重复。
OC 中的命名不应该带下划线。
NSLog 还是不要直接使用为好,会在 release 环境下出 log(除非直接或间接 import 了 AllLogMacros.h,将 NSLog 覆盖)