สามารถใช้หลักการความรับผิดชอบเดี่ยว / กับรหัสใหม่ได้หรือไม่?


20

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

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


6
@ Frank - มันถูกกำหนดโดยทั่วไปเช่นนั้น - ดูเช่นen.wikipedia.org/wiki/Single_responsibility_principle
Joris Timmermans

1
วิธีที่คุณใช้ถ้อยคำไม่ใช่วิธีที่ฉันเข้าใจความหมายของ SRP
Pieter B

2
รหัสทุกบรรทัดมี (อย่างน้อย) สองเหตุผลในการเปลี่ยน: มันก่อให้เกิดข้อผิดพลาดหรือรบกวนข้อกำหนดใหม่
Bart van Ingen Schenau

1
@BartvanIngenSchenau: LOL ;-) หากคุณเห็นด้วยวิธีนี้ SRP จะไม่สามารถใช้ได้ทุกที่
Doc Brown

1
@DocBrown: คุณสามารถทำได้ถ้าคุณไม่ทำคู่ SRP กับการเปลี่ยนซอร์สโค้ด ตัวอย่างเช่นหากคุณตีความ SRP ว่าสามารถให้บัญชีที่สมบูรณ์เกี่ยวกับสิ่งที่คลาส / ฟังก์ชั่นทำในหนึ่งประโยคโดยไม่ต้องใช้คำและ (และไม่มีถ้อยคำพังพอนเพื่อหลีกเลี่ยงข้อ จำกัด นั้น)
Bart van Ingen Schenau ใน

คำตอบ:


27

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

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

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

 void RunPrintWorkflow()
 {
     var document = ReadDocument();
     var formattedDocument = FormatDocument(document);
     PrintDocumentToScreen(formattedDocument);
 }

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

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

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


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

3
@thecapsaicinkid: ใช่คุณสามารถ (อย่างน้อยโดยการปรับโครงสร้างใหม่ทันที) แต่คุณจะได้ฟังก์ชั่นที่เล็กมาก ๆ และไม่ใช่โปรแกรมเมอร์ทุกคนที่ชอบมัน ดูตัวอย่างนี้: sites.google.com/site/unclebobconsultingllc/ …
Doc Brown

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

1
@thecapsaicinkid: ดูการแก้ไขของฉัน ความรับผิดชอบหลักของฟังก์ชั่นด้านนอกไม่ได้พิมพ์ไปยังอุปกรณ์เฉพาะหรือจัดรูปแบบเอกสาร - มันคือการรวมเวิร์กโฟลว์การพิมพ์ และเมื่อเวิร์กโฟลว์นี้เปลี่ยนนั่นคือเหตุผลหนึ่งเดียวว่าทำไมฟังก์ชั่นจะเปลี่ยน
Doc Brown

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

7

ฉันคิดว่าคุณเข้าใจผิด SRP

เหตุผลเดียวสำหรับการเปลี่ยนแปลงไม่ได้เกี่ยวกับการเปลี่ยนรหัส แต่เกี่ยวกับสิ่งที่รหัสของคุณทำ


3

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

หนึ่งในปมที่ดีที่สุดสำหรับสิ่งนี้คือเมื่อคุณเลือกชื่อคลาสหรือฟังก์ชัน หากไม่ชัดเจนในทันทีว่าควรใช้ชื่อคลาสใดหรือชื่อมีความยาว / ซับซ้อนเป็นพิเศษหรือชื่อใช้คำศัพท์ทั่วไปเช่น "ผู้จัดการ" หรือ "ยูทิลิตี้" นั่นอาจเป็นการละเมิด SRP ในทำนองเดียวกันเมื่อทำเอกสาร API มันควรจะปรากฏอย่างรวดเร็วหากคุณละเมิด SRP ตามหน้าที่การใช้งานที่คุณกำลังอธิบาย

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

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


3

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

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

Refactor เพื่อลดรหัส

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

สร้างเป้า

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

การใช้งานครั้งเดียวไม่ได้หมายความว่าพร่ามัวที่ไม่ชัดเจน

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

คุณแน่ใจหรือว่าusageมีการเปลี่ยนแปลงอย่างมีนัยสำคัญ?

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

ผู้ชายคนใหม่จะสามารถคิดออกได้อย่างรวดเร็วหรือไม่?

รักษาซอร์สโค้ดของคุณไว้ในองค์กรที่เข้าใจง่ายที่สุดเสมอ

อย่าเป็นช่างซ่อมนาฬิกา

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

ป้อนคำอธิบายรูปภาพที่นี่


2

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

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

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

แน่นอนว่า YAGNI กำลังบอกคุณว่าคุณไม่ควร คุณต้องหาสมดุลระหว่างหลักการออกแบบ


2

Flup มุ่งหน้าไปในทิศทางที่ถูกต้อง "หลักการความรับผิดชอบเดี่ยว" เดิมใช้กับขั้นตอน ตัวอย่างเช่น Dennis Ritchie จะบอกว่าฟังก์ชั่นควรทำสิ่งหนึ่งและทำได้ดี จากนั้นใน C ++ Bjarne Stroustrup จะบอกว่าคลาสควรทำสิ่งหนึ่งและทำได้ดี

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

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

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

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

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

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

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


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

1
อาคุณเป็นหนึ่งในนั้นเช่นหนึ่งในผู้จัดการเก่าของฉัน "เราไม่ต้องการที่จะเข้าใจมัน: เราต้องการที่จะปรับปรุง!" ประเด็นสำคัญที่นี่คือหนึ่งในหลักการ: นั่นคือ "P" ใน "SRP" บางทีฉันอาจตอบคำถามโดยตรงถ้าเป็นคำถามที่ถูกต้อง: ไม่ใช่ คุณสามารถตอบคำถามนี้กับผู้ที่เคยตั้งคำถาม
จัดการ

มีคำตอบที่ดีฝังอยู่ที่นี่ที่ไหนซักแห่ง ฉันคิดว่า ...
RubberDuck

0

ใช่ควรมีการใช้หลักการความรับผิดชอบเดียวกับรหัสใหม่

แต่! ความรับผิดชอบคืออะไร?

"พิมพ์รายงานความรับผิดชอบ" หรือไม่ คำตอบฉันเชื่อว่า "อาจจะ"

ลองใช้คำจำกัดความของ SRP ว่า "มีเพียงเหตุผลเดียวที่จะเปลี่ยน"

สมมติว่าคุณมีฟังก์ชั่นที่พิมพ์รายงาน หากคุณมีการเปลี่ยนแปลงสองอย่าง:

  1. เปลี่ยนฟังก์ชันนั้นเนื่องจากรายงานของคุณต้องมีพื้นหลังสีดำ
  2. เปลี่ยนฟังก์ชั่นนั้นเพราะคุณต้องพิมพ์เป็น pdf

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

แต่ถ้าการเปลี่ยนแปลงครั้งที่สองของคุณน่าจะเป็น:

2b เปลี่ยนฟังก์ชั่นนั้นเพราะรายงานของคุณต้องการแบบอักษรอื่น

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

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


0

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

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

อ่านดีเกี่ยวกับสิ่งเหล่านี้: สถาปัตยกรรมแบบลีนโดย Coplien


0

"พิมพ์" เป็นเหมือน "มุมมอง" ใน MVC มาก ใครก็ตามที่เข้าใจพื้นฐานของวัตถุจะเข้าใจสิ่งนั้น

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

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


0

เป็นความคิดที่ดีกว่าหรือที่จะเริ่มใช้ SRP เมื่อคำขอเปลี่ยนรหัสเริ่มเข้ามาเท่านั้น

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

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

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

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

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

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

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