ตัวแปรทั่วโลกแย่หรือเปล่า? [ปิด]


247

ใน C / C ++ ตัวแปรทั่วโลกไม่ดีเท่าที่อาจารย์คิด


17
ฉันจะกัดในกรณีที่เขาพยายามเล่าเรื่องตลก ... "พวกเขาช่างเลวร้าย"
Zach Scrivena

13
ฉันคิดว่าคำถามนี้น่าสนใจทีเดียว! การพัฒนาซอฟต์แวร์ยังคงเผชิญกับข้อผิดพลาดเดิม ๆ ตั้งแต่เริ่มต้นและโปรแกรมเมอร์มักจะไม่ทราบว่าการใช้ตัวแปรระดับโลก, gotos, ชื่อตัวแปรแบบสั้นไม่ใช่ปัญหา มีการเขียนรหัสที่ไม่ดีทุกวันโดยไม่ใช้ +1
Sylvain Rodrigue

69
เราจะตอบอย่างไร เขาไม่ได้บอกเราว่าอาจารย์ของเขาคิดว่าแย่แค่ไหน :)
Steve Fallows

9
@ Juan Mendes ฉันเห็นด้วยกับคุณ 100%! ปัญหาที่ฉันพูดถึงคือนักพัฒนาหลายคนรู้ว่าพวกเขาไม่ควรใช้ตัวแปรทั่วโลก แต่พวกเขาไม่รู้ว่าทำไม! ดังนั้นฉันจึงได้เห็นซอฟต์แวร์ขนาดใหญ่จำนวนมากที่แต่ละฟังก์ชั่นทุกตัวได้รับโครงสร้างขนาดใหญ่ที่ประกอบด้วยเขตข้อมูล +100 - ดูสิไม่มีตัวแปรทั่วโลก! ปัญหาเดียวกับที่เรียกกันว่า "แนวปฏิบัติที่ดี": เป็นแนวปฏิบัติที่ดีในบริบทบางอย่างไม่ใช่ในทุกบริบท ใช้พวกเขาอาจสร้างรหัสที่ไม่สามารถเคลื่อนไหวได้ ไชโย
Sylvain Rodrigue

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

คำตอบ:


257

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

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

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


10
คำตอบนี้ดีจริงๆ รวมสิ่งนี้เข้ากับคำตอบ 'ขอบเขตตัวแปรที่น้อยที่สุด' คำตอบstackoverflow.com/questions/357187/…
bobobobo

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

2
คำถามไม่กี่ข้อ (1) 2) "สามารถทำได้ ... เสียเวลาทั้งหมด)" คุณยกตัวอย่างได้ไหม 3) "หากคุณไม่ต้องพึ่งพาตัวแปรทั่วโลก ... คุณไม่จำเป็นต้องคำนึงถึงสถานะโลก" ฉันไม่เข้าใจว่าเป็นข้อได้เปรียบอย่างไร อาจเป็นตัวอย่างของการทำงานให้ฉัน
อังเดร

2
@bobobobo ลิงก์ที่ขาดเราจะได้ภาพหน้าจอจากคุณผู้ใช้ 10k + หรือไม่
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆไปเลย! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

สิ่งสำคัญคือการจำเป้าหมายโดยรวม: ความชัดเจน

กฎ "ไม่มีตัวแปรกลาง" อยู่ที่นั่นเพราะส่วนใหญ่แล้วตัวแปรกลางทำให้ความหมายของรหัสชัดเจนน้อยลง

อย่างไรก็ตามเช่นเดียวกับหลาย ๆ กฎผู้คนจำกฎได้และไม่ใช่กฎที่ตั้งใจจะทำ

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

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


8
การแนะนำให้ใช้โกลบอลแทนการส่งผ่านตัวแปรเป็นสูตรในการทำให้โค้ดของคุณไม่สามารถใช้ซ้ำได้และไม่ปลอดภัยสำหรับการทำเธรดหลายตัว
Juan Mendes

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

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

3
หากใครบางคนผ่าน 100 ตัวแปรแล้วพวกเขาไม่ได้เรียนรู้สิ่งที่เป็นวัตถุ การใช้การอ้างอิงไปยังวัตถุนี้นั้นผ่านตัวชี้ที่เลวร้ายที่สุด ฉันจะบอกว่ากฎไม่ได้เป็นเพียงความชัดเจน แต่การทดสอบด้วย - และการใช้แบบ non-global มีแนวโน้มที่จะทำให้การทดสอบง่ายขึ้นมาก
UKMonkey

2
"ถ้ามีคนผ่าน 100 ตัวแปรแล้วพวกเขาไม่ได้เรียนรู้สิ่งที่เป็นวัตถุ" เห็นด้วย แต่ไม่ใช่โลกทั้งใบเป็นแบบวัตถุ ตัวอย่างส่วนตัวของฉันเกี่ยวกับขนาดโค้ดสองเท่าเป็นโปรแกรม Fortran ขนาดใหญ่ประมาณปี 1986 ในฐานะพนักงานใหม่ของมหาวิทยาลัยฉันได้ "ปรับปรุง" โดยเพิ่มพารามิเตอร์ประมาณ 30 ตัวในการโทรแต่ละครั้ง จากนั้นก็เลิกปรับปรุงเมื่อฉันรู้ว่าฉันทำอะไรลงไป
Tom West

64

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


25
จริงอยู่ พวกเขาเป็นเหมือน gotos ถ้าคุณไม่รู้ว่าจะใช้เมื่อไหร่ก็ไม่เคยทำ
David Holm

5
ที่ บริษัท ปัจจุบันของฉันพวกเขาใช้staticตัวแปรทั่วโลกเป็นจำนวนมากภาษาคือ C. เมื่อถูก จำกัด อยู่ในหน่วยการแปลที่ค่อนข้างเล็กพวกเขาเริ่มคล้ายกับตัวแปรคลาสของวัตถุ C ++
Vorac

1
@Vorac คงที่ตัวแปรไม่ใช่ตัวแปรทั่วโลกพวกเขาเป็นตัวแปรท้องถิ่น ตัวแปรทั่วโลกเป็นตัวแปรที่มีอยู่ทุกที่ในโปรแกรม (เพราะฉะนั้น "global", duh) เพื่อไม่ให้สับสนกับตัวแปรขอบเขตไฟล์ซึ่งเป็นตัวแปรที่ประกาศภายนอกฟังก์ชั่นใด ๆ ตัวแปรขอบเขตไฟล์สแตติกไม่ได้เป็นตัวแปรส่วนกลาง
Lundin

1
เพื่อแก้ไขตัวเอง, program lifetime, file scope variables. และพวกเขากลายเป็นระดับโลกเลยทีเดียวเมื่อคุณผ่านตัวชี้ไปยังตัวแปรกับโลกภายนอก (ซึ่งเป็นไปไม่ได้กับตัวแปรอัตโนมัติ) ..
Vorac

@Lundin ฉันยอมรับstaticตัวแปรทั่วโลกมีขอบเขต จำกัด ในหน่วยการแปลเดียวกัน แต่พวกเขามีอายุการใช้งานจนถึงสิ้นสุดโปรแกรมเป็นตัวแปรทั่วโลก
akhilesh1988

38

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

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


2
ข้อยกเว้นหนึ่งที่ฉันเห็นในปีวิทยาลัยของฉันคือฟังก์ชั่นกราฟิกโทรกลับ ใน XWindows, เมาส์เรียกกลับไม่ได้มีข้อโต้แย้งเป็นโมฆะ * ข้อมูลที่ได้รับอนุญาตให้คุณสามารถผ่านรอบชิ้นโดยพลการของรัฐโปรแกรม ... (ไม่ว่าปลายที่ขึ้นเป็นดีกว่าอยู่แล้วทั่วโลก ... )
ไบรอัน Postow

10
+1 สำหรับ "สิ่งต่าง ๆ เช่นการเชื่อมต่อฐานข้อมูลดูเหมือนจะเป็นของโลก แต่ไม่ใช่"
. GitHub หยุดช่วย ICE

1
ตารางอินเตอร์รัปต์ไม่ใช่แบบโกลบอลมีหนึ่งตัวต่อตัวประมวลผล - แต่มีอินสแตนซ์หนึ่งของโปรแกรมของคุณต่อตัวประมวลผลดังนั้นจึง "ยกเลิก"
253751

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

33

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

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

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

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

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

ปัญหาเล็กน้อยจากตัวแปรทั่วโลกที่ต้องแก้ไข

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

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

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

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

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

ใช้ C ++ namespaceและstructเทคนิคสำหรับ C

สำหรับภาษาการเขียนโปรแกรม C ++ namespaceคำสั่งจะช่วยได้มากในการลดโอกาสในการปะทะกันของชื่อ namespaceพร้อมกับclassและคำหลักการเข้าถึงที่หลากหลาย ( private, protectedและpublic) มอบเครื่องมือส่วนใหญ่ที่คุณต้องการเพื่อแค็ปซูลตัวแปร อย่างไรก็ตามภาษาการเขียนโปรแกรม C ไม่ได้มีคำสั่งนี้ การโพสต์สแต็คโฟลว์โฟลว์เนมสเปซใน Cมีเทคนิคบางอย่างสำหรับ C

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

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

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


นี่เป็นคำอธิบายที่ดีที่สุดในการอธิบายสิ่งที่อยู่ในนั้น รุ่งโรจน์!
johndoevodka

ภาษาของคุณควรมีกฎรหัสเพื่อห้ามไม่ให้คุณใช้คัปปลิ้งคลาสมากเกินไป
นักพัฒนาเมลเบิร์น

19

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

มันเป็นค่าใช้จ่ายทางอ้อมระยะยาวและคนส่วนใหญ่คิดว่ามันไม่เลว


19

หากเป็นไปได้รหัสของคุณจะสิ้นสุดลงภายใต้การพิจารณาอย่างละเอียดในระหว่างการพิจารณาคดีของศาลฎีกาคุณต้องการให้แน่ใจว่าจะหลีกเลี่ยงตัวแปรส่วนกลาง

ดูบทความนี้: รหัส Buggy breathalyzer สะท้อนให้เห็นถึงความสำคัญของการตรวจสอบแหล่งที่มา

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

ชายฉันคิดว่านักพัฒนาเหล่านั้นต้องการที่จะไม่ใช้ตัวแปรทั่วโลก


6
นั่นคือเสียงหัวเราะที่ดีที่สุดที่ฉันมีในขณะที่ ตัวอย่างจริงของสาเหตุที่การพัฒนาแหล่งข้อมูลปิดเพื่อผลกำไรไม่ดีและตัวอย่างที่ดีของ vars ทั่วโลกผิดพลาด!
Evil Spork

สิ่งที่สร้างไว้ที่นี่คือตัวแปรทั่วโลกถูกดูด้วยความรังเกียจ ไม่มีอะไรที่นี่ที่แสดงให้เห็นว่าตัวแปรทั่วโลกเป็นปัญหาของแท้ในรหัส SysTest กล่าวว่าในขณะที่รหัสคือ "ไม่ได้เขียนในลักษณะที่สอดคล้องกับแนวทางปฏิบัติที่ดีที่สุดในการออกแบบซอฟต์แวร์ปกติ" แต่มันก็ยังคง "ให้ผลลัพธ์การทดสอบที่สอดคล้องกันอย่างน่าเชื่อถือ" ดังนั้นจึงไม่มีการรับรองอันตรายจากกลม อย่างที่ฉันเห็นมันพวกเขาเพิ่งสร้างมันขึ้นมาว่า "เอาล่ะ dev เหล่านี้ไม่ได้ฝึกฝนศาสนาการเข้ารหัสที่เหมือนกับโลกที่เหลือ"
LionKimbro

19

ตัวแปรทั่วโลกไม่ดีเท่าที่คุณทำไม่น้อยกว่า

หากคุณกำลังสร้างโปรแกรม encapsulated อย่างสมบูรณ์คุณสามารถใช้ globals มันเป็น "บาป" ที่จะใช้กลม แต่การเขียนโปรแกรมบาปเป็นปรัชญาอย่างหนัก

หากคุณตรวจสอบL.in.oleumคุณจะเห็นภาษาที่มีตัวแปรเป็นระดับโลกเพียงอย่างเดียว มันไม่สามารถปรับขนาดได้เพราะห้องสมุดทุกแห่งไม่มีทางเลือกนอกจากใช้ globals

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

ไม่ใช่ทั้ง Gotos ถ้าคุณใช้ถูกต้อง

ปัญหาใหญ่ "เลวร้าย" ก็คือถ้าคุณใช้มันผิดคนกรีดร้องผู้ก่อกวนดาวอังคารตกและโลกก็ระเบิดขึ้น .... หรืออะไรทำนองนั้น


17
การแสดงปัญหาของการใช้กลมกลืนกับนักเรียนที่สับสนนั้นไม่ใช่ความคิดที่ดี
GEOCHET

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

7
รวยถูกต้อง คำตอบนี้ไม่ได้พูดอะไรเกี่ยวกับสิ่งที่เป็น / ไม่เลว (หรือวิธีกลมกลืนสามารถใช้งานได้อย่างปลอดภัย) เพียงว่า "พวกเขาไม่ได้เลวร้ายอย่างที่เป็นเช่นนั้นมันเพียงแสดงให้เห็นถึงปัญหา
jalf

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

@ gariepy จนรู้ว่าฉันพูดถึง statics: D โอเคนั่นคือ ... และแอพของฉันมีตัวแปรทั่วโลกเพียงหนึ่งหรือสองตัวนั่นคือมาพร้อมกับ Visual Studio, DEBUG และ TRACE ซึ่งปกติเราไม่ได้ใช้: D
deadManN

17

ฉันจะตอบคำถามนี้ด้วยคำถามอื่น: คุณใช้singeltons / singeltons ไม่ดีหรือไม่?

เพราะการใช้งาน singelton (เกือบทั้งหมด) เป็นตัวแปรทั่วโลกที่ได้รับเกียรติ


11
ฉันกำลังจะโพสต์ความคิดเห็นอันชาญฉลาดโดยกล่าวว่า "พวกเขาจะไม่ดีถ้าคุณเรียกพวกเขาว่า globals แทน singletons" แต่คุณเอาชนะฉันไปที่มัน
smo

ฉันยังคงพยายามที่จะคิดออกว่าสิ่งที่นรกเดี่ยวคือฮ่า ๆ
GeoffreyF67

1
@Geoffrey: นี่คือคำอธิบาย SO ที่ดีบางอย่าง - stackoverflow.com/questions/11831/และสำหรับลิงก์ที่ดีบางอย่าง: stackoverflow.com/questions/11831/…
Gavin Miller

10
สำหรับเร็กคอร์ดซิงเกิลตันเป็นตัวแปรทั่วโลกที่มีชื่อ Design Patterns (tm) (lol) เพื่อให้ได้เสียงที่ถูกต้องตามกฎหมาย มันไม่ดีเท่ากันด้วยเหตุผลเดียวกันทั้งหมด
. GitHub หยุดช่วยน้ำแข็ง

@GavinMiller กำลังพูดว่ามันโอเคถ้าคุณใช้คำว่า simpleton ... ooops, euphemism ซิงเกิล?
Juan Mendes

14

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

ข้อดีไม่กี่:

  • สามารถเข้าถึงได้จากฟังก์ชั่นใด ๆ
  • สามารถเข้าถึงได้จากหลายกระทู้
  • จะไม่ออกนอกขอบเขตจนกว่าโปรแกรมจะจบ

ข้อเสียไม่กี่:

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

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

แนวทางแก้ไขที่เป็นไปได้สำหรับปัญหาบางประการ:

  • พิจารณาว่าพวกเขาเป็นทางออกที่ดีที่สุดหรือมีประสิทธิภาพมากที่สุดสำหรับปัญหา หากมีใด ๆการแก้ปัญหาที่ดีกว่าใช้แทน
  • วางไว้ในเนมสเปซ [C ++] หรือโครงสร้างซิงเกิลตัน [C, C ++] ด้วยชื่อเฉพาะ (ตัวอย่างที่ดีจะเป็นGlobalsหรือGlobalVars) หรือใช้หลักการตั้งชื่อมาตรฐานสำหรับตัวแปรทั่วโลก (เช่นglobal_[name]หรือg_module_varNameStyle(ดังที่กล่าวถึงโดย underscore_d ในความคิดเห็น )) ทั้งสองนี้จะบันทึกการใช้งานของพวกเขา (คุณสามารถค้นหารหัสที่ใช้ตัวแปรส่วนกลางโดยค้นหาชื่อ namespace / struct) และลดผลกระทบต่อเนมสเปซส่วนกลาง
  • สำหรับฟังก์ชันใด ๆ ที่เข้าถึงตัวแปรโกลบอลให้บันทึกเอกสารอย่างชัดเจนว่าตัวแปรใดที่อ่านและเขียน สิ่งนี้จะทำให้การแก้ไขปัญหาง่ายขึ้น
  • วางไว้ในไฟล์ต้นฉบับของตนเองและประกาศไว้externในส่วนหัวที่เกี่ยวข้องดังนั้นการใช้งานจะถูก จำกัด ไว้ที่หน่วยการคอมไพล์ที่จำเป็นต้องเข้าถึง หากรหัสของคุณขึ้นอยู่กับตัวแปรส่วนกลางจำนวนมาก แต่หน่วยการคอมไพล์แต่ละหน่วยต้องการการเข้าถึงเพียงเล็กน้อยเท่านั้นคุณสามารถพิจารณาจัดเรียงไฟล์เหล่านั้นเป็นไฟล์ต้นฉบับได้หลายไฟล์ดังนั้นจึงง่ายกว่าที่จะ จำกัด การเข้าถึงตัวแปรโกลบอลแต่ละไฟล์
  • ตั้งค่ากลไกเพื่อล็อคและปลดล็อคพวกเขาและ / หรือออกแบบรหัสของคุณเพื่อให้ฟังก์ชั่นน้อยที่สุดจำเป็นต้องแก้ไขตัวแปรส่วนกลาง การอ่านมีความปลอดภัยมากกว่าการเขียนแม้ว่าการแข่งเธรดอาจยังทำให้เกิดปัญหาในโปรแกรมแบบมัลติเธรด
  • โดยทั่วไปลดการเข้าถึงและลดความซ้ำซ้อนของชื่อ คุณต้องการหลีกเลี่ยงการชนชื่อและมีฟังก์ชั่นน้อยที่สุดที่สามารถแก้ไขตัวแปรที่กำหนด

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

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


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


1
+1 สำหรับการปฏิบัตินิยม ซิงเกิลหนึ่งมักจะเพิ่มสำเร็จรูปสำเร็จรูปเพื่อสร้างอินสแตนซ์ & refactor ให้กับสมาชิกและคุณท้ายด้วย ... ตัวแปรทั่วโลกเพียงแค่ทำการปลอมภายใต้ชื่ออื่น ทำไมต้องกังวลนอกเหนือไปจากการหลีกเลี่ยง Sin of Globals ในด้านเทคนิคเท่านั้น? Namespaces นั้นดีเหมือนกำแพงกั้น แต่ฉันพบว่ามันg_module_varNameStyleอ่านง่ายอย่างสมบูรณ์ เพื่อความชัดเจนฉันไม่ได้ใช้ globals ถ้าฉันสามารถหลีกเลี่ยงได้ง่าย - คำสำคัญได้อย่างง่ายดายเพราะเมื่อฉันหยุดเชื่อว่าพวกเขาจะต้องหลีกเลี่ยง - หรือค่อนข้างงง - ค่าใช้จ่ายทั้งหมดฉันมีเวลาที่ดีขึ้นมาก & รหัส is (shock!) far tidier
underscore_d

@underscore_d ส่วนใหญ่มีเพียงวิธีที่จะแยกความแตกต่างระหว่างตัวแปรโกลบอลและท้องถิ่นได้ง่ายขึ้นและเพื่อให้ง่ายต่อการค้นหาตัวแปรทั่วโลกเมื่อค้นหารหัสของคุณด้วยความตั้งใจที่จะป้องกันความสับสนว่าตัวแปรนั้นเป็นโลกหรือท้องถิ่น / พารามิเตอร์ / สมาชิก / ฯลฯ การตั้งชื่อแบบมาตรฐานเช่นคุณทำงานได้ดีตราบเท่าที่มันสอดคล้องกัน แก้ไขคำตอบของฉันด้วยแนวคิดการตั้งชื่อมาตรฐานขอบคุณ
Justin Time - Reinstate Monica

1
"สำหรับฟังก์ชั่นใด ๆ ... เอกสารที่ตัวแปรอย่างชัดเจน" - จำไว้ว่านี่คือความสัมพันธ์สกรรมกริยา ถ้าฟังก์ชันเรียกฟังก์ชั่น B และ C แล้วมันอ่านและเขียนตัวแปรที่เขียนโดยทั้งสอง (บวกคนโดยตรงในร่างกาย)
Caleth

11

ดังที่มีคนพูดว่า (ฉันถอดความ) ในหัวข้ออื่น "กฎเช่นนี้ไม่ควรเสียจนกว่าคุณจะเข้าใจผลของการทำเช่นนั้น"

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

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


1
ฉันเห็นด้วยถ้าคุณเข้าใจผลที่ตามมาก็โอเคทำลายกฎ แต่ถ้าคุณจับตัวเองทำมันบ่อยครั้งคุณกำลังทำอะไรผิด
Juan Mendes

9

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

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


9

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


คำอุปมาขี้เกียจไร้บริบท! = answer
underscore_d

1
@underscore_d: ฉันไม่เห็นด้วย นี่คือคำถามการสนทนาแม้ว่าจะไม่ได้ติดแท็กเช่นนี้ (อาจเป็นเพราะอายุของมัน) ดังนั้นคำตอบเช่นนี้จึงสมบูรณ์และมันก็เป็นประเด็นที่ตอบคำถาม OPs
gariepy

7

ตัวแปรทั่วโลกไม่ดีถ้าพวกเขาอนุญาตให้คุณจัดการกับแง่มุมต่าง ๆ ของโปรแกรมที่ควรจะแก้ไขเฉพาะที่ ใน OOP globals มักขัดแย้งกับแนวคิด encapsulation


7

ฉันคิดว่าอาจารย์ของคุณกำลังพยายามที่จะหยุดนิสัยที่ไม่ดีก่อนที่มันจะเริ่ม

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


7

ไม่ได้อย่างแน่นอน. ในทางที่ผิดแม้ว่า ... ที่ไม่ดี

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


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

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

1
เผง พวกเขาไม่ได้ "เลวร้าย" มากนักเพราะพวกมัน "แตกง่าย" โดยทั่วไป หากคุณรู้วิธีการใช้โดยไม่ทำลายอะไรและเมื่อใดที่จะใช้แทนที่จะเป็นทางเลือกพวกเขาก็มีประโยชน์ มิฉะนั้น ... ไม่มาก
Justin Time - Reinstate Monica

4

ตัวแปรทั่วโลกใช้ได้ในโปรแกรมขนาดเล็ก แต่น่ากลัวหากใช้แบบเดียวกันกับตัวใหญ่

ซึ่งหมายความว่าคุณสามารถใช้มันในขณะที่เรียนรู้ได้อย่างง่ายดาย นี่คือสิ่งที่อาจารย์ของคุณพยายามปกป้องคุณ

เมื่อคุณมีประสบการณ์มากขึ้นมันจะง่ายต่อการเรียนรู้เมื่อพวกเขาไม่เป็นไร


4

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

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

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

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

โปรดทราบว่าหัวข้อเช่นนี้มักจะเป็นที่ถกเถียงกันอยู่ในที่ทำงานและจะยังคงดำเนินต่อไปในขณะที่คอมไพเลอร์และตัวประมวลผล (และภาษา) มีวิวัฒนาการเช่นเดียวกันกับกฎเหล่านี้และไม่มีการป้องกันตำแหน่งของคุณ ก้าวไปข้างหน้า.

ในเวลานั้นให้ทำอะไรก็ตามที่พูดเสียงดังหรือถือไม้เท้าที่ใหญ่ที่สุดพูด (จนกว่าจะถึงเวลาที่คุณเป็นคนดังตะโกนเสียงดังและถือไม้ที่ใหญ่ที่สุด)


4
นี่เป็นอีกวิธีหนึ่งในการพูดว่า "ไม่มีใครถูกไล่ออกจากการซื้อ IBM" หรือไม่?
Gordon Potter

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

4

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

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

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

ฉันไม่ได้เรียกร้อง globals ในขณะที่จุดอื่น ๆ ยังคงอยู่จุดของฉันเป็นเพียงว่าจำนวนกระทู้ในโปรแกรมไม่มีอะไรเกี่ยวข้องกับขอบเขตของตัวแปร


3

ใช่เพราะถ้าคุณปล่อยให้โปรแกรมเมอร์ที่ไร้ความสามารถใช้มัน (อ่าน 90% โดยเฉพาะนักวิทยาศาสตร์) คุณจบลงด้วยตัวแปรทั่วโลก 600+ ไฟล์มากกว่า 20+ ไฟล์และโครงการ 12,000 บรรทัดที่ 80% ของฟังก์ชั่นเป็นโมฆะส่งคืนโมฆะและใช้งาน ทั้งหมดในรัฐโลก

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


2

การใช้ตัวแปร Globalนั้นขึ้นอยู่กับข้อกำหนด ข้อดีของมันคือช่วยลดค่าใช้จ่ายในการส่งผ่านค่าซ้ำ ๆ

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

ตัวอย่างเช่น:-

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


2

ทั่วโลกเป็นสิ่งที่ดีเมื่อมันมาถึงการกำหนดค่า เมื่อเราต้องการเรากำหนดค่า / การเปลี่ยนแปลงที่จะมีผลกระทบต่อโลกในโครงการทั้งหมด

ดังนั้นเราจึงสามารถเปลี่ยนการตั้งค่าหนึ่งและการเปลี่ยนแปลงจะนำไปโครงการทั้งหมด แต่ฉันต้องเตือนคุณจะต้องฉลาดมากที่จะใช้ globals


1

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

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


1

ฉันมักจะใช้ globals สำหรับค่าที่ไม่ค่อยมีการเปลี่ยนแปลงเช่น singletons หรือตัวชี้ฟังก์ชั่นการทำงานในห้องสมุดโหลดแบบไดนามิก การใช้ globals ที่เปลี่ยนแปลงได้ในแอพพลิเคชั่นแบบมัลติเธรดมีแนวโน้มที่จะนำไปสู่การติดตามบั๊กยากดังนั้นฉันจึงพยายามหลีกเลี่ยงสิ่งนี้ตามกฎทั่วไป

การใช้ทั่วโลกแทนที่จะผ่านการโต้แย้งมักจะเร็วกว่า แต่ถ้าคุณเขียนแอพพลิเคชั่นแบบมัลติเธรดซึ่งคุณมักทำอยู่ทุกวันนี้มันมักจะใช้งานไม่ได้ดี (คุณสามารถใช้เธรด - สแตติก .


1

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


1

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


0

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


-1

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

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

เพิ่มเติมเกี่ยวกับเรื่องนี้ที่นี่https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded- รหัส


สำหรับลูกหลาน: นี่เป็นบางส่วนที่ถูกต้องที่สุด "ตัวแปรโลคัล" ในคำตอบนี้อ้างถึงตัวแปรเธรด -local แทนตัวแปรขอบเขตโลคัลทั่วไปที่ OP อ้างถึง ผลข้างเคียงของการแก้ไขตัวแปรโกลบอลในแบบเธรดที่ไม่ปลอดภัยนั้นแตกต่างอย่างมากจากการเปลี่ยนแปลงสถานะโกลบอลในแบบไม่พร้อมกัน
จูลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.