กำลังมองหาคำแนะนำการออกแบบ OO


12

ฉันกำลังพัฒนาแอพที่จะใช้ในการเปิดและปิดวาล์วในสภาพแวดล้อมอุตสาหกรรมและกำลังคิดถึงบางสิ่งที่เรียบง่ายเช่นนี้: -

public static void ValveController
{
    public static void OpenValve(string valveName)
    {
        // Implementation to open the valve
    }

    public static void CloseValve(string valveName)
    {
        // Implementation to close the valve
    }
}

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

นักพัฒนาอีกคนถามว่าเราควรสร้างคลาสแยกต่างหากสำหรับแต่ละวาล์วทางกายภาพซึ่งมีอยู่เป็นสิบหรือไม่ ฉันยอมรับว่ามันจะดีกว่าที่จะเขียนโค้ดเหมือนPlasmaValve.Open()มากกว่าValveController.OpenValve("plasma")แต่นี่เป็น overkill หรือไม่

นอกจากนี้ฉันยังสงสัยว่าวิธีที่ดีที่สุดในการจัดการกับการออกแบบโดยคำนึงถึงความต้องการในอนาคตของสมมุติสองสามข้อ: -

  1. เราได้รับการร้องขอให้สนับสนุนวาล์วชนิดใหม่ที่ต้องการค่าต่าง ๆ ในการเปิดและปิด (ไม่ใช่ 0 และ 1)
  2. เราถูกขอให้สนับสนุนวาล์วที่สามารถตั้งค่าได้ตั้งแต่ 0-100 มากกว่าเพียงแค่ "เปิด" หรือ "ปิด"

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


2
ฉันจะสร้างคลาสวาล์วทั่วไปซึ่งมีตัวระบุสำหรับวาล์วเฉพาะ (ไม่ใช่สตริงบางที enum) และข้อมูลใด ๆ ที่จำเป็นสำหรับการควบคุมการไหลภายในของวิธี OpenValve / CloseValve อีกทางหนึ่งคุณสามารถสร้างคลาสนามธรรม valv และทำการแยกใช้งานสำหรับแต่ละอันที่วาล์วเปิด / ปิดเพียงแค่เรียกตรรกะภายในคลาสวาล์วที่กำหนดสำหรับเหตุการณ์ที่วาล์วต่าง ๆ มีกลไกการเปิด / ปิดที่แตกต่างกัน กลไกทั่วไปจะถูกกำหนดไว้ในคลาสฐาน
จิมมี่ฮอฟฟา

2
ไม่ต้องกังวลกับข้อกำหนดในอนาคตที่สมมุติขึ้น YAGNI
pdr

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

2
ผู้ชาย 'การแต่งเพลงมากกว่าการรับมรดก' เกินความจริง ฉันจะสร้างคลาส / อินเตอร์เฟสแบบนามธรรมจากนั้นซับคลาสลงใน PlasmaValve จากนั้นฉันก็ต้องทำให้แน่ใจว่า ValveController ของฉันจะทำงานกับ Valve โดยไม่สนใจว่า subclass ใดที่แน่นอน
MrFox

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

คำตอบ:


12

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

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


1
+1 สำหรับการกล่าวถึงคำสั่ง switch ตามประเภทเป็นกลิ่นรหัส ฉันมักจะเห็นคำแถลงสวิตช์ประเภทนี้ซึ่งผู้พัฒนาอ้างว่าเขากำลังติดตาม KISS อยู่บ่อยครั้ง ตัวอย่างที่สมบูรณ์แบบของวิธีการออกแบบที่ผิดเพี้ยน Heh
Jimmy Hoffa

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

1

Gripe หลักของฉันใช้สายอักขระเพื่อระบุพารามิเตอร์ของวาล์ว

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

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

ถ้าคุณชอบการทดสอบคุณควรสร้างValveControllerซิงเกิลตันเพื่อให้คุณสามารถล้อเลียน (หรือสร้างเครื่องฝึกอบรมสำหรับผู้ปฏิบัติงาน)


ฉันไม่เคยเห็นใครแนะนำซิงเกิลตันเพื่อการทดสอบมาก่อน - โดยปกติแล้วมันจะไปทางอื่น
Kazark

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