รายการพารามิเตอร์ของวิธีการควรมีวัตถุหรือตัวระบุวัตถุ?


10

ทีมของเรากำลังสนทนากันดังต่อไปนี้:

สมมติว่าเรามีสองวิธีต่อไปนี้:

public Response Withdraw(int clubId, int terminalId,int cardId, string invoice, decimal amount);

public Response Withdraw(Club club, Terminal terminal,Card card, string invoice, decimal amount);

อะไรที่ส่งผ่านสายเป็นเพียงรหัส

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

อีกด้านหนึ่งบอกว่าวิธีที่สองนั้นถูกต้องเพราะมีความยืดหยุ่นมากกว่า

เราคุ้นเคยกับแนวคิดพารามิเตอร์วัตถุอีกด้านหนึ่งคิดว่าพารามิเตอร์วัตถุควรมีวัตถุเป็นคุณสมบัติ

วิธีใดที่ถูกต้อง

อาจจะมีวิธีที่สามที่ดียิ่งขึ้น?


อะไรนะ ...........
James

1
บริบท? บริการเว็บ? WCF?
CodesInChaos

1
@ James - ขอโทษด้วยฉันเขียนคำถามนี้เร็วแล้วคุณช่วยบอกฉันหน่อยได้ไหมว่าอะไรที่ไม่เข้าใจเพื่อที่ฉันจะแก้ไขได้?
Mithir

@CodesInChaos วิธีการเป็นวิธีการ BL จริง
Mithir

คำตอบ:


10

คำตอบนั้นขึ้นอยู่กับบริบท

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

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

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

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

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


3
+1 ฉันจะเพิ่มอีกหนึ่งจุดเท่านั้น: สำหรับวิธีการที่เรียกจากระยะไกล ("ผ่านลวด" หรือไม่) การผ่านวัตถุสามารถทำให้เกิดลำดับวัตถุต้นไม้ที่กว้างขวางได้ ID เป็นสิ่งทดแทนที่ยอดเยี่ยมสำหรับวัตถุเมื่อคุณกังวลเกี่ยวกับขนาดของ payload การโทรทางไกล
Ross Patterson

1
ในกรณีนี้ดูเหมือนว่าคุณกำลังเชื่อมโยงกับชุดของ abstractions ดังนั้นการส่งผ่านรหัสจะไม่ซื้อความยืดหยุ่นมากขึ้นและอาจเพิ่มโอกาสที่คุณจะย้อนกลับพารามิเตอร์ คำถามคือรหัสในวิธีการอย่างแน่นหนาควบคู่กับ abstractions ที่ฉันส่งผ่านได้อย่างไร ตัวอย่างเช่นวิธีการเช่น "validateCreditCard (บัตรสตริง, สตริง cvi)" น่าจะอยู่กับวิธีดั้งเดิมเพื่อหลีกเลี่ยงการจับคู่กับวัตถุเครดิตการ์ดบางชนิดอย่างแน่นหนา
ipaul

ฉันจะพบกลางและใช้ส่วนติดต่อในรายการพารามิเตอร์ จากนั้นสโมสรของคุณสามารถเป็นสโมสร แต่ยังมีซาวน่าในอนาคต
Pieter B

13

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

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

string invoiceดังนั้นแม้ฉันยังคงมองไปที่ ใบแจ้งหนี้เป็นสตริงจริงหรือ อะไรamountหมายถึง? นี่น่าจะเป็นค่าเงิน

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

คำอธิบายที่ดีที่สุดที่ผมเคยเห็นในความโปรดปรานของวิธีการนี้อยู่ในกฎที่ 3 ของการเพาะกายวัตถุ :

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


ดังนั้นวิธีที่สองได้รับการกำหนดไว้ล่วงหน้า? แม้ว่าจะมีออบเจ็กต์คลับที่มีคุณสมบัติ id เต็มอยู่ใช่ไหม
Mithir

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

@ James ไม่มีคำตอบที่ชัดเจนสำหรับคำถามนี้โดยเฉพาะอย่างยิ่งเนื่องจาก OP ไม่ได้ให้บริบทกับเรามากนัก ใครก็ตามที่มีการอ้างอย่างเป็นทางการว่าวิธีการหนึ่งเป็นที่นิยมมากกว่าวิธีอื่น ๆ ไม่ใช่ขาวดำนั่น
MattDavey

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

5
@ James: สิ่งที่ MattDavey พูดนั้นเป็นข้อเท็จจริงที่ได้รับการยอมรับอย่างดี เขาไม่ได้บอกว่าประเภทดั้งเดิมนั้นไม่ดีสิ่งที่เขาพูดว่า: someMethod (int, int, int, string, decimal) นั้นยากที่จะเข้าใจและใช้งานโดยลูกค้ามากกว่า someMethod (Club, Terminal, Card, String , ทศนิยม)
c_maker

2

ไม่มีคำตอบที่ถูกต้องสำหรับคนนี้ ตัวเลือกอาจเหมาะกับงาน เกือบทุกวิธีอาร์กิวเมนต์ใบแจ้งหนี้ยกร่องบนคิ้วของฉันฉันไม่มีเงื่อนงำสิ่งที่มาจากการอ่านรหัส

หากคุณส่งรหัสจากนั้นทั้งสองระบบจะต้องเชื่อมโยงอย่างแน่นหนากับสิ่งที่แสดงถึง ClubID เป็นกุญแจสำคัญในตารางสโมสร ตรงประเด็นทั้งผู้โทรและผู้รับจำเป็นต้องยอมรับสิ่งที่เรียกว่าตาราง Clubs และฐานข้อมูลที่มีอยู่หากคุณไม่ต้องการหรือไม่สามารถกำหนดข้อ จำกัด ดังกล่าวได้คุณจะต้องผ่านวัตถุโดยใช้คำอธิบายทั่วไป เนทีฟ, อนุกรม, xml, name = value อะไรก็ตาม, ไฟล์ ini :)

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

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