Clean Code คืออะไร

clean code

Clean Code คืออะไร

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

“คุณภาพโค้ด” เป็น “การตรวจสอบโค้ดอย่างต่อเนื่อง” จากนั้น “คุณภาพโค้ดและความปลอดภัยของโค้ด”

รู้สึกเหมือนอยู่ใน ในช่วงสองสามปีที่ผ่านมา ในที่สุดเราก็สามารถจัดการกับสิ่งที่เรามองหาตั้งแต่เริ่มต้นได้ : Clean Code

เรื่องเกี่ยวกับ Clean Code

ปัญหาที่เราแก้ไขที่ Sonar เป็นปัญหาใหญ่โตและส่งผลกระทบไปในวงกว้าง เราช่วยยกระดับประสิทธิภาพ ลดความเสี่ยงและช่วงเวลาหยุดทำงาน รวมถึงเพิ่มความรับผิดชอบต่อโค้ด เราส่งผลต่อโค้ดต้นฉบับโดยตรง และแน่นอน ส่งผลต่อซอฟต์แวร์ทางอ้อมด้วย

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

  1. ความสนใจของเรามุ่งเน้นไปที่ code เท่านั้น
  2. เราควรมุ่งเน้นไปที่สาเหตุของปัญหา ไม่ใช่ผลที่ตามมา
  3. เราเรียกสิ่งที่เราทำว่า Clean Code

เมื่อตัดสินใจเหล่านี้แล้ว คุณก็เริ่มเห็นคำว่า “Clean Code” ปรากฏอยู่ทั่วไปหมด ปัญหาคลี่คลายหรือยัง? เรารู้ว่าเราทำอะไรและโฟกัสไปที่อะไร แต่ยังมีช่องโหว่อยู่: เราจะจำแนกความไม่สอดคล้องของ Clean Code ได้อย่างไร ถ้าเรายังอยากยึดโยงกับโค้ดจริง ไม่ใช่ผลลัพธ์ที่เกิดขึ้นตามมา? หลังจากตัดสินใจใช้ “Clean Code” เป็นแนวทางหลัก Sonar เจออีกความท้าทาย

การจำแนกประเภทของความไม่สอดคล้องกับ Clean Code

รากฐานของการจำแนกประเภทของความไม่สอดคล้องกับ Clean Code คือโค้ดที่สะอาดและมีคุณสมบัติดังนี้: มีความสม่ำเสมอ, มีเจตนาชัดเจน, สามารถปรับเปลี่ยนได้ และมีความรับผิดชอบกล่าวอีกนัยหนึ่ง เมื่อใดก็ตามที่โค้ดมีปัญหา ปัญหานั้นจะ “ทำลาย” คุณสมบัติ ทั้ง 4 หมวดนี้

สม่ำเสมอ ( Consistent )

รหัสควรสอดคล้องและเป็นไปตามรูปแบบทั่วไป ซึ่งหมายความว่าโค้ดทั้งหมด แม้ว่าจะใช้งานโดยบุคคลอื่นเมื่อเวลาผ่านไป แต่ก็ควรมีลักษณะที่คล้ายคลึงกันและเป็นไปตามรูปแบบที่กำหนดไว้ ความสอดคล้องนี้ควรใช้ไม่เพียงแต่กับโค้ดเบสเฉพาะเท่านั้น แต่ยังรวมถึงระบบนิเวศของภาษาการเขียนโปรแกรมทั้งหมดด้วย

ตัวอย่างที่ 1:

โค้ดควรได้รับการจัดรูปแบบให้อ่านง่าย ยกตัวอย่างเช่น แม้ว่าคุณอาจไม่คุ้นเคยกับโค้ดภาษาจาวา แต่คุณก็น่าจะคาดหวังว่าโค้ดนั้นจะมีการเยื้องบรรทัดอย่างสม่ำเสมอ ไม่ได้อยู่ที่ว่าใช้การเว้นวรรคหรือแท็บ แต่อยู่ที่ความสม่ำเสมอของการจัดวาง

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S1120/java

ตัวอย่างที่ 2 :

รหัสควรเป็นสำนวนและเป็นไปตามแบบแผนไวยากรณ์ ตัวอย่างเช่น ใน C++ >= 11 type alias สามารถประกาศผ่านทางใดทางหนึ่งได้ typedef กับ using อย่างไรก็ตาม คุณควรเลือกอย่างหลังสำหรับโค้ดสมัยใหม่

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S5416/cfamily

ตัวอย่างที่ 3 :

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

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S101/csharp

ตั้งใจ ( Intentional )

Intentional Code อ่านได้ราวกับเขียนด้วยความใส่ใจและใส่ใจในการถ่ายทอดวัตถุประสงค์ โค้ดควรอธิบายได้ในตัวและอนุญาตให้ตีความได้เพียงครั้งเดียวเท่านั้น ทุกคำสั่งมีเหตุผล มีรูปแบบที่เหมาะสม และเพียงสื่อถึงพฤติกรรมของมัน รหัสไม่ควรคลุมเครือหรือเหลือพื้นที่ให้คาดเดา

ตัวอย่างที่ 1 :

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

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S1481/python

ตัวอย่างที่ 2 :

โค้ดควรมีเฉพาะคำสั่งที่สมเหตุสมผลเท่านั้น ตัวอย่างเช่นใน JavaScript มี NaN ซึ่งย่อมาจาก ‘Not-a-Number’ ‘ หมายถึงประเภทข้อมูลตัวเลขที่ไม่ใช่ตัวเลขที่ถูกต้อง NaN ไม่เท่ากับค่าใดๆ แม้แต่ตัวมันเอง และพฤติกรรมนี้สามารถนำไปสู่ผลลัพธ์ที่ไม่คาดคิดได้

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S2688/javascript

ตัวอย่างที่ 3 :

รหัสควรจะละเอียด ตัวอย่างใน PHP คือการใช้คุกกี้ที่ปลอดภัย วิธีการ setcookie ช่วยให้คุณสร้างคุกกี้ที่สามารถส่งผ่าน HTTP เป็นค่าเริ่มต้น ทำให้เนื้อหาสามารถอ่านได้ เนื่องจากคุกกี้มักจะมีข้อมูลที่ละเอียดอ่อน สิ่งสำคัญคือต้องแน่ใจว่ามีการถ่ายโอนข้อมูลอย่างปลอดภัยเพื่อให้บรรลุวัตถุประสงค์ที่ตั้งใจไว้ คุณต้องผ่านอาร์กิวเมนต์สุดท้ายเพื่อเปิดใช้งาน HTTPS เท่านั้น

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S2092/php

ตัวอย่างที่ 4 :

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

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S6587/docker

ปรับตัวได้ ( Adaptable )

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

ตัวอย่างที่ 1 :

รหัสควรแตกต่างและลดความซ้ำซ้อน ตัวอย่างเช่น การทำซ้ำตัวอักษรสตริงจะเพิ่มความเสี่ยงของข้อผิดพลาดเมื่อทำการอัปเดต เนื่องจากแต่ละเหตุการณ์จะต้องเปลี่ยนแปลงแยกกัน แนวทางที่ดีกว่าคือการใช้ค่าคงที่ที่สามารถอ้างอิงได้จากหลายที่ ทำให้สามารถอัปเดตได้ในที่เดียว นี่คือตัวอย่างการใช้ Ruby

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S1192/ruby

ตัวอย่างที่ 2 :

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

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S1996/swift

ตัวอย่างที่ 3 :

โค้ดควรเป็นแบบโมดูลาร์ (แยกส่วน) หนึ่งในส่วนสำคัญคือการทำ encapsulation (การห่อหุ้มข้อมูล) ในภาษาเชิงวัตถุ (Object-Oriented) การทำ encapsulation มักเกี่ยวข้องกับการทำให้ฟีลด์ (fields) เป็น private ด้วยวิธีนี้ คลาสจะยังคงควบคุมรายละเอียดของการแสดงภายในของตน และป้องกันไม่ให้ส่วนอื่นๆ ของโค้ดมีความรู้มากเกินไปเกี่ยวกับการทำงานภายในอย่างไรก็ตาม การห่อหุ้มข้อมูลมีหลายระดับ และแม้แต่การปรับปรุงเล็กน้อยก็สามารถส่งผลได้ ตัวอย่างเช่น หากคุณกำลังทำงานกับ VB.Net ซึ่งอนุญาตให้เข้าถึงฟิลด์สาธารณะได้ จะเป็นการดีกว่าที่จะหลีกเลี่ยงการใช้ฟิลด์เหล่านั้นและใช้คุณสมบัติแทน คุณสมบัติทำงานคล้ายกับฟิลด์ แต่เป็นส่วนหนึ่งของอินเทอร์เฟซและสามารถแทนที่ได้โดย getters และ setters

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S2357/vbnet

ตัวอย่างที่ 4 :

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

มีตัวอย่างแปลกๆ ที่คุณมีโฟลเดอร์ทดสอบหรือไฟล์ทดสอบโดยไม่มีกรณีทดสอบจริงอยู่ข้างใน ซึ่งอาจทำให้นักพัฒนารายอื่นเข้าใจผิดได้ : https://sonarsource.github.io/rspec/#/rspec/S2187/

นอกจากนั้น ยังมีกรณีที่การทดสอบถูกข้ามไปและคอมมิทไปโดยไม่ได้ตั้งใจ ซึ่งอาจจะไม่มีใครสังเกตเห็นได้หากไม่ติดตามใดๆ : https://sonarsource.github.io/rspec/#/rspec/S1607/

รับผิดชอบ ( Responsible )

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

ตัวอย่างที่ 1 :

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

โดยใช้ Go

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/S2068/go

ตัวอย่างที่ 2 :

รหัสควรจะถูกต้องตามกฎหมาย ควรเคารพกฎข้อบังคับด้านลิขสิทธิ์และลิขสิทธิ์ขั้นพื้นฐาน ใช้สิทธิ์ของผู้สร้างและให้เกียรติสิทธิ์ของผู้อื่นในการอนุญาตรหัสของตนตัวอย่างทั่วไปประการหนึ่งคือบริษัทที่บังคับใช้ส่วนหัวลิขสิทธิ์ในไฟล์โค้ดของตน :

อ่านเพิ่มเติมได้ที่ : https://sonarsource.github.io/rspec/#/rspec/S1451/

ตัวอย่างที่ 3 :

โค้ดควรให้ความเคารพและครอบคลุม ควรหลีกเลี่ยงการใช้ภาษาที่เลือกปฏิบัติหรือไม่เหมาะสม และเลือกใช้คำศัพท์ที่ครอบคลุมทุกครั้งที่ทางเลือกที่เหมาะสมสื่อสารความหมายเดียวกัน สามารถใช้นิพจน์ทั่วไป (regular expression) เพื่อติดตามชื่อตัวระบุและความคิดเห็นได้

รหัสที่ไม่สอดคล้อง :

รหัสที่สอดคล้อง :

อ่านเพิ่มเติม : https://sonarsource.github.io/rspec/#/rspec/?query=naming%20convention

แล้วมันเกี่ยวอะไร?

ก่อนอื่น เรารู้สึกดีมากกับการจำแนกประเภทนี้ (ในแต่ละหมวดหมู่ยังแบ่งออกเป็นหมวดหมู่ย่อย) เราคิดว่านี่เป็นรากฐานที่แข็งแกร่งสำหรับ Clean Code ตอนนี้ เราต้องการที่จะค่อยๆ นำคำจำกัดความโดยละเอียดของ Clean Code นี้ไปใช้ในผลิตภัณฑ์ของ Sonar โดยเริ่มต้นจากวิธีการที่เราจัดประเภทปัญหาในโค้ด ขั้นตอนแรกมีให้ใช้งานแล้วใน SonarCloud, SonarLint และ SonarQube 10.2นอกจากนี้ เราจะเริ่มดำเนินการจัดประเภทผลกระทบที่เกิดขึ้นกับซอฟต์แวร์ เมื่อโค้ดไม่สะอาด เช่น ในด้านความปลอดภัย ความน่าเชื่อถือ ความสามารถในการดูแลรักษา และอื่นๆ

ข้อมูลจาก : https://www.sonarsource.com/blog/what-is-clean-code/

Naruemon Paengjaem
Naruemon Paengjaem