อาร์กิวเมนต์เอาท์พุทคืออะไรตามที่อ้างถึงใน Clean Code ของ Martin


14

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

ตัวอย่างเช่นมาร์ตินสำหรับอาร์กิวเมนต์ส่งออกเรียกฟังก์ชันappendFooter(s); public void appendFooter(StringBuffer report)การปรับปรุงรหัสของเขาคือreport.appendFooter();

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

ฟังก์ชั่นต่อไปนี้จะถือว่าเป็นตัวอย่างของโค้ดที่ไม่สะอาดตามหลักการข้างต้นหรือไม่

int[] numberArray = {3, 5, 7, 1};
sortArray(numberArray);

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

ObjectWithArrayField numberArray = new ObjectWithArrayField(3, 5, 7, 1);
numberArray.sort();

คำตอบ:


11

บ๊อบมาร์ตินเป็นเพียงการพูดคุยเกี่ยวกับการอ่าน

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

อย่างไรก็ตามบ็อบมาร์ตินไม่ได้พูดว่า "ไม่เคยใช้อาร์กิวเมนต์เอาท์พุท" เขาพูด "โดยทั่วไปคุณควรหลีกเลี่ยงเพราะจะช่วยให้โค้ดของคุณสะอาดยิ่งขึ้น" ดังนั้นนี่ไม่ใช่กฎการขนส่งสินค้าทางสมองที่ควรปฏิบัติตามอย่างสุ่มสี่สุ่มห้า

Sortวิธีการสำหรับอาร์เรย์และคอลเลกชันมาตรฐานแตกต่างกันเล็กน้อย การมีsortวิธีการที่ฟังก์ชั่นสมาชิกของประเภทข้อมูลอาร์เรย์มาตรฐานแต่ละประเภทจะมีข้อบกพร่องเล็กน้อยจากมุมมองของนักออกแบบภาษาเช่นการมีวิธีการเช่นArray.sortอนุญาตให้เก็บสิ่งนี้ไว้ในไลบรารีมาตรฐานนอกจาวารันไทม์ แต่ถ้าคุณต้องการสร้างคอลเลกชันแต่ละประเภทซึ่งบางครั้งจะต้องมีการเรียงลำดับการเพิ่มsortเป็นฟังก์ชันสมาชิกอาจเป็นความคิดที่ดีกว่าการใส่ประเภทนั้นลงในคลาสที่แยกต่างหาก


2
sortArray(numberArray)แน่นอนnumberArrayในสถานที่ หรือมันทำสำเนาnumberArrayเรียงลำดับสำเนาและส่งคืนสำเนาที่เรียงลำดับโดยไม่เปลี่ยนแปลงnumberArrayเลย?
8bittree

@ 8bittree: นั่นเป็นความจริง แต่นั่นไม่ใช่จุดของการพูดคุยที่นี่ - sort()วิธีการของคอนเทนเนอร์สามารถทำงานในสถานที่ได้เช่นกันโดยไม่ต้องใช้ "อาร์กิวเมนต์เอาท์พุท" ดังนั้นเพียงเพราะsortArray(numberArray)เป็นวิธีการในสถานที่ไม่มีเหตุผลอย่างที่เหตุผล "รูปแบบการส่งออกอาร์กิวเมนต์" ไม่มีเหตุผล
Doc Brown

1
ประเด็นของฉันยิ่งกว่านั้นไม่ชัดเจนว่าsortArray(numberArray)กำลังทำอะไรอยู่ มันจะชัดเจนหากไม่คืนค่าชนิดเดียวกันกับที่ยอมรับจากนั้นจะต้องอยู่ในตำแหน่ง แต่ไม่เห็นประเภทการคืนสินค้าหรือถ้าประเภทการคืนสินค้าตรงกับประเภทอินพุตก็ไม่มีความชัดเจนโดยไม่ต้องดูคำจำกัดความ
8bittree

1
@ 8bittree: โอเคคุณเข้าใจแล้วฉันลบคำแถลงนี้ออกจากคำตอบของฉัน อย่างไรก็ตามปัญหาที่คุณอธิบายไม่หายไปโดยใช้ฟังก์ชั่นสมาชิก - แม้แต่ฟังก์ชั่นสมาชิก "เรียงลำดับ" ก็สามารถทำงานได้เช่นกัน
Doc Brown

11

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

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

ข้อยกเว้นเดียวสำหรับอัลกอริทึมทั่วไปมาก ตัวอย่างเช่นอัลกอริทึมการเรียงลำดับอาจถูกแยกออกจากคอนเทนเนอร์ที่เรียงลำดับโดยชอบธรรมหากสามารถนำไปใช้กับคอนเทนเนอร์ประเภทใดประเภทหนึ่งโดยทั่วไปโดยใช้ส่วนต่อประสานสาธารณะ appendFooterฟังก์ชั่นone-shot ไม่มีข้อแก้ตัวนั้น

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