From 65f28f68c38d59759f7ddc888db78cdab27c2c6d Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Sun, 7 Apr 2024 16:05:55 +0700 Subject: [PATCH 1/5] =?UTF-8?q?=E0=B9=81=E0=B8=99=E0=B8=A7=E0=B8=97?= =?UTF-8?q?=E0=B8=B2=E0=B8=87=E0=B8=81=E0=B8=B2=E0=B8=A3=E0=B9=80=E0=B8=82?= =?UTF-8?q?=E0=B8=B5=E0=B8=A2=E0=B8=99=E0=B9=82=E0=B8=84=E0=B9=89=E0=B8=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-coding-style/article.md | 335 +++--------------- 1 file changed, 47 insertions(+), 288 deletions(-) diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index 655e3d125..cb74400fd 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -1,12 +1,12 @@ # แนวทางการเขียนโค้ด -โค้ดของเราต้องสะอาดและอ่านง่ายที่สุดเท่าที่จะเป็นไปได้ +โค้ดของเราต้องเขียนให้สะอาดและอ่านง่ายที่สุดเท่าที่จะเป็นไปได้ -นั่นคือศิลปะของการเขียนโปรแกรม -- การนำงานที่ซับซ้อนมาเขียนโค้ดในลักษณะที่ถูกต้องและอ่านง่ายสำหรับมนุษย์ การมีแนวทางการเขียนโค้ดที่ดีช่วยในเรื่องนี้ได้มาก +นั่นคือศิลปะของการเขียนโปรแกรม -- การเขียนโค้ดสำหรับงานที่ซับซ้อนในลักษณะที่ถูกต้องและมนุษย์อ่านเข้าใจได้ การมีสไตล์การเขียนโค้ดที่ดีจะช่วยในเรื่องนี้ได้มาก -## ไวยากรณ์ +## รูปแบบไวยากรณ์ -นี่คือ cheat sheet ที่มีกฎที่แนะนำบางส่วน (ดูรายละเอียดด้านล่าง): +ต่อไปนี้คือตารางสรุปกฎที่แนะนำ (ดูรายละเอียดเพิ่มเติมด้านล่าง): ![](code-style.svg) -ตอนนี้มาคุยกันถึงกฎและเหตุผลของมันโดยละเอียดกัน +ทีนี้มาคุยถึงกฎและเหตุผลของกฎเหล่านี้อย่างละเอียดกันดีกว่า -```warn header="ไม่มีกฎ \"คุณต้อง\"" -ทุกอย่างไม่ได้ตายตัว นี่เป็นแค่สไตล์ที่แนะนำ ไม่ใช่หลักคำสอนทางศาสนา +```warn header="ไม่มีกฎ \"ต้องทำ\" ตายตัว" +ไม่มีอะไรที่ตายตัวที่นี่ ข้อเสนอแนะเหล่านี้เป็นแค่รสนิยมในการจัดรูปแบบโค้ด ไม่ใช่หลักคำสอนทางศาสนา ``` -### ปีกกาปีกกา +### วงเล็บปีกกา -ในโปรเจ็กต์ JavaScript ส่วนใหญ่ ปีกกาปีกกาจะถูกเขียนในแบบ "Egyptian" โดยเปิดปีกกาในบรรทัดเดียวกับคีย์เวิร์ดที่สอดคล้องกัน -- ไม่ได้เปิดในบรรทัดใหม่ และควรมีช่องว่างหนึ่งตัวก่อนเปิดวงเล็บ แบบนี้: +ในโปรเจ็กต์ JavaScript ส่วนใหญ่ วงเล็บปีกกาจะเขียนในสไตล์ "อียิปต์" โดยวงเปิดจะอยู่บรรทัดเดียวกันกับคีย์เวิร์ดที่เกี่ยวข้อง -- ไม่ใช่บรรทัดใหม่ และควรมีช่องว่างก่อนวงเปิดด้วย แบบนี้: ```js if (condition) { // ทำอันนี้ - // ...แล้วก็อันนี้ - // ...และอันนี้ + // ...แล้วก็อันนั้น + // ...แล้วก็อันนู่น } ``` -โครงสร้างบรรทัดเดียว เช่น `if (condition) doSomething()` เป็นกรณีพิเศษที่สำคัญ เราควรใช้ปีกกาปีกกาไหม? - -ต่อไปนี้คือตัวเลือกที่มีคำอธิบายกำกับ เพื่อให้คุณสามารถตัดสินความสามารถในการอ่านได้ด้วยตัวเอง: - -1. 😠 มือใหม่บางครั้งทำแบบนี้ แย่มาก! ไม่จำเป็นต้องใช้ปีกกาปีกกา: - ```js - if (n < 0) *!*{*/!*alert(`Power ${n} ไม่รองรับ`);*!*}*/!* - ``` -2. 😠 แยกเป็นบรรทัดแยกต่างหากโดยไม่มีปีกกา อย่าทำแบบนี้เลย ง่ายต่อการผิดพลาดเวลาเพิ่มบรรทัดใหม่: - ```js - if (n < 0) - alert(`Power ${n} ไม่รองรับ`); - ``` -3. 😏 บรรทัดเดียวโดยไม่มีปีกกา - ยอมรับได้ ถ้ามันสั้น: - ```js - if (n < 0) alert(`Power ${n} ไม่รองรับ`); - ``` -4. 😃 ตัวเลือกที่ดีที่สุด: - ```js - if (n < 0) { - alert(`Power ${n} ไม่รองรับ`); - } - ``` - -สำหรับโค้ดที่สั้นมากๆ อนุญาตให้เขียนบรรทัดเดียวได้ เช่น `if (cond) return null` แต่บล็อกโค้ด (ตัวเลือกสุดท้าย) มักจะอ่านง่ายกว่า +กรณีพิเศษที่สำคัญคือประโยคบรรทัดเดียว เช่น `if (condition) doSomething()` เราควรใช้วงเล็บปีกกาหรือไม่? + +ต่อไปนี้คือตัวเลือกพร้อมคำอธิบาย เพื่อให้คุณตัดสินความสามารถในการอ่านทำความเข้าใจด้วยตัวเอง: + +1. 😠 มือใหม่บางคนทำแบบนี้ ไม่ดีเลย! ไม่จำเป็นต้องใช้วงเล็บปีกกา: + ```js + if (n < 0) *!*{*/!*alert(`เลขยกกำลัง ${n} ไม่รองรับ`);*!*}*/!* + ``` +2. 😠 แยกเป็นบรรทัดใหม่โดยไม่ใช้วงเล็บปีกกา อย่าทำแบบนี้เลย เพราะจะผิดพลาดง่ายเวลาเพิ่มบรรทัดใหม่: + ```js + if (n < 0) + alert(`เลขยกกำลัง ${n} ไม่รองรับ`); + ``` +3. 😏 เขียนบรรทัดเดียวโดยไม่ใช้วงเล็บปีกกา - ยอมรับได้ถ้าสั้น: + ```js + if (n < 0) alert(`เลขยกกำลัง ${n} ไม่รองรับ`); + ``` +4. 😃 ตัวเลือกที่ดีที่สุด: + ```js + if (n < 0) { + alert(`เลขยกกำลัง ${n} ไม่รองรับ`); + } + ``` + +สำหรับโค้ดที่สั้นมากๆ อนุญาตให้เขียนบรรทัดเดียวได้ เช่น `if (cond) return null` แต่โดยทั่วไปแล้วการเขียนเป็นบล็อกโค้ด (ตัวเลือกสุดท้าย) จะอ่านเข้าใจง่ายกว่า ### ความยาวบรรทัด -ไม่มีใครชอบอ่านบรรทัดโค้ดแนวนอนยาวๆ หลักปฏิบัติที่ดีคือแบ่งมันออก +ไม่มีใครชอบอ่านบรรทัดโค้ดยาวๆ ในแนวนอน ถือเป็นแนวปฏิบัติที่ดีที่จะตัดแบ่งบรรทัดพวกนั้น -ตัวอย่างเช่น: +ยกตัวอย่างเช่น: ```js -// อัญประกาศ backtick ` ช่วยให้แบ่งสตริงเป็นหลายบรรทัดได้ +// เครื่องหมาย backtick ` ทำให้แบ่งสตริงเป็นหลายบรรทัดได้ let str = ` - ECMA International's TC39 คือกลุ่มนักพัฒนา JavaScript, - ผู้ใช้ นักวิชาการ และอื่นๆ ร่วมมือกับชุมชน - เพื่อดูแลและพัฒนานิยามของ JavaScript + ECMA International's TC39 เป็นกลุ่มนักพัฒนา JavaScript, + ผู้ทำระบบ, นักวิชาการ และอีกมากมาย ที่ร่วมกันดูแลรักษากับชุมชน + เพื่อปรับปรุงและพัฒนานิยามของ JavaScript `; ``` -และสำหรับคำสั่ง `if`: +และสำหรับประโยค `if`: ```js if ( id === 123 && - moonPhase === 'Waning Gibbous' && + moonPhase === 'Waning Gibbous' && zodiacSign === 'Libra' ) { letTheSorceryBegin(); } ``` -ความยาวบรรทัดสูงสุดควรตกลงกันในระดับทีม มักจะเป็น 80 หรือ 120 ตัวอักษร - -### การเยื้อง - -มีการเยื้องสองแบบ: - -- **การเยื้องแนวนอน: 2 หรือ 4 ช่องว่าง** - - การเยื้องแนวนอนทำได้โดยใช้ 2 หรือ 4 ช่องว่าง หรือสัญลักษณ์แท็บ (ปุ่ม `key:Tab`) ว่าจะเลือกใช้แบบไหนเป็นสงครามศักดิ์สิทธิ์เก่าแก่ ปัจจุบันนิยมใช้ช่องว่างมากกว่า - - ข้อดีอย่างหนึ่งของช่องว่างเหนือแท็บคือช่องว่างช่วยให้กำหนดค่าการเยื้องได้ยืดหยุ่นกว่าสัญลักษณ์แท็บ - - ตัวอย่างเช่น เราสามารถจัดพารามิเตอร์ให้ตรงกับวงเล็บเปิดได้ แบบนี้: - - ```js no-beautify - show(parameters, - aligned, // 5 ช่องว่างที่ด้านซ้าย - one, - after, - another - ) { - // ... - } - ``` - -- **การเยื้องแนวตั้ง: บรรทัดว่างเพื่อแบ่งโค้ดเป็นบล็อกตามตรรกะ** - - แม้แต่ฟังก์ชันเดียวก็มักจะแบ่งออกเป็นบล็อกตามตรรกะได้ ในตัวอย่างด้านล่าง การกำหนดค่าตัวแปร ลูปหลัก และการส่งค่ากลับถูกแบ่งออกในแนวตั้ง: - - ```js - function pow(x, n) { - let result = 1; - // <-- - for (let i = 0; i < n; i++) { - result *= x; - } - // <-- - return result; - } - ``` - - แทรกบรรทัดว่างเพิ่มเติมในจุดที่ช่วยให้โค้ดอ่านง่ายขึ้น ไม่ควรมีโค้ดเกินเก้าบรรทัดโดยไม่มีการเยื้องแนวตั้ง - -### เครื่องหมายอัฒภาค - -ควรมีเครื่องหมายอัฒภาคหลังแต่ละคำสั่ง แม้ว่าบางทีอาจจะข้ามไปได้ - -มีบางภาษาที่เครื่องหมายอัฒภาคเป็นตัวเลือกจริงๆ และใช้น้อย แต่ใน JavaScript มีกรณีที่เว้นบรรทัดไม่ได้ถูกตีความเป็นเครื่องหมายอัฒภาค ทำให้โค้ดเสี่ยงต่อข้อผิดพลาด ดูเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในบท - -ถ้าคุณเป็นโปรแกรมเมอร์ JavaScript มากประสบการณ์ คุณอาจเลือกสไตล์โค้ดแบบไม่ใช้เครื่องหมายอัฒภาคอย่าง [StandardJS](https://standardjs.com/) ได้ มิฉะนั้นแล้ว การใช้เครื่องหมายอัฒภาคจะดีที่สุดเพื่อหลีกเลี่ยงข้อผิดพลาดที่อาจเกิดขึ้น นักพัฒนาส่วนใหญ่ใส่เครื่องหมายอัฒภาค - -### ระดับการซ้อน - -พยายามหลีกเลี่ยงการซ้อนโค้ดลึกเกินไป - -ตัวอย่างเช่น ในลูป บางทีก็เป็นความคิดที่ดีที่จะใช้คำสั่ง [`continue`](info:while-for#continue) เพื่อหลีกเลี่ยงการซ้อนพิเศษ - -ตัวอย่างเช่น แทนที่จะเพิ่มเงื่อนไข `if` ซ้อนแบบนี้: - -```js -for (let i = 0; i < 10; i++) { - if (cond) { - ... // <- อีกหนึ่งระดับการซ้อน - } -} -``` - -เราสามารถเขียนได้ว่า: - -```js -for (let i = 0; i < 10; i++) { - if (!cond) *!*continue*/!*; - ... // <- ไม่มีระดับการซ้อนพิเศษ -} -``` - -สิ่งที่คล้ายกันสามารถทำได้กับ `if/else` และ `return` - -ตัวอย่างเช่น โครงสร้างสองอย่างด้านล่างเหมือนกัน - -ตัวเลือก 1: - -```js -function pow(x, n) { - if (n < 0) { - alert("'n' ติดลบไม่รองรับ"); - } else { - let result = 1; - - for (let i = 0; i < n; i++) { - result *= x; - } - - return result; - } -} -``` - -ตัวเลือก 2: - -```js -function pow(x, n) { - if (n < 0) { - alert("'n' ติดลบไม่รองรับ"); - return; - } - - let result = 1; - - for (let i = 0; i < n; i++) { - result *= x; - } - - return result; -} -``` - -ตัวที่สองอ่านง่ายกว่าเพราะ "กรณีพิเศษ" ของ `n < 0` ถูกจัดการตั้งแต่แรก เมื่อตรวจสอบเสร็จแล้ว เราสามารถดำเนินการตามโค้ดหลักต่อไปได้โดยไม่จำเป็นต้องซ้อนพิเศษ - -## การวางตำแหน่งฟังก์ชัน - -ถ้าคุณเขียนฟังก์ชัน "ผู้ช่วย (helper)" หลายตัว และโค้ดที่ใช้พวกมัน มีสามวิธีในการจัดระเบียบฟังก์ชัน - -1. ประกาศฟังก์ชัน*ก่อน*โค้ดที่ใช้พวกมัน: - - ```js - // *!*ประกาศฟังก์ชัน*/!* - function createElement() { - ... - } - - function setHandler(elem) { - ... - } - - function walkAround() { - ... - } - - // *!*โค้ดที่ใช้ฟังก์ชัน*/!* - let elem = createElement(); - setHandler(elem); - walkAround(); - ``` -2. โค้ดก่อน จากนั้นฟังก์ชัน - - ```js - // *!*โค้ดที่ใช้ฟังก์ชัน*/!* - let elem = createElement(); - setHandler(elem); - walkAround(); - - // --- *!*ฟังก์ชันผู้ช่วย*/!* --- - function createElement() { - ... - } - - function setHandler(elem) { - ... - } - - function walkAround() { - ... - } - ``` -3. แบบผสม: ประกาศฟังก์ชันในจุดที่มันถูกใช้ครั้งแรก - -ส่วนใหญ่แล้ว ตัวเลือกที่สองเป็นที่นิยมกว่า - -เพราะเมื่ออ่านโค้ด สิ่งแรกที่เราอยากรู้คือ *มันทำอะไร* ถ้าโค้ดไปก่อน มันจะชัดเจนตั้งแต่เริ่มต้น จากนั้นเราอาจไม่จำเป็นต้องอ่านฟังก์ชันเลย โดยเฉพาะถ้าชื่อของมันบอกได้ว่ามันทำอะไร - -## คู่มือสไตล์ - -คู่มือสไตล์มีกฎทั่วไปเกี่ยวกับ "วิธีเขียน" โค้ด เช่น ใช้อัญประกาศแบบไหน เว้นระยะเท่าไหร่ ความยาวสูงสุดของบรรทัด ฯลฯ เป็นเรื่องเล็กๆ น้อยๆ เยอะมาก - -เมื่อสมาชิกทุกคนในทีมใช้คู่มือสไตล์เดียวกัน โค้ดจะดูเป็นเนื้อเดียวกัน ไม่ว่าใครในทีมจะเป็นคนเขียนก็ตาม - -แน่นอนว่าทีมสามารถเขียนคู่มือสไตล์ของตัวเองได้เสมอ แต่ปกติแล้วไม่จำเป็น มีคู่มือที่มีอยู่แล้วมากมายให้เลือกใช้ - -ตัวเลือกยอดนิยมบางส่วน: - -- [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html) -- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) -- [Idiomatic.JS](https://github.com/rwaldron/idiomatic.js) -- [StandardJS](https://standardjs.com/) -- (และอีกมากมาย) - -ถ้าคุณเป็นนักพัฒนามือใหม่ ให้เริ่มจาก cheat sheet ตอนต้นของบทนี้ จากนั้นคุณสามารถเรียกดูคู่มือสไตล์อื่นๆ เพื่อเก็บไอเดียเพิ่มเติมและตัดสินใจว่าชอบอันไหนที่สุด - -## เครื่องมือ Linter อัตโนมัติ - -Linter คือเครื่องมือที่สามารถตรวจสอบสไตล์ของโค้ดคุณโดยอัตโนมัติ และให้คำแนะนำในการปรับปรุง - -สิ่งที่ยอดเยี่ยมเกี่ยวกับมันคือ การตรวจสอบสไตล์ยังสามารถพบบั๊กบางอย่างได้ด้วย เช่น การพิมพ์ผิดในชื่อตัวแปรหรือฟังก์ชัน เพราะคุณสมบัตินี้ จึงแนะนำให้ใช้ linter แม้ว่าคุณจะไม่อยากยึดติดกับ "สไตล์โค้ด" แบบใดแบบหนึ่งก็ตาม - -นี่คือเครื่องมือ linting ที่รู้จักกันดีบางส่วน: - -- [JSLint](https://www.jslint.com/) -- หนึ่งใน linter ตัวแรกๆ -- [JSHint](https://jshint.com/) -- มีการตั้งค่ามากกว่า JSLint -- [ESLint](https://eslint.org/) -- อาจเป็นตัวใหม่ที่สุด - -ทุกตัวสามารถทำงานได้ ผู้เขียนใช้ [ESLint](https://eslint.org/) - -Linter ส่วนใหญ่ผสานรวมเข้ากับเอดิเตอร์ยอดนิยมหลายตัว: แค่เปิดใช้งานปลั๊กอินในเอดิเตอร์และกำหนดค่าสไตล์ - -ตัวอย่างเช่น สำหรับ ESLint คุณควรทำดังนี้: - -1. ติดตั้ง [Node.js](https://nodejs.org/) -2. ติดตั้ง ESLint ด้วยคำสั่ง `npm install -g eslint` (npm คือตัวติดตั้งแพ็คเกจ JavaScript) -3. สร้างไฟล์กำหนดค่าชื่อ `.eslintrc` ในรูทของโปรเจ็กต์ JavaScript ของคุณ (ในโฟลเดอร์ที่ใส่ไฟล์ทั้งหมดของคุณ) -4. ติดตั้ง/เปิดใช้งานปลั๊กอินสำหรับเอดิเตอร์ของคุณที่ผสานรวมกับ ESLint ส่วนใหญ่จะมีอยู่แล้ว - -นี่คือตัวอย่างของไฟล์ `.eslintrc`: - -```js -{ - "extends": "eslint:recommended", - "env": { - "browser": true, - "node": true, - "es6": true - }, - "rules": { - "no-console": 0, - "indent": 2 - } -} -``` - -ที่นี่คำสั่ง `"extends"` หมายถึงว่าการกำหนดค่าอิงจากชุดการตั้งค่า "eslint:recommended" หลังจากนั้น เราจะระบุของเราเอง - -เรายังสามารถดาวน์โหลดชุดกฎสไตล์จากเว็บและขยายมันแทนได้ ดูรายละเอียดเพิ่มเติมเกี่ยวกับการติดตั้งได้ที่ - -นอกจากนี้ IDE บางตัวยังมี linting ในตัวด้วย ซึ่งสะดวก แต่ไม่ยืดหยุ่นเท่า ESLint - -## สรุป - -กฎไวยากรณ์ทั้งหมดที่อธิบายในบทนี้ (และในคู่มือสไตล์ที่อ้างถึง) มีจุดมุ่งหมายเพื่อเพิ่มความสามารถในการอ่านโค้ดของคุณ ทุกอย่างยังถกเถียงกันได้ - -เมื่อเราคิดถึงการเขียนโค้ด "ที่ดีขึ้น" คำถามที่เราควรถามตัวเองคือ "อะไรที่ทำให้โค้ดอ่านง่ายและเข้าใจง่ายขึ้น?" และ "อะไรที่ช่วยให้เราหลีกเลี่ยงข้อผิดพลาดได้?" พวกนี้คือสิ่งหลักที่ต้องคำนึงถึงเมื่อเลือกและโต้แย้งสไตล์โค้ด - -การอ่านคู่มือสไตล์ยอดนิยมจะช่วยให้คุณติดตามแนวคิดล่าสุดเกี่ยวกับเทรนด์สไตล์โค้ดและแนวปฏิบัติที่ดีที่สุดได้ +ความยาวสูงสุดของบรรทัดควรตกลงกันในระดับทีมงาน ปกติแล้วมักเป็น 80 หรือ 120 ตัวอักษร \ No newline at end of file From e5b205107405cc81532c42ae7b3f0a8464d4b86f Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Sun, 7 Apr 2024 16:10:58 +0700 Subject: [PATCH 2/5] =?UTF-8?q?=E0=B8=81=E0=B8=B2=E0=B8=A3=E0=B9=80?= =?UTF-8?q?=E0=B8=A2=E0=B8=B7=E0=B9=89=E0=B8=AD=E0=B8=87=E0=B8=9A=E0=B8=A3?= =?UTF-8?q?=E0=B8=A3=E0=B8=97=E0=B8=B1=E0=B8=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-coding-style/article.md | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index cb74400fd..56a56b16f 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -104,4 +104,53 @@ if ( } ``` -ความยาวสูงสุดของบรรทัดควรตกลงกันในระดับทีมงาน ปกติแล้วมักเป็น 80 หรือ 120 ตัวอักษร \ No newline at end of file +ความยาวสูงสุดของบรรทัดควรตกลงกันในระดับทีมงาน ปกติแล้วมักเป็น 80 หรือ 120 ตัวอักษร + +### การเยื้องบรรทัด + +มี 2 วิธีในการเยื้องบรรทัด: + +- **การเยื้องในแนวนอน: เว้นวรรค 2 หรือ 4 ช่อง** + + การเยื้องในแนวนอนทำได้โดยใช้การเว้นวรรค 2 หรือ 4 ช่อง หรือใช้สัญลักษณ์แท็บ (ปุ่ม `key:Tab`) ที่จะเลือกใช้แบบไหนเป็นประเด็นถกเถียงกันมานาน ปัจจุบันนิยมใช้การเว้นวรรคมากกว่า + + ข้อดีของการเว้นวรรคเหนือแท็บคือ สามารถกำหนดระยะการเยื้องได้ยืดหยุ่นกว่าการใช้สัญลักษณ์แท็บ + + ตัวอย่างเช่น เราสามารถจัดตำแหน่งพารามิเตอร์ให้ตรงกับวงเล็บเปิดได้ แบบนี้: + + ```js no-beautify + show(parameters, + aligned, // เว้นวรรค 5 ช่องจากทางซ้าย + one, + after, + another + ) { + // ... + } + ``` + +- **การเว้นบรรทัดในแนวตั้ง: เว้นบรรทัดว่างเพื่อแบ่งโค้ดเป็นกลุ่มย่อยตามลำดับขั้นตอน** + + แม้แต่ฟังก์ชันเดียวก็มักแบ่งเป็นกลุ่มย่อยตามลำดับขั้นตอนได้ ในตัวอย่างด้านล่างนี้ มีการแบ่งแยกส่วนการกำหนดค่าตัวแปรเริ่มต้น, ลูปหลัก และการส่งค่ากลับ ออกจากกันในแนวตั้ง: + + ```js + function pow(x, n) { + let result = 1; + // <-- + for (let i = 0; i < n; i++) { + result *= x; + } + // <-- + return result; + } + ``` + + เพิ่มบรรทัดว่างในจุดที่ช่วยให้อ่านโค้ดเข้าใจง่ายขึ้น ไม่ควรมีโค้ดยาวเกิน 9 บรรทัดโดยไม่มีการเว้นบรรทัดในแนวตั้ง + +### เครื่องหมายอัฒภาค (semicolon) + +ควรมีอัฒภาคปิดท้ายแต่ละประโยคเสมอ แม้ในบางกรณีจะละเว้นได้ก็ตาม + +บางภาษามีอัฒภาคเป็นตัวเลือกล้วนๆ และแทบไม่เห็นใช้เลย แต่ในภาษา JavaScript มีบางกรณีที่ตัวขึ้นบรรทัดใหม่ไม่ได้ถูกตีความเป็นอัฒภาค ทำให้โค้ดมีความเสี่ยงเกิดข้อผิดพลาดได้ อ่านรายละเอียดเพิ่มเติมในบท + +หากคุณเป็นโปรแกรมเมอร์ JavaScript ที่มีประสบการณ์สูง คุณอาจเลือกใช้สไตล์การเขียนโค้ดแบบไม่ใส่อัฒภาค เช่น [StandardJS](https://standardjs.com/) ได้ มิฉะนั้นแล้ว แนะนำให้ใส่อัฒภาคเสมอจะดีกว่า เพื่อหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น นักพัฒนาส่วนใหญ่ใส่อัฒภาคในโค้ดเป็นปกติอยู่แล้ว \ No newline at end of file From a6acbad6ed12ae73a1fd9aa14580a0d1c2c5f176 Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Sun, 7 Apr 2024 16:14:32 +0700 Subject: [PATCH 3/5] =?UTF-8?q?=E0=B8=A3=E0=B8=B0=E0=B8=94=E0=B8=B1?= =?UTF-8?q?=E0=B8=9A=E0=B8=84=E0=B8=A7=E0=B8=B2=E0=B8=A1=E0=B8=A5=E0=B8=B6?= =?UTF-8?q?=E0=B8=81=E0=B8=82=E0=B8=AD=E0=B8=87=E0=B8=81=E0=B8=B2=E0=B8=A3?= =?UTF-8?q?=E0=B8=8B=E0=B9=89=E0=B8=AD=E0=B8=99=E0=B9=82=E0=B8=84=E0=B9=89?= =?UTF-8?q?=E0=B8=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-coding-style/article.md | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index 56a56b16f..3e0c549c6 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -153,4 +153,72 @@ if ( บางภาษามีอัฒภาคเป็นตัวเลือกล้วนๆ และแทบไม่เห็นใช้เลย แต่ในภาษา JavaScript มีบางกรณีที่ตัวขึ้นบรรทัดใหม่ไม่ได้ถูกตีความเป็นอัฒภาค ทำให้โค้ดมีความเสี่ยงเกิดข้อผิดพลาดได้ อ่านรายละเอียดเพิ่มเติมในบท -หากคุณเป็นโปรแกรมเมอร์ JavaScript ที่มีประสบการณ์สูง คุณอาจเลือกใช้สไตล์การเขียนโค้ดแบบไม่ใส่อัฒภาค เช่น [StandardJS](https://standardjs.com/) ได้ มิฉะนั้นแล้ว แนะนำให้ใส่อัฒภาคเสมอจะดีกว่า เพื่อหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น นักพัฒนาส่วนใหญ่ใส่อัฒภาคในโค้ดเป็นปกติอยู่แล้ว \ No newline at end of file +หากคุณเป็นโปรแกรมเมอร์ JavaScript ที่มีประสบการณ์สูง คุณอาจเลือกใช้สไตล์การเขียนโค้ดแบบไม่ใส่อัฒภาค เช่น [StandardJS](https://standardjs.com/) ได้ มิฉะนั้นแล้ว แนะนำให้ใส่อัฒภาคเสมอจะดีกว่า เพื่อหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น นักพัฒนาส่วนใหญ่ใส่อัฒภาคในโค้ดเป็นปกติอยู่แล้ว + +### ระดับความลึกของการซ้อนโค้ด + +พยายามหลีกเลี่ยงการซ้อนโค้ดลึกเกินไปหลายชั้น + +ยกตัวอย่างเช่น ในลูป บางครั้งการใช้คำสั่ง [`continue`](info:while-for#continue) เพื่อข้ามการซ้อนโค้ดเพิ่มเติมเป็นวิธีที่ดี + +เช่น แทนที่จะเพิ่มเงื่อนไข `if` ซ้อนกันแบบนี้: + +```js +for (let i = 0; i < 10; i++) { + if (cond) { + ... // <- ซ้อนลึกลงไปอีกชั้น + } +} +``` + +เราสามารถเขียนเป็น: + +```js +for (let i = 0; i < 10; i++) { + if (!cond) *!*continue*/!*; + ... // <- ไม่ต้องซ้อนลึกลงไปอีกชั้น +} +``` + +สามารถทำแบบเดียวกันได้กับ `if/else` และ `return` + +ตัวอย่างเช่น โครงสร้างสองแบบด้านล่างนี้ให้ผลลัพธ์เหมือนกัน + +แบบที่ 1: + +```js +function pow(x, n) { + if (n < 0) { + alert("ไม่รองรับ 'n' ติดลบ"); + } else { + let result = 1; + + for (let i = 0; i < n; i++) { + result *= x; + } + + return result; + } +} +``` + +แบบที่ 2: + +```js +function pow(x, n) { + if (n < 0) { + alert("ไม่รองรับ 'n' ติดลบ"); + return; + } + + let result = 1; + + for (let i = 0; i < n; i++) { + result *= x; + } + + return result; +} +``` + +แบบที่สองอ่านเข้าใจง่ายกว่า เพราะจัดการ "กรณีพิเศษ" ที่ `n < 0` ตั้งแต่เนิ่นๆ เมื่อตรวจสอบผ่านแล้ว เราก็สามารถไปต่อที่โค้ดส่วนหลักได้เลย โดยไม่ต้องซ้อนโค้ดลึกลงไปอีก \ No newline at end of file From a41a4d37cfb3feee7e28659b88cfcf8057800d54 Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Sun, 7 Apr 2024 16:17:17 +0700 Subject: [PATCH 4/5] =?UTF-8?q?=E0=B8=81=E0=B8=B2=E0=B8=A3=E0=B8=88?= =?UTF-8?q?=E0=B8=B1=E0=B8=94=E0=B8=A7=E0=B8=B2=E0=B8=87=E0=B8=95=E0=B8=B3?= =?UTF-8?q?=E0=B9=81=E0=B8=AB=E0=B8=99=E0=B9=88=E0=B8=87=E0=B8=9F=E0=B8=B1?= =?UTF-8?q?=E0=B8=87=E0=B8=81=E0=B9=8C=E0=B8=8A=E0=B8=B1=E0=B8=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-coding-style/article.md | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index 3e0c549c6..e018db8de 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -221,4 +221,58 @@ function pow(x, n) { } ``` -แบบที่สองอ่านเข้าใจง่ายกว่า เพราะจัดการ "กรณีพิเศษ" ที่ `n < 0` ตั้งแต่เนิ่นๆ เมื่อตรวจสอบผ่านแล้ว เราก็สามารถไปต่อที่โค้ดส่วนหลักได้เลย โดยไม่ต้องซ้อนโค้ดลึกลงไปอีก \ No newline at end of file +แบบที่สองอ่านเข้าใจง่ายกว่า เพราะจัดการ "กรณีพิเศษ" ที่ `n < 0` ตั้งแต่เนิ่นๆ เมื่อตรวจสอบผ่านแล้ว เราก็สามารถไปต่อที่โค้ดส่วนหลักได้เลย โดยไม่ต้องซ้อนโค้ดลึกลงไปอีก + +## การจัดวางตำแหน่งฟังก์ชัน + +หากคุณกำลังเขียนฟังก์ชัน "ผู้ช่วย" หลายๆ ฟังก์ชัน และโค้ดที่เรียกใช้ฟังก์ชันเหล่านั้น มีวิธีจัดวางฟังก์ชัน 3 แบบดังนี้ + +1. ประกาศฟังก์ชัน *ก่อน* โค้ดที่เรียกใช้: + + ```js + // *!*ประกาศฟังก์ชัน*/!* + function createElement() { + ... + } + + function setHandler(elem) { + ... + } + + function walkAround() { + ... + } + + // *!*โค้ดที่เรียกใช้ฟังก์ชัน*/!* + let elem = createElement(); + setHandler(elem); + walkAround(); + ``` + +2. เขียนโค้ดที่เรียกใช้ฟังก์ชันก่อน จากนั้นตามด้วยฟังก์ชัน + + ```js + // *!*โค้ดที่เรียกใช้ฟังก์ชัน*/!* + let elem = createElement(); + setHandler(elem); + walkAround(); + + // --- *!*ฟังก์ชันผู้ช่วย*/!* --- + function createElement() { + ... + } + + function setHandler(elem) { + ... + } + + function walkAround() { + ... + } + ``` + +3. ผสมกันระหว่างสองแบบข้างต้น: ประกาศฟังก์ชันในตำแหน่งที่มีการเรียกใช้ครั้งแรก + +โดยส่วนใหญ่แล้ว นิยมใช้แบบที่ 2 มากกว่า + +เพราะเวลาอ่านโค้ด เราต้องการทราบก่อนว่า *โค้ดทำอะไร* ถ้าเขียนโค้ดไว้ข้างบนสุด ความตั้งใจของโค้ดจะชัดเจนตั้งแต่แรก และในบางครั้งเราอาจไม่จำเป็นต้องอ่านฟังก์ชันเลยก็ได้ โดยเฉพาะอย่างยิ่งเมื่อชื่อฟังก์ชันบ่งบอกหน้าที่ของมันได้ดีอยู่แล้ว \ No newline at end of file From b1b91373c8ec8b2cd50998df2009bdebfff30ab6 Mon Sep 17 00:00:00 2001 From: Prasit Tongpradit Date: Sun, 7 Apr 2024 16:23:41 +0700 Subject: [PATCH 5/5] =?UTF-8?q?=E0=B8=84=E0=B8=B9=E0=B9=88=E0=B8=A1?= =?UTF-8?q?=E0=B8=B7=E0=B8=AD=E0=B8=AA=E0=B9=84=E0=B8=95=E0=B8=A5=E0=B9=8C?= =?UTF-8?q?=E0=B8=81=E0=B8=B2=E0=B8=A3=E0=B9=80=E0=B8=82=E0=B8=B5=E0=B8=A2?= =?UTF-8?q?=E0=B8=99=E0=B9=82=E0=B8=84=E0=B9=89=E0=B8=94=20=E0=B9=81?= =?UTF-8?q?=E0=B8=A5=E0=B8=B0=20=E0=B8=AA=E0=B8=A3=E0=B8=B8=E0=B8=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../02-coding-style/article.md | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/1-js/03-code-quality/02-coding-style/article.md b/1-js/03-code-quality/02-coding-style/article.md index e018db8de..3bf7072f6 100644 --- a/1-js/03-code-quality/02-coding-style/article.md +++ b/1-js/03-code-quality/02-coding-style/article.md @@ -275,4 +275,76 @@ function pow(x, n) { โดยส่วนใหญ่แล้ว นิยมใช้แบบที่ 2 มากกว่า -เพราะเวลาอ่านโค้ด เราต้องการทราบก่อนว่า *โค้ดทำอะไร* ถ้าเขียนโค้ดไว้ข้างบนสุด ความตั้งใจของโค้ดจะชัดเจนตั้งแต่แรก และในบางครั้งเราอาจไม่จำเป็นต้องอ่านฟังก์ชันเลยก็ได้ โดยเฉพาะอย่างยิ่งเมื่อชื่อฟังก์ชันบ่งบอกหน้าที่ของมันได้ดีอยู่แล้ว \ No newline at end of file +เพราะเวลาอ่านโค้ด เราต้องการทราบก่อนว่า *โค้ดทำอะไร* ถ้าเขียนโค้ดไว้ข้างบนสุด ความตั้งใจของโค้ดจะชัดเจนตั้งแต่แรก และในบางครั้งเราอาจไม่จำเป็นต้องอ่านฟังก์ชันเลยก็ได้ โดยเฉพาะอย่างยิ่งเมื่อชื่อฟังก์ชันบ่งบอกหน้าที่ของมันได้ดีอยู่แล้ว + +## คู่มือสไตล์การเขียนโค้ด + +คู่มือสไตล์ประกอบด้วยกฎทั่วไปเกี่ยวกับ "วิธีเขียน" โค้ด เช่น ควรใช้เครื่องหมายคำพูดแบบไหน เว้นย่อหน้ากี่ช่อง ความยาวสูงสุดของบรรทัดคือเท่าไร เป็นต้น ซึ่งเป็นรายละเอียดเล็กๆ น้อยๆ จำนวนมาก + +เมื่อสมาชิกทุกคนในทีมใช้คู่มือสไตล์ชุดเดียวกัน โค้ดจะมีรูปแบบที่เป็นเอกภาพ ไม่ว่าจะเขียนโดยสมาชิกคนไหนก็ตาม + +แน่นอนว่า ทีมสามารถเขียนคู่มือสไตล์เป็นของตัวเองได้เสมอ แต่โดยทั่วไปแล้วมักไม่จำเป็น เพราะมีคู่มือสำเร็จรูปให้เลือกใช้อยู่แล้วมากมาย + +ตัวเลือกยอดนิยมบางส่วน ได้แก่: + +- [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html) +- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) +- [Idiomatic.JS](https://github.com/rwaldron/idiomatic.js) +- [StandardJS](https://standardjs.com/) +- (และอีกมากมาย) + +สำหรับนักพัฒนามือใหม่ แนะนำให้เริ่มต้นจากตารางสรุปที่หัวข้อแรกของบทนี้ จากนั้นค่อยๆ ศึกษาคู่มือสไตล์อื่นๆ เพื่อเก็บเกี่ยวไอเดียเพิ่มเติม แล้วตัดสินใจเลือกสไตล์ที่ถูกใจที่สุด + +## เครื่องมือตรวจสอบโค้ดอัตโนมัติ (Automated Linters) + +Linter คือเครื่องมือที่ช่วยตรวจสอบสไตล์โค้ดให้โดยอัตโนมัติ และเสนอแนะจุดที่ควรปรับปรุงแก้ไข + +ข้อดีคือ การตรวจสอบสไตล์ยังสามารถช่วยค้นพบบั๊กบางอย่างได้ด้วย เช่น การสะกดชื่อตัวแปรหรือฟังก์ชันผิด ด้วยเหตุนี้ จึงแนะนำให้ใช้ linter แม้คุณจะไม่อยากยึดติดกับ "สไตล์โค้ด" แบบใดแบบหนึ่งโดยเฉพาะก็ตาม + +ต่อไปนี้คือเครื่องมือ linting ที่มีชื่อเสียง: + +- [JSLint](https://www.jslint.com/) -- หนึ่งใน linter รุ่นแรกๆ +- [JSHint](https://jshint.com/) -- มีตัวเลือกการตั้งค่ามากกว่า JSLint +- [ESLint](https://eslint.org/) -- น่าจะเป็นตัวล่าสุด + +ทั้งหมดนี้ใช้งานได้เหมือนกัน ผู้เขียนเองใช้ [ESLint](https://eslint.org/) + +Linter ส่วนใหญ่ผสานรวมอยู่ในเครื่องมือแก้ไขโค้ดหลายตัวที่นิยมใช้กัน: เพียงเปิดใช้ปลั๊กอินในตัวแก้ไขโค้ด แล้วกำหนดค่าสไตล์ที่ต้องการ + +ยกตัวอย่างสำหรับ ESLint ให้ทำตามขั้นตอนต่อไปนี้: + +1. ติดตั้ง [Node.js](https://nodejs.org/) +2. ติดตั้ง ESLint ด้วยคำสั่ง `npm install -g eslint` (npm คือตัวจัดการแพ็คเกจของ JavaScript) +3. สร้างไฟล์กำหนดค่าชื่อ `.eslintrc` ไว้ที่ root ของโปรเจ็กต์ JavaScript (ในโฟลเดอร์ที่เก็บไฟล์ทั้งหมด) +4. ติดตั้ง/เปิดใช้ปลั๊กอินสำหรับเครื่องมือแก้ไขโค้ดที่เชื่อมต่อกับ ESLint โดยทั่วไปเครื่องมือแก้ไขโค้ดส่วนใหญ่จะมีปลั๊กอินนี้ + +ตัวอย่างไฟล์ `.eslintrc` เป็นดังนี้: + +```js +{ + "extends": "eslint:recommended", + "env": { + "browser": true, + "node": true, + "es6": true + }, + "rules": { + "no-console": 0, + "indent": 2 + } +} +``` + +ในที่นี้ คำสั่ง `"extends"` หมายถึงใช้การกำหนดค่าพื้นฐานจากชุด "eslint:recommended" จากนั้นเราก็ปรับแต่งเพิ่มเติมเอง + +นอกจากนี้ยังดาวน์โหลดชุดกฎสไตล์จากเว็บมาต่อยอดได้ด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับการติดตั้งได้ที่ + +IDE บางตัวก็มี linter ติดตั้งมาในตัวแล้ว ซึ่งสะดวกแต่ปรับแต่งได้ไม่เท่า ESLint + +## สรุป + +กฎไวยากรณ์ทั้งหมดที่กล่าวถึงในบทนี้ (และในคู่มือสไตล์ที่อ้างถึง) ล้วนมีเป้าหมายเพื่อเพิ่มความสามารถในการอ่านทำความเข้าใจโค้ดของคุณ และทุกกฎก็สามารถถกเถียงได้ + +เมื่อเราคิดถึงการเขียนโค้ดให้ "ดีขึ้น" คำถามที่ควรถามตัวเองคือ "อะไรที่ช่วยให้โค้ดอ่านง่ายและทำความเข้าใจได้มากขึ้น" และ "อะไรที่ช่วยให้เราหลีกเลี่ยงข้อผิดพลาด" นี่คือสิ่งสำคัญที่ต้องคำนึงถึงเวลาเลือกหรือโต้แย้งสไตล์โค้ด + +การอ่านคู่มือสไตล์ยอดนิยมจะช่วยให้คุณอัพเดตแนวคิดล่าสุดเกี่ยวกับเทรนด์และแนวปฏิบัติที่ดีที่สุดในการจัดสไตล์โค้ดได้ \ No newline at end of file