เหตุใดจึงควรหลีกเลี่ยงการสร้างมรดก


9

ฉันจำการเรียนรู้ VB4 และการลากปุ่มไปยังแบบฟอร์มดับเบิลคลิกที่ปุ่มนั้นและพิมพ์รหัสลงในตัวจัดการเหตุการณ์ที่ฉันเพิ่งได้รับพรอย่างน่าอัศจรรย์ มาจาก QBASIC ฉันตื่นเต้นกับ "V" ใน "VB" นักออกแบบภาพเป็นสิ่งที่ดีที่สุดตั้งแต่ขนมปังหั่นบาง ๆ

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

แต่ไม่กี่ปีที่ผ่านมาฉันเริ่มเรียนรู้เกี่ยวกับ C # และ. net framework และรู้สึกทึ่งกับทุกสิ่งที่ฉันคิดว่าฉันรู้ว่าเพิ่งออกไปนอกหน้าต่าง มีเวทมนต์มากมายที่เกิดขึ้นใน VB6 ที่เปิดเผยอย่างสมบูรณ์ใน. net: ใช้ตัวสร้างและInitializeComponentsวิธีการเช่น ในภายหลังคุณจะพบอินสแตนซ์ควบคุมทั้งหมดที่คุณลากจากกล่องเครื่องมือกิจกรรมทั้งหมดที่คุณลงทะเบียนและคุณสมบัติที่คุณตั้งไว้ในตัวออกแบบ

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

ศาสนาและโรงเรียนที่มีความคิดนอกเหนือจากความเป็นกลางทุกอย่างเราไม่ควรได้รับแบบฟอร์มจากรูปแบบพื้นฐานแทนและมีปุ่ม "ตกลง" (และเพื่อน ๆ ทุกคน) อยู่ในรูปแบบฐานหรือไม่ บางสิ่งบางอย่างเช่นFormBaseที่มาจากDialogFormBase; คลาสทั้งหมดที่สร้างขึ้นในเวลาไม่นาน ... โดยการพิมพ์รหัส ปุ่มถูกสร้างขึ้นโดยขึ้นอยู่กับว่าคลาสนั้นถูกสร้างขึ้นอย่างไร (เช่นคอนสตรัคชัน enum อาร์กิวเมนต์กำหนดว่าจะสร้างปุ่มใด) การควบคุมจะถูกวางไว้ภายในการจัดเรียงของพาเนลแยกและแผงเลย์เอาต์การไหลContentที่เหมาะกับแผงเนื้อหาหลัก นี่ไม่ใช่สิ่งที่ ASP.net ทำกับหน้าต้นแบบและตัวแทนเนื้อหา ฉันได้รับแบบฟอร์มเมื่อฉันต้องการ "มาสเตอร์เพจ" ใหม่ แต่ "มาสเตอร์เพจ" ใหม่นี้ยังคงได้มาจากคลาสฟอร์มพื้นฐานดังนั้นภาพจึงสอดคล้องกันทั่วทั้งแอปพลิเคชัน

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

พวกเราทุกคนไม่ได้ขี้เกียจดังนั้นฉันขาดอะไรไป


ฉันไม่เข้าใจ คุณหมายถึงว่าเราไม่ควรใช้นักออกแบบภาพและเขียนรหัส GUI ทั้งหมดด้วยมือ?
ร่าเริง

พื้นฐาน. NET รหัสที่ควบคุมวัตถุทั้งหมดถูกลากบนแบบฟอร์มที่ไหน
JeffO

1
@JeffO ตัดสินจากรหัสดั้งเดิมที่ฉันได้รับฉันจะบอกว่าถูกต้องในรูปแบบหนึ่งระหว่าง ad-hoc แบบอินไลน์ SQL และตรรกะทางธุรกิจ ประเด็นคือ WinForms คือ . net ดังนั้นหากนักออกแบบทำงานได้ดีกับสิ่งที่มีกลิ่นในปัจจุบันเช่น "รหัสไม่ดี" และ "นิสัยการเขียนรหัสไม่ดี" และจริง ๆ แล้วแบ่งเมื่อคุณเริ่มโครงสร้างสิ่งต่าง ๆ ขึ้นมาฉันพูดวางนักออกแบบและรักษาแบบฟอร์ม และการเข้ารหัสเลเยอร์ UI ใน C # แตกต่างจากการเข้ารหัสเลเยอร์ UI ใน ExtJS อย่างไร มัน "น่าเบื่อ" ในการทำเช่นนั้นใน WinForms เพราะ "เฮ้ดูมีนักออกแบบ"? การเข้ารหัส ExtJS UI น่าเบื่อหรือไม่
Mathieu Guindon

ฉันจะอ้างผู้ใช้รายอื่น: CodeCaster; ตัวจัดการเหตุการณ์มีไว้เพื่อเชื่อมต่อ GUI กับตรรกะทางธุรกิจของคุณ หากคุณมีกล่องข้อความเพื่อป้อนชื่อผู้ใช้และปุ่มเพิ่มการคลิกปุ่มเพิ่มควรเรียก _userRepository.AddUser (UsernameTextbox.Text) เท่านั้น คุณไม่ต้องการตรรกะทางธุรกิจในตัวจัดการเหตุการณ์ stackoverflow.com/questions/8048196/…
Pieter B

@Pieter นั่นไม่ได้ทำให้การพึ่งพา DAL ในเลเยอร์การนำเสนอของคุณหรือไม่
Mathieu Guindon

คำตอบ:


9

ฉันจะคัดค้านคุณด้วยกระบวนทัศน์ที่แตกต่าง: ชอบองค์ประกอบมากกว่ามรดก

แม้ว่าคุณจะเริ่มเขียนโค้ด GUI ด้วยมือและใช้การสืบทอดเพื่อแบ่งปันพฤติกรรมและภาพระหว่างแบบฟอร์มคุณจะพบปัญหาเช่นเดียวกับการออกแบบ OOP ปกติ ให้บอกว่าคุณมี DialogForm ซึ่งมีปุ่ม OK / Cancel และ GridForm ที่มีกริด คุณได้รับกล่องโต้ตอบทั้งหมดจาก DialogForm และทุกรูปแบบด้วย Grid จาก GridForm แล้วคุณจะพบว่าคุณต้องการแบบฟอร์มที่มีทั้งคู่ คุณจะแก้ปัญหาอย่างไร หากคุณใช้การสืบทอดแบบฟอร์มจากนั้นจะไม่มีวิธีแก้ไข ในอีกด้านหนึ่งถ้าคุณใช้ UserControls คุณสามารถวาง GridControl ไว้ในแบบฟอร์มของคุณและใช้งานได้ และคุณยังสามารถใช้ตัวออกแบบกับ UserControls ได้ดังนั้นคุณไม่ต้องเสียเวลาเขียนโค้ด GUI ที่น่าเบื่อ


รูปแบบพื้นฐานเป็นเพียงแค่มี SplitContainer ที่มี Panel2 คงที่ซึ่งมี FlowLayoutPanel ที่เรียกว่าBottomPanelและโฮสต์พฤติกรรม Ok / Cancel / Apply / Close ทั่วไป panel1 มี SplitContainer กับ panel1 คงที่ (ให้เป็นเจ้าภาพร่วมกัน "คำแนะนำ" ฉลากหรือเมนูแถบเครื่องมือสิ่งที่จะไปอยู่ด้านบน) และ Panel2 ถือแผงการป้องกันที่เรียกว่าMainContent; การนำไปปฏิบัติจริงแต่ละครั้งจะตัดสินว่าจะเติมเต็มอย่างไร เนื้อหาทั้งหมดสามารถถูกฉีดเข้าไปในการใช้งานและใช่นี้สามารถควบคุมผู้ใช้ที่ทำกับนักออกแบบเพื่อประหยัดเวลาจุดดี .. แต่สิ่งที่เกี่ยวกับรูปแบบของตัวเอง?
Mathieu Guindon

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

2
'ปัญหาเกี่ยวกับสเกล' ไม่มีอยู่ถ้าคุณมีการออกแบบที่เหมาะสมครึ่งทางเรามีโครงการที่ฉันทำงานกับสองสามร้อยรูปแบบเราใช้การสืบทอดแบบฟอร์มอย่างหนักเพื่อให้ความสอดคล้องและการทำงานทั่วไปและเราไม่เคยมีปัญหาใด ๆ กับมัน.
Mason Wheeler

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

1
@Eparhoric: นักออกแบบคนไหน? เราใช้ Delphi และนักออกแบบก็ใช้ได้ดีกับรูปแบบที่สืบทอดมา และอีกครั้งที่คุณไม่ได้มีปัญหาเหล่านี้ถ้าคุณมีการออกแบบที่ดี หากคุณไม่ได้วางแผนอะไรเลยแน่นอนว่าทุกอย่างจะเปราะและแตกเมื่อใดก็ตามที่คุณสัมผัส แต่ก็ไม่ต่างจากรหัสอื่น ๆ
Mason Wheeler

2

เรื่องนี้เกี่ยวข้องกับเทคโนโลยีที่เลือกไว้

WinForms และ WPF อาจเป็นทั้งกรอบงาน. NET UI แต่แตกต่างกันอย่างมากในวิธีที่คุณบรรลุเป้าหมายที่วางไว้ กระบวนทัศน์บางอย่างย้ายไปมาระหว่างเทคโนโลยีได้ดี แต่คนอื่นทำไม่ได้และคุณไม่ควรลองและบังคับใช้กระบวนทัศน์เพียงเพราะคุณรู้สึกว่ามันมีอยู่ในทุกกรอบ มีเหตุผลที่ MVVM มุ่งที่ WPF / SL และ MVC เป็นแนวคิดแยกใน ASP.NET จาก WebForms และอื่น ๆ เทคโนโลยีบางอย่างทำงานได้ดีขึ้นกับกระบวนทัศน์บางอย่าง

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


0

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

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


0

ฉันเห็นด้วยกับ Mason Wheeler อย่างเต็มที่แม้ว่าในอีกสามปีที่ผ่านมาบางทีตัวเขาเองก็เปลี่ยนใจ

ฉันกำลังพยายามหาทางเลือกในการโยกย้ายจาก Delphi executables ไปยังเว็บ

ถึงตอนนี้ฉันตัดสินใจรับตัว UNIGUI เพราะฉันยังสามารถใช้การสืบทอดฟอร์มได้ ฉันอยากให้เดลฟี่มีมิกซ์อินเหมือนดาร์ทเพราะมันจะทำให้ฉันมีบรรพบุรุษน้อยกว่า แต่ฉันรู้สึกว่าผู้คนเขียนโค้ดใน MVC มากกว่าด้วย Visual Form Inheritance เนื่องจากการนำทางส่วนใหญ่เรียกกฎการตรวจสอบใน datamodule (นำไปใช้ใหม่) เกณฑ์การกรอง sql การค้นหาชุดข้อมูลไคลเอนต์ทุกอย่างเขียนด้วย 5 บางที 6 บรรพบุรุษบรรพบุรุษ

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

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