動機: 凸顯意圖、降低閱讀複雜度
作法: 將分支中的條件邏輯抽成 函式 (Extract Function)
From
if (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd))
charge = quantity * plan.summerRate;
else
charge = quantity * plan.regularRate + plan.regularServiceCharge;
To
if (summer())
charge = summerCharge();
else
charge = regularCharge();
To
const charge = summer() ? summerCharge() : regularCharge()
動機: 當檢查不同、底下卻做相同的事時,代表 1. 檢查可結合、 2. 可抽出函式 (Extract Function)凸顯意圖 (封裝、隱藏細節,從說 how 變成說 why)
作法:
From
function disabilityAmount (anEmployee) {
if (anEmployee.seniority < 2) return 0;
if (anEmployee .monthsDisabled > 12) return 0;
if (anEmployee.isPartTime) return 0;
// 計算 disability amount
...
}
To
function disabilityAmount (anEmployee) {
if (isNotEligableForDisability()) return 0;
//計算 disability anount
...
function isNotEligableForDisability() {
return ((anEmployee.seniority < 2)
|| (anEmployee.monthsDisabled > 12)
|| (anEmployee.isPartTime));
}
}
From
if(anEmployee.onVacation)
if (anEmployee.seniority > 10)
return 1;
return 0.5;
To
if ((anEmployee.onVacation) && (anEmployee.seniority > 10)) return 1;
return 0.5;
動機: 使入口和出口更“清晰”!
防衛敘句能指出某情況非功能“核心”,發生了就採取行動離開。有意識到思考你的條件分支是屬於正常 or 異常,(2組都正常,用 if/else <= 權重相同;有一組為異常 <= 提早離開)
作法:
From
function getPayAmount () {
let result;
if (isDead)
result = deadAmount();
else {
if (isSeparated)
result = separatedAmount();
else {
if (isRetired)
result = retiredAmount();
else
result = normalayAmount();
}
}
return result;
}
To
function getPayAmount () {
if (isDead) return deadAmount() ;
if (isSeparated) return separatedAmount();
if (isRetired) return retiredAmount();
return normalPayAmount ();
}
From
function adjustedCapital (anInstrument) {
let result = 0;
if (anInstrument.capital > 0) {
if (anInstrument.interestRate > 0 && anInstrument.duration > 0){
result = (anInstrument.income / anInstrument.duration) * anInstrument.adjustmentFactor;
}
}
return result;
}
// 條件反轉、簡化過程
+ if (anInstrument.capital <= 0) return result
+ if (!(anInstrument.interestRate > 0 && anInstrument.duration > 0)) return result
+ if (anInstrument.interestRate <= 0 || anInstrument.duration <= 0) return result
+ 合併 12,14 行
+ 移除多餘的變數 result
註解:狄摩根定律 (!a) && (!b) === !(a || b)
和 (!a) || (!b) === !(a && b)
To
function adjustedCapital (anInstrument) {
if ( anInstrument.capital <= 0
|| anInstrument.interestRate <= 0
|| anInstrument.duration<= 0 ) return 0;
return (anInstrument.income / anInstrument .duration) * anInstrument .adjustmentFactor
動機: 凸顯意圖、寶貴的溝通工具、除錯的好幫手
作法: 當你見到一個條件為真的狀況時,加入斷言來說明此事
From
if(this.discountRate)
base = base - (this.discountRate * base)
To
assert(this.discountRate >= 0) // 斷言失敗代表程式碼有錯
if(this.discountRate)
base = base - (this.discountRate * base)
// assert 大致會長得像下面這樣,nodejs 有提供 API
function assert(condition, message) {
if (!condition) {
throw new Error(message || "Assertion failed");
}
}
disabled = !isEligible || !isActive
disabled = !(isEligible && isActive)
enabled = isEligible && isActive
expect(add(5, 5)).toBe(10);
let str: unknown = "geeksforgeeks";
let len: number = (str as string).length;
const content = (() => {
switch (status) {
case 'loading':
return <LoadingBar />;
case 'loaded':
return <Table />;
default:
return null;
}
})();
return (
<Container>
{content}
</Container>
const user = {
firstName: "Seán",
lastName: "Barry",
email: "my.address@email.com",
number: "00447123456789",
};
switch (true) {
case !user:
throw new Error("User must be defined.");
case !user.firstName:
throw new Error("User's first name must be defined");
case typeof user.firstName !== "string":
throw new Error("User's first name must be a string");
// ...lots more validation here
default:
return user;
}
// from
var drinks;
switch(type) {
case 'coke':
drink = 'Coke';
break;
case 'pepsi':
drink = 'Pepsi';
break;
default:
drink = 'Unknown drink!';
}
// to
function getDrink (type) {
var drinks = {
'coke': 'Coke',
'pepsi': 'Pepsi',
'lemonade': 'Lemonade',
'default': 'Default item'
};
return 'The drink I chose was ' + (drinks[type] || drinks['default']);
}
1. What is Hydration 儘管 Server-Side Rendering 已經有效改善 First Content Paint 但是不一定能提高好的 Time To Interactive 網站看似好了,但實際上「Buy Now」其實還沒辦法跟 User 互動(Interactive) 原因:因為 JavaScript 還沒好 -> 還沒被載入 or 還沒被處理
May 14, 2022Terms (1). 主題、對象、目標 Subject -> 被(大眾)觀察的對象、名人 (2). 觀察者、訂閱者 Observer, Subscriber (3). 觀察者 如何跟 主題 產生連結,開啟小鈴鐺「訂閱(Subscribe)」 觀察者選擇有興趣的主題進行訂閱 * Ken 訂閱 JavaScript Weekly * Ken 追蹤 PJCHENder網頁開發咩腳 (4). 名人藉由通知(Notify),將新訊息傳給訂閱者 * JavaScript Weekly 每週都會發新文章連結到 Ken 的信箱
Mar 26, 2022前言 身為一位優秀的 Software Engineer(SWE),就是將自身具備軟體工程知識、商業領域知識應用到軟體開發中,並且產出優良、具有商業價值的軟體。軟體開發的過程中,總是不斷循環著決策、規劃、執行及驗收等週期。 要生產一個好的軟體,從最開始的需求探索、釐清...到實際進入開發環節時的架構規劃、介面設計、細節實作,乃至最後的驗收、驗證等一系列漫長的過程。 SWE 日常主要的工作任務包含:撰寫程式碼(實踐商業需求)、撰寫測試及除錯等;而重構一詞,經常在撰寫程式碼、測試的環節時被聽見。 重構在軟體開發中的意義是什麼?能為軟體帶來什麼更大的價值?今天就要來與大家一起探索何謂重構。 什麼是重構?
Jan 27, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up