概述
命名的好坏在开发中往往也不怎么重视,毕竟差的命名也不会影响程序逻辑。但是不好的命名在大项目中带来的隐形维护成本是相当高的,这些在项目开始时可能还很难察觉,而后来会陷入前仆后继的维护困境中。我们往往非常重视项目逻辑的复杂性,却不能好好的把“简单”的命名做好。其实,如果简单的东西都做不好,那么做出再复杂的东西那也是垃圾。
命名规范
分类(类别)命名
与类命名相同,此外需添加要扩展的类名和“+”
举例:NSString+URLEncoding
协议(委托)命名
与类命名相同,此外需添加“Delegate”后缀
举例:ReplyViewDelegate
方法命名
首字母小写,之后每个单词首字母都大写
方法名使用动词短语
举例:- (void)setupPostWithValue:(int)value
“要什么”往往被胡乱命名为get
开头的方法。首先get是一个动词,所以它还是“做什么”或者说“做的是要什么”。那么get方法不要用于返回对象,但它可用于参数。
- (XXItem *)getItemAtIndex:(NSUInteger)index //Bad!! 不规范的命名- (XXItem *)itemAtIndex:(NSUInteger)index //Good, 命名清晰- (void)getItem:(XXItem **)outItem atIndex:(NSUInteger)index //比较符合规范,但第二种更好。
参数命名
首字母小写,之后每个单词首字母都大写
每个参数前要加参数的名称提示
举例:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
对象命名
采用修饰+类型的方式
举例:
titleLabel //表示标题的label, 是UILabel类型confirmButton //表示确认的button, 是UIButton类型
图片命名
使用英文,全部小写 ,添加模块名作为前缀,避免冲突 。图片应该与类文件一样,按模块分组放置
举例:
Home(界面名称)_(功能属性简写+描述).png
如: home_btn_recommended.png
或:
compose_mentionbutton_background@2x.png
compose_mentionbutton_background_highlighted@2x.png
分组命名
使用英文,首字母大写,之后每个单词首字母都大写
每个分组使用模块的名字
使用的开源库统一放在“Library”分组下
使用的公共组件统一放在“Common”分组下
使用资源统一放在"Resource"分组下,包括文件、音频、图片、证书等
编码规范
编码规范简单来说就是为了保证写出来的代码具备三个原则:可复用, 易维护, 可扩展. 这其实也是面向对象的基本原则. 可复用, 简单来说就是不要写重复的代码, 有重复的部分要尽量封装起来重用。
判断nil或者YES/NO
推荐:
if (someObject) { ... } if (!someObject) { ... }
不推荐:
if (someObject == YES) { ...} if (someObject != nil) { ...}
if (someObject == YES)容易误写成赋值语句
条件赋值
推荐:
result = object ? : [self createObject];
不推荐:
result = object ? object : [self createObject];
如果是存在就赋值本身, 简洁。
BOOL赋值
推荐:
BOOL isAdult = age > 18;
不推荐:
BOOL isAdult;if (age > 18){ isAdult = YES;}else{ isAdult = NO;}
拒绝死值
推荐:
if (car == Car.Nissan)orconst int adultAge = 18; if (age > adultAge) { ... }
不推荐:
if (carName == "Nissan")orif (age > 18) { ... }
死值每次修改的时候容易被遗忘, 地方多了找起来就悲剧了. 而且定义成枚举或者static可以让错误发生在编译阶段. 另外仅仅看到一个数字, 完全不知道这个数字代表的意义. 纳尼?
复杂的条件判断
推荐:
if ([self canDeleteJob:job]) { ... } - (BOOL)canDeleteJob:(Job *)job{ BOOL invalidJobState = job.JobState == JobState.New || job.JobState == JobState.Submitted || job.JobState == JobState.Expired; BOOL invalidJob = job.JobTitle && job.JobTitle.length; return invalidJobState || invalidJob;}
不推荐:
if (job.JobState == JobState.New || job.JobState == JobState.Submitted || job.JobState == JobState.Expired || (job.JobTitle && job.JobTitle.length)){ //....}
清晰明了, 每个函数DO ONE THING!
嵌套判断
推荐:
- (void) someMethod { if (![someOther boolValue]) { return; } //Do something important}
不推荐:
- (void) someMethod { if ([someOther boolValue]) { //Do something important }}
一旦发现某个条件不符合, 立即返回, 条理更清晰。
所有的逻辑块必须使用花括号包围,即使条件体只需编写一行代码也必须使用花括号
推荐:
if (!error) { return success;}
不推荐:
if (!error) return success;...if (!error) return success;
参数过多
推荐:
- (void)registerUser(User *user){ // to do... }
不推荐:
- (void)registerUserName:(NSString *)userName password:(NSString *)password email:(NSString *)email{ // to do...}
当发现实现某一功能需要传递的参数太多时, 就预示着你应该聚合成一个model类了...这样代码更整洁, 也不容易因为参数太多导致出错。
点标记语法
属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法。
推荐:
view.backgroundColor = [UIColor orangeColor];[UIApplication sharedApplication].delegate;
不推荐:
[view setBackgroundColor:[UIColor orangeColor]];UIApplication.sharedApplication.delegate;
枚举
枚举使用Objective-C方式来定义,枚举命名是 类前缀+枚举名,枚举值要加枚举名。
举例:
typedef NS_ENUM(NSUInteger, HGMachineState) { HGMachineStateNone, HGMachineStateIdle, HGMachineStateRunning, HGMachineStatePaused};
常量
常量应该类名称+“骆峰式”单词大写。
推荐:
static const NSTimeInterval HGSignInViewControllerFadeOutAnimationDuration = 0.4;
不推荐:
static const NSTimeInterval fadeOutTime = 0.4;
常数是优于串联字符串或数字的,允许多个地方使用常用变量,可以迅速改变不需要查找和替换。常量应该声明为静态常量而不使用宏定义,除非明确需要定义一个宏。
推荐:
static NSString * const ZOCCacheControllerDidClearCacheNotification = @"ZOCCacheControllerDidClearCacheNotification";static const CGFloat ZOCImageThumbnailHeight = 50.0f;
不推荐:
#define CompanyName @"Apple Inc."#define magicNumber 42
单例模式
使用GCD代替使用sharedInstance,每次调用+ (id)sharedInstance函数都会付出取锁的代价。
推荐:
+ (instancetype)sharedInstance{ static id sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance;}
不推荐:
+ (instancetype)sharedInstance{ static id sharedInstance; @synchronized(self) { if (sharedInstance == nil) { sharedInstance = [[MyClass alloc] init]; } } return sharedInstance;}
代理
定义一个协议是 类名+Delegate,并要使用weak 弱指针,协议使用可选@optional
@class ZOCSignUpViewController;@protocol ZOCSignUpViewControllerDelegate@required- (void)signUpViewController:(ZOCSignUpViewController *)controller didProvideSignUpInfo:(NSDictionary *);@optional- (void)signUpViewControllerDidPressSignUpButton:(ZOCSignUpViewController *)controller;@end@interface ZOCSignUpViewController : UIViewController@property (nonatomic, weak) id delegate;@end
在发送委托代理方法之前,一定要先检查该委托方法已经被实现(否则会崩溃)。
if ([self.delegate respondsToSelector:@selector(signUpViewControllerDidPressSignUpButton:)]) { [self.delegate signUpViewControllerDidPressSignUpButton:self];}
动画
推荐
[UIView animateWithDuration:1.0 animations:^{ // something } completion:^(BOOL finished) { // something }];
不推荐
[UIView animateWithDuration:1.0 animations:^{ // something } completion:^(BOOL finished) { // something}];
Pragma Mark
使用“#pargma mark - ”实现方法的分组。建议按下面几点单独分组:
1.功能分组
2.代理协议实现分组
3.重写父类方法
- (void)dealloc { /* ... */ }- (instancetype)init { /* ... */ }#pragma mark - View Lifecycle- (void)viewDidLoad { /* ... */ }- (void)viewWillAppear:(BOOL)animated { /* ... */ }- (void)didReceiveMemoryWarning { /* ... */ }#pragma mark - Custom Accessors- (void)setCustomProperty:(id)value { /* ... */ }- (id)customProperty { /* ... */ }#pragma mark - IBActions- (IBAction)submitData:(id)sender { /* ... */ }#pragma mark - Public- (void)publicMethod { /* ... */ }#pragma mark - Private- (void)zoc_privateMethod { /* ... */ }#pragma mark - UITableViewDataSource- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { /* ... */ }#pragma mark - ZOCSuperclass// ... overridden methods from ZOCSuperclass#pragma mark - NSObject- (NSString *)description { /* ... */ }
抽象方法定义
@interface TestClass : NSObject#pragma mark - Abstract Method//抽象方法-(void)doWork;@end
抽象类不允许被实例化,所以需要在init方法中添加判断代码
@implementation TestClass- (id)init { if( [self class] == [TestClass class]) { @throw [NSException exceptionWithName:@"抽象类无法实例化" reason:@"抽象类无法实例化: TestClass" userInfo:nil]; } else { self = [super init]; if(self){ } return self; }}#pragma mark - Abstract Method- (void)doWork { @throw [NSException exceptionWithName:@"抽象方法没有被实现" reason:@"抽象方法没有被实现: doWork" userInfo:nil];}@end
参数链接: