if-else重構優化

引言:javascript

在咱們編程寫代碼的時候,咱們會用到if-else或者switch-case的條件判斷來負責絕大部分代碼,可是不合理的使用if-else條件判斷會使咱們的程序複雜度大大提高,同時也會使代碼的可讀性急速降低,後期維護難度也大大提升。如今咱們一塊兒來用幾種方法重構優化一下。java

正文:編程

A、合理拆解markdown

咱們在符合條件下要執行函數時,當這段函數代碼片斷至關長,或者該函數是一段大型函數時,在帶有複雜邏輯的條件判斷中,檢查條件的代碼和實現功能的代碼會讓咱們不清楚是要實現什麼功能,從而使代碼的可讀性大大下降。咱們來看一段代碼片斷:app

toothAppointCancel(res: any) {
  if (TYPE === XXXX || TYPE === YYYY) {
      history.replace({
      pathname: `/appointmentdetail?jdAppointmentId=${res.msg}&type=${TYPE}`,
    });
    } else {
    window.location.reload();
  }
}
複製代碼

該代碼片斷主要實現了若是當前場景符合某些業務線時去作相應的功能實現,然而從代碼表現上看,咱們比較難以很快的看出代碼所表達的意圖。咱們能夠將他拆解爲多個獨立的函數,拆解的函數能夠根據功能來命名,並在原修改處調用該獨立的函數來清楚表達咱們的意圖。函數

image

讓咱們實現一下吧:優化

toothAppointCancel(res: any) {
  const isTooth = () => {
    return TYPE === XXXX || TYPE === YYYY;
  };
  const handleToothUpdate = () => {
    history.replace({
    pathname: `/appointmentdetail?jdAppointmentId=${res.msg}&type=${TYPE}`,
  });
  const handleReload = () => {
    window.location.reload();
  };
  isTooth() ? handleToothUpdate() : handleReload();
}
複製代碼

B、合併邏輯ui

有這麼一種狀況,咱們有不少的條件檢查,可是執行的功能函數倒是一致的,那麼咱們能夠用」邏輯與「或者」邏輯或「來把他們合併成一個表達式。若是咱們這些彼此獨立的條件判斷能夠被視爲同一次檢查的場景時,一次檢查的意圖明顯在可讀性上優於屢次的條件檢查。咱們來看一段代碼片斷:url

if (!(staffInfo.patientName && staffInfo.phone)) {
  // doSomething
}
...
if (!(staffInfo.phone && staffInfo.idCardNum)) {
  // doSomething
}

複製代碼

image

咱們能夠修改成以下:spa

if(!(staffInfo.patientName && staffInfo.phone) || !(staffInfo.phone && staffInfo.idCardNum)){
  // doSomething
} 
複製代碼

C、提早退出

當咱們在一個if條件判斷裏面再次編寫一個if判斷,而且裏面的if條件依賴於外部的if條件時,咱們也能夠用」邏輯與「來優化一下這個實現。咱們來看一下這個代碼片斷:

function handleEvent(event) {
  if (event) {
    const target = event.target;
    if (target) {
      ...
    }
  }
}
複製代碼

咱們檢查了下對象event是否爲真,以及屬性target是否可用。咱們能夠以下修改:

image

function handleEvent(event) {
  if (!event || !event.target) {
    return;
  }
  ...
}
複製代碼

D、return調整邏輯優先級

若是咱們的if-lese嵌套層級過多而且當咱們判斷只有一個條件分支是正常的,另外一個是異常狀況,若是異常不容易出現時應該單獨檢查這個異常的條件。咱們能夠區分每一層條件的優先級,把優先級高的放在第一層進行判斷,優先級低的放在後面判斷,這樣咱們能夠比較容易的分辨出每一層條件的重要性,能夠突出邏輯重點。」每個函數都應該只有一個入口和一個出口「觀念,咱們也能夠用在if-else中用return模擬這種思想。

image

咱們看一個代碼片斷:

if (!res) {
  if (relativesType === 1) {
    // doSomething
  }else {
    if (formData.sex === 2 && formData.married === 2) {
    // doSomething
  }
}

複製代碼

優化後:

function errorMery(){Toast.show('婚姻狀態與套餐不符');}
function alreadyMery(){setDialogInfo({
  ...dialogInfo,
  btnType: 1,
  titleText: '舒適提示',
  contText: MARRIED_TEXT,
  isDialogShow: true,
})}
if (!res) return;
if (relativesType === 1) return errorMery();
if (currLabel === 'married') return alreadyMery();

複製代碼

E、用多態替換switch場景

咱們在寫switch的時候,對於新手來講忘記寫break實在是再普通不過了,就算是老猿忘記寫也是時有發生的事情,而這個語法錯誤在諸多的語法檢查器上沒有辦法檢查出來的,由於從語法角度來講是正確的,但是代碼的處理邏輯倒是錯誤的。Switch儘管對於break很寬容,可是對判斷條件很嚴苛,case後面只能設置常量。還有一種狀況是有一個基礎邏輯,基於這個基礎邏輯又有一些變體,那麼咱們能夠把基礎邏輯放到超類,把各類變體邏輯放到各個子類。基於此,咱們能夠用面向對象中多態的特性來優雅的改善這些問題。 咱們來看一段代碼片斷:

fixAppointToUrl: (obj: any, type: number) => {
  let url = '';
  switch (type) {
    case TYPEA:
      ...
      url = "B_JD_PE_FIX_URL";
      break;
    case TYPEB:
      ...
      url = "BC_TOOTH_FIX_URL";
      break;
    case TYPEC:
      ...
      url = "C_BACTERIN_FIX_URL";
      break;
    case TYPED:
      ...
      url = "B_TOOTH_FIX_URL";
      break;
    default:
      ...
      url = "DEFAULT_FIX_URL";
  }
  return url;
}
repeatAppointToUrl: (obj: any, type: number) => {
   let url = '';
   switch (type) {
   case TYPEA:
      ...
      url = "B_JD_PE_REPEAT_URL";
      break;
   case TYPEB:
      ...
      url = "BC_TOOTH_REPEAT_URL";
      break;
   case TYPEC:
      ...
      url = "C_BACTERIN_REPEAT_URL";
      break;
   case TYPED:
      ...
      url = "B_TOOTH_REPEAT_URL";
      break;
   default:
      ...
      url = "DEFAULT_REPEAT_URL";
   }
   return url; 
}

複製代碼

咱們能夠建立一個工廠函數返回一個對象實例,而後將條件邏輯函數轉移到超類,在子類中建立函數複寫超類中條件表達式的函數。

image

優化後:

class HandleUrl {
  get fixUrl(){
    return 'DEFAULT_FIX_URL';
  }
  get repeatUrl(){
    return 'DEFAULT_REPEAT_URL';
  }
}
class TYPEA extends HandleUrl{
   get fixUrl(){
    return 'B_JD_PE_FIX_URL';
   }
   get repeatUrl(){
    return 'B_JD_PE_REPEAT_URL';
   }
}
class TYPEB extends HandleUrl{
   get fixUrl(){
    return 'BC_TOOTH_FIX_URL';
   }
   get repeatUrl(){
    return 'BC_TOOTH_REPEAT_URL';
   }
}
class TYPEC extends HandleUrl{
   get fixUrl(){
    return 'C_BACTERIN_FIX_URL';
   }
   get repeatUrl(){
    return 'C_BACTERIN_REPEAT_URL';
   }
}
class TYPED extends HandleUrl{
   get fixUrl(){
    return 'B_TOOTH_FIX_URL';
   }
   get repeatUrl(){
    return 'B_TOOTH_REPEAT_URL';
   }
}

複製代碼

咱們使用時能夠建立一個子類對象調用該業務線特定的url鏈接:

const typed = new TYPED();
console.log(typed.fixUrl)
複製代碼

總結:

對於改善優化if-else條件邏輯代碼,咱們使用了分解條件來處理複雜的條件表達式,可使用合併條件來清晰的梳理邏輯,可使用return改善嵌套條件邏輯,可使用多態優化switch判斷,由此咱們能夠在具體使用傳統條件邏輯判斷的場景以外多了一種功能實現的選擇。

相關文章
相關標籤/搜索