利用程式具有區段的能力,我們可以將 [如果 A 成立就做 B]
轉換成 [如果 A 不成立就離開]
,用這個方式做邏輯反相可以讓原本看似複雜的程式簡化很多,讓程式變得清晰思慮也會變的清晰,困難的問題就變得簡單,或著就不在是問題了。
這是一段重構前的程式:
- foreach (var item in list)
- {
- Guid guid = new Guid(item.project_GUID.Value.ToString());
- var project = _dc.Project.FirstOrDefault(w => w.ProjectID == guid);
- if (project != null)
- {
- var mails = !String.IsNullOrEmpty(project.AlertEmail) ? project.AlertEmail.Split(new char[]{';'}) : null;
- if (mails != null)
- {
- if(!mails.Any(x => x.mail == "a@b.c"))
- {
- foreach (var mail in mails)
- {
- if (!mailDic.ContainsKey(mail.Trim()))
- mailDic.Add(mail, new List<int>());
- mailDic[mail].Add(item.projectID);
- }
- }
- }
- }
- }
將邏輯反相重構後的程式:
- foreach (var item in list)
- {
- Guid guid = new Guid(item.project_GUID.Value.ToString());
- var project = _dc.Project.FirstOrDefault(w => w.ProjectID == guid);
- if (project == null) { continue; }
- if (String.IsNullOrEmpty(project.AlertEmail)) { continue; }
- var mails = project.AlertEmail.Split(new char[]{';'});
- if(mails.Any(x => x.mail == "a@b.c")){ continue; }
- foreach (var mail in mails)
- {
- if (!mailDic.ContainsKey(mail.Trim()))
- { mailDic.Add(mail, new List<int>()); }
- mailDic[mail].Add(item.projectID);
- }
- }
可以看出程式的縮排階層減少了,也簡化了程式的複雜度,重構的方法就是將 if 反相將 else 前移,也許一開始很難用這種方式寫程式,但是人腦是可以訓練的,在每次重構時進行調整改寫,習慣這種模式後很自然就會用這種[跳離]的思維去寫程式邏輯了。
當然這種方式也是有缺點的,就是有時候不這麼直覺會不好理解,但是可以增加一些註解來輔助描述,或是拆分判斷條件例如:
- if (a != null || b == null) { return; }
- /* 這可以拆分成兩行,不用拘泥一行完成 */
- if (a != null) { return; }
- if (b == null) { return; }
程式邏輯有一個有趣的事,往往用正向邏輯無法處理的問題,改用反相邏輯就會簡單很多,例如:需要用特定的邏輯尋找符合的項目,可能因為那個特定邏輯讓效能非常的差,這時候如果改用不符合特定邏輯的項目排除,留下來的就會是符合的項目,因為是用消去法所以要尋找的數量會越算越少,所以執行效能會收斂。
0 回應:
張貼留言