摘要:面對(duì)這樣的已經(jīng)上線的代碼,我并沒(méi)有想去重構(gòu)他因?yàn)槌杀咎撸缓帽薏咦约翰灰獙懗鲞@種代碼面對(duì)的問(wèn)題有時(shí)候,我們可能面對(duì)這樣的業(yè)務(wù)邏輯。一坨一坨的看著非常不舒服,并且難以維護(hù)。如果不滿足條件返回調(diào)用職責(zé)鏈的下一個(gè)節(jié)點(diǎn)。
前言
新入職的公司,前人留下來(lái)一個(gè)項(xiàng)目,里面充斥著大量的if...else...,則倒是其次,主要連注釋寫的都很少。面對(duì)這樣的已經(jīng)上線的代碼,我并沒(méi)有想去重構(gòu)他因?yàn)槌杀咎?,只好鞭策自己不要寫出這種代碼
面對(duì)的問(wèn)題?有時(shí)候,我們可能面對(duì)這樣的業(yè)務(wù)邏輯。(公司項(xiàng)目的業(yè)務(wù)邏輯),如果是回答過(guò)題目通過(guò),如果回答過(guò)題目沒(méi)有通過(guò),如果沒(méi)有回答過(guò)題目。如果不使用特定的模式,可能會(huì)寫出下面這樣的代碼。一坨一坨的if...else看著非常不舒服,并且難以維護(hù)。
/** * 初始化函數(shù) * if...else if... 的情況較為簡(jiǎn)單 * @return undefined */ function init () { // 是否回答過(guò)題目 1-回答過(guò), 通過(guò) 2-回答過(guò), 沒(méi)有通過(guò) 3-沒(méi)有回答過(guò) let isAnswer // 是否是老用戶 1-老用戶 2-新用戶 let isOldUser if (isAnswer === 1) { // ... } else if (isAnswer === 2) { // ... } else if (isAnswer === 3) { // ... } if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } }
/** * 初始化函數(shù) * if...else if... 嵌套的情況 * @return undefined */ function init () { if (isAnswer === 1) { if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } } else if (isAnswer === 2) { if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } } else if (isAnswer === 3) { if (isOldUser === 1) { // ... } else if (isOldUser === 2) { // ... } } }解決辦法1: 查找表, 職責(zé)鏈查找表
雖然可能看著是治標(biāo)不治本,其實(shí)不然,init函數(shù)的復(fù)雜度大大的降低了。我們已經(jīng)把控制流程的復(fù)雜邏輯,拆分到determineAction函數(shù)中
// 可以解決if...else if...簡(jiǎn)單的問(wèn)題 const rules = { isAnswer1 () { return code }, isAnswer2 () { return code }, isAnswer3 () { return code } } function determineAction (type) { if (isAnswer === 1) { return "isAnswer1" } else if (isAnswer === 2) { return "isAnswer2" } else if (isAnswer === 3) { return "isAnswer3" } } function init () { let key = determineAction(isAnswer) return rules[key] }
// 面對(duì)if...else if...else 嵌套的復(fù)雜情況 const rules = [ { match (an, old) { if (an === 1) { return true } }, action (an, old) { if (old === 1) { // ... } else if (old === 2) { // ... } } }, { match (an, old) { if (an === 2) { return true } }, action (an, old) { if (old === 1) { // ... } else if (old === 2) { // ... } } }, { match (an, old) { if (an === 3) { return true } }, action (an, old) { if (old === 1) { // ... } else if (old === 2) { // ... } } } ] function init (an, old) { for (let i = 0; i < rules.length; i++) { // 如果返回true if (rules[i].match(an, old)) { rules[i].action(an, old) } } } init(isAnswer, isOldUser)
??上面復(fù)雜的情況,也可以吧action的判斷抽離出來(lái)但是可能要寫出三個(gè)抽離的函數(shù),因?yàn)閍n值有三種不同的情況
解決辦法2: 面向切面的編程(AOP)為Function的原型鏈,擴(kuò)展after語(yǔ)法,如果滿足要求直接在函數(shù)內(nèi)運(yùn)算并返回結(jié)果。如果不滿足條件返回"next"調(diào)用職責(zé)鏈的下一個(gè)節(jié)點(diǎn)。所謂的Function.prototype.after就是在本函數(shù)執(zhí)行前執(zhí)行after添加的函數(shù)
// 可以解決if...else if...簡(jiǎn)單的問(wèn)題 Function.prototype.after = function (nextFn) { let self = this return function (...rest) { let code = self(...rest) if (code === "next") { return nextFn(...rest) } return code } } // 重構(gòu)原函數(shù) function isAnswer1 (type) { if (type === 1) { return code } return "next" } function isAnswer2 () { if (type === 2) { return code } return "next" } function isAnswer3 () { if (type === 3) { return code } return "next" } let isAnswerFn = isAnswer1.after(isAnswer2).after(isAnswer3) isAnswerFn(isAnswer)
// 面對(duì)if...else if...else 嵌套的復(fù)雜情況 function isAnswer1 (an, old) { if (an === 1) { return isOldUserFn1(an, old) } return "next" } function isAnswer2 (an, old) { if (an === 2) { return isOldUserFn2(an, old) } return "next" } function isAnswer3 (an, old) { if (an === 3) { return isOldUserFn3(an, old) } return "next" } /** * isAnswer == 1 isOldUser == 1 的情況 */ function isAnswer1IsOldUser1 (an, old) { if (old === 1) { return code } return "next" } /** * isAnswer == 1 isOldUser == 2 的情況 */ function isAnswer1IsOldUser2 (an, old) { if (old === 2) { return code } return "next" } /** * isAnswer == 2 isOldUser == 1 的情況 */ function isAnswer2IsOldUser1 (an, old) { if (old === 1) { return code } return "next" } /** * isAnswer == 2 isOldUser == 2 的情況 */ function isAnswer2IsOldUser2 (an, old) { if (old === 2) { return code } return "next" } /** * isAnswer == 3 isOldUser == 1 的情況 */ function isAnswer3IsOldUser1 (an, old) { if (old === 1) { return code } return "next" } /** * isAnswer == 3 isOldUser == 2 的情況 */ function isAnswer3IsOldUser2 (an, old) { if (old === 2) { return code } return "next" } let isAnswerFn = isAnswer1.after(isAnswer2).after(isAnswer3) // 三條職責(zé)鏈 let isOldUserFn1 = isAnswer1IsOldUser1.after(isAnswer1IsOldUser2) let isOldUserFn2 = isAnswer2IsOldUser1.after(isAnswer2IsOldUser2) let isOldUserFn3 = isAnswer3IsOldUser1.after(isAnswer3IsOldUser2) isAnswerFn(isAnswer, isOldUser)解決辦法3: 函數(shù)式編程
利用ramda等函數(shù)式編程庫(kù)解決這種問(wèn)題,
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104541.html
摘要:重構(gòu)定義重構(gòu)是對(duì)軟件內(nèi)部結(jié)構(gòu)的調(diào)整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。重構(gòu)節(jié)奏小步前進(jìn),頻繁測(cè)試。 1.重構(gòu)定義: 重構(gòu)是對(duì)軟件內(nèi)部結(jié)構(gòu)的調(diào)整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。 2.重構(gòu)節(jié)奏: 小步前進(jìn),頻繁測(cè)試。 3.重構(gòu)意義: 1.改進(jìn)軟件設(shè)計(jì) 2.使軟件更容易被理解 3.幫助找到bug 4.提高編程速度 惡...
摘要:原文作者給你的代碼增加一點(diǎn)點(diǎn)函數(shù)式編程的特性最近我對(duì)函數(shù)式編程非常感興趣。對(duì)我而言,函數(shù)式編程最大的作用就是強(qiáng)制你編寫聲明性代碼代碼描述你做什么,而不是在描述如何做。事實(shí)證明,編寫聲明式代碼是函數(shù)式編程中最簡(jiǎn)單的部分之一。 原文:Writing flat & declarative code作者:Peeke Kuepers -- 給你的代碼增加一點(diǎn)點(diǎn)函數(shù)式編程的特性 最近我對(duì)函數(shù)式編程...
摘要:重構(gòu)在不改變代碼的外在的行為的前提下對(duì)代碼進(jìn)行修改最大限度的減少錯(cuò)誤的幾率本質(zhì)上,就是代碼寫好之后修改它的設(shè)計(jì)。重構(gòu)可以深入理解代碼并且?guī)椭业?。同時(shí)重構(gòu)可以減少引入的機(jī)率,方便日后擴(kuò)展。平行繼承目的在于消除類之間的重復(fù)代碼。 重構(gòu) (refactoring) 在不改變代碼的外在的行為的前提下 對(duì)代碼進(jìn)行修改最大限度的減少錯(cuò)誤的幾率 本質(zhì)上, 就是代碼寫好之后 修改它的設(shè)計(jì)。 1,書中...
摘要:通常情況下,面向?qū)ο缶幊套屛覀兊靡员苊鈼l件式,并代之以繼承和多態(tài)。同時(shí),使用條件式簡(jiǎn)寫來(lái)表示值。因此,對(duì)于以這種方式編寫的代碼,你需要使用進(jìn)行編譯。 原文地址:Tips and Tricks for Better JavaScript Conditionals and Match Criteria 原文作者:Milos Protic 介紹 如果你像我一樣樂(lè)于見(jiàn)到整潔的代碼,那么你...
摘要:在開(kāi)發(fā)的過(guò)程中相信你也會(huì)寫很多的語(yǔ)句吧,此篇主要來(lái)講講如何在日常開(kāi)發(fā)的過(guò)程中盡量少的使用語(yǔ)句。策略一單例模式這種單例模式在類一加載的時(shí)候就將單例對(duì)象創(chuàng)建完畢,總是這個(gè)對(duì)象存在內(nèi)存中,避免了通過(guò)線程同步來(lái)生成對(duì)象,線程安全的創(chuàng)建方式。 在開(kāi)發(fā)的過(guò)程中相信你也會(huì)寫很多的if else語(yǔ)句吧,此篇主要來(lái)講講如何在日常開(kāi)發(fā)的過(guò)程中盡量少的使用if else語(yǔ)句。 0x01 為什么要去if el...
閱讀 1529·2021-11-18 10:02
閱讀 1680·2021-09-04 16:40
閱讀 3180·2021-09-01 10:48
閱讀 882·2019-08-30 15:55
閱讀 1860·2019-08-30 15:55
閱讀 1379·2019-08-30 13:05
閱讀 3022·2019-08-30 12:52
閱讀 1632·2019-08-30 11:24