代码规范

Posted 「违规用户」

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码规范相关的知识,希望对你有一定的参考价值。

原文:https://github.com/cncnTech/ios-development-guideline#%E5%9F%BA%E6%9C%AC%E5%8E%9F%E5%88%99


Objective-C 编码规范

iOS 工程开发实践

目录

  1. 代码格式
  2. 命名原则
  3. 注释
  4. 编码风格

1. Objective-C 编码规范及原则

代码格式

项目内使用 Clang Format 来约束 C/C++/Objective-C 编码风格

Clang Format 配置步骤(Xcode):

  1. Xcode 安装 ClangFormat-Xcode 插件(https://github.com/travisjeffery/ClangFormat-Xcode)
  2. 配置快捷键,Xcode -> Edit -> Format Code,勾选使用File使用根目录下的.clang-format作为约束文件,勾选Enable Format on Save
  3. 将本文档同目录下的.clang-format文件放入新建工程的根目录下,命名为.clang-format
  4. 后续在 Xcode 保存该工程的代码文件时,会自动根据.clang-format来规范代码格式

排序
包括头文件引用工程 group 排序,无特殊说明时,按字母顺序排序。每次工程中添加新 group 时,需重新按字母排序。

需要额外注意的事项

clang-format 在部分格式上不支持强制在 // 后保留一个空格,需要在写代码时额外注意。

// Preferred:
// 这里是注释

// Not Preferred:
//这里是注释

在使用 block 时,应尽量通过拆分和换行,减少 block 内代码块的整体缩进,尽量控制在小宽度屏幕也能比较方便的阅读代码

// Preferred:
MSTClientCompletionHandler handler = ^(NSInteger code, NSString *msg, id data) 
    // do something.
;
[[MSTClient sharedInstance]
    fetchPhoneCertCodeWithPhone:telephone
              completionHandler:^(NSInteger code, NSString *msg, id data) 
                  handler(code, msg, data);
              ];

// Preferred:
[[MSTClient sharedInstance]
    fetchPhoneCertCodeWithPhone:telephone
              completionHandler:^(NSInteger code, NSString *msg, id data) 
                  // do something.
              ];

// Not Preferred:
[[MSTClient sharedInstance] fetchPhoneCertCodeWithPhone:self.telephone
                                      completionHandler:^(NSInteger code, NSString *msg, id data) 
                                          // do something.
                                      ];

例外
在宏定义文件(eg. MSTMacro.h)中,需要的代码格式不同于其他文件,使用clang-format off来关闭 clang-format

// clang-format off

// 非标准代码风格的代码

// clang-format on

空行

  • #import 块前后保留一个空行
  • @interface 与 @protocol 间保留一个空行
  • 多个 @property 时,如果涉及不同区块、不同职能属性,可使用空行分隔成多组
  • .m 文件中 @interface 与 @implementation 使用两个空行隔开
  • 方法间使用一个空行分隔
  • @end 之后保留一个空行
  • 方法内部空行一般用于分隔两个相对独立的代码区块,不要随意添加无意义的空行
// Preferred:
#import <UIKit/UIKit.h>

@class MSTHotelSearchParams;
@class MSTHotelList;
@interface MSTHotelSearchResultChildViewController : UITableViewController

@property (strong, nonatomic) MSTHotelList *hotels;

- (id)initWithSearchParams:(MSTHotelSearchParams )params;
- (void)configureWithSearchParams:(MSTHotelSearchParams *)params;

@end


// Not Preferred:
#import <UIKit/UIKit.h>
@class MSTHotelSearchParams;
@class MSTHotelList;
@interface MSTHotelSearchResultChildViewController : UITableViewController
@property (strong, nonatomic) MSTHotelList *hotels;
- (id)initWithSearchParams:(MSTHotelSearchParams *)params;
- (void)configureWithSearchParams:(MSTHotelSearchParams *)params;
@end

ViewController.m 文件结构

使用 #pragma mark 区分不同代码块,可引用Code Snippets For Xcode in cncn.com & cncn.net,code snippet 来快速生成结构,一个典型的 ViewController.m 结构如下:

///--------------------------------------
#pragma mark - life cycle
///--------------------------------------

- (void)viewDidLoad

    [super viewDidLoad];



///--------------------------------------
#pragma mark - setup & configuration
///--------------------------------------



///--------------------------------------
#pragma mark - custom delegate
///--------------------------------------



///--------------------------------------
#pragma mark - event response
///--------------------------------------



///--------------------------------------
#pragma mark - update views
///--------------------------------------



///--------------------------------------
#pragma mark - helper/private methods
///--------------------------------------



///--------------------------------------
#pragma mark - getters and setters
///--------------------------------------

命名原则

基本原则

  • 清晰

命名应该尽可能的清晰和简洁,但在Objective-C中,清晰比简洁更重要。由于Xcode强大的自动补全功能,我们不必担心名称过长的问题。

// Preferred:
insertObject:atIndex:

// Not Preferred: insert的对象类型和at的位置属性没有说明
insert:at:

// Preferred:
removeObjectAtIndex:

// Not Preferred:,remove的对象类型没有说明,参数的作用没有说明
remove:

除官方推荐的缩写外,尽量不使用单词缩写,拼写出完整的单词:

// Preferred:
destinationSelection
setBackgroundColor:

// Not Preferred: 不要使用简写
destSel
setBkgdColor:

有部分单词简写在Objective-C编码过程中是非常常用的,以至于成为了一种规范,这些简写可以在代码中直接使用,下面列举了部分:

alloc   == Allocate                 max    == Maximum
alt     == Alternate                min    == Minimum
app     == Application              msg    == Message
calc    == Calculate                nib    == Interface Builder archive
dealloc == Deallocate               pboard == Pasteboard
func    == Function                 rect   == Rectangle
horiz   == Horizontal               Rep    == Representation (used in class name such as NSBitmapImageRep).
info    == Information              temp   == Temporary
init    == Initialize               vert   == Vertical
int     == Integer

命名方法或者函数时要避免歧义

// Not Preferred: 有歧义,是返回sendPort还是send一个Port?
sendPort

// Not Preferred: 有歧义,是返回一个名字属性的值还是display一个name的动作?
displayName
  • 一致性

使用前缀

如果代码需要打包成Framework给别的工程使用,或者工程项目非常庞大,需要拆分成不同的模块,使用命名前缀是非常有用的。

  • 前缀由大写的字母缩写组成,比如Cocoa中NS前缀代表Founation框架中的类,IB则代表Interface Builder框架。
  • 可以在为类、协议、函数、常量以及typedef宏命名的时候使用前缀,但注意不要为成员变量或者方法使用前缀,因为他们本身就包含在类的命名空间内。
  • 命名前缀的时候不要和苹果SDK框架冲突。

项目的工程命名尽量不直接使用业务名称的拼音或者对应的英文名(业务在后续中可能会变化发展),例如旅游顾问项目的项目代号为 Mansinthe, 前缀为 MST。

现有的基础类库从旅游顾问项目中拆分,仍以 MST 为前缀。

命名类和协议(Class&Protocol)

类名以大写字母开头,应该包含一个名词来表示它代表的对象类型,同时可以加上必要的前缀,比如NSStringNSDate,NSScannerNSApplication等等。

而协议名称应该清晰地表示它所执行的行为,而且要和类名区别开来,所以通常使用ing词尾来命名一个协议,比如NSCopying,NSLocking

有些协议本身包含了很多不相关的功能,主要用来为某一特定类服务,这时候可以直接用类名来命名这个协议,比如NSObject协议,它包含了id对象在生存周期内的一系列方法。

命名头文件(Headers)

源码的头文件名应该清晰地暗示它的功能和包含的内容:

  • 如果头文件内只定义了单个类或者协议,直接用类名或者协议名来命名头文件,比如NSLocale.h定义了NSLocale类。

  • 如果头文件内定义了一系列的类、协议、类别,使用其中最主要的类名来命名头文件,比如NSString.h定义了NSStringNSMutableString

  • 每一个Framework都应该有一个和框架同名的头文件,包含了框架中所有公共类头文件的引用,比如Foundation.h

  • Framework中有时候会实现在别的框架中类的类别扩展,这样的文件通常使用被扩展的框架名+Additions的方式来命名,比如NSBundleAdditions.h

命名方法(Methods)

Objective-C的方法名通常都比较长,这是为了让程序有更好地可读性,按苹果的说法“好的方法名应当可以以一个句子的形式朗读出来”

方法一般以小写字母打头,每一个后续的单词首字母大写,方法名中不应该有标点符号(包括下划线),有两个例外:

  • 可以用一些通用的大写字母缩写打头方法,比如PDF,TIFF等。
  • 可以用带下划线的前缀来命名私有方法或者 Category 中的方法。

如果方法表示让对象执行一个动作,使用动词打头来命名,注意不要使用dodoes这种多余的关键字,动词本身的暗示就足够了:

// 动词打头的方法表示让对象执行一个动作
- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem;

如果方法是为了获取对象的一个属性值,直接用属性名称来命名这个方法,注意不要添加get或者其他的动词前缀:

// Preferred: 使用属性名来命名方法
- (NSSize)cellSize;

// Not Preferred: 添加了多余的动词前缀
- (NSSize)calcCellSize;
- (NSSize)getCellSize;

对于有多个参数的方法,务必在每一个参数前都添加关键词,关键词应当清晰说明参数的作用:

// Preferred: 保证每个参数都有关键词修饰
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag;

// Not Preferred: 遗漏关键词
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;

// Preferred:
- (id)viewWithTag:(NSInteger)aTag;

// Not Preferred: 关键词的作用不清晰
- (id)taggedView:(int)aTag;

不要用and来连接两个参数,通常and用来表示方法执行了两个相对独立的操作(从设计上来说,这时候应该拆分成两个独立的方法):

// Not Preferred: 不要使用"and"来连接参数
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;

// Preferred: 使用"and"来表示两个相对独立的操作
- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;

方法的参数命名也有一些需要注意的地方:

  • 和方法名类似,参数的第一个字母小写,后面的每一个单词首字母大写
  • 不要再方法名中使用类似pointer,ptr这样的字眼去表示指针,参数本身的类型足以说明
  • 不要使用只有一两个字母的参数名
  • 不要使用简写,拼出完整的单词

下面列举了一些常用参数名:

...action:(SEL)aSelector
...alignment:(int)mode
...atIndex:(int)index
...content:(NSRect)aRect
...doubleValue:(double)aDouble
...floatValue:(float)aFloat
...font:(NSFont *)fontObj
...frame:(NSRect)frameRect
...intValue:(int)anInt
...keyEquivalent:(NSString *)charCode
...length:(int)numBytes
...point:(NSPoint)aPoint
...stringValue:(NSString *)aString
...tag:(int)anInt
...target:(id)anObject
...title:(NSString *)aString

存取方法(Accessor Methods)

存取方法是指用来获取和设置类属性值的方法,属性的不同类型,对应着不同的存取方法规范:

// 属性是一个名词时的存取方法范式
- (type)noun;
- (void)setNoun:(type)aNoun;
// 栗子
- (NSString *)title;
- (void)setTitle:(NSString *)aTitle;

// 属性是一个形容词时存取方法的范式
- (BOOL)isAdjective;
- (以上是关于代码规范的主要内容,如果未能解决你的问题,请参考以下文章

cc分享java:Java开发之代码规范详解

js命名规则

通俗易懂的 RESTful API 设计规范

前端代码规范

简洁 RESTful API 设计规范!整个人都清爽了!

代码规范