ฉันลำเอียงยอมรับว่าเป็นหนึ่งในการใช้แนวคิดดังกล่าวใน C ++ โดยภาษาและลักษณะของมันเช่นเดียวกับโดเมนของฉันและแม้กระทั่งวิธีที่เราใช้ภาษา แต่เมื่อได้รับสิ่งเหล่านี้ฉันคิดว่าการออกแบบที่ไม่เปลี่ยนรูปแบบเป็นสิ่งที่น่าสนใจน้อยที่สุดเมื่อพูดถึงการได้รับผลประโยชน์จำนวนมากที่เกี่ยวข้องกับการเขียนโปรแกรมการทำงานเช่นความปลอดภัยของเธรดความง่ายในการให้เหตุผลเกี่ยวกับระบบ รวมพวกเขาในลำดับใด ๆ โดยไม่ต้องประหลาดใจอันไม่พึงประสงค์) ฯลฯ
ใช้ตัวอย่าง C ++ แบบง่าย ๆ (ไม่เหมาะสำหรับความเรียบง่ายเพื่อหลีกเลี่ยงความอับอายต่อหน้าผู้เชี่ยวชาญด้านการประมวลผลภาพ):
// Inputs an image and outputs a new one with the specified size.
Image resized_image(const Image& src, int new_w, int new_h)
{
Image dst(new_w, new_h);
for (int y=0; y < new_h; ++y)
{
for (int x=0; x < new_w; ++x)
dst[y][x] = src.sample(x / (float)new_w, y / (float)new_h);
}
return dst;
}
ในขณะที่การใช้งานฟังก์ชั่นนั้นเปลี่ยนแปลงสถานะโลคอล (และชั่วคราว) ในรูปแบบของตัวแปรตัวนับสองตัวและอิมเมจโลคัลชั่วคราวเพื่อส่งออก แต่ก็ไม่มีผลข้างเคียงภายนอก มันใส่ภาพและเอาท์พุทใหม่ เราสามารถมัลติเธรดให้กับเนื้อหาในใจของเรา มันง่ายที่จะให้เหตุผลเกี่ยวกับและง่ายต่อการทดสอบอย่างละเอียด มันเป็นข้อยกเว้นที่ปลอดภัยเพราะถ้ามีอะไรเกิดขึ้นภาพใหม่จะถูกยกเลิกโดยอัตโนมัติและเราไม่ต้องกังวลกับการย้อนกลับผลข้างเคียงภายนอก (ไม่มีภาพภายนอกที่ถูกแก้ไขนอกขอบเขตของฟังก์ชั่นดังนั้นจะพูด)
ฉันเห็นว่าน้อยที่จะได้รับและอาจจะหายไปมากโดยการทำให้Image
ไม่เปลี่ยนรูปในบริบทข้างต้นใน C ++ ยกเว้นว่าจะทำให้ฟังก์ชั่นดังกล่าวข้างต้นไม่สะดวกต่อการใช้งานมากขึ้นและอาจมีประสิทธิภาพน้อยลงเล็กน้อย
ความบริสุทธิ์
ฟังก์ชั่นที่บริสุทธิ์ (ปราศจากผลข้างเคียงภายนอก ) เป็นสิ่งที่น่าสนใจสำหรับฉันและฉันเน้นความสำคัญของการให้ความสำคัญกับพวกเขาบ่อยครั้งต่อสมาชิกในทีมแม้ใน C ++ แต่การออกแบบที่ไม่เปลี่ยนรูปแบบซึ่งโดยทั่วไปมักจะใช้บริบทและความแตกต่างกันเล็กน้อยนั้นไม่น่าสนใจสำหรับฉันเนื่องจากมีความจำเป็นตามธรรมชาติของภาษาจึงมักมีประโยชน์และเป็นประโยชน์ในการเปลี่ยนแปลงวัตถุชั่วคราวบางอย่างในกระบวนการได้อย่างมีประสิทธิภาพ สำหรับนักพัฒนาและฮาร์ดแวร์) ใช้งานฟังก์ชั่นแท้
การคัดลอกโครงสร้างที่แข็งแรงราคาถูก
คุณสมบัติที่มีประโยชน์มากที่สุดลำดับที่สองที่ฉันพบคือความสามารถในการคัดลอกโครงสร้างข้อมูลที่มีราคาถูกมากเมื่อค่าใช้จ่ายในการทำเช่นนั้นมักจะเกิดขึ้นเพื่อทำให้ฟังก์ชั่นนั้นบริสุทธิ์เนื่องจากลักษณะอินพุต / เอาท์พุตที่เข้มงวด สิ่งเหล่านี้จะไม่เป็นโครงสร้างขนาดเล็กที่สามารถใส่ลงในสแต็กได้ พวกมันจะมีโครงสร้างที่ใหญ่และหนักหน่วงเช่นเดียวกับScene
วิดีโอเกม
ในกรณีนี้ค่าใช้จ่ายในการทำสำเนาสามารถป้องกันโอกาสในการขนานที่มีประสิทธิภาพเพราะมันอาจเป็นเรื่องยากที่จะทำให้ขนานฟิสิกส์และการเรนเดอร์ได้อย่างมีประสิทธิภาพโดยไม่ต้องล็อคและคอขวดถ้ากันและกัน คัดลอกฉากเกมทั้งหมดรอบ ๆ เพื่อเอาท์พุทหนึ่งเฟรมโดยใช้ฟิสิกส์อาจไม่ได้ผลเท่ากัน อย่างไรก็ตามหากระบบฟิสิกส์นั้น 'บริสุทธิ์' ในแง่ที่ว่ามันใส่เพียงฉากและเอาออกใหม่โดยใช้ฟิสิกส์และความบริสุทธิ์นั้นไม่ได้มาจากค่าใช้จ่ายในการคัดลอกทางดาราศาสตร์มันสามารถทำงานได้อย่างปลอดภัยพร้อมกับ โหมดแสดงภาพโดยไม่มีใครรออีก
ดังนั้นความสามารถในการคัดลอกข้อมูลที่หนักหน่วงของสถานะแอปพลิเคชั่นของคุณรอบ ๆ และส่งออกเวอร์ชันใหม่ที่ถูกแก้ไขด้วยค่าใช้จ่ายน้อยที่สุดในการประมวลผลและการใช้หน่วยความจำสามารถเปิดประตูใหม่สำหรับความบริสุทธิ์และขนานได้อย่างมีประสิทธิภาพ จากวิธีการนำโครงสร้างข้อมูลถาวรมาใช้ แต่สิ่งที่เราสร้างขึ้นโดยใช้บทเรียนดังกล่าวไม่จำเป็นต้องขัดขืนอย่างเต็มที่หรือเสนออินเทอร์เฟซที่ไม่เปลี่ยนรูป (อาจใช้ copy-on-write เช่นหรือ "builder / transient") เพื่อให้บรรลุความสามารถนี้ในราคาถูก เพื่อคัดลอกและแก้ไขเฉพาะส่วนของการคัดลอกโดยไม่เพิ่มการใช้หน่วยความจำและการเข้าถึงหน่วยความจำในการค้นหาคู่ขนานและความบริสุทธิ์ในฟังก์ชัน / ระบบ / ไปป์ไลน์ของเรา
การเปลี่ยนไม่ได้
ในที่สุดก็มีการเปลี่ยนแปลงไม่ได้ซึ่งฉันคิดว่าน่าสนใจน้อยที่สุดในสามสิ่งนี้ แต่มันสามารถบังคับใช้ด้วยกำปั้นเหล็กเมื่อการออกแบบวัตถุบางอย่างไม่ได้มีวัตถุประสงค์เพื่อใช้เป็นขมับในท้องถิ่นเพื่อการทำงานที่บริสุทธิ์และในบริบทที่กว้างขึ้น ชนิดของ "ความบริสุทธิ์ระดับวัตถุ" ในทุกวิธีไม่ก่อให้เกิดผลข้างเคียงจากภายนอกอีกต่อไป (ไม่มีการกลายพันธุ์ตัวแปรสมาชิกที่อยู่นอกขอบเขตเฉพาะของวิธีการทันที)
และในขณะที่ฉันคิดว่ามันน่าสนใจน้อยที่สุดในสามภาษานี้เช่น C ++ มันสามารถทำให้การทดสอบและความปลอดภัยของเธรดและการใช้เหตุผลของวัตถุที่ไม่ใช่เรื่องเล็ก ๆ น้อย ๆ ง่ายขึ้น มันสามารถเป็นภาระในการทำงานกับการรับประกันว่าวัตถุไม่สามารถได้รับการรวมกันของรัฐที่ไม่ซ้ำกันใด ๆ นอกตัวสร้างของมันและเราสามารถผ่านมันได้อย่างอิสระแม้โดยการอ้างอิง / ตัวชี้โดยไม่ต้องพึ่งพาความมั่นคงและอ่าน เฉพาะตัววนซ้ำและหมายเลขอ้างอิงเท่านั้นและในขณะที่รับประกัน (อย่างน้อยที่สุดเท่าที่เราจะทำได้ในภาษา) ว่าเนื้อหาต้นฉบับจะไม่ถูกเปลี่ยนแปลง
แต่ฉันพบว่าคุณสมบัตินี้น่าสนใจน้อยที่สุดเพราะวัตถุส่วนใหญ่ที่ฉันเห็นว่ามีประโยชน์ในการใช้งานชั่วคราวในรูปแบบที่ไม่แน่นอนเพื่อใช้ฟังก์ชั่นที่บริสุทธิ์ (หรือแม้แต่แนวคิดที่กว้างขึ้นเช่น "ระบบบริสุทธิ์" ซึ่งอาจเป็นวัตถุหรือชุดของ ฟังก์ชั่นที่มีเอฟเฟ็กต์ขั้นสูงสุดเพียงแค่ป้อนข้อมูลบางอย่างและแสดงผลสิ่งใหม่โดยไม่ต้องสัมผัสสิ่งอื่นใด) และฉันคิดว่าสิ่งที่ไม่สามารถเปลี่ยนแปลงได้ที่นำไปสู่ความสุดโต่งในภาษาที่จำเป็นอย่างยิ่ง ฉันจะใช้มันเท่าที่จำเป็นสำหรับส่วนต่าง ๆ ของ codebase ซึ่งช่วยได้มากที่สุด
สุดท้าย:
[... ] ดูเหมือนว่าโครงสร้างข้อมูลถาวรนั้นไม่เพียงพอในการจัดการสถานการณ์ที่เธรดหนึ่งทำการเปลี่ยนแปลงที่สามารถมองเห็นเธรดอื่นได้ สำหรับเรื่องนี้ดูเหมือนว่าเราจะต้องใช้อุปกรณ์เช่นอะตอมการอ้างอิงหน่วยความจำทรานแซคชันของซอฟต์แวร์หรือแม้กระทั่งการล็อคแบบคลาสสิกและกลไกการซิงโครไนซ์
โดยธรรมชาติหากการออกแบบของคุณเรียกร้องให้มีการปรับเปลี่ยน (ในแง่ของการออกแบบระดับผู้ใช้) เพื่อให้มองเห็นหลายเธรดพร้อมกันเมื่อเกิดขึ้นเราจะกลับมาซิงโครไนซ์หรืออย่างน้อยกระดานวาดภาพเพื่อหาวิธีที่ซับซ้อน ฉันได้เห็นตัวอย่างที่ซับซ้อนมากที่ผู้เชี่ยวชาญใช้จัดการกับปัญหาประเภทต่างๆเหล่านี้ในการเขียนโปรแกรมเชิงหน้าที่)
แต่ฉันได้พบว่าเมื่อคุณได้รับการคัดลอกและความสามารถในการส่งออกโครงสร้างที่แข็งแรงบางส่วนราคาถูกอย่างที่คุณจะได้รับพร้อมกับโครงสร้างข้อมูลแบบถาวรเป็นตัวอย่างมันมักจะเปิดประตูและโอกาสมากมายที่คุณอาจ ไม่เคยคิดมาก่อนที่จะขนานรหัสที่สามารถทำงานได้อย่างสมบูรณ์เป็นอิสระจากกันในการเรียงลำดับ I / O ที่เข้มงวดของไปป์ไลน์แบบขนาน แม้ว่าบางส่วนของอัลกอริทึมจะต้องต่อเนื่องกันตามธรรมชาติคุณอาจเลื่อนการประมวลผลไปที่เธรดเดียว แต่พบว่าการพึ่งพาแนวคิดเหล่านี้ได้เปิดประตูให้ง่ายขึ้นและไม่ต้องกังวลให้ขนาน 90% ของงานหนักเช่น