คุณสมบัติใน C # ควรมีผลข้างเคียงนอกเหนือจากการแจ้งการเปลี่ยนแปลงสถานะหรือไม่?
ฉันเคยเห็นคุณสมบัติที่ใช้ในหลายวิธี จากคุณสมบัติที่จะโหลดค่าในครั้งแรกที่เข้าถึงคุณสมบัติที่มีผลข้างเคียงจำนวนมากเช่นทำให้เกิดการเปลี่ยนเส้นทางไปยังหน้าอื่น
คุณสมบัติใน C # ควรมีผลข้างเคียงนอกเหนือจากการแจ้งการเปลี่ยนแปลงสถานะหรือไม่?
ฉันเคยเห็นคุณสมบัติที่ใช้ในหลายวิธี จากคุณสมบัติที่จะโหลดค่าในครั้งแรกที่เข้าถึงคุณสมบัติที่มีผลข้างเคียงจำนวนมากเช่นทำให้เกิดการเปลี่ยนเส้นทางไปยังหน้าอื่น
คำตอบ:
ฉันสมมติว่าคุณกำลังพูดถึงคุณสมบัติแบบอ่านอย่างเดียวหรืออย่างน้อยคุณสมบัติตัวกระจายเนื่องจากคุณสมบัติตัวตั้งค่าในเกือบทุกกรณีจะมีผลข้างเคียง ไม่อย่างนั้นมันมีประโยชน์ไม่มาก
โดยทั่วไปแล้วการออกแบบที่ดีเป็นไปตามหลักการของความประหลาดใจน้อยที่สุด อย่าทำสิ่งที่ผู้โทรไม่คาดหวังให้คุณทำโดยเฉพาะอย่างยิ่งหากสิ่งเหล่านั้นอาจเปลี่ยนผลลัพธ์ในอนาคต
โดยทั่วไปนั่นหมายความว่าผู้ให้บริการสถานที่พักไม่ควรมีผลข้างเคียง
อย่างไรก็ตามขอให้ระมัดระวังเกี่ยวกับสิ่งที่เราหมายถึงโดย "ผลข้างเคียง"
ผลข้างเคียงที่เป็นเทคนิคใด ๆการปรับเปลี่ยนของรัฐ นั่นอาจเป็นสถานะที่สาธารณชนเข้าถึงได้หรือ ... อาจเป็นสถานะส่วนตัวโดยสิ้นเชิง
Lazy / deferred loader เป็นตัวอย่างหนึ่งของสถานะที่เกือบจะเป็นส่วนตัวโดยเฉพาะ ตราบใดที่มันไม่ใช่ความรับผิดชอบของผู้โทรที่จะทำให้ทรัพยากรนั้นว่างคุณจะลดความประหลาดใจและความซับซ้อนโดยทั่วไปโดยใช้การเริ่มต้นรอการตัดบัญชี โดยปกติแล้วผู้เรียกไม่คาดหวังว่าจะต้องส่งสัญญาณการเริ่มต้นของโครงสร้างภายในอย่างชัดเจน ดังนั้นการเริ่มต้นขี้เกียจไม่ได้ละเมิดหลักการข้างต้น
ตัวอย่างอื่นคือคุณสมบัติที่ซิงโครไนซ์ เพื่อให้วิธีการมีความปลอดภัยต่อเธรดนั้นมักจะต้องได้รับการป้องกันโดยส่วนที่สำคัญหรือ mutex การเข้าสู่ส่วนที่สำคัญหรือการรับ mutex เป็นผลข้างเคียง คุณกำลังแก้ไขสถานะโดยปกติเป็นสถานะโกลบอล อย่างไรก็ตามผลข้างเคียงนี้มีความจำเป็นเพื่อป้องกันความประหลาดใจที่แย่กว่านั้นคือความประหลาดใจของข้อมูลที่ถูกแก้ไข (หรือแย่กว่านั้นแก้ไขบางส่วน) โดยเธรดอื่น
ดังนั้นผมจึงจะคลายข้อ จำกัด บิตต่อไปนี้: ทรัพย์สินอ่านไม่ควรจะต้องมองเห็นผลข้างเคียงหรือผลข้างเคียงที่เปลี่ยนความหมายของพวกเขา
หากไม่มีวิธีที่เป็นไปได้สำหรับผู้โทรที่จะได้รับผลกระทบจากหรือแม้แต่ตระหนักถึงผลข้างเคียงจากนั้นผลข้างเคียงนั้นจะไม่ทำอันตรายใด ๆ ถ้ามันเป็นไปไม่ได้ที่คุณจะเขียนแบบทดสอบเพื่อตรวจสอบว่ามีผลข้างเคียงที่เฉพาะเจาะจงจากนั้นก็แปลเป็นภาษาท้องถิ่นว่าเพียงพอที่จะระบุว่าเป็นรายละเอียดของการใช้งานส่วนตัวและไม่เกี่ยวข้องกับโลกภายนอก
แต่ระวังให้ดี ตามกฎของหัวแม่มือคุณควรพยายามหลีกเลี่ยงผลข้างเคียงเพราะบ่อยครั้งที่สิ่งที่คุณคิดว่าเป็นรายละเอียดการปฏิบัติส่วนตัวอาจรั่วไหลโดยไม่คาดคิดและกลายเป็นสาธารณะได้
ฉันจะตอบคำถามของคุณด้วยคำถาม: จะเกิดอะไรขึ้นเมื่อคุณแก้ไขคุณสมบัติความกว้างของแบบฟอร์ม
เพิ่งออกจากหัวฉันจะ:
(ข้อจำกัดความรับผิดชอบ: ฉันเป็นนักพัฒนา Delphi ไม่ใช่นักพัฒนา. NET นี่อาจไม่ถูกต้อง 100% สำหรับ C # แต่ฉันคิดว่ามันใกล้เคียงกันมาก
"ผลข้างเคียง" ทั้งหมดเหล่านี้เกิดขึ้นเมื่อคุณเปลี่ยนคุณสมบัติความกว้างในแบบฟอร์ม คนใดคนหนึ่งดูเหมือนว่าไม่เหมาะสมหรือไม่ถูกต้องอย่างใด?
ดูกฎการออกแบบของ Microsoftโดยเฉพาะหนึ่งในนั้น:
CA1024: ใช้คุณสมบัติตามความเหมาะสม
... วิธีการคือผู้สมัครที่ดีที่จะกลายเป็นสถานที่ให้บริการหากมีเงื่อนไขใด ๆ ต่อไปนี้:
- ไม่รับข้อโต้แย้งและส่งคืนข้อมูลสถานะของวัตถุ
- ยอมรับอาร์กิวเมนต์เดี่ยวเพื่อตั้งค่าบางส่วนของสถานะของวัตถุ
คุณสมบัติควรประพฤติเหมือนเป็นฟิลด์ หากวิธีการไม่สามารถทำได้ก็ไม่ควรเปลี่ยนเป็นคุณสมบัติ วิธีการนั้นดีกว่าคุณสมบัติในสถานการณ์ต่อไปนี้:
- วิธีการดำเนินการใช้เวลานาน วิธีการนั้นช้ากว่าเวลาที่ต้องใช้ในการตั้งค่าหรือรับค่าของเขตข้อมูล
- วิธีการทำการแปลง การเข้าถึงฟิลด์จะไม่ส่งคืนข้อมูลเวอร์ชันที่แปลงแล้วซึ่งเก็บไว้
- วิธีการรับมีผลข้างเคียงที่สังเกตได้ การดึงค่าของเขตข้อมูลไม่ก่อให้เกิดผลข้างเคียงใด ๆ
- ลำดับของการดำเนินการเป็นสิ่งสำคัญ การตั้งค่าของเขตข้อมูลไม่ได้ขึ้นอยู่กับการดำเนินงานอื่น ๆ
- การเรียกวิธีการสองครั้งติดต่อกันจะสร้างผลลัพธ์ที่แตกต่างกัน
- วิธีการเป็นแบบคงที่ แต่ส่งกลับวัตถุที่สามารถเปลี่ยนแปลงได้โดยผู้โทร การดึงค่าของเขตข้อมูลไม่อนุญาตให้ผู้เรียกเปลี่ยนข้อมูลที่จัดเก็บโดยเขตข้อมูล
- วิธีการส่งกลับอาร์เรย์ ...
ฉันเชื่อว่าคุณสมบัติไม่ควรมีผลข้างเคียง อย่างไรก็ตามมีข้อยกเว้นหนึ่งข้อสำหรับกฎนี้: lazy loading หากคุณต้องการขี้เกียจโหลดบางอย่างในพร็อพเพอร์ตี้ก็ไม่เป็นไรเพราะลูกค้าไม่สามารถบอกได้ว่าการโหลดขี้เกียจเกิดขึ้นและโดยทั่วไปแล้วไม่สนใจ
แก้ไข : โอ้อีกอย่างหนึ่ง - ยิงเหตุการณ์ที่พูดว่า "PropertyXYZ เปลี่ยนแล้ว" (เช่นINotifyPropertyChanged
) - ใช้ได้กับตัวเซ็ต
นอกจากการโหลดที่กล่าวถึงก่อนหน้านี้แล้วยังมีกรณีของฟังก์ชันการบันทึก สิ่งเหล่านี้จะหายาก แต่ไม่ใช่คำถาม
แทบจะไม่มีข้อสรุปในการเขียนโปรแกรมเพื่อตอบคำถามของคุณเราต้องดูคุณสมบัติที่ต้องการของวัตถุและดูว่าเป็นสิ่งที่ใช้กับกรณีของเราหรือไม่
หากเราตอบว่าใช่แล้วคำถามเหล่านี้ก็เป็นความคิดที่ดีที่จะคิดอย่างรอบคอบเกี่ยวกับคุณสมบัติและผลข้างเคียงของมัน ฉันคิดว่าเมื่อคุณพูดว่าผลข้างเคียงที่คุณหมายถึงรองผลข้างเคียงตั้งแต่การปรับปรุงค่าเป็นผลข้างเคียงที่อยู่ในตัวเอง
ผลข้างเคียงที่มากขึ้นโดยทั่วไปการทดสอบที่ยากขึ้นก็จะยิ่งมากขึ้น ยิ่งมีผลข้างเคียงรองมากเท่าไรการจัดการภาวะพร้อมกันก็จะยากขึ้น แต่นั่นเป็นปัญหาที่ยากที่อาจต้องใช้การออกแบบที่สำคัญ
gotcha ขนาดใหญ่น่าจะเป็นสำหรับคนที่ปฏิบัติต่อชั้นเรียนของคุณในฐานะ "กล่องดำ" มันจะไม่พร้อมที่บางรัฐมีการเปลี่ยนแปลงเพียงเพราะพวกเขาได้อ่านทรัพย์สินหรือการเปลี่ยนแปลงคุณสมบัติอื่น ๆ เพราะการเปลี่ยนแปลงอื่น (ซึ่งอาจนำไปสู่ ไปที่การปรับปรุงเรียงซ้อน)
ดังนั้นโดยทั่วไปแล้วเราต้องการให้คุณสมบัติเป็นเรื่องง่ายที่จะให้เหตุผลและง่ายที่สุดเท่าที่จะเป็นไปได้นั่นคือโดยนัยในการตัดสินใจออกแบบมิฉะนั้นมันจะเป็นวิธีการ โปรแกรมเมอร์ที่ดีสามารถทำลายกฎได้เสมอ แต่ต้องแน่ใจว่าคุณมีเหตุผลที่ดีจริงๆ :)