ประสิทธิภาพ

โปรแกรมเมอร์ที่มีประสบการณ์สามารถบอกสถาปัตยกรรมที่ดีจากสถาปัตยกรรมที่ไม่ดีได้อย่างง่ายดาย แต่ถ้าถูกขอให้อธิบายด้วยคำไม่กี่คำ พวกเขาไม่น่าจะสามารถทำเช่นนั้นได้ ไม่มีเกณฑ์เดียวสำหรับสถาปัตยกรรมที่ดีและไม่มีคำจำกัดความเดียว

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

เมื่อโปรแกรมมีสถาปัตยกรรมที่ดี มันก็ง่ายพอที่จะเข้าใจวิธีการทำงานและตำแหน่งที่จะเขียนโค้ด โปรแกรมที่มีสถาปัตยกรรมที่ดีนั้นง่ายต่อการเปลี่ยนแปลง ทดสอบ ดีบัก และพัฒนา คนฉลาดได้กำหนดเกณฑ์ต่อไปนี้สำหรับสถาปัตยกรรมที่ดี:

  • ประสิทธิภาพ;
  • ความยืดหยุ่น;
  • ความสามารถในการขยาย;
  • ความสามารถในการปรับขนาด;
  • ความสามารถในการทดสอบ;
  • การบำรุงรักษารหัส

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

คุณจะพบโปรแกรมที่ไม่ทำในสิ่งที่อ้างว่าทำอยู่ตลอดเวลา

  • Libre Office เป็นการทดแทนอย่างสมบูรณ์สำหรับ Microsoft Office (ไม่ใช่จริงๆ);
  • เบราว์เซอร์ Edge รองรับมาตรฐานเว็บทั้งหมด (ไม่จริง);
  • ธนาคารให้ความสำคัญกับความปลอดภัยของข้อมูลส่วนบุคคลของผู้ใช้ (จริง ๆ แล้วไม่ใช่)

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

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

ความยืดหยุ่น

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

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

มันไม่สมเหตุสมผลเลยที่จะพยายามทำนายเพราะจะมีบางสิ่งที่ไม่คาดคิดอยู่เสมอ แต่คุณต้องคำนึงว่างานดังกล่าวจะปรากฏขึ้น ดังนั้นในกระบวนการพัฒนา ให้พยายามประเมินสิ่งที่ได้รับในแง่ของวิธีการที่จะต้องเปลี่ยนแปลง

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

เมื่อใดก็ตามที่เป็นไปได้ การตัดสินใจทางสถาปัตยกรรมไม่ควรกลายเป็นหิน และควรจำกัดผลที่ตามมาของข้อผิดพลาดทางสถาปัตยกรรมอย่างสมเหตุสมผล "สถาปัตยกรรมที่ดีช่วยให้คุณชะลอการตัดสินใจที่สำคัญ" (Bob Martin) และลด "ต้นทุน" ของความผิดพลาดให้เหลือน้อยที่สุด

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

ความสามารถในการปรับขนาด

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

ดูเหมือนว่ากฎนี้จะดำเนินการด้วยตัวเอง แต่ในทางปฏิบัติทุกอย่างตรงกันข้าม มีกระทั่งหนังสือยอดนิยมอย่างThe Mythical Man-Monthซึ่งอธิบายว่าทำไมเมื่อมีการเพิ่มคนใหม่ๆ ในโครงการ เวลาในการพัฒนาจึงเพิ่มขึ้น

ความสามารถในการขยาย

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

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

ข้อกำหนดที่ว่าสถาปัตยกรรมของระบบจะยืดหยุ่นและขยายได้ (นั่นคือ สามารถเปลี่ยนแปลงและวิวัฒนาการได้) มีความสำคัญมากจนต้องมีการกำหนดเป็นหลักการแยกต่างหาก นั่นคือ "หลักการแบบเปิด/แบบปิด " Open-Closed Principleเป็นหลักการที่สองในห้าหลักการ SOLID: เอนทิตีซอฟต์แวร์ (คลาส โมดูล ฟังก์ชัน) ควรเปิดไว้เพื่อขยาย แต่ปิดเพื่อแก้ไข

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

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

ในกรณีนี้ การเกิดขึ้นของข้อกำหนดใหม่จะไม่นำมาซึ่งการแก้ไขตรรกะที่มีอยู่ แต่สามารถดำเนินการได้โดยหลักโดยการขยาย หลักการนี้เป็นพื้นฐานของ "สถาปัตยกรรมปลั๊กอิน" (Plugin Architecture) เทคนิคที่สามารถทำได้จะกล่าวถึงในภายหลัง

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

เป็นการประดิษฐ์แนวคิดตัวกรอง (เซิร์ฟเล็ตบริการ) ที่ทำให้สามารถย้ายฟังก์ชันบริการต่างๆ ไปยังเลเยอร์ที่แยกจากกัน และในอนาคตเมื่อเปลี่ยนพฤติกรรมของตัวกรองก็ไม่จำเป็นต้องเปลี่ยนเซิร์ฟเล็ต

ก่อนการประดิษฐ์ตัวกรอง ตรรกะบริการทั้งหมดที่รับผิดชอบในการร้องขอการเปลี่ยนทิศทางอยู่ในเซิร์ฟเล็ตเอง และบ่อยครั้งที่การเปลี่ยนแปลงเล็กน้อยในตรรกะจะนำไปสู่ความจำเป็นในการดำเนินการผ่านเซิร์ฟเล็ตทั้งหมดและทำการเปลี่ยนแปลงหลายอย่างกับทั้งหมด

ความสามารถในการทดสอบ

หากคุณเป็น Java Backend Developer แอปพลิเคชันเซิร์ฟเวอร์ของคุณมักจะเปิดเผยชุดของเมธอดเป็น REST API และเพื่อตรวจสอบว่าวิธีการทั้งหมดของคุณทำงานได้ตามที่ต้องการ จำเป็นต้องมีการทดสอบ

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

ทันทีที่คุณเริ่มเขียนการทดสอบ คุณจะรู้ว่าโค้ดส่วนใหญ่ไม่สามารถทดสอบได้เลย: วิธีการส่วนตัว การมีเพศสัมพันธ์ที่แข็งแกร่ง คลาสและตัวแปรแบบสแตติก

“ทำไมเราต้องทดสอบว่าโค้ดใช้ได้หรือไม่” ผู้เริ่มต้นจะถาม

“เหตุใดเราจึงต้องการรหัสการทำงานหากไม่สามารถทดสอบได้” ผู้เชี่ยวชาญจะถาม

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

ต่อไปนี้คือข้อความจากหนังสือ Ideal Architecture: “ใช้หลักการของ “การทดสอบได้” ของคลาสเป็น “การทดสอบกระดาษลิตมัส” ของการออกแบบคลาสที่ดี แม้ว่าคุณจะไม่ได้เขียนโค้ดการทดสอบแม้แต่บรรทัดเดียว การตอบคำถามนี้ใน 90 % ของคดีจะช่วยให้เข้าใจว่าทุกอย่างดี" หรือ "แย่" กับการออกแบบของเขาอย่างไร"

มีวิธีการทั้งหมดสำหรับการพัฒนาโปรแกรมโดยอิงจากการทดสอบ ซึ่งเรียกว่า Test-Driven Development (TDD) แน่นอนว่านี่เป็นสิ่งที่สุดโต่ง: เขียนโค้ดก่อนที่คุณจะเขียนโค้ด

การบำรุงรักษารหัส

ตามกฎแล้วผู้คนจำนวนมากทำงานในโปรแกรม - บางคนออกไปคนใหม่มา เวลาทำงานเฉลี่ยของโปรแกรมเมอร์ในบริษัทไอทีคือหนึ่งปีครึ่ง ดังนั้นหากคุณเข้าร่วมโครงการที่มีอายุ 5 ปี เพื่อนร่วมงานของคุณเพียง 20% เท่านั้นที่ทำงานตั้งแต่เริ่มต้น

การบำรุงรักษาและพัฒนาโปรแกรมที่ผู้อื่นเขียนขึ้นนั้นเป็นเรื่องยากมาก แม้ว่าจะเขียนโปรแกรมไว้แล้ว ก็มักจะจำเป็นต้องบำรุงรักษาโปรแกรมต่อไป: แก้ไขข้อผิดพลาดและทำการแก้ไขเล็กน้อย และมักจะต้องทำโดยผู้ที่ไม่ได้มีส่วนร่วมในการเขียน

ดังนั้น สถาปัตยกรรมที่ดีควรทำให้ผู้คนใหม่ๆ เข้าใจระบบได้ง่ายและรวดเร็ว โครงการจะต้อง:

  • มีโครงสร้างที่ดี
  • ห้ามมีการซ้ำซ้อน
  • มีรหัสรูปแบบที่ดี
  • เป็นที่พึงปรารถนาที่จะรวมเอกสาร
  • จำเป็นต้องใช้โซลูชันมาตรฐานและคุ้นเคยสำหรับโปรแกรมเมอร์

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

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