สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video
Clean code คืออะไร ?
“เราทุกคนล้วนไม่ชอบบ้านรกๆครับ code ก็เช่นกัน”
การ clean code คือการเขียน code ให้ง่ายต่อการอ่าน ทำความเข้าใจและดูแลรักษา (maintain) ได้ง่ายขึ้น โดย concept ของ clean code โดยทั่วไปจะไม่ได้พูดถึงแค่การทำให้ code ดูดีอย่างเดียว แต่จะพูดถึงการทำให้ code มีประสิทธิภาพที่ดีขึ้นด้วย และ ส่งผลทำให้เกิด Error ลดลงได้ด้วย (จากการ implement code ให้ถูก Practice)
ในบทความนี้เราจะเล่าการทำ Clean code ผ่านภาษา Javascript กัน เนื่องจากเป็นภาษาที่มีผู้ใช้ใน github “มากที่สุด” ในโลก (จากช่วงปี 2023 ที่ผ่านมา)
มีวิธีไหนที่สามารถทำให้ code clean ขึ้นได้บ้าง
สิ่งนี้เป็นการรวบรวมจากประสบการณ์ผมเอง + จากการอ่านข้อมูลหลาๆแหล่งข้อมูลมาใช้ร่วมกัน โดยเราจะไล่ระดับตั้งแต่เรื่องง่ายๆ ไปจนถึงเรื่องยากๆกัน (ไม่ได้ยากในแง่การทำ แต่ยากในแง่การคิดว่าจะต้องทำสิ่งนั้นตอนไหน)
เพื่อให้เห็นภาพเราจะยกตัวอย่าง code มาเทียบกัน 2 ชุดมาเทียบกัน ว่ามีความแตกต่างกันอย่างไร โดยในบทความนี้เราจะเรียกว่า BAD คือ code ที่ไม่ตรงตาม practice ของ clean code และ GOOD คือ code ที่ตรงตาม practice ของ clean code ครับ
และ ที่สำคัญ “เรื่องนี้ไม่มีคำตอบตายตัว” ทั้งนี้อาจจะขึ้นอยู่กับทีมที่ร่วมงานและอาจจะเปลี่ยนแปลงได้ตามยุคสมัยเช่นเดียวกัน (เช่น ตัวภาษาอาจจะมีการ update บางอย่างเพิ่มเติมส่งผลทำให้การเขียนบางคำสั่งสามารถเขียนได้ง่ายขึ้น เป็นต้น)
โดยประเด็นที่เราจะหยิบมาเล่าในบทความนี้ เราจะแยกออกเป็นประเด็นตามนี้คือ
Variable (ตัวแปร)
Functions
Concurrency (callback, promise, async-await)
Error Handling
อื่นๆ (Comment, Formating, Principle อื่นๆ)
ย้ำไว้ก่อนว่า ที่เขียนในนี้ยังไม่ใช่ทั้งหมดของ Clean code นะครับ จริงๆ Practice ของ clean code มันเยอะมาก (มากๆเลยแหละ) แต่ผมจะหยิบตัวที่ผมรู้สึกว่า “ควร” หรือ “ต้องทำ” จริงๆ เพื่อให้ code ออกมาเรียบร้อยมากขึ้นนะครับ (เรื่องที่อยู่ในบทความนี้จะอยู่ในระดับพื้นฐานที่ควรทำเสมอ ไม่ว่า code จะเป็น style functional หรือ OOP ก็ตามนะครับ)
1. Variable
ตั้งชื่อตัวแปรให้มีความหมาย
ใช้ชื่อตัวแปรที่สื่อโดยตรงว่ากำลังเก็บอะไรไว้อยู่ (ใช้คำที่มีความหมายจริง)
BAD:
let tmrw = new Date (); // ไม่ชัดเจนว่าคืออะไร ใช้ทำอะไร
let data = ' John Doe ' ; // data ของอะไร
let number = 42 ; // ตัวเลขของอะไร
GOOD:
let currentDate = new Date (); // ชัดเจนว่าวันปัจจุบัน
let userName = ' JohnDoe ' ; // ชัดเจนว่าเก็บ user name
let maxScore = 42 ; // ชัดเจนว่าใช้สำหรับเก็บ score
รวมกลุ่มศัพท์ประเภทเดียวกัน
เป็นการกันสับสนว่าข้อมูลเป็นประเภทเดียวกันหรือไม่ ?
BAD:
// อ่อ user setting สักจุด
let userSettings = { theme : ' dark ' , language : ' English ' };
// อ่อ เกี่ยวกับ theme user แต่ใช้ตรง setting ใช่ไหม ?
let userProfilePreferences = { theme : ' light ' , fontSize : ' medium ' };
// เอ๊ะ member กับ user นี่เหมือนกันหรือป่าว ?
let memberOptions = { language : ' French ' , notifications : true };
GOOD:
// ชัดเจนว่าทั้ง 3 อันใช้ที่ Setting เหมือนกัน
let userSettings = { theme : ' dark ' , language : ' English ' };
let displaySettings = { theme : ' light ' , fontSize : ' medium ' };
let notificationSettings = { email : true , sms : false };
ใช้ชื่อที่สามารถค้นหาได้และอ่านได้
อย่าใช้ตัวแปร (เช่น ตัวแปรตัวเดียว) หรือค่าคงที่ “ที่อธิบายไม่ได้” วางไว้ใน code
BAD:
setTimeout (updateFunction, 86400000 ); // 86400000 คืออะไร ?
GOOD:
// อ่อ นี่คือจำนวน miliseconds ต่อวัน
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000 ; //86400000;
setTimeout (blastOff, MILLISECONDS_PER_DAY );
เลี่ยงใช้ตัวย่อ
พยายามใช้คำเต็ม เพื่อกันสับสนว่ากำลังสื่อถึงอะไรอยู่
BAD:
let loc = [ ' Austin ' , ' New York ' , ' San Francisco ' ]; // loc คืออะไร ?
for ( let i = 0 ; i < loc. length ; i ++ ) {
GOOD:
let cities = [ ' Austin ' , ' New York ' , ' San Francisco ' ]; // อ่อมันคือ array ของ cities
for ( let cityIndex = 0 ; cityIndex < cities. length ; cityIndex ++ ) {
// process cities[cityIndex]
// city คือแต่ละเมืองที่กำลัง loop ไป
ไม่ต้องใส่ Context ซ้ำๆกันในตัวแปรประเภทเดียวกัน
พวก class / object ถ้าตัวมันเองสื่อถึงความหมายอยู่แล้ว ไม่จำเป็นต้องย้ำของที่อยู่ภายในว่าเป็นสิ่งนั้น
BAD:
// ใช้ student ภายใน key ซ้ำๆกัน ทั้งที่เราก็รู้อยู่แล้วว่ามันสื่อถึง Student
GOOD:
ใช้ค่า default แทนการ shortcut condition
เป็นการบอกกลายๆว่า ตัวแปรนี้ “เมื่อไม่มีการเรียกใช้เลย” จะการันตีว่ามีค่าอยู่แน่นอนได้
BAD:
function createGreeting ( name , timeOfDay ) {
name = name || ' Guest ' ; // Short circuiting
timeOfDay = timeOfDay || ' Day ' ; // Short circuiting
return `Good ${ timeOfDay } , ${ name } !` ;
console. log ( createGreeting ()); // Output: "Good Day, Guest!"
console. log ( createGreeting ( ' Alice ' )); // Output: "Good Day, Alice!"
GOOD:
// ใส่ default ไปเลย จะได้ไม่ต้องมาคอยดักแต่ละค่าไว้
function createGreeting ( name = ' Guest ' , timeOfDay = ' Day ' ) {
return `Good ${ timeOfDay } , ${ name } !` ;
console. log ( createGreeting ()); // Output: "Good Day, Guest!"
console. log ( createGreeting ( ' Alice ' )); // Output: "Good Day, Alice!"
console. log ( createGreeting ( ' Alice ' , ' Morning ' )); // Output: "Good Morning, Alice!"
2. Functions
แน่นอน ในเรื่องของการตั้งชื่อ function นั้นเราสามารถ follow ตามแบบเดียวกับหัวข้อของ Variable ได้ ในหมวดนี้เราจะพยายามเน้นไปที่สาระสำคัญของ “การสร้าง function” กันว่า ควรคำนึงถึงประเด็นไหนกันบ้างนะครับ
Function Arguments (2 or Fewer Ideally)
guideline นี้สร้างขึ้นเพื่อทำการลดทอนจำนวนของ arguments ของ function ลง เพื่อให้สามารถอ่านได้ง่ายขึ้น และเพื่อเป็นการลดทอนความซับซ้อนของ function ลงเช่นเดียวกัน (จะได้รู้ว่า function นี้เกี่ยวกับการจัดการเรื่องไหนได้เลย แทนที่จะต้องมาไล่ดูทีละตัวแปรว่ามาจากอะไร)
BAD:
// ตัวแปรทั้งหมดเกี่ยวกับ user แท้ๆ แต่พอกระจาย argument ก็จะสับสนได้ว่าแต่ละตัวแปรมีที่มายังไง
function createUser ( firstName , lastName , age , email , phoneNumber , address ) {
// Code to create a new user
GOOD:
// ก็จะเหลือเพียงแค่ 2 argument ที่ใช้จัดการใน function แทน
function createUser ( name , contactDetails ) {
// Code to create a new user
// หรือสามารถใช้ไอเดียของ `ES2015/ES6 destructuring syntax` ในการจัดการได้เหมือนกัน
function createUser ({ firstName , lastName }, { age , email , phoneNumber , address }) {
// Code to create a new user
{ firstName : ' John ' , lastName : ' Doe ' },
{ age : 30 , email : ' john.doe@example.com ' , phoneNumber : ' 123-456-7890 ' , address : ' 123 Main St ' }
ลบ duplicate code !
หาก function ไหนมีการทำงานเหมือนกัน ให้รวมเป็น function เดียวกันออกมาแทน
BAD:
function updateUserProfile ( userId , newProfileData ) {
let user = database. fetchUserById (userId); // Fetching user
user.profile = newProfileData;
database. saveUser (user); // Saving changes
function updateUserEmailPreferences ( userId , newEmailPreferences ) {
let user = database. fetchUserById (userId); // Fetching user
user.emailPreferences = newEmailPreferences;
database. saveUser (user); // Saving changes
GOOD:
// รวมเป็น function สำหรับ update ตัวเดียว (เทคนิคนี้เรียกว่า High order function)
function updateUser ( userId , updateFunction ) {
let user = database. fetchUserById (userId);
updateFunction (user); // เรียกใช้ function ที่ส่งเข้ามาแทน
function updateUserProfile ( userId , newProfileData ) {
updateUser (userId, user => {
user.profile = newProfileData;
function updateUserEmailPreferences ( userId , newEmailPreferences ) {
updateUser (userId, user => {
user.emailPreferences = newEmailPreferences;
Functions ควรทำแค่สิ่งเดียว
เพื่อให้ง่ายตอนการใช้งานและการทำ Unit test การให้ function มีเพียงแค่จุดประสงค์เดียวจะลดความซับซ้อนของ code ลงได้
BAD:
function processAndSaveUserData ( inputData ) {
let data = JSON . parse (inputData);
if ( ! data.name || ! data.email) {
throw new Error ( " Invalid data - name and email are required " );
GOOD:
function parseUserData ( inputData ) {
return JSON . parse (inputData);
function validateUserData ( data ) {
if ( ! data.name || ! data.email) {
throw new Error ( " Invalid data - name and email are required " );
function saveUserData ( data ) {
function processAndSaveUserData ( inputData ) {
let data = parseUserData (inputData);
เหตุผลที่ทำแบบนี้ดีกว่าเพราะ
ตอนเรากลับมาแก้ จะชัดเจนว่าแต่ละจุดของ code ทำอะไรบ้าง
เวลาที่มีปัญหาต้องแก้กับส่วนไหน (parseUserData, validateUserData, saveUserData) สามารถแยกส่วนแก้และแยกส่วน Test ได้
ชื่อ function ควรบอกว่าทำอะไร
ชื่อควรชัดเจนว่ามีการกระทำอะไรและมีจุดประสงค์เพื่อได้ผลลัพธ์อะไรออกมา
BAD:
if (data.purchaseAmount > 1000 ) {
function handle ( number ) {
GOOD:
// อ่อ เช็คว่า user สามารถใช้ discount ได้ไหม
function isUserEligibleForDiscount ( userPurchaseData ) {
if (userPurchaseData.purchaseAmount > 1000 ) {
// อ่อ ทำการยกกำลังสองของตัวเลข
function calculateSquareOfNumber ( number ) {
// Code to calculate the square of a number
Set default objects ด้วย Object.assign
นอกเหนือจากการรับ argument ที่ไม่เยอะแล้ว ทุก functions ควรจะมีค่า default ของตัวเองเช่นเดียวกัน ซึ่ง javascript สามารถทำได้โดยใช้คำสั่ง Object.assign
ซึ่งเป็นคำสั่งสำหรับการ merge object 2 ตัวเข้าด้วยกัน โดย Object.assign
จะยึดตามค่าที่ส่งมา และจะเพิ่มเติมหากไม่มีค่าอะไรใน key นั้น เพื่อทำให้มั่นใจได้ว่า “ทุก key ใน object มีค่าเสมอแน่นอน”
BAD:
// ต้องมาคอยไล่ set แต่ละ key เพื่อให้แน่ใจ
function createReport ( data , options ) {
title : options.title || ' Default Report Title ' ,
pageSize : options.pageSize || ' A4 ' ,
format : options.format || ' PDF ' ,
headerColor : options.headerColor || ' #000 ' ,
GOOD:
// เพียงใช้ Object.assign สามารถ set ได้ในบรรทัดเดียว
function createReport ( data , options = {}) {
title : ' Default Report Title ' ,
options = Object. assign ({}, defaultOptions, options);
ไม่ควรใช้ parameter เพื่อแยกเคส function
จะทำให้การใช้งานเกิดการสับสนได้ว่า จุดประสงค์ของ function นี้จริงๆมันมีไว้่เพื่อทำอะไร
BAD:
// ทำได้ทั้ง 2 อย่างเลยทั้งลบทั้ง update
function updateDatabaseEntry ( id , data , isDelete ) {
database. deleteEntry (id);
database. updateEntry (id, data);
updateDatabaseEntry ( 123 , someData, false ); // to update
updateDatabaseEntry ( 123 , null , true ); // to delete
GOOD:
// แยกจุดประสงค์ให้ชัดเจนไปเลย อันไหน update, อันไหน delete
function updateDatabaseEntry ( id , data ) {
database. updateEntry (id, data);
function deleteDatabaseEntry ( id ) {
database. deleteEntry (id);
updateDatabaseEntry ( 123 , someData); // to update
deleteDatabaseEntry ( 123 ); // to delete
Encapsulate conditionals
การห่ออะไรก็ตามที่เป็น condition ยาวๆออกมาเป็น function แทนเพื่อให้ตรวจสอบได้ง่ายขึ้นและเข้าใจวัตถุประสงค์ของ function นั้นมากขึ้น
BAD:
hasValidMembership : true ,
if (user.age > 18 && user.hasValidMembership && user.memberSince > 2 ) {
GOOD:
hasValidMembership : true ,
isEligibleForDiscount () {
return this .age > 18 && this .hasValidMembership && this .memberSince > 2 ;
if (user. isEligibleForDiscount ()) {
Remove dead code
Dead code คือ code ที่จะไม่ถูกแตะหรือเข้าถึง เนื่องจากไม่ได้ใช้งานหรือไม่มีเงื่อนไขใดสามารถไปถึงมันได้แล้ว
BAD:
function processUserInput ( input ) {
if (input === null || input === undefined ) {
processedInput = ' No input provided ' ;
processedInput = input. trim ();
// condition นี้จะไม่มีวันได้ทำงาน เพราะ processedInput จะมีค่าเสมอจาก if - else อันบน
if (processedInput === undefined ) {
return ' Undefined input ' ;
// function นี้ก็ไม่ได้ใช้
function neverUsedFunction () {
console. log ( " This function is never called anywhere in the code. " );
// variable นี้ก็ไม่ได้ใช้
const redundantVariable = " Not used anywhere " ;
console. log ( processUserInput ( " Hello World " ));
GOOD:
function processUserInput ( input ) {
if (input === null || input === undefined ) {
return ' No input provided ' ;
console. log ( processUserInput ( " Hello World " ));
Avoid Side Effects
หลีกเลี่ยงการสร้าง function ที่ให้ผลลัพธ์ไม่เหมือนเดิม เนื่องจากมีการใช้ตัวแปรที่ dependency กัน เช่น
มี state บางอย่างถูกใช้งานจากภายนอกหรือใช้งานร่วมกันหลายๆที่ จาก global variable
มีการส่ง object ที่ดัดแปลง value ใน object
มีการจัดการผ่าน I/O บางอย่าง ที่ส่งผลทำให้แต่ละรอบจะขึ้นอยู่กับ file อื่นๆ
ซึ่งสิ่งนี้สามารถแก้ได้โดยการให้ทุก function ต้องทำแบบ “Pure function” (function ที่ต้องไม่มีีการทำอะไรกับ external state) เพื่อให้ function สามารถให้ผลลัพธ์เหมือนกันในทุกๆรอบที่ run ออกมาได้
เช่น เคสที่ 1 global variable
BAD:
function increaseAge ( newAge ) {
userAge = newAge; // Modifies the global variable userAge
console. log (userAge); // 31 - The global variable has been changed
GOOD:
function getIncreasedAge ( currentAge , increment ) {
return currentAge + increment; // Pure function with no side effects
let newUserAge = getIncreasedAge (userAge, 1 );
console. log (userAge); // 30 - Original age is unchanged
console. log (newUserAge); // 31 - New age is calculated and returned
เช่น เคสที่ 2 site effect จาก object
BAD:
// เมื่อ cart มีการนำไปใช้งานต่อ จะได้ข้อมูลเพิ่มต่อได้
const addItemToCart = ( cart , item ) => {
cart. push ({ item, date : Date. now () });
GOOD:
// ใช้ ... เพื่อทำการกระจายของในตัวแปรเพื่อสร้างเป็นตัวแปรใหม่ออกมา
const addItemToCart = ( cart , item ) => {
return [ ... cart, { item, date : Date. now () }];
site effect สามารถศึกษาแบบลึกซึ้งได้จากการเขียน program แบบ Functional Programming (จริงๆแล้วหลายปัญหาของ function สามารถแก้ไขจากการเขียน program style functional programming ได้)
3. Concurrency
ตระกูลนี้จะเป็น set ของ function แบบ asynchronous ที่จะมีการทำงาน function ไปพร้อมๆกัน
ใช้ Promises, ไม่ใช้ callbacks
Callback นั้นมีปัญหาทำให้ code เกิดความไม่ clean ทั้งจากการซ้อนกัน (เป็น callback hell) การต้องใช้ต่อเนื่องกันหรือแม้แต่การ handle error ที่ค่อนข้างยาก ด้วย ES2015/ES6
Promise ได้ถูก built-in เป็น default ไว้เป็นที่เรียบร้อย และส่งผลทำให้ code handle ได้ง่ายขึ้นกว่าเดิมเยอะมาก
ด้วย Promise สามารถทำเป็น chain ของ asynchronous function ได้แทนที่จะต้องซ้อน function กันต่อๆไปเหมือน Callback
BAD:
function fetchData ( url , callback ) {
const data = " Sample data from " + url
fetchData ( " https://api.example.com " , ( error , data ) => {
console. error ( " Error: " , error)
console. log ( " Received data: " , data)
GOOD:
function fetchData ( url ) {
return new Promise (( resolve , reject ) => {
const data = " Sample data from " + url
fetchData ( " https://api.example.com " )
. then (( data ) => console. log ( " Received data: " , data))
. catch (( error ) => console. error ( " Error: " , error))
ใช้ Async/Await อ่านง่ายกว่า Promises
Async/await
เป็นตัวที่ถูกนำเสนอมาเพิ่มใน ECMAScript 2017 ซึ่งเป็นการเพิ่มความสามารถของ asynchronous โดยเป็นการ build on top Promises เพิ่มมาอีกที ซึ่งจุดแข็งใหญ่ๆของ Async/await
เพื่อให้สามารถจัดการ asynchronous code แบบ “synchronous code” ได้
ซึ่งสิ่งนี้จะส่งผลทำให้ syntax จัดการได้ด้วยวิธีการ try/catch
ตามปกติได้ (ซึ่งจะเป็นการปรับมุมมองจาก .then()
, .catch()
ให้ใช้งานง่ายขึ้น) ซึ่งจะส่งผลทำให้ code อ่านง่ายขึ้นกว่าเดิมพอสมควร
เช่นตามตัวอย่างนี้
BAD:
function fetchData ( url ) {
return new Promise (( resolve , reject ) => {
const data = `Data from ${ url } `
fetchData ( " https://api.example.com " )
. then (( data ) => console. log ( " Received data: " , data))
. catch (( error ) => console. error ( " Error: " , error))
GOOD:
async function fetchData ( url ) {
return new Promise (( resolve , reject ) => {
const data = `Data from ${ url } `
async function displayData () {
const data = await fetchData ( " https://api.example.com " )
console. log ( " Received data: " , data)
console. error ( " Error: " , error)
สังเกตว่า displayData()
จะตรงไปตรงมาเหมือน code synchronous ส่งผลทำให้เวลากลับมาอ่าน code จะอ่าน code ได้ง่ายกว่า Promise ด้วยเช่นกัน
4. Error Handling
อีกหนึ่งเรื่องที่สำคัญคือการจัดการ Error ใน Javascript นอกเหนือจากการเขียนจัดการ control flow แล้ว การจัดการ Error ก็สำคัญเช่นเดียวกัน การจัดการ Error ให้ clean จึงเป็นเรื่องสำคัญเหมือนกัน
โดยสาระสำคัญของการจัดการ Error จะมี 2 เร่ืองใหญ่ๆเลย (ซึ่งเอาจริงๆ ถ้าใครเขียน code จนเคยน่าจะทำกันอยู่และ)
handle error เสมอกับ asynchronous
ใช่ครับ จากประสบการณ์ที่ผมเจอมา ผมเจอว่า asynchronous code ส่วนหนึ่ง (สำหรับมือใหม่) จะไม่ได้มีการ handle error เอาไว้ ส่งผลทำให้ไม่รู้ว่าตอนเกิด error แบบ asynchronous เกิดขึ้น ทำให้ไม่รู้ว่าเกิดขึ้นจากจุดไหนของ code ซึ่งไม่ว่าจะเป็นเคส Promise หรือ Async/Await ได้เตรียมวิธีจัดการให้เรียบร้อยเช่นเดียวกัน
สำหรับเคส Promise
BAD:
function fetchData ( url ) {
return fetch (url) // fetch returns a Promise
. then (( response ) => response. json ())
fetchData ( " https://api.example.com/data " ). then (( data ) =>
console. log ( " Data: " , data)
// No .catch() for handling errors
GOOD:
function fetchData ( url ) {
return fetch (url). then (( response ) => {
throw new Error ( `HTTP error! status: ${ response . status } ` )
fetchData ( " https://api.example.com/data " )
. then (( data ) => console. log ( " Data: " , data))
. catch (( error ) => console. error ( " Failed to fetch data: " , error))
สำหรับเคส Async/Await ใช้ Try catch
BAD:
async function fetchData ( url ) {
const response = await fetch (url)
return await response. json ()
async function displayData () {
const data = await fetchData ( " https://api.example.com/data " )
console. log ( " Data: " , data)
GOOD:
async function fetchData ( url ) {
const response = await fetch (url)
throw new Error ( `HTTP error! status: ${ response . status } ` )
return await response. json ()
async function displayData () {
const data = await fetchData ( " https://api.example.com/data " )
console. log ( " Data: " , data)
console. error ( " Failed to fetch data: " , error)
ไม่มองข้าม Error
ไม่ว่าจะเป็นเคส Promise หรือ Async/Await ก็ตาม ในการจัดการ Error ควรจัดการอย่างอื่นเพิ่มเติมด้วย นอกเหนือจากการ console.log(error)
อย่างเดียว ควรทำอย่างอื่นเพิ่มเติม เพื่อให้ฝั่ง user รู้ว่ามี Error เกิดขึ้นด้วย
BAD:
// try catch error ทิ้งไว้
functionThatMightThrow (data);
GOOD:
// One option (more noisy than console.log):
// ทำ function บางอย่างเพิ่มเติมไป เพื่อให้ user รู้ว่า error เกิดขึ้น
functionThatMightThrow (data);
// ทำ function บางอย่างเพิ่มเติมไป เพื่อให้ user รู้ว่า error เกิดขึ้น
5. อื่นๆ
นอกเหนือจากเรืื่องพื้นฐานเหล่านี้แล้วจริงๆ Practice ของการ clean code ยังมีอีกหลายอย่างให้ศึกษาเพิ่มเติมได้
เช่น
การเขียน Comment ที่ดีว่าควรเขียนเป็นแบบไหน (มีหลายสำนักมาก)
การจัด Formating ที่ดีว่าควรจัด format code ออกมาเป็นแบบไหน (อนาคตเดี๋ยวผมจะกลับมาเล่าเพิ่มเติมในหัวข้อที่เกี่ยวกับ Linter)
Principle อื่นๆ ที่เป็น guideine ในการเขียน code ได้เช่น DRY (Don’t repeat yourself), SOLID (สำหรับสาย OOP)
ขอแนะนำบทความนี้เพิ่มเติม (เป็นบทความที่ผมใช้ Reference ด้วยเช่นเดียวกัน) สำหรับคนที่สนใจในหมวดหมู่อื่นๆเพิ่มเติม
https://github.com/ryanmcdermott/clean-code-javascript
สรุป
นี่คือไอเดียของการ Clean code ของ javascript แบบเบื้องต้น การทำสิ่งเหล่านี้นอกเหนือจากการที่ทำให้ code เป็นระเบียบเรียบร้อยแล้ว จะยังทำให้ code เขียนสัั้นลงและจัดการได้ง่ายขึ้นด้วย ขอส่งท้ายไว้ว่า แต่ละภาษาก็มีวิธีการที่ไม่เหมือนกัน หากใครมีภาษาอื่นเป็นตัวหลักแนะนำให้ศึกษาภาษานั้นๆเพิ่มเติมนะครับ
หวังว่าจะ Enjoy กับการทำความสะอาด code กันนะครับ 😁
Related Post
6 ธ.ค. 2566 2 ส.ค. 2566 18 ม.ค. 2567 3 ม.ค. 2567