You are here
Home > Web programming > javascript > [แปล] สรุปการเขียน Javascript ที่ดี ตอนที่ 1

[แปล] สรุปการเขียน Javascript ที่ดี ตอนที่ 1

javascript การเขียนโค้ดที่ดี

พอดีไปเจอมาเลยกะมาแบ่งปันครับหลายๆคนก็เขียน javascript มาเยอะแล้วแต่อาจจะหลงลืมไปบ้างในการเขียนทีดี เขียนให้ทำงานได้นั้นดี แต่จะดีกว่าครับหากเขียนให้เป็น style ที่ทำงานเร็วขึ้นและเป็นระเบียบมากขึ้นครับ

Writing Maintainable Code

การแก้ไข Bug เป็นค่าใช้จ่ายที่ราคาแพง และราคาของการจัดการจะเพิ่มขึ้นเรื่อยๆ โดยเฉพาะ Bug ที่ไปเจอตอนที่ขึ้น production ไปแล้ว ( เหมือนเวลาปล่อยเว็บขึ้นจริงแล้วไปเจอตอนโชว์ของให้ชาวบ้านดูนั่นแหละ ) แต่มันจะดีกว่าไหมถ้าเราสามารถจัดการมันได้ในทันทีเมื่อคุณเจอมัน แต่การจะทำอย่างนี้ได้ต่อเมื่อคุณทำงานอยู่กับงานนี้ แล้วถ้าวันหนึ่งคุณต้องย้ายไปจัดการงานอย่างอื่นล่ะ ? และลืมไปหมดแล้วสำหรับโค้ดของงานเก่า ( ผมเจอบ่อยมาก ! ) ในการกลับมาแก้ไขงานเก่าของเราหรือของคนอื่นต้องประกอบไปด้วยสองอย่างหลักๆคือ

  • เวลาสำหรับการเรียนรู้และทำความเข้าใจปัญหา
  • เวลาสำหรับการเข้าใจโค้ดเพื่อจะแก้ไขปัญหา

ปัญหาอย่างอื่นที่ตามมาคือ ลองคิดดูถ้าหากเป็นโปรเจ็คใหญ่ๆหรือของบริษัทคนที่จะมาแก้ไข Bug เนี้ยก็ไม่ใช่คนเดียวกับคนที่สร้าง Bug และไม่ใช่คนที่เจอมันด้วย ทำให้ต้องเสียเวลาทำความเข้าใจ ซึ่งมันมีผลกระทบต่อสิ่งแรกคือ รายได้และสิ่งที่สองอารมณ์ของ Developer เองอีกด้วย แทนที่จะเอาเวลาไปพัฒนาโปรเจ็คใหม่ๆกลับต้องมาแก้ไขโค้ดสมัยก่อนๆ ( โปรแกรมเมอร์หลายคนคงเข้าใจความรู้สึกนี้ ฮา )

ความจริงของชีวิตสำหรับการพัฒนา software คือเราสูญเสียเวลาสำหรับการ อ่านโค้ดมากกว่าการเขียนโค้ด ในขณะที่เราต้องแก้ไข Bug ที่เกิดขึ้น คุณสามารถนั่งเสียเวลาหมดไปครึ่งวันสำหรับการพิจารณาโค้ดเกือบทั้งหมด

บางที … โค้ดมันอาจจะทำงานของมันได้ ณ ตอนนี้แต่เมื่อถึงเวลาที่มันสมบูรณ์จะมีหลายสิ่งเกิดขึ้นที่จะต้องใช้โค้ดของคุณเข้าไปประกอบด้วย ( เหมือนเวลาทำรับหน้าที่ทำอะไรซักอย่างหนึ่งของระบบแล้วจะเอาไปเชื่อมต่อกับโปรแกรมชาวบ้านนั่นแหละครับ ) ตัวอย่างเช่น

  • Bug ที่ไม่ได้อยู่ในการครอบคลุม ( เช่นคิดว่าจะส่งค่าเท่านี้เพราะตอนที่เราสร้างมีแค่นี้แต่พอไปเชื่อมต่อแล้วมีส่งค่าที่ไม่ได้คิดถึง หรือมีค่าที่ไม่ได้กำหนดไว้ส่งมาทำเกิด Bug )
  • การเพิ่ม Feature ใหม่ๆของโปรแกรมครับ ( เช่น ตอนนี้ทำระบบ Login ไม่มี Facebook แต่หลังๆเจ้านายต้องการแล้วพอเราทำเสร็จดันมีค่าบางอย่างที่ไม่ได้ตั้งใจให้มีเกิดขึ้นทำนองนี้ครับ )
  • โปรแกรมต้องไปทำงานใน environment ใหม่ๆ ( เช่น ตอนแรกรันอยู่ใน linux แต่ต้องย้ายไปทำงานบน window server หรือต้องทำงานใน Browser ใหม่ๆได้ )
  • โค้ดเปลี่ยนวัตถุประสงค์ใหม่ๆ ( ตอนแรกกะว่าจะทำงานได้แค่สองค่า ตอนต้องทำงานรับได้ 3 ค่าก็ต้องมาเปลี่ยนแปลงโค้ดกันใหม่ ซึ่งอาจทำให้เกิด Bug ได้ )
  • โค้ดต้องเขียนใหม่หมดหรือต้องเปลี่ยนไปใช้สถาปัตยกรรมใหม่ๆ ( เช่น mysql -> mongoDB ) หรือแม้แต่การเปลี่ยนไปใช้ภาษาใหม่ๆ ( PHP -> node.js )

ทุกๆการเปลี่ยนแปลงเหล่านี้ เราต้องเสียเวลาหลายชั่วโมงในการเขียนโค้ดให้เสร็จแต่เราจะเสียเวลาเป็นสัปดาห์สำหรับการอ่านมัน นั่นคือที่มาว่าทำไมเราควรจะเขียนโค้ดแบบมีประสิทธิภาพจึงเป็นการเขียนโปรแกรมที่ดี

Maintainable code คือสิ่งเปล่านี้

  • อ่านรู้เรื่อง
  • มั่นคงสอดคล้องกัน
  • ค้นหาได้ง่าย
  • เขียนเหมือนเป็นคนๆเดียวกันเขียน เพราะควรจะเขียนให้เหมือนๆกันทุกคน
  • มันคือเอกสารในตัว

Minimizing Globals

Javascript จะมีขอบเขตของตัวแปรใน function ของตัวเอง และแน่นอนนอกเหนือ function เราจะมีตัวแปรที่ไปได้ทุก function นั่นคือ “global” ตรงหัวข้อนี้เขาพยายามบอกว่า อย่าใช้เยอะ ! เพราะว่าการใช้ global variable นั่นอาจจะทำให้โปรแกรมของเราหยุดทำงานได้ทันที

เพราะว่าตัวแปรแบบ global เมื่อเราประกาศมันจะไปอยู่ใน object ของ window เรียกว่าอยู่เหนือสุดเลยจึงสามารถเรียกได้ที่ทุกเวลาเหมือนจะสะดวกแต่ไม่เลยเพราะมันอาจจะทำให้เกิดปัญหากับโปรแกรมอื่นๆดังนี้

  • third-party Javascript library คือเราไปเอาโค้ด login FB มาแต่ดันใช้ตัวแปรเดียวกันแบบบังเอิญอาจทำให้โปรแกรมหยุดทำงาน
  • Script จาก advertising partner หากเว็บเรามีโฆษณาด้วยบางคนตัวแปรของเราอาจจะไปชนกับ script โฆษณานั่นหมายถึงทำให้รายได้เราหดหาย
  • Script tracking and analytic พวก script สำหรับการตรวจสอบเช่น โค้ดของ google analytic หรือของยี่ห้ออื่นๆ ซึ่งถ้าทำให้หยุดทำงานเราจะวิเคราะห์อะไรไม่ได้เลย
  • Widget, badge and button โค้ดส่วนอื่นๆที่เราอาจจะตั้งชื่อตัวแปรโดยบังเอิญทำให้หยุดทำงานครับ

และเวลาที่เราสร้าง function อะไรมาแล้วไม่ประกาศตัวแปร Javascript จะถือว่าตัวแปรนั้นเป็น global เองเลยเช่น

ตัวแปร result จะเป็น global โดยทันที ซึ่งนั่นอาจจะเป็นหายนะในภายหลังแล้วจะแก้ไขอย่างไรแน่ะหรอง่ายนิดเดียวครับพี่น้องแค่ประกาศ “var” ไปว่าให้ตัวแปรนี้อยู่แค่ใน function sum เท่านั้นนะก็จะได้แหละ

และบางคนเคยประกาศแบบนี้ครับ

ถ้าหากประกาศแบบนี้ตัวแปร b จะเป็น global โดยทันทีเพราะอะไรหรอ ? เพราะว่ามันคำนวนจาก ขวามาซ้าย แล้วทำให้เกิดการคำนวนแบบนี้ครับ คอมพิวเตอร์จะคำนวนว่า b = 0 ก่อนซึ่งเราไม่ได้ประกาศ b เมื่อไม่ได้ประกาศก็เข้าเงื่อนไขที่บอกไว้ก่อนหน้านี้ว่ามันจะทำการเข้าใจว่า b คือ global โดยทันทีครับผม หากไม่อยากจะสร้างตัวแปร global แบบไม่ได้ตั้งใจก็ให้ประกาศอย่างนี้ซะก่อน

จากตัวอย่างที่กล่าวมาคงจะเห็นแล้วว่าการตั้งชื่อตัวแปรแบบ global ไม่ใช่ว่าไม่ให้ใช้ถ้าจะใช้ก็ควรเป็นชื่อที่ไม่เหมือนใครเลยจะดีมาก และใช้มันให้น้อยที่สุดเท่าที่จะเป็นได้ครับ

Side Effects When Forgetting var

นอกจากเรื่องการประกาศตัวแปรแบบ global โดยตั้งใจและไม่ตั้งใจยังมีข้อแตกต่างอีกนิดด้วยครับคือ

  • ตัวแปรที่เราตั้งใจประกาศเป็นแบบ global นั้นจะ ไม่สามารถลบได้!!!
  • ตัวแปรที่ไม่ได้ตั้งใจประกาศเช่น ไม่ใส่ var ใน function จะสามารถลบได้ครับ

เอาล่ะเรามาดูตัวอย่างกันเลยครับ

จากโค้ดข้างบนนั้นตัวแปร global_var ถูกประกาศแบบตั้งใจ และสองตัวที่เหลือนั้นเป็นการประกาศแบบอาจจะไม่ได้ตั้งใจให้เป็นตัวแปร global ซึ่งผลก็อย่างที่เห็นครับตัวแปร global_var ไม่สามารถลบออกได้

Access to the Global Object

ทุกๆ browser นั้นการเข้าถึงตัวแปร global สามารถเข้าถึงใน property ของตัวแปร window อีกทีแต่ในบางกรณีเราสามารถเข้าถึงโดยไม่ต้องทำการ hardcode ในตัวแปร window โดยการทำอย่างนี้ครับ

ประกาศอย่างนี้ใน function ของคุณก็จะสามารถเข้าถึงตัวแปร window ได้ทันที โดยเราไม่ต้อง hardcode ตัว window ครับแต่ผมดูแล้วว่ามันอาจจะไม่สะดวกก็ได้ยังไงก็ลองเอาไปใช้กันดู

Single var Pattern

ใช้การประกาศครั้งเดียวสำหรับหลายๆตัวแปร สิ่งที่จะได้รับจากการทำอย่างนี้คือ

  • มีจุดสำหรับสังเกตุว่ามีตัวแปรไหนชื่ออะไรบ้าง ไม่ต้องประกาศหลายทีดูที่เดียวส่วนใหญ่แล้วจะประกาศบรรทัดแรกสุดไม่ก็ตอนเริ่มต้นของ function ครับ
  • ป้องกันการถูกเรียกใช้ก่อนที่จะประกาศทำให้ไม่เกิด error ครับผม
  • ช่วยให้เราจดจำได้ว่าประกาศอะไรไปแล้วบ้างชื่ออะไร จะได้ลดการใช้ global ด้วย
  • ทำให้โค้ดสั้นลงนิดนึง

ตัวอย่างการใช้นะครับ

การทำอย่างนี้เป็นตัวอย่างที่ดี เพราะการประกาศพร้อมๆกับใส่ค่าเริ่มต้นให้แก่ตัวแปรจะลดการเกิด error undifined ของตัวแปรลงครับและช่วยให้โค้ดอ่านง่ายขึ้นอีกด้วย ถึงแม้ว่าจะกลับมาอ่านทีหลังก็ยังทำให้เราเข้าใจว่าตัวแปรไหนรับค่าอะไร และที่สำคัญเราสามารถยัดค่า DOM ( Document Object Model ) และ element ต่างๆเข้าไปยังตัวแปรได้อีกด้วยครับ ตัวอย่าง

 

Hoisting: A Problem with Scattered vars

มันปัญหาบางอย่างในการประกาศชื่อตัวแปรซ้ำกันใน function กับ global โดยเราไม่ได้ตั้งใจและทำให้ตัว Javascript นั้นทำงานผิดพลาดตัวอย่างครับ

หลายๆคนที่เขียนจะเข้าใจว่าการ alert ครั้งที่ 1 ค่ามันต้องเป็น global สิทำไมเป็น undefined นั่นก็เพราะว่าตัวแปร local ใน function นั้นชื่อเหมือนกับตัวแปร global โดยตัว Javascript มันจะเข้าใจว่าตัวแปร myname ที่อยู่ใน function ยังไม่ถูกประกาศ เหมือนเราเรียกใช้งานก่อนอ่ะครับ จึงไม่มีค่าพอหาค่าไม่ได้จึงกลายเป็น undefined นั่นเอง จริงๆทางแก้ไขก็คืออาจจะไม่ใช้ชื่อที่เหมือนกับตัว global หรืออีกทางก็คือประกาศ var ไว้แต่แรกๆเลยก็ช่วยลดการผิดพลาดแต่แรกได้ครับ เพราะไม่ว่าคุณจะประกาศตัวแปร myname ไว้ตรงไหนของ function มันก็จะเข้าใจว่าขอบเขตคืออยู่ใน function เท่านั้นครับ

for Loops

การวนซ้ำทำซ้ำที่หลายๆคนต้องใช้กับ array ซึ่งหลายๆคนก็เขียนประมาณนี้

ปัญหาสำหรับการเขียนโค้ดแบบนี้คือ ทุกๆครั้งของการวน 1 รอบมันจะทำการถามค่าจาก array ทุกครั้ง ซึ่งมันจะทำให้โค้ดทำงานได้ ช้า โดยเฉพาะอย่างยิ่งถ้าหากตัวแปร myarray ไม่ใช่ array แต่เป็น HTMLCollection object แล้วเจ้า HTMLCollection object มันคืออะไรหว่า ?

  • document.getElementsByName()
  • document.getElementsByClassName()
  • document.getElementsByTagName()

ซึ่งมันจะช้ายังไง ให้คุณคิดอย่างนี้ครับทุกๆรอบการวนนั้นมันจะเข้าไปถาม dom บางตัวว่าค่านี้เป็นเท่าไรทุกๆครั้ง จบ 1 รอบก็ต้องโหลด element ในหน้านั้นมาถามใหม่ทุกครั้ง ram มันจะเต็มเอาครับทางแก้ไขง่ายๆครับกำหนดตัวแปรอีกตัวรับค่าตัวเลขสำหรับการวนรอไว้เลย

จะเห็นว่ามีเพิ่ม max = myarray.length เข้ามารับค่าตัวเลขสำหรับการวนครับทำให้ไม่ต้องไปถามทุกครั้งตัวเลขก็คงที่เสมอ งั้นก็มีคำถามอีกว่าหากต้องการตัวเลขที่มันมีการเปลี่ยนแปลงตลอดเวลาล่ะทำอย่างไร เช่นอยากรู้ว่า user สร้าง input มาทั้งหมดกี่ตัวแหละ ถ้าเป็นกรณีอย่างนี้ตัวแปร max ของเราจะไม่ใช่ค่าคงที่ ( constant ) ให้เราทำฟังก์ชั่นอย่างนี้ครับ

จะสังเกตุว่าเราไม่ได้ประกาศ var ภายในลูปอีกต่อไปทำให้เราสามารถปรับเปลี่ยนค่าได้ หากเราทำการเปลี่ยนแปลงค่าก็อาจจะโยนค่าอะไรเข้าไปใน function looper แล้วกำหนดค่าใหม่ให้แก่ max ก็ทำได้ครับ การทำ function อย่างนี้ดีตรงที่สามารถย้าย function ไปไหนก็ได้โดยเราจะไม่ลืมค่า i และ max เพราะจะมีติดไปด้วยตลอด

ต่อมาที่เราจะทำการ optimize ตัว i++ เนี้ยแหละคือจุดเล็กๆที่หลายๆคนพลาดครับโดยการปรับแบบใหม่เราจะทำให้ได้ประโยชน์คือ

  • ลดตัวแปรได้อีก 1 ตัวนั่นคือ ไม่ใช่ตัวแปร max อีกต่อไป
  • การเปรียบเทียบค่ากลับไปที่ 0 นั้นเร็วกว่า

เราไปดูกันว่าทำอย่างไรครับ

โดยเราใช้ตัวแปร i มารับค่า max แล้วทำการวิ่งถอยกลับไปที่ 0 จะเร็วกว่าแต่อย่าลืมว่ามันเหมือนเอาค่า array มานับจากตัวมี index มากสุดกลับไปที่น้อยสุดนะครับ แต่ก็สามารถใช้ฟังก์ชั่นในการจัดเรียงทีหลังได้หากมีการปรับเปลี่ยนแล้ว

เอาล่ะ ! วันนี้คงแปลได้เท่านี้ก่อนไว้ มีไฟ + เวลาจะกลับมาเขียนต่อนะครับพี่น้อง หากคุณคิดว่าบทความนี้ดีและน่าสนใจคุณสามารถสนับสนุนได้โดยการกด shard บทความนี้ไปยัง social media ของคุณครับไว้เจอกันครั้งหน้าของคุณครับ

admin
เป็นโปรแกรมเมอร์ที่ตามหาคุณค่าของชีวิตและความฝันในวัยเด็ก ชอบเล่นเกม เรียนรู้ทุกอย่าง ชอบเจอคนใหม่ๆ งานสังคมทุกชนิด ออกกำลังกายในวันว่าง อ่านหนังสือ มีเว็บรีวิวด้วย www.readraide.in.th
//www.oxygenyoyo.com
Top