前言
由于當時項目進度趕得緊竞阐,功能相對簡單疮薇,代碼寫的隨意妒茬,到后來的多次小改大改,改到最后以至于不得不重構的地步,
業(yè)務邏輯已經相當的復雜弓千,維護起來很是吃力。于是就產生了重構的想法献起,重構時才發(fā)現很多不合理的設計计呈。
寫出一個龐然大View,再加上復雜的邏輯代碼征唬,這一塊的代碼很可能就演變成了誰都不敢動的禁區(qū)捌显。
另外說一下: 一個ViewController類的有效代碼超過500行,這個ViewController就會變得難以維護总寒。
場景說明和重構設計
效果圖中的功能為一個上報的模塊扶歪,該模塊需要填寫的內容非常的多,上傳的字段大約有80-90個,分為多個模塊區(qū)善镰,
每個模塊中都可能使用到上述的這五個類型的控件妹萨,
自定義控件化后整個上報模塊的頁面布局和值的賦值和讀取都變得非常清晰簡單。
而且本文中的時間的選擇炫欺、照片的選擇乎完、多選框的選擇在工程中都是在 BaseViewController中統(tǒng)一處理的,這也是為了復用而做的處理品洛。
#import <UIKit/UIKit.h>
@interface BaseItem : UIView
@property(copy,nonatomic)NSString *itemTitle;//標題
@property(copy,nonatomic)NSString *itemText;
@property(copy,nonatomic)NSString *itemNo;
@property(assign,nonatomic)BOOL isMust;//是否是必填子段
- (void)setLeftStarImage;
- (void)setRightUnit :(NSString *)unitName;
@end
- BaseItem 是基礎父類树姨,定義公共的方法入口
- BaseItemForText 是文本輸入控件,可設置文本框右側的單位
- BaseItemForPopView 是下拉彈框控件
- BaseItemForSelectTime 是點擊底部彈出日期選擇桥状,選擇后展示日期的控件
- BaseItemForSelectImage 是點擊拍照或者選擇相冊中相片的控件
- BaseItemForMoreSelect 多選彈框控件
[self.leftLabel setSingleLineAutoResizeWithMaxWidth:Scale_X(150)];//自動根據內容設定寬度帽揪。
不同子類通過重寫 BaseItem 的公共屬性的 set、get 方法來達到初始化組件或者獲取所需提交數據等
這一步中把轉化的邏輯都寫在了自定義控件內部辅斟,對外只暴露公共入口转晰,使外部的調用非常的簡單。
簡化必填子段驗證
- (BOOL)backEmptyKeyWarn;
{
for (int i = 0; i<25; i++) {
if (baseItem[i].superview) {
if (baseItem[i].isMust && NilStr(baseItem[i].itemText) ) {
return NO;
}
}
}
return YES;
}
原來的邏輯設置:
1.沒有控件話士飒,頁面都是基本UILabel查邢、UIButton 等貼的,而且控件之間由于一開始很簡單酵幕,沒有完全相對布局侠坎,里面有很多絕對坐標。
2.絕對布局對于需要根據選擇的內容不同動態(tài)隱藏或者展示某塊區(qū)域裙盾,某個大的模塊來說是非常的不友好实胸,大量的硬編碼(y值的硬計算)使得修改和維護起來很是吃力。
3.在VC【眾多自定義視圖是 VC 的View的子視圖】中定義所有自定義視圖的下拉彈框的數據源和處理所有自定義視圖的交互事件番官,使得代碼耦合度更大庐完,不符合開閉原則,很容易造成一處修改徘熔,誤使其他模塊出錯的現象门躯。
4.上報時需要一個個判斷是否為空來驗證必填參數是否已經填寫。
5.參數的收集和初始化賦值的時候都是一個一個對應著設置酷师,不同視圖需要不同操作讶凉,很是麻煩和易錯。
重構后
1.絕對布局全部換成相對布局山孔,這樣在后續(xù)新需求時添加懂讯、刪除頁面元素更方便修改。
2.每個小控件和大的自定義視圖都自動設置自身高度台颠,省去手動計算定值高度的麻煩褐望。
3.隱藏/展示某個控件或者自定義視圖時可以直接設置其高度,在需要改變的地方調用統(tǒng)一的刷新方法刷新整體布局。
4.每個自定義視圖處理自己的下拉彈框的數據源初始化和交互事件瘫里,使得職責更加的內聚合实蔽。
5.通過 for 循環(huán)即可驗證必填參數的自定義控件是否為空,節(jié)省了一大坨代碼并使驗證的邏輯更加簡明易懂谨读。
6.由于父類的存在局装,設置統(tǒng)一賦值、取值的公共方法入口劳殖,使得對自定義控件的賦值铐尚、取值都是一致和簡單的。
心得總結
重構中你只能通過設計把邏輯變得更易懂和更易維護及擴展闷尿,但是無法減少已有的邏輯塑径,該有的邏輯還是無法省去的女坑。
【1】注釋
#pragma mark------ XXXX---------
清晰的注釋對代碼的邏輯梳理有非常大的幫助填具。而且個人固定的代碼風格也有助于代碼邏輯的理解,沒有固定風格的代碼隨心所欲的寫法是很讓人頭疼的匆骗。
【2】類的命名和方法的命名都可以通過名稱達到歸類和易于理解的效果劳景。
【3】代碼復用:
1.公共組件,工程中多處調用碉就。
2.繼承盟广,在父類中統(tǒng)一處理。
3.抽象成類中的公用方法瓮钥,多處調用筋量。
【4】純代碼寫頁面中,所有的代碼布局都應該是 相對布局碉熄,可以使用 SDAutolayout 實現完全自動布局桨武,里面有 SC 和 Cell的自動布局,都是設置底部依據試圖锈津,設置邊距即可呀酸。
使用SDAutolayout 可以徹底解決所有情景下的高度自適應問題,而不單單是 cell的高度自適應問題琼梆。
PS:重構中一定要注意低級錯誤性誉。自己在這上面浪費了很多時間和精力。
第一個控件的 get 方法重寫時寫錯了茎杂,其他的都是拷貝第一個的错览,結果一直沒有調用子類“重寫的get方法” 其實沒有重寫父類的,因為方法寫的都不對煌往。