我們有很多的方法可以用程式實現我們的功能,但作為一個工程師是否寫出可維護的程式碼在於自己,卻往往對於團隊有很大的影響。好的程式碼不會有績效,在下班之餘再去看 clean code 的 CP 值很低?也許像在 Side Project 就可以自由發揮,但為了未來的擴展性,以及為了實現我們都有一個想成為一個更好的工程師的願望。當然 Clean Code 的細節很多,我想主要分享在《Good Code, Bad Code》這本書裡提到的六個大原則。
此外,我想舉實際的例子,以下是我分別實現了拖曳功能的兩個版本,包括重構前和重構後。首先需要強調的是,在我們尚未明確定義處理需求之前就開始編寫程式碼時,我們往往難以清晰區分功能和流程,也難以進行函式的模組化。換句話說,函式可能處理多個耦合的步驟。因為很重要,所以特別在這裡說明。或許在需求快速變化的情況下,我們無法投入足夠的時間或技術來編寫具有足夠彈性的程式碼,這就不可避免地導致了重構的需求。然而,我們仍然可以降低重構所需的時間成本,並盡量遵循一些簡潔程式碼的原則。
=== 重構前 ===
從 mousedown 開始一條龍處理 mousemove, mouseup 事件
const dragstart_handler = (event) => {
//此函式主要是使用者點擊 mousedown 之後出發
//處理滑鼠拖曳卡片樣式變化,主要為位置
currentDraggingStyle.value = {
position: "absolute",
zIndex: 1000,
};
document.body.append(card.value);
const moveAt = (pageX, pageY) => {
currentDraggingStyle.value = {
position: "absolute",
zIndex: 1000,
left: pageX - card.value.offsetWidth / 2 + "px",
top: pageY - card.value.offsetHeight / 2 + "px",
};
cardWidth.value = card.value.offsetWidth;
cardHeight.value = card.value.offsetHeight;
cardX.value = pageX - card.value.offsetWidth / 2 + "px";
cardY.value = pageY - card.value.offsetHeight / 2 + "px";
cardPosition.leftTop = {
x: pageX - card.value.offsetWidth / 2,
y: pageY - card.value.offsetHeight / 2,
};
cardPosition.leftBottom = {
x: pageX - card.value.offsetWidth / 2,
y: pageY + card.value.offsetHeight / 2,
};
cardPosition.rightTop = {
x: pageX + card.value.offsetWidth / 2,
y: pageY - card.value.offsetHeight / 2,
};
cardPosition.rightBottom = {
x: pageX + card.value.offsetWidth / 2,
y: pageY + card.value.offsetHeight / 2,
};
};
moveAt(event.pageX, event.pageY);
const dragmove_handler = (ev) => {
moveAt(ev.pageX, ev.pageY);
// 處理卡片是否要顯示提示框,以及插入不同的位置
handleTimelineObserver();
};
//處理使用者開始移動手指
document.addEventListener("mousemove", dragmove_handler);
//處理使用者手指放開結束拖曳
card.value.addEventListener("mouseup", () => {
document.removeEventListener("mousemove", dragmove_handler);
groupAnimated.value = false;
if (isMoveInTimeline.value) {
cardLists.value.splice(overOutlineCount.value, 0, currentCard.value);
cardLists.value[overOutlineCount.value].isCorrect = judgeOrder(
overOutlineCount.value
);
setTimeout(() => {
groupAnimated.value = true;
cardLists.value.sort(function (a, b) {
return a.order - b.order;
});
}, 1000);
updateStep();
}
cardContainer.value.append(card.value);
currentDraggingStyle.value = {
position: "static",
zIndex: 0,
left: "auto",
top: "auto",
transition: "all 2s ease-in-out",
};
isMoveInTimeline.value = false;
isOverOutline.value = false;
overOutlineCount.value = 0;
updateTimelineStyles();
card.value.removeEventListener("mouseup", () => {});
});
};
=== 重構後 ===
使用 Vue 框架提供的事件監聽處理器,
@mousedown.stop="handleClueCardClick(index, $event)"
@mouseup.stop="handleClueCardClickOff(index)"
...略
遵循這些最佳實踐和原則將有助於編寫出更可維護、更可靠的程式碼。