decoupling
ในที่สุดมันก็เกี่ยวกับ decoupling ให้ฉันในตอนท้ายของวันที่ระดับการออกแบบขั้นพื้นฐานที่สุดโดยปราศจากความแตกต่างของลักษณะของคอมไพเลอร์และลิงเกอร์ของเรา ฉันหมายถึงคุณสามารถทำสิ่งต่าง ๆ เช่นทำให้แต่ละส่วนหัวกำหนดเพียงหนึ่งคลาสใช้ pimpls การประกาศไปข้างหน้าไปยังประเภทที่ต้องประกาศเท่านั้นไม่ได้กำหนดบางทีแม้แต่ใช้ส่วนหัวที่เพิ่งมีการประกาศไปข้างหน้า (เช่น:) <iosfwd>
หนึ่งส่วนหัวต่อไฟล์ต้นฉบับ จัดระเบียบระบบอย่างต่อเนื่องตามประเภทของสิ่งที่ประกาศ / กำหนด ฯลฯ
เทคนิคในการลด "การพึ่งพาเวลารวบรวม"
และเทคนิคบางอย่างสามารถช่วยได้นิดหน่อย แต่คุณสามารถพบว่าตัวเองเหนื่อยล้ากับการปฏิบัติเหล่านี้และยังพบว่าไฟล์ต้นฉบับของคุณในระบบของคุณต้องการการเริ่มนำแบบสองหน้า #include
คำสั่งที่จะทำอะไรที่มีความหมายเล็กน้อยกับเวลาสร้างที่พุ่งสูงขึ้นหากคุณให้ความสำคัญกับการลดการพึ่งพาเวลาคอมไพล์ในระดับส่วนหัวโดยไม่ลดการพึ่งพาตรรกะในการออกแบบส่วนต่อประสานของคุณและในขณะนั้นอาจไม่พิจารณาว่า ยังคงบอกว่ามันแปลเป็นปัญหาที่เป็นอันตรายต่อการเพิ่มผลผลิตในทางปฏิบัติ ในตอนท้ายของวันหากหน่วยการรวบรวมของคุณยังคงต้องการข้อมูลเรือที่จะมองเห็นได้ที่จะทำอะไรก็จะแปลเพื่อเพิ่มเวลาสร้างและคูณด้วยเหตุผลที่คุณต้องย้อนกลับไปและต้องเปลี่ยนสิ่งต่าง ๆ ในขณะที่นักพัฒนา รู้สึกเหมือนว่าพวกเขากำลังเฮือกสุดท้ายของระบบแค่พยายามทำให้การเข้ารหัสประจำวันเสร็จสิ้น มัน'
ตัวอย่างเช่นคุณสามารถทำให้แต่ละระบบย่อยมีไฟล์ส่วนหัวที่เป็นนามธรรมและอินเทอร์เฟซหนึ่งไฟล์ แต่ถ้าระบบย่อยไม่ได้แยกออกจากกันคุณจะได้รับสิ่งที่คล้ายปาเก็ตตี้อีกครั้งด้วยส่วนต่อประสานระบบย่อยขึ้นอยู่กับส่วนต่อประสานระบบย่อยอื่นที่มีกราฟพึ่งพาที่ดูเหมือนระเบียบเพื่อให้ทำงาน
ส่งต่อการประกาศไปยังประเภทภายนอก
จากเทคนิคทั้งหมดที่ฉันใช้พยายามที่จะได้รับ codebase เก่าที่ใช้เวลาสร้างสองชั่วโมงในขณะที่นักพัฒนาบางครั้งรอ 2 วันสำหรับการเปิดที่ CI ในการสร้างเซิร์ฟเวอร์ของเรา (คุณเกือบจะนึกภาพเครื่องสร้างเหล่านั้นเป็นสัตว์เหนื่อยหมดภาระ เพื่อติดตามและล้มเหลวในขณะที่นักพัฒนาซอฟต์แวร์ผลักดันการเปลี่ยนแปลง) สิ่งที่น่าสงสัยที่สุดสำหรับฉันคือการประกาศล่วงหน้าประเภทที่กำหนดไว้ในส่วนหัวอื่น ๆ และฉันจัดการเพื่อให้ได้ codebase ที่ลดลงเป็น 40 นาทีหรือมากกว่านั้นหลังจากอายุของการทำเช่นนี้ในขั้นตอนที่เพิ่มขึ้นเล็กน้อยในขณะที่พยายามลด "หัวปาเก็ตตี้" ซึ่งเป็นวิธีปฏิบัติที่น่าสงสัยที่สุดในการเข้าใจถึงปัญหาหลังเหตุการณ์ การออกแบบในขณะที่อุโมงค์ที่มองเห็นในการพึ่งพาส่วนหัว) เป็นประเภทการประกาศไปข้างหน้าที่กำหนดไว้ในส่วนหัวอื่น ๆ
หากคุณนึกภาพFoo.hpp
ส่วนหัวที่มีลักษณะดังนี้:
#include "Bar.hpp"
และใช้เฉพาะBar
ในส่วนหัวด้วยวิธีที่ต้องการการประกาศไม่ใช่คำจำกัดความ แล้วมันอาจดูเหมือนว่าไม่มีเกมง่ายๆที่จะประกาศclass Bar;
เพื่อหลีกเลี่ยงการทำให้คำจำกัดความที่Bar
มองเห็นได้ในส่วนหัว ยกเว้นในทางปฏิบัติบ่อยครั้งที่คุณจะพบหน่วยการคอมไพล์ส่วนใหญ่ที่ใช้Foo.hpp
ยังคงต้องBar
มีการกำหนดต่อไปด้วยภาระเพิ่มเติมของการรวมBar.hpp
ตัวเองไว้ด้านบนFoo.hpp
หรือคุณพบกับสถานการณ์อื่นที่ช่วยได้จริงและ 99 % ของหน่วยการรวบรวมของคุณสามารถทำงานได้โดยไม่ต้องBar.hpp
ยกเว้น แต่จะเพิ่มคำถามการออกแบบขั้นพื้นฐานเพิ่มเติม (หรืออย่างน้อยฉันคิดว่ามันควรจะทุกวันนี้) ว่าทำไมพวกเขาต้องเห็นการประกาศBar
และทำไมFoo
แม้จะต้องใส่ใจที่จะรู้เกี่ยวกับมันถ้ามันไม่เกี่ยวข้องกับกรณีการใช้งานมากที่สุด (ทำไมภาระการออกแบบที่มีการอ้างอิงกับอีกคนหนึ่งแทบจะไม่เคยใช้?)
เพราะแนวคิดเราไม่แยกFoo
จากBar
กันจริงๆ เราเพิ่งสร้างมันขึ้นมาเพื่อให้ส่วนหัวของFoo
ไม่ต้องการข้อมูลมากนักเกี่ยวกับส่วนหัวBar
และนั่นก็ไม่ได้มีความสำคัญเท่ากับการออกแบบที่ทำให้ทั้งสองตัวนี้เป็นอิสระจากกันอย่างแท้จริง
สคริปต์ฝังตัว
นี่เป็นโค้ดเบสขนาดใหญ่กว่าจริง ๆ แต่เทคนิคอื่นที่ฉันคิดว่ามีประโยชน์อย่างมากก็คือการใช้ภาษาสคริปต์ฝังตัวในส่วนที่สูงที่สุดของระบบของคุณ ฉันพบว่าฉันสามารถฝัง Lua ในหนึ่งวันและทำให้มันสามารถเรียกคำสั่งทั้งหมดในระบบของเราได้อย่างสม่ำเสมอ (คำสั่งนั้นเป็นนามธรรมขอบคุณมาก) น่าเสียดายที่ฉันวิ่งเข้าไปในสิ่งกีดขวางบนถนนที่บรรดาผู้ที่ไม่ไว้วางใจนำภาษาอื่นมาใช้และอาจเป็นเรื่องที่แปลกประหลาดที่สุดโดยมีการแสดงเป็นความสงสัยที่ยิ่งใหญ่ที่สุดของพวกเขา แต่ในขณะที่ฉันสามารถเข้าใจข้อกังวลอื่น ๆ ได้ประสิทธิภาพจะไม่เป็นปัญหาหากเราใช้สคริปต์เพื่อเรียกใช้คำสั่งเมื่อผู้ใช้คลิกปุ่มเท่านั้นตัวอย่างเช่นไม่มีการวนซ้ำของตนเอง (เราพยายามทำอะไร กังวลเกี่ยวกับความแตกต่างของนาโนวินาทีในเวลาตอบสนองสำหรับการคลิกปุ่มหรือไม่?)
ตัวอย่าง
ในขณะที่วิธีที่มีประสิทธิภาพที่สุดที่ฉันเคยเห็นหลังจากเทคนิคการลดเวลาในการรวบรวมใน codebases ขนาดใหญ่นั้นเป็นสถาปัตยกรรมที่ลดจำนวนข้อมูลที่จำเป็นสำหรับสิ่งใดสิ่งหนึ่งในระบบให้ทำงานได้อย่างแท้จริงเปอร์สเปคทีฟ แต่ต้องการให้ผู้ใช้อินเทอร์เฟซเหล่านี้ทำสิ่งที่พวกเขาต้องทำในขณะที่รู้ (ทั้งจากมุมมองของมนุษย์และคอมไพเลอร์การแยกความจริงที่นอกเหนือจากการพึ่งพาคอมไพเลอร์)
ECS เป็นเพียงตัวอย่างหนึ่ง (และฉันไม่แนะนำให้คุณใช้) แต่เมื่อพบว่ามันแสดงให้ฉันเห็นว่าคุณสามารถมีรหัสเบสที่ยอดเยี่ยมที่ยังคงสร้างขึ้นอย่างรวดเร็วอย่างน่าประหลาดใจในขณะที่ใช้เทมเพลตและสินค้าอื่น ๆ มากมายเพราะ ECS ธรรมชาติสร้างสถาปัตยกรรมที่แยกจากกันโดยเฉพาะที่ระบบจำเป็นต้องรู้เกี่ยวกับฐานข้อมูล ECS และโดยทั่วไปจะมีเพียงไม่กี่ประเภทคอมโพเนนต์ (บางครั้งเพียงหนึ่ง) ในการทำสิ่ง:
ออกแบบออกแบบออกแบบ
และประเภทของการออกแบบสถาปัตยกรรมที่แยกจากกันในมนุษย์ระดับแนวคิดมีประสิทธิภาพมากขึ้นในแง่ของการย่อเวลาการคอมไพล์น้อยกว่าเทคนิคใด ๆ ที่ฉันสำรวจข้างต้นเมื่อโค้ดเบสของคุณเติบโตและเติบโตและเติบโตเพราะการเติบโตนั้นไม่ได้แปล หน่วยการรวบรวมทวีคูณข้อมูลจำนวนเงินที่จำเป็นในการรวบรวมและการเชื่อมโยงเวลาในการทำงาน (ระบบใด ๆ ที่ต้องการให้นักพัฒนาโดยเฉลี่ยของคุณรวมถึงสิ่งที่ต้องทำสิ่งที่ต้องทำและยังไม่ใช่พวกคอมไพเลอร์เท่านั้นที่รู้เกี่ยวกับข้อมูลจำนวนมาก ) นอกจากนี้ยังมีประโยชน์มากกว่าการลดเวลาในการสร้างและการแยกส่วนหัวเนื่องจากมันยังหมายความว่านักพัฒนาของคุณไม่จำเป็นต้องรู้อะไรมากมายเกี่ยวกับระบบนอกเหนือจากสิ่งที่จำเป็นในทันทีเพื่อทำบางสิ่งกับมัน
ตัวอย่างเช่นหากคุณสามารถจ้างนักพัฒนาฟิสิกส์มืออาชีพเพื่อพัฒนาเครื่องมือฟิสิกส์สำหรับเกม AAA ของคุณซึ่งครอบคลุม LOC นับล้านและเขาสามารถเริ่มต้นได้อย่างรวดเร็วในขณะที่รู้ข้อมูลขั้นต่ำที่แน่นอนที่สุดเท่าที่มีอยู่ในประเภทและอินเตอร์เฟส เช่นเดียวกับแนวคิดของระบบของคุณนั่นคือการแปลข้อมูลตามปริมาณที่ลดลงสำหรับเขาและผู้แปลเพื่อสร้างเครื่องมือฟิสิกส์ของเขาและแปลให้ลดเวลาการสร้างที่ยอดเยี่ยมในขณะเดียวกันก็หมายความว่าไม่มีอะไรคล้ายปาเก็ตตี้ ทุกที่ในระบบ และนั่นคือสิ่งที่ฉันแนะนำให้จัดลำดับความสำคัญเหนือเทคนิคอื่น ๆ ทั้งหมดเหล่านี้: วิธีที่คุณออกแบบระบบของคุณ เทคนิคอื่น ๆ ที่ใช้หมดไปจะเป็นไอซิ่งที่อยู่ด้านบนหากคุณทำในขณะนั้นมิฉะนั้น