หลักการความรับผิดชอบเดี่ยวใช้กับฟังก์ชันได้หรือไม่


17

อ้างอิงจากโรเบิร์ตซี. มาร์ติน SRP ระบุว่า:

ไม่ควรมีเหตุผลมากกว่าหนึ่งข้อในการเปลี่ยนชั้นเรียน

อย่างไรก็ตามในClean Codeในหนังสือของเขาบทที่ 3: ฟังก์ชั่นเขาแสดงบล็อคของรหัสต่อไปนี้:

    public Money calculatePay(Employee e) throws InvalidEmployeeType {
        switch (e.type) {
            case COMMISSIONED:
                return calculateCommissionedPay(e);
            case HOURLY:
                return calculateHourlyPay(e);
            case SALARIED:
                return calculateSalariedPay(e);
            default:
                throw new InvalidEmployeeType(e.type);
        }
    }

แล้วสหรัฐฯ:

มีปัญหาหลายอย่างกับฟังก์ชั่นนี้ อย่างแรกคือมันมีขนาดใหญ่และเมื่อมีการเพิ่มประเภทพนักงานใหม่ก็จะเพิ่มขึ้น ประการที่สองมันชัดเจนมากกว่าสิ่งหนึ่ง ประการที่สามมีการละเมิด Single รับผิดชอบหลักการ (SRP) เพราะมีมากกว่าเหตุผลหนึ่งที่ทำให้มันมีการเปลี่ยนแปลง [เน้นเหมือง]

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


5
ดูเหมือนว่ากรณีตำราเรียนสำหรับ polymorphism
wchargin

นี่เป็นหัวข้อที่น่าสนใจมาก มีโอกาสที่คุณจะเพิ่มวิธีแก้ไขปัญหาต่อไปนี้ในปัญหานี้หรือไม่? ฉันจะแยกแยะได้ว่าหนึ่งใส่ fPayntion แบบคำนวณ paypal ในแต่ละระดับพนักงาน แต่นั่นอาจจะเป็นเรื่องที่ไม่ดีในขณะนี้แต่ละระดับพนักงานสามารถเปลี่ยนได้เนื่องจาก: 1 การคำนวณการจ่ายเงิน 2. เพิ่มคุณสมบัติเพิ่มเติมให้กับคลาส ฯลฯ
Stav Alfi

คำตอบ:


13

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

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

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


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

@MichaelShaw ลองดูจากเวลา 10:40 น. ลุงบ๊อบกล่าวว่ารหัสจะ "เปลี่ยนด้วยเหตุผลที่แตกต่างกันเพราะคนอื่น" ฉันคิดว่านั่นอาจเป็นสิ่งที่ MichelHenrich พยายามชี้ให้เราเห็น
Enrique

ดูวิดีโอ YouTube ทั้งหมดในเวลา 50 นาทีเสร็จแล้วส่วนใหญ่ไม่เกี่ยวกับสิ่งที่ควรจะชี้แจง ฉันสังเกตเห็นเครื่องหมาย 16:00 ว่าเขาย้ายจากหัวข้อนั้นไปแล้วและเขาไม่เคยกลับมา "คำอธิบาย" เป็นสิ่งจำเป็นอย่างยิ่งในเรื่องนี้: "ความรับผิดชอบ" ใน SRP ไม่ได้หมายความว่ามันหมายถึง "เหตุผลที่แตกต่างกันสำหรับการเปลี่ยนแปลง" ซึ่งหมายถึง "การเปลี่ยนแปลงตามคำร้องขอของคนอื่น" ซึ่งหมายถึง "การเปลี่ยนแปลงที่ คำขอบทบาทที่แตกต่างที่ผู้คนเล่น ". "คำอธิบาย" ไม่ได้อธิบายอะไรเลย แต่จะแทนที่คำที่คลุมเครือด้วยคำอื่น
Michael Shaw

2
@MichaelShaw เหมือนในใบเสนอราคาจากหนังสือหากคุณต้องการแนะนำพนักงานประเภทต่าง ๆ คุณต้องเปลี่ยนระดับพนักงาน บทบาทที่แตกต่างกันอาจรับผิดชอบการชำระเงินประเภทพนักงานที่แตกต่างกันดังนั้นในกรณีนี้ระดับพนักงานต้องมีการเปลี่ยนแปลงมากกว่าหนึ่งบทบาทจึงเป็นการละเมิด SRP
MichelHenrich

1
@MichaelShaw ใช่คุณพูดถูก - SRP ขึ้นอยู่กับวิธีการจัดองค์กร นั่นคือเหตุผลที่ฉันเพิ่ม "อาจ" หรือ "อาจ" ในความคิดเห็นทั้งหมดของฉัน :) อย่างไรก็ตามแม้ในกรณีเหล่านั้นแม้ว่ารหัสอาจไม่ละเมิด SRP แต่ก็เป็นการละเมิด OCP อย่างแน่นอน
MichelHenrich

3

บนหน้า 176, บทที่ 12: การเกิดขึ้น, ในส่วนชื่อคลาสที่น้อยที่สุดและวิธีการที่หนังสือมีการแก้ไขบ้างโดยระบุ:

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

และ

การนับชั้นสูงและวิธีการบางครั้งเป็นผลมาจากความหยิ่งยโสไร้จุดหมาย

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


3

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

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

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

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


-2

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

คำสั่ง 'เหตุผลในการเปลี่ยนแปลง' บางครั้งอาจทำให้เข้าใจผิดเล็กน้อย แต่ถ้าคุณเปลี่ยนcalculateSalariedPayหรือcalculateHourlyPayหรือ enum ของEmployee.typeคุณต้องเปลี่ยนวิธีนี้

ในตัวอย่างของคุณฟังก์ชั่น:

  • ตรวจสอบประเภทของพนักงาน
  • เรียกใช้ฟังก์ชันอื่นซึ่งคำนวณเงินตามประเภท

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

เราไม่รู้ว่าควรคำนวณ 'เงิน' อย่างไร แต่วิธีที่ง่ายที่สุดคือการใช้Employeeอินเทอร์เฟซและการใช้งานที่เป็นรูปธรรมด้วยgetMoneyวิธีการต่างๆ ในกรณีนั้นฟังก์ชั่นทั้งหมดไม่มีความจำเป็น

หากมีความซับซ้อนในการคำนวณมากขึ้นเราสามารถใช้รูปแบบผู้เยี่ยมชมซึ่งไม่ใช่ SRP 100% แต่มี OCP มากกว่ากรณีสวิตช์


2
ไม่แน่ใจว่าคุณจะแสดงรายการสิ่งที่ฟังก์ชั่นทำได้ 2 อย่างไร แต่บอกว่าไม่ใช่การละเมิด SRP
JeffO

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