มีเหตุผลที่จะไม่แก้ไขค่าของพารามิเตอร์ที่ส่งผ่านโดยค่าหรือไม่?


9

มีข้อโต้แย้งวิศวกรรมซอฟต์แวร์ที่สนับสนุนหรือต่อต้านการแก้ไขค่าของพารามิเตอร์ค่าในร่างกายของฟังก์ชันหรือไม่?

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

นี่เป็นความขัดแย้งทางศาสนาที่ไม่สามารถแก้ไขได้หรือมีเหตุผลทางวิศวกรรมซอฟต์แวร์ที่ดีทั้งในทิศทางใดทิศทางหนึ่งหรือไม่?

หมายเหตุ: คำถามของหลักการยังคงอยู่โดยไม่คำนึงถึงรายละเอียดการใช้งานของภาษานั้น ๆ ใน JavaScript เช่นที่รายการอาร์กิวเมนต์เป็นไดนามิกเสมอพารามิเตอร์สามารถถือได้ว่าเป็นน้ำตาล syntactic สำหรับการเริ่มต้นตัวแปรท้องถิ่นจากargumentsวัตถุ ถึงกระนั้นใคร ๆ ก็สามารถปฏิบัติต่อตัวระบุพารามิเตอร์ที่ประกาศว่าเป็น "พิเศษ" เพราะพวกเขายังคงจับภาพการส่งผ่านข้อมูลจากผู้โทรไปยังผู้รับ


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

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

ฉันคิดว่าต้องมีการถามก่อนหน้านี้ แต่สิ่งเดียวที่ฉันสามารถหาได้คือคำถาม SO ที่เก่ากว่านี้
Doc Brown

3
มันถือเป็นข้อผิดพลาดน้อยที่เกิดขึ้นได้ง่ายสำหรับภาษาที่จะห้ามมิให้โต้แย้งการกลายพันธุ์เช่นเดียวกับนักออกแบบภาษาที่ใช้งานได้พิจารณาการมอบหมาย“ ปล่อย” เพื่อให้เกิดข้อผิดพลาดน้อยลง ฉันสงสัยว่าทุกคนได้พิสูจน์สมมติฐานนี้โดยใช้การศึกษา
Frank Hileman

คำตอบ:


15

ฉันไม่เห็นด้วยและถือว่าพารามิเตอร์ไม่มีอะไรมากไปกว่าตัวแปรท้องถิ่นที่เริ่มต้นด้วยไวยากรณ์ของการเรียกวิธีการ

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

  1. มันทำให้รหัสง่ายขึ้น "รันในหัวของฉัน"
  2. มันช่วยให้ชื่อที่อธิบายเพิ่มเติมสำหรับตัวแปร

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

ต้องเผชิญกับวิธีเดียวกันนี้คราวนี้มีตัวแปรน้อยลง แต่ที่เปลี่ยนค่าตลอดเวลาตอนนี้ฉันต้องจำสถานะปัจจุบันของตัวแปรเหล่านั้นเช่นเดียวกับการทำงานในสิ่งที่รหัสทำ

จากประสบการณ์ของฉันอดีตนั้นง่ายกว่าสมองที่ไม่ดีของฉัน อื่น ๆ ชาวบ้านที่ฉลาดกว่าฉันอาจไม่มีปัญหานี้ แต่มันก็ช่วยฉันได้

สำหรับจุดอื่น ๆ :

double Foo(double r)
{
    r = r * r;
    r = Math.Pi * r;
    return r;
}

กับ

double Foo(int r)
{
    var rSquared = r * r;
    var area = Math.Pi * rSquared;
    return area;
} 

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


"ตัวแปรโลคัล ... ควรถือว่าไม่เปลี่ยนรูปโดยค่าเริ่มต้น" - อะไร?
whatsisname

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

@RobertHarvey for (const auto thing : things)มีไว้สำหรับลูปและตัวแปรที่แนะนำคือ (ภายในเครื่อง) ไม่เปลี่ยนรูป for i, thing in enumerate(things):ยังไม่ได้กลายพันธุ์ท้องถิ่นใด ๆ
Caleth

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

3
ว้าวการอ่านความคิดเห็นเหล่านี้ฉันเห็นได้ว่ามีผู้คนมากมายที่นี่ไม่เคยศึกษากระบวนทัศน์การทำงาน
โจชัวโจนส์

4

นี่เป็นความขัดแย้งทางศาสนาที่ไม่สามารถแก้ไขได้หรือมีเหตุผลทางวิศวกรรมซอฟต์แวร์ที่ดีทั้งในทิศทางใดทิศทางหนึ่งหรือไม่?

นั่นเป็นสิ่งหนึ่งที่ฉันชอบเกี่ยวกับ (เขียนได้ดี) C ++: คุณสามารถเห็นสิ่งที่คาดหวัง const string& x1คือการอ้างอิงคงที่string x2เป็นสำเนาและconst string x3เป็นสำเนาคงที่ ฉันรู้ว่าจะเกิดอะไรขึ้นในฟังก์ชั่น x2 จะมีการเปลี่ยนแปลงเพราะถ้ามันไม่ได้จะไม่มีเหตุผลที่จะทำให้มันไม่ใช่ const

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

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


อีกสิ่งที่ดีคือint f(const T x)และint f(T x)แตกต่างกันในฟังก์ชั่นของร่างกาย
Deduplicator

3
ฟังก์ชั่น C ++ ที่มีพารามิเตอร์เช่นconst int xเดียวกับการทำให้ x ชัดเจนไม่มีการเปลี่ยนแปลงภายใน? ดูเหมือนจะเป็นสไตล์ที่แปลกมากสำหรับฉัน
Doc Brown

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

@nvoigt: หากมีคนต้องการแก้ไขพารามิเตอร์ฟังก์ชั่น ("โดยค่า") เขาก็จะตัดconstออกจากรายการพารามิเตอร์ถ้ามันเป็นอุปสรรคต่อเขา ดังนั้นฉันไม่คิดว่านี่จะตอบคำถามได้
Doc Brown

@DocBrown แล้วมันจะไม่ const อีกต่อไป มันไม่สำคัญว่าจะเป็นกลุ่มหรือไม่สิ่งสำคัญคือภาษานั้นมีวิธีสื่อสารกับนักพัฒนาโดยไม่ต้องสงสัย คำตอบของฉันคือมันไม่สำคัญตราบใดที่คุณสื่อสารอย่างชัดเจนซึ่ง C ++ ทำให้ง่ายผู้อื่นอาจไม่ต้องการและคุณต้องการการประชุม
nvoigt

1

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

ถือเป็นโมฆะเผยแพร่ (วัตถุ OBJECT *, double t0, double dt) {
  double t = t0; / * โลคัลสำเนาของ t0 เพื่อหลีกเลี่ยงการเปลี่ยนค่า * /
  ในขณะที่ (อะไรก็ตาม) {
    timestep_the_object ( ... );
    t + = dt; }
  กลับ; }

ดังนั้นที่นี่เพียงเพราะชื่ออาร์กิวเมนต์t0ฉันอาจเลือกที่จะไม่เปลี่ยนค่า แต่สมมติว่าเราเปลี่ยนชื่ออาร์กิวเมนต์เป็นtNowหรืออะไรทำนองนั้น ถ้าอย่างนั้นฉันก็จะลืมสำเนาในเครื่องและเขียนtNow + = dt; สำหรับคำสั่งสุดท้ายนั้น

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

คำตอบสำหรับคำถามสไตล์เหล่านี้เกิดขึ้นจากประสบการณ์และไม่ค่อยมีคำตอบทางศาสนาที่เป็นที่ยอมรับ ใครก็ตามที่คิดว่ามีคำตอบแบบหนึ่งเดียวเท่านั้น (และเขารู้ดี :) อาจต้องการประสบการณ์มากกว่านี้

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