基本原則:
清晰又簡(jiǎn)潔的代碼當(dāng)然是最好皇忿,但簡(jiǎn)潔不如清晰重要。不要使用單詞的簡(jiǎn)寫坦仍,除了非常常用的簡(jiǎn)寫以外鳍烁,盡量使用單詞全稱。API的名稱不要有歧義繁扎,一看API就知道是以什么方式做了什么事情幔荒。
1、命名
類的命名:
大駝峰式命名:即每個(gè)單詞的首字母采用大些字母梳玫。
使用能夠反映類功能的名詞短語(yǔ)爹梁。
DoneCourseListView
分類(類別)命名:
與類命名相同,此外需添加要擴(kuò)展的類名和“+”
NSString+MTValidate
方法命名:
小駝峰式命名:首字母小寫提澎,之后每個(gè)單詞首字母都大寫
方法名使用動(dòng)詞短語(yǔ)姚垃。
- (void)setPostValue:(int)value
方法參數(shù)命名:
首字母小寫,之后每個(gè)單詞首字母都大寫
具有足夠的說明性盼忌,不需要添加類型前綴
- (void)sendUserInfo:(NSDictionary*)userInfo
宏命名:
全部大寫积糯,單詞間用 _ 分隔。[不帶參數(shù)]
#define THIS_IS_AN_MACRO @"THIS_IS_AN_MACRO"
以字母 k 開頭碴犬,后面遵循大駝峰命名絮宁。[不帶參數(shù)]
#define kWidth self.frame.size.width
小駝峰命名。[帶參數(shù)]
#define getImageUrl(url) [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",kBaseUrl,url]]
枚舉類型命名:
Enum類型的命名與類的命名規(guī)則一致
Enum中枚舉內(nèi)容的命名需要以該Enum類型名稱開頭
NS_ENUM定義通用枚舉服协,NS_OPTIONS定義位移枚舉
typedef NS_ENUM(NSInteger,UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown
};
typedef NS_OPTIONS(NSUInteger,UIControlState) {
UIControlStateNormal=0,
UIControlStateHighlighted=1<<0,
UIControlStateDisabled=1<<1
};
分組命名:
使用英文绍昂,首字母大寫,之后每個(gè)單詞首字母都大寫
每個(gè)分組使用模塊的名字
使用的開源庫(kù)統(tǒng)一放在“Library”分組下
使用的公共組件統(tǒng)一放在“Common”分組下
視圖控制器及AppDelegate統(tǒng)一放在“Controllers”分組下
后綴要求:
視圖控制器的子類應(yīng)該以“ViewController”或者“Controller”做后綴
CourseViewController
試圖的子類應(yīng)該以“View”做后綴
CourseView
協(xié)議(委托)使用Delegate或者DataSource作為后綴
VideoPlayerDelegate
按鈕的子類應(yīng)添加后綴“Button”,UI控件以此類推
LoginButton
2窘游、注釋
優(yōu)秀的代碼大部分是可以自描述的唠椭,我們完全可以用代碼本身來表達(dá)它到底在干什么,而不需要注釋的輔助忍饰,如果做不到命名盡量的見名知意的話贪嫂,就可以適當(dāng)?shù)奶砑右恍┳⑨尰蛘適ark。
但是以下三種情況比較適合寫注釋:
1艾蓝、公共接口(注釋要告訴閱讀代碼的人力崇,當(dāng)前類能實(shí)現(xiàn)什么功能)。
2赢织、涉及到比較深層專業(yè)知識(shí)的代碼(注釋要體現(xiàn)出實(shí)現(xiàn)原理和思想)亮靴。
3、容易產(chǎn)生歧義的代碼(但是嚴(yán)格來說于置,容易讓人產(chǎn)生歧義的代碼是不允許存在的)茧吊。
除了上述這三種情況,如果別人只能依靠注釋才能讀懂你的代碼的時(shí)候八毯,就要反思代碼出現(xiàn)了什么問題搓侄。對(duì)于注釋的內(nèi)容,相對(duì)于“做了什么”话速,更應(yīng)該說明“為什么這么做”讶踪。
注釋示例:
1、屬性注釋
/// 學(xué)生
@property (nonatomic, strong) Student *student;
2尿孔、類注釋
/** 類信息俊柔。此注釋用在類聲明的開頭。
@TestClass
@這是一個(gè)測(cè)試類
*/
@interfaceTestClass :UIView
@end
3活合、方法命名注釋
/**
根據(jù)請(qǐng)求的 URL 與 parameters 同步取出緩存數(shù)據(jù)
@param URL 請(qǐng)求的URL
@param parameters 請(qǐng)求的參數(shù)
@return 緩存的服務(wù)器數(shù)據(jù)
*/
+ (id)httpCacheForURL:(NSString *)URL parameters:(id)parameters;
4雏婶、import注釋
如果有一個(gè)以上的import語(yǔ)句,就對(duì)這些語(yǔ)句進(jìn)行分組白指,每個(gè)分組的注釋是可選的留晚。
// Frameworks
#import<Foundation/Foundation.h>;
// Models
#import "UserInfoModel.h"
// Views
#import "CourseCountView"
#import "MineHeaderView.h"
5、代碼塊注釋
單行的用//+空格開頭告嘲,多行的采用/* */注釋
// [self.allCourseV dataWithTitle:@"購(gòu)買課時(shí)" count:[NSString stringWithFormat:@"%lu", (unsigned long)allCount] desc:@""];
6错维、TODO
使用//TODO:說明 標(biāo)記一些未完成的或完成的不盡如人意的地方
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//TODO:增加初始化
return YES;
}
3、格式化代碼
1橄唬、 指針 "*" 位置
定義一個(gè)對(duì)象時(shí)赋焕,指針 "*" 靠近變量
NSString *userName;
2、 方法的聲明和定義
在 - 仰楚、+ 和 返回值 之間留一個(gè)空格隆判,方法名和第一個(gè)參數(shù)之間不留空格
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
3犬庇、 代碼縮進(jìn)
- 使用 xcode 默認(rèn)縮進(jìn),即 tab = 4空格
- 使用 xcode 中 re-indent 功能定期對(duì)代碼格式進(jìn)行整理侨嘀,步聚:點(diǎn)選要進(jìn)行重構(gòu)的文檔臭挽, Control+A 全選該文檔,然后選擇XCODE -> Editor -> Structure -> Re-Indent 即可對(duì)代碼進(jìn)行重構(gòu) !
- 相同類型變量聲明需要獨(dú)行聲明
4咬腕、對(duì)方法進(jìn)行分組
使用 #pragma mark -方式對(duì)類的方法進(jìn)行分組
方法與方法之間空一行
#pragma mark - private methods
- (**void**)samplePrivateMethod
{...}
- (**void**)sampleForIf
{...}
5欢峰、 大括號(hào)寫法
對(duì)于類的method: 左括號(hào)另起一行寫(遵循蘋果官方文檔)
對(duì)于其他使用場(chǎng)景(if,for,while,switch等): 左括號(hào)跟在第一行后邊
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
任何需要寫大括號(hào)的部分,不得省略
//錯(cuò)誤示例
- (void)wrongExamples
{
BOOL someCondition = YES;
if (someCondition)
NSLog(@"this is wrong!!!");
while (someCondition)
NSLog(@"this is wrong!!!");
}
4涨共、編碼規(guī)范
1纽帖、if語(yǔ)句
①、須列出所有分支(窮舉所有的情況)举反,而且每個(gè)分支都須給出明確的結(jié)果抛计。
推薦
var hintStr;
if (count <3) {
hintStr ="Good";
} else {
hintStr ="";
}
不推薦
var hintStr;
if (count <3) {
hintStr ="Good";
}
②、不要使用過多的分支照筑,要善于使用return來提前返回錯(cuò)誤的情況,把最正確的情況放到最后返回瘦陈。
推薦
if (!user.UserName) return NO;
if (!user.Password) return NO;
if (!user.Email) return NO;
return YES;
不推薦
BOOL isValid = NO;
if (user.UserName)
{
if (user.Password)
{
if (user.Email) isValid = YES;
}
}
return isValid;
③、條件過多,過長(zhǎng)的時(shí)候應(yīng)該換行(1)褒傅。條件表達(dá)式如果很長(zhǎng)捷绒,則需要將他們提取出來賦給一個(gè)BOOL值(2),或者抽取出一個(gè)方法(3)
(1)
if(condition1 &&
condition2 &&
condition3 &&
condition4) {
// Do something
}
(2)
BOOL finalCondition = condition1 && condition2 && condition3 && condition4
if (finalCondition) {
// Do something
}
(3)
if ([self canDelete]){
// Do something
}
- (BOOL)canDelete
{
BOOL finalCondition1 = condition1 && condition2
BOOL finalCondition2 = condition3 && condition4
return condition1 && condition2;
}
不推薦
if (condition1 && condition2 && condition3 && condition4) {
// Do something
}
④捉貌、條件語(yǔ)句的判斷應(yīng)該是變量在右支鸡,常量在左。
if (object == nil)容易誤寫成賦值語(yǔ)句, if (!object)寫法很簡(jiǎn)潔
推薦
if (6== count) {
}
if (nil == object) {
}
if (!object) {
}
不推薦
if(count == 6) {
}
if(object == nil) {
}
⑤趁窃、每個(gè)分支的實(shí)現(xiàn)代碼都須被大括號(hào)包圍
推薦:
if (!error) {
return success;
}
也可以:
if (!error) return success;
不推薦
if (!error)
return success;
2牧挣、for語(yǔ)句
①、不可在for循環(huán)內(nèi)修改循環(huán)變量醒陆,防止for循環(huán)失去控制瀑构。
②、避免使用continue和break刨摩。
- continue和break所描述的是“什么時(shí)候不做什么”寺晌,所以為了讀懂二者所在的代碼,我們需要在頭腦里將他們?nèi)》础?/li>
- 最好不要讓這兩個(gè)東西出現(xiàn)澡刹,因?yàn)槲覀兊拇a只要體現(xiàn)出“什么時(shí)候做什么”就好了呻征,而且通過適當(dāng)?shù)姆椒ǎ强梢詫⑦@兩個(gè)東西消滅掉的:
- 如果出現(xiàn)了continue罢浇,只需要把continue的條件取反即可
var filteredProducts = Array()
for level in products {
if level.hasPrefix("bad") {
continue陆赋;
}
filteredProducts.append(level)
}
我們可以看到沐祷,通過判斷字符串里是否含有“bad”這個(gè)prefix來過濾掉一些值。其實(shí)我們是可以通過取反奏甫,來避免使用continue的:
for level in products {
if !level.hasPrefix("bad") {
filteredProducts.append(level)
}
}
消除 while 里的 break:將 break 的條件取反戈轿,并合并到主循環(huán)里
在 while 里的 break 其實(shí)就相當(dāng)于“不存在”,既然是不存在的東西就完全可以在最開始的條件語(yǔ)句中將其排除阵子。
while 里的 break:
while (condition1) {
...
if (condition2) {
break;
}
}
取反并合并到主條件:
while (condition1 && !condition2) {
...
}
在有返回值的方法里消除break:將break轉(zhuǎn)換為return立即返回
//在有返回值的方法里break之后思杯,再返回某個(gè)值。其實(shí)完全可以在break的那一行直接返回挠进。
func hasBadProductIn(products: Array<String>) -> Bool {
var result = false
for level in products {
if level.hasPrefix("bad") {
result = true
break
}
}
return result
}
//這樣寫的話不用特意聲明一個(gè)變量來特意保存需要返回的值色乾,看起來非常簡(jiǎn)潔,可讀性高领突。
func hasBadProductIn(products: Array<String>) -> Bool {
for level in products {
if level.hasPrefix("bad") {
return true
}
}
return false
}
3暖璧、Switch語(yǔ)句
①、每個(gè)分支都必須用大括號(hào)括起來
switch (integer) {
case 1: {
// ...
break;
}
case 2: {
// ...
break;
}
default: {
// ...
break;
}
}
②君旦、使用枚舉類型時(shí)澎办,不能有default分支, 除了使用枚舉類型以外金砍,都必須有default分支局蚀,在Switch語(yǔ)句使用枚舉類型的時(shí)候,如果使用了default分支恕稠,在將來就無法通過編譯器來檢查新增的枚舉類型了琅绅。
RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
switch (menuType) {
case RWTLeftMenuTopItemMain: {
// ...
break;
}
case RWTLeftMenuTopItemShows: {
// ...
break;
}
case RWTLeftMenuTopItemSchedule: {
// ...
break;
}
}
4、函數(shù)
①鹅巍、一個(gè)函數(shù)只做一件事(單一原則)
②千扶、對(duì)于有返回值的函數(shù)(方法),每一個(gè)分支都必須有返回值
③骆捧、對(duì)輸入?yún)?shù)的正確性和有效性進(jìn)行檢查澎羞,參數(shù)錯(cuò)誤立即返回
④、如果在不同的函數(shù)內(nèi)部有相同的功能凑懂,應(yīng)該把相同的功能抽取出來單獨(dú)作為另一個(gè)函數(shù)
⑤煤痕、將函數(shù)內(nèi)部比較復(fù)雜的邏輯提取出來作為單獨(dú)的函數(shù)
5、團(tuán)隊(duì)規(guī)范
說明:一個(gè)好的團(tuán)隊(duì)接谨,理所當(dāng)然有其嚴(yán)格的代碼規(guī)范摆碉,好的代碼不僅可以提高團(tuán)隊(duì)的開放效率,也更利于團(tuán)隊(duì)項(xiàng)目的后期維護(hù)脓豪,統(tǒng)一的代碼風(fēng)格巷帝,也是團(tuán)隊(duì)的核心,所以規(guī)范代碼很有必要扫夜!
1楞泼、刪除多余的空行 所有方法與方法之間空1行 所有代碼塊之間空1行
2驰徊、刪除多余的注釋
刪除注釋掉的代碼
刪除沒有意義的注釋
3、刪除多余的方法
如果方法沒有使用到堕阔,請(qǐng)刪除它
如果方法沒有執(zhí)行任何業(yè)務(wù)邏輯棍厂,請(qǐng)刪除它或者給出一定注釋
4、刪除未被使用的資源文件
5超陆、添加必要的注釋
所有.h 文件中的property 需要給出注釋
所有自定義的方法需要給出注釋
比較大的代碼塊需要給出注釋
所有代碼中出現(xiàn)的阿拉伯?dāng)?shù)字需要給出注釋
程序中出現(xiàn)加密/解密 邏輯的操作地方牺弹,需要給出注釋說明過程(無論是系統(tǒng)還是自定義)
6、整體代碼風(fēng)格需要統(tǒng)一
代碼后面的”{“ 不需要單獨(dú)占用一行
邏輯運(yùn)算符 與“|” 代碼之前空一格
“#pragmamark -” 與下面的代碼之前不要空行
遵循一般性的代碼規(guī)范
參考: