QiuZH‘s Programming|代码规范
一些原则
- 1、长的,描述性的方法和变量命名是好的。不要使用简写,除非是一些大家都知道的场景比如 VIP。不要使用 bgView,推荐使用 backgroundView
- 2、见名知意。含义清楚,做好不加注释代码自我表述能力强。(前提是代码足够规范)
- 3、不要过分追求技巧,降低代码可读性
- 4、删除没必要的代码。比如我们新建一个控制器,里面会有一些不会用到的代码,或者注释起来的代码,如果这些代码不需要,那就删除它,留着偷懒吗?下次需要自己手写
- 5、在方法内部不要重复计算某个值,适当的情况下可以将计算结果缓存起来
- 6、尽量减少单例的使用。
- 7、提供一个统一的数据管理入口,不管是 MVC、MVVM、MVP 模块内提供一个统一的数据管理入口会使得代码变得更容易管理和维护。
变量
- 1、一个变量最好只有一个作用,切勿为了节省代码行数,觉得一个变量可以做多个用途。(单一原则)
- 2、方法内部如果有局部变量,那么局部变量应该靠近在使用的地方,而不是全部在顶部声明全部的局部变量。
运算符
- 1、1元运算符和变量之间不需要空格。例如:++n
- 2、2元运算符与变量之间需要空格隔开。例如: containerWidth = 0.3 * Screen_Width
- 3、当有多个运算符的时候需要使用括号来明确正确的顺序,可读性较好。例如: 2 << (1 + 2 * 3 - 4)
条件表达式
- 1、当有条件过多、过长的时候需要换行,为了代码看起来整齐些
//good
if (condition1() &&
condition2() &&
condition3() &&
condition4()) {
// Do something
}
//bad
if (condition1() && condition2() && condition3() && condition4()) { // Do something }
- 2、在一个代码块里面有个可能的情况时善于使用 return 来结束异常的情况。
- (void)doHomework
{
if (self.hungry) {
return;
}
papapa.then.over;
}
- 3、每个分支的实现都必须使用 {} 包含。
// bad
if (self.hungry) self.eat()
// good
if (self.hungry) {
self.eat()
}
- 4、条件判断的时候应该是变量在左,条件在右。
if ( currentCursor == 2 ) { //... }
- 5、switch 语句后面的每个分支都需要用大括号括起来。
类名
-
1、大写驼峰式命名。每个单词首字母大写。比如「申请记录控制器」
ApplyRecordsViewController
-
2、每个类型的命名以该类型结尾。
- ViewController:使用 ViewController 结尾。例子:ApplyRecordsViewController
- View:使用 View 结尾。例子:分界线:boundaryView
- NSArray:使用 s 结尾。比如商品分类数据源。categories
- UITableViewCell:使用 Cell 结尾。比如 MyProfileCell
- Protocol:使用 Delegate 或者 Datasource 结尾。比如 XQScanViewDelegate
- Tool:工具类
- 代理类:Delegate
- Service 类:Service
枚举
枚举的命名和类的命名相近。
typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) {
UIControlContentVerticalAlignmentCenter = 0,
UIControlContentVerticalAlignmentTop = 1,
UIControlContentVerticalAlignmentBottom = 2,
UIControlContentVerticalAlignmentFill = 3,
};
宏
- 1、全部大写,单词与单词之间用
_
连接。 - 2、以
K
开头。后面遵循大写驼峰命名。「不带参数」
#define HOME_PAGE_DID_SCROLL @"com.xq.home.page.tableview.did.scroll"
#define KHomePageDidScroll @"com.xq.home.page.tableview.did.scroll"
属性
书写规则,基本上就是 @property
之后空一格,括号,里面的 线程修饰词、内存修饰词、读写修饰词,空一格 类 对象名称
根据不同的场景选择合适的修饰符。
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, assign, readonly) BOOL loading;
@property (nonatomic, weak) id<#delegate#> delegate;
@property (nonatomic, copy) <#returnType#> (^<#Block#>)(<#parType#>);
私有变量
推荐以 _
开头,写在 .m 文件中。例如 NSString * _somePrivateVariable
代理方法
- 1、类的实例必须作为方法的参数之一。
- 2、对于一些连续的状态的,可以加一些 will(将要)、did(已经)
- 3、以类的名称开头
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
方法
- 1、方法与方法之间间隔一行
- 2、大量的方法尽量要以组的形式放在一起,比如生命周期函数、公有方法、私有方法、setter && getter、代理方法..
- 3、方法最后面的括号需要另起一行。遵循 Apple 的规范
- 4、对于其他场景的括号,括号不需要单独换行。比如 if 后面的括号。
- 5、如果方法参数过多过长,建议多行书写。用冒号进行对齐。
- 6、一个方法内的代码最好保持在50行以内,一般经验来看如果一个方法里面的代码行数过多,代码的阅读体验就很差(别问为什么,做过重构代码行数很长的人都有类似的心情)
- 7、一个函数只做一个事情,做到单一原则。所有的类、方法设计好后就可以类似搭积木一样实现一个系统。
- 8、对于有返回值的函数,且函数内有分支情况。确保每个分支都有返回值
- 9、函数如果有多个参数,外部传入的参数需要检验参数的非空、数据类型的合法性,参数错误做一些措施:立即返回、断言。
- 10、多个函数如果有逻辑重复的代码,建议将重复的部分抽取出来,成为独立的函数进行调用
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
- (void)doHomework:(NSString *)name
period:(NSInteger)second
score:(NSInteger)score;
- 11、方法如果有多个参数的情况下需要注意是否需要介词和连词。很多时候在不知道如何抉择测时候思考下苹果的一些 API 的方法命名。
//good
- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
//bad
- (instancetype)initWithAge:(NSInteger)age andName:(NSString *)name;
- (void)tableView:(UITableView *)tableView :(NSIndexPath *)indexPath;
- 13、方法组之间也有个顺序问题。
- 1、在生命周期的方法里面,比如 viewDidLoad 里面只做界面的添加,而不是做界面的初始化
- 2、不要在除了getter之外的结构中设置view基本坐标、属性等。getter方法中不要添加比较重要重要的业务逻辑,重要的业务逻辑应该单独拿出来,放在对应的pragra mark 下,否则对于代码的阅读者来说,比较难以定位逻辑的入口位置。实际开发中遇到过多次这样的情况,焦头烂额的寻找关键逻辑入口处,纵里寻她千百度,结果它却躺在 getter方法中。
- 3、在viewDidAppear里面做Notification的监听之类的事情
- 4、每一个代理方法都对应上相应的协议,否则后期随着代码量的增加,很难找出某一代理方法对应的协议,不利于代码的可读性。
- 5、getter 和setter 方法写在代码的最后面。
- 6、UI布局可以说比较重要,也可以说不重要。重要是因为一个新手接手新项目,如果对布局还没有了解,业务逻辑便无从谈起;UI布局不重要是因为只要相关控件封装的足够好,页面UI布局通常会很简单;因为UI布局比较重要,所以笔者将它放在固定位置(setter&getter上面),因为UI布局通常比较简单,所以将其放在代码中比较靠后的位置。
#pragra mark - life cycle
#pragra mark - notification
#pragra mark - action
#pragra mark - UITableViewDelegate
.....总之这里是各种代理就对了
#pragra mark - UI
#pragra mark - setter & getter
图片资源
- 1、单个文件的命名
文件资源的命名也需要一定的规范,形式为:功能模块名_类别_功能_状态@nx.png
Setting_Button_search_selected@2x.png、Setting_Button_search_selected@3x.png - 2、资源的文件夹命名 最好也参考 App 按照功能模块建立对应的实体文件夹目录,最后到对应的目录下添加相应的资源文件。
版本规范
采用 A.B.C 三位数字命名,比如:1.0.2,当有更新的情况下按照下面的依据
版本号 | 右说明对齐标题 | 示例 |
---|---|---|
A .b.c |
属于重大内容的更新 | 1.0.2 -> 2.0.0 |
a.B .c |
属于小部分内容的更新 | 1.0.2 -> 1.1.1 |
a.b.C |
属于补丁更新 | 1.0.2 -> 1.0.3 |