พารามิเตอร์ทางเลือกมีประโยชน์หรือเป็นอุปสรรคต่อการบำรุงรักษาแอปพลิเคชันหรือไม่ [ปิด]


15

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


3
Disclaimer: คุณสมบัติภาษาใด ๆ ในมือที่ไม่ถูกต้องสามารถถูกละเมิด หากภาษาใช้สิ่งนี้อย่างชาญฉลาดและคุณลักษณะภาษานี้ไม่ทับซ้อนกันมากเกินไปกับคุณลักษณะภาษาที่มีอยู่ในแบบทื่อแล้วพวกเขาก็ใช้ได้จริงในความเป็นจริงค่อนข้างมีประโยชน์ Python มีการบรรจุ / แยกบรรจุเรียบร้อยและ "เทคนิค" พารามิเตอร์อื่น ๆ (เทคนิคที่ดีไม่ใช่ความรู้สึก Perl)
งาน

ลองเขียนแอพใน C # ที่เชื่อมต่อกับ Excel โดยไม่ต้องใช้พารามิเตอร์เพิ่มเติม ที่ควรตอบคำถามของคุณโดยปราศจากข้อสงสัยที่สมเหตุสมผล
Dunk

คำตอบ:


22

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

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


1
+1 และมันมีค่าด้วยเมธอดโอเวอร์โหลดที่เพิ่มอาร์กิวเมนต์เช่นnew Circle(size, color, filled, ellipseProportions)ที่sizeและcolorจำเป็นและส่วนที่เหลือเป็นค่าเริ่มต้น
Michael K

15

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

ค้นหาพารามิเตอร์ที่สามารถจัดกลุ่มได้เช่น (x และ y กลายเป็นจุด)

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

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

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


1
+1 สำหรับการระมัดระวัง คุณลักษณะใด ๆ ไม่ว่าจะดีเพียงใดก็สามารถถูกทำร้ายได้
Michael K

3
นี่คือคำแนะนำที่ดีสำหรับการสร้างรหัสราวีโอลี่ที่ผู้ใช้ API ของคุณต้องใช้อย่างน้อย 6 คลาสและ 15 ฟังก์ชันเพื่อให้ได้สิ่งที่ง่ายที่สุด
dsimcha

1
@dsimcha คุณจะได้รับจากสิ่งที่ฉันเขียนได้อย่างไร ว้าว. กรุณาอธิบาย? นั่นจะเป็นการออกแบบที่ไม่ดีเท่า ๆ กันสำหรับการมี "ฟังก์ชั่นสุดยอด" ซึ่งเป็นสิ่งที่คุณได้รับเมื่อคุณมีพารามิเตอร์ทางเลือกมากมาย อ่านเกี่ยวกับหลักการออกแบบ SOLID และการเขียนโค้ดที่สามารถทดสอบได้ ควรใช้ TDD อย่างยิ่ง จากนั้นกลับมาลองอธิบายให้ฉันฟังว่าการลดพารามิเตอร์ในฟังก์ชั่นเป็นสิ่งที่ไม่ดี
CaffGeek

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

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

4

พารามิเตอร์ทางเลือกนั้นใช้ได้

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

นี่คือตัวอย่างบางส่วน:

1. คุณต้องการหลีกเลี่ยงการโอเวอร์โหลดและไม่ต้องการระบุอาเรย์

ลองดูที่printf ()จาก C, Perl, Java เป็นต้นมันเป็นตัวอย่างที่ดีของประสิทธิภาพของพารามิเตอร์ทางเลือก

ตัวอย่างเช่น:

printf("I want %d %s %s",1,"chocolate","biccies");

printf("I want %d banana",1);

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

2. คุณต้องการอนุญาตให้ใช้ค่าเริ่มต้นและซ่อนไว้จากผู้ใช้วิธีการนั้น

sendemail ( "test@example.org");

เมธอด sendEmail ตรวจพบว่ามีค่าสำคัญต่าง ๆ ขาดหายไปและเติมเต็มในการใช้ค่าเริ่มต้นที่กำหนดไว้ (หัวเรื่อง, ร่างกาย, cc, bcc ฯลฯ ) API นั้นสะอาด แต่มีความยืดหยุ่น

หมายเหตุเกี่ยวกับพารามิเตอร์มากเกินไป

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

String myMethod(String x, String y, String z, String a, int b, String c, int d) {}

เป็นตัวเลือกที่เหมาะสำหรับการแนะนำการสร้างวัตถุพารามิเตอร์ใหม่อีกครั้ง

String myMethod(ParameterObject po) {}

class ParameterObject {
  // Left as public for clarity
  public String x;
  public String y;
  ... etc

}

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


1
ฟังก์ชั่นการจัดรูปแบบสตริงเช่น printf เป็นข้อยกเว้นของกฎหนึ่งอาจโต้แย้งว่าในขณะที่พวกเขาใช้รายการไม่ จำกัดของพารามิเตอร์ทางเลือกก็เหมือนอาร์กิวเมนต์เป็นอาร์เรย์กว่ามันเป็นพารามิเตอร์ทางเลือกแม้จะมีการดำเนินการ
CaffGeek

@Chad ฉันได้ปรับคำตอบของฉันให้ดีขึ้นเพื่อแยกความแตกต่างระหว่างพารามิเตอร์ทางเลือกและเมื่อพวกเขาเปลี่ยนเป็นกลิ่นรหัส (ตามที่คุณได้กล่าวไว้ในคำตอบของคุณ)
Gary Rowe

@Gary Rowe พารามิเตอร์ตัวเลือกมากเกินไปก็ไม่ดีเช่นกันในกรณีส่วนใหญ่
CaffGeek

@Chad ฉันเห็นด้วย แต่ภาษาส่วนใหญ่ไม่มีวิธีระบุข้อ จำกัด เกี่ยวกับจำนวนอาร์กิวเมนต์ที่เป็นตัวเลือกดังนั้นจึงเป็นวิธีการทั้งหมดหรือไม่เลย คุณถูกบังคับให้ทิ้งไว้กับวิธีการของคุณในการบังคับใช้และชัดเจนว่าวิธีการของคุณเกี่ยวข้องกับตัวแปร 500 ตัวหรือไม่ดังนั้นจึงจำเป็นต้องได้รับการปรับโครงสร้างใหม่อย่างแน่นอน
Gary Rowe

@Gary Rowe คุณหมายถึง "ภาษาส่วนใหญ่ไม่มีวิธีระบุข้อ จำกัด เกี่ยวกับจำนวนอาร์กิวเมนต์ที่เป็นตัวเลือก" ในภาษาส่วนใหญ่คุณทำเครื่องหมายเป็นเช่นนั้นหรือไม่ให้ค่าเมื่อเรียกใช้ฟังก์ชัน แต่ส่วนหัวของฟังก์ชันยังคงมีพารามิเตอร์ที่กำหนดไว้ จริงอยู่ในบางภาษาคุณสามารถเพิ่มพารามิเตอร์ได้มากเท่าที่คุณต้องการหลังจากที่คุณเติมพารามิเตอร์ที่กำหนดไว้ แต่ฉันไม่คิดว่าเป็นพารามิเตอร์ตัวเลือกที่เรากำลังพูดถึงที่นี่ (นอกเหนือจากข้อยกเว้นการจัดรูปแบบสตริง)
CaffGeek

2

ปัญหาอย่างหนึ่งของพารามิเตอร์เริ่มต้นใน C # (ฉันกำลังคิดว่าโมฆะ DoSomething (int x = 1)) เป็นค่าคงที่ ซึ่งหมายความว่าหากคุณเปลี่ยนค่าเริ่มต้นคุณจะต้องคอมไพล์ผู้บริโภคของการเรียกใช้เมธอดนั้นอีกครั้ง ในขณะนี้เป็นเรื่องง่ายพอที่จะทำมีโอกาสที่สิ่งนี้เป็นอันตราย


1

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


1

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

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


1

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

bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )

1

พารามิเตอร์ที่เป็นทางเลือกนั้นเป็นวิธีที่แตกต่างกันในการโอเวอร์โหลดฟังก์ชั่น ดังนั้นสิ่งนี้โดยทั่วไปมาถึง: "มีการใช้งานฟังก์ชันมากเกินไปหรือไม่"?


1

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


0

ฉันคิดว่ามันจะดีกว่าที่จะโอเวอร์โหลดฟังก์ชั่นที่มีลายเซ็นที่แตกต่างกัน (เช่นพารามิเตอร์) กว่าการใช้พารามิเตอร์ทางเลือก


ทำไม? ฉันคิดว่ามันจะสะอาดกว่าถ้าคุณสามารถรวมวิธีการโอเวอร์โหลดหลาย ๆ แบบไว้ในวิธีการเดียวโดยใช้พารามิเตอร์เริ่มต้นหากวิธีการทั้งหมดมีฟังก์ชั่นพื้นฐานแบบเดียวกัน
Amit Wadhwa

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