“ ผลข้างเคียงคืออะไร”


87

ฉันไม่เข้าใจแนวคิดของผลข้างเคียงอย่างชัดเจน

  • ผลข้างเคียงในการเขียนโปรแกรมคืออะไร?
  • มันขึ้นอยู่กับการเขียนโปรแกรมภาษา
  • มีผลข้างเคียงภายนอกและภายในไหม?

โปรดยกตัวอย่างสาเหตุที่สร้างผลข้างเคียง


7
ฟังดูเหมือนการบ้าน
gnasher729

3
@ gnasher729 ที่ใส่ใจนี้จะเป็นประโยชน์อย่างมาก :)
ชาร์ลีปาร์กเกอร์

คำตอบ:


108

ผลข้างเคียงจะหมายเพียงเพื่อการปรับเปลี่ยนบางชนิดของรัฐ - เช่น:

  • การเปลี่ยนค่าของตัวแปร
  • การเขียนข้อมูลลงดิสก์
  • การเปิดใช้งานหรือปิดการใช้งานปุ่มในส่วนต่อประสานผู้ใช้

ตรงกันข้ามกับสิ่งที่บางคนพูดว่า:

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

  • ผลข้างเคียงที่มีอะไรจะทำอย่างไรกับ Idempotency ฟังก์ชั่น idempotent สามารถมีผลข้างเคียงและฟังก์ชั่นที่ไม่ใช่ idempotent อาจไม่มีผลข้างเคียง (เช่นการรับวันที่และเวลาของระบบปัจจุบัน)

มันง่ายมากจริงๆ ผลข้างเคียง = การเปลี่ยนแปลงบางสิ่งบางอย่าง

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


38
วลีที่ว่า "ผลข้างเคียง" ทำให้เสียงเหมือนบางสิ่งบางอย่างอื่นจะถูกเปลี่ยนแปลงอื่น ๆ นอกเหนือจากสิ่งที่ตั้งใจ ในทางการแพทย์ยาเสพติดจะมีผลกระทบหลักของการลดความเจ็บปวดและบางครั้งผลข้างเคียงของการทำให้เลือดออกจมูกเวียนศีรษะ ฯลฯ ... วัตถุประสงค์ของยาเสพติดที่จะไม่ทำให้เกิดเลือดออกจมูก แต่บางครั้งที่เกิดขึ้นเป็น ที่ไม่ได้ตั้งใจเป็นพิเศษผล
FrustratedWithFormsDesigner

15
@Frustrated: +1 เมื่อใดก็ตามที่ฉันเห็นคำว่าฉันไม่สามารถช่วย แต่สงสัยว่ามันไม่ได้ถูกเลือกโดย FP สนับสนุนเพื่อสร้างความหมายแฝงที่น่ากลัวอย่างละเอียด
Mason Wheeler

6
@Mason Wheeler มันมีอยู่นานก่อนที่จะ FP และไม่ใช่ความหมายแฝงที่น่ากลัวอย่างละเอียด มันเป็นความชั่วที่แบนราบและเป็นเช่นนี้มาตลอด สำหรับ 3 ทศวรรษที่ฉันได้รับการเขียนคำสั่ง "การเข้ารหัสลับ" - ผลข้างเคียง - ทำให้ผู้คนหนักใจ คำแถลงการมอบหมายเก่าแบบธรรมดานั้นง่ายต่อการจัดการ
S.Lott

7
@Mason ล้อ: ++aในซี ดูไม่เหมือนงานที่มอบหมาย b = ++a;มีผลข้างเคียงที่สอง aที่เห็นได้ชัดหนึ่งและการเข้ารหัสลับการโอน นั่นคือสิ่งที่เป็นผลข้างเคียงที่ต้องการ (สำหรับบางคน) แต่ได้รับการขนานนามว่าเป็นผลข้างเคียงสำหรับอาชีพการงานทั้งหมดของฉันเพื่อทำให้มันไม่ลึกซึ้ง
S.Lott

5
@ Zachary โปรดดูหัวข้อย่อยสุดท้ายในคำตอบของฉัน สิ่งที่คุณอ้างถึงคือพฤติกรรม idempotent (หรือสิ่งที่ขาดหายไป) ที่ไม่ได้บอกอะไรคุณเกี่ยวกับผลข้างเคียง การตรวจสอบนาฬิการะบบไม่ได้เป็นผลข้างเคียง ในความเป็นจริงฟังก์ชั่นหรือวิธีการใด ๆ ที่นำหน้าด้วยคำว่า "รับ" เป็นสิ่งที่คุณควรคาดหวังว่าจะไม่มีผลข้างเคียงใด ๆ
Aaronaught

36

การดำเนินการใด ๆ ที่แก้ไขสถานะของคอมพิวเตอร์หรือการโต้ตอบกับโลกภายนอกมีการกล่าวถึงผลข้างเคียง วิกิพีเดียดูผลข้างเคียง

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

int square(int x) { return x * x; }

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

int n = 0;
int next_n() { return n++; }
void set_n(int newN) { n = newN; }      

ฟังก์ชั่นนี้มีผลข้างเคียงของการเขียนข้อมูลไปยังเอาต์พุต คุณไม่เรียกใช้ฟังก์ชันเนื่องจากคุณต้องการส่งคืนค่า คุณเรียกมันว่าเพราะคุณต้องการผลที่มันมีต่อ "โลกภายนอก":

int Write(const char* s) { return printf("Output: %s\n", s); }

1
นี่เป็นคำนิยามที่ดี แต่ฉันไม่ได้คลั่งไคล้กับการทำอย่างละเอียดเหมือนในคำตอบของThorbjørnส่วนหนึ่งของมันดูเหมือนว่าจะทำให้เกิดปัญหาผลข้างเคียงกับการทำงานของ idempotent; ตามWriteตัวอย่างของคุณแสดงให้เห็นว่าการมีผลข้างเคียงไม่ได้หมายความว่าฟังก์ชั่นจะเปลี่ยนผลลัพธ์เมื่อเทียบกับอินพุตหรือแม้แต่เอาต์พุตนั้นขึ้นอยู่กับอินพุตเลย
Aaronaught

6
มันไม่เกี่ยวกับการเป็น idempotent ความจริงที่ว่ามันสร้างผลลัพธ์หมายความว่ามันมีผลข้างเคียง
Kristopher Johnson

ในบางระบบการเรียกใช้square(x)อาจทำให้โมดูลที่ฟังก์ชันถูกกำหนดให้โหลดจากดิสก์ ควรคำนึงถึงผลข้างเคียงหรือไม่ ท้ายที่สุดบุรุษคนนี้ที่การโทร (ครั้งแรก) ใช้เวลานานโดยไม่คาดคิดการใช้งาน RAM ก็สูงขึ้น ฯลฯ
Hagen von Eitzen

1
@HagenvonEitzen ทุกการดำเนินการทำให้เกิดการเปลี่ยนแปลงสถานะของคอมพิวเตอร์ (ลงทะเบียน CPU, หน่วยความจำ, การใช้พลังงาน, ความร้อน, ฯลฯ ) "ผลข้างเคียง" มักจะหมายถึงสภาพแวดล้อมการดำเนินการในอุดมคติของจินตภาพซึ่งไม่มีอะไรเกี่ยวกับสภาพแวดล้อมนั้นเปลี่ยนแปลงเว้นแต่ว่าโปรแกรมจะเปลี่ยนแปลงอย่างชัดเจน แต่ถ้าคุณกำลังโทรsquare(x) เพราะคุณต้องการให้สถานะคอมพิวเตอร์ภายนอกเปลี่ยนแปลงคุณอาจพิจารณาว่าเป็นผลข้างเคียง
Kristopher Johnson

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

20

ฉันคิดว่าคำตอบที่มีอยู่ค่อนข้างดี ฉันต้องการอธิบายรายละเอียดในบางประเด็นที่ IMO ยังไม่ได้รับการเน้นย้ำมากพอ

ในวิชาคณิตศาสตร์ฟังก์ชั่นเป็นเพียงการทำแผนที่จาก tuple ของค่าไปยังค่า ดังนั้นให้ฟังก์ชั่นfและค่าx, มักจะเป็นผลเดียวกันf(x) yคุณอาจแทนที่f(x)ด้วยyทุกที่ในการแสดงออกและไม่มีอะไรจะเปลี่ยนแปลง

สิ่งที่เรียกว่าฟังก์ชั่น (หรือโพรซีเดอร์) ในภาษาการเขียนโปรแกรมจำนวนมากคือโครงสร้าง (ส่วนของโค้ด) ที่สามารถดำเนินการได้เพราะ:

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

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

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

สังเกตได้ว่า

  1. ขั้นตอนบางอย่างมีประโยชน์สำหรับทั้งค่าส่งคืนและผลข้างเคียง
  2. บางขั้นตอนคำนวณค่าผลลัพธ์และไม่มีผลกระทบอื่น พวกเขามักจะเรียกว่าฟังก์ชั่นที่บริสุทธิ์เพราะสิ่งที่พวกเขาทำคือการคำนวณฟังก์ชั่นในความรู้สึกทางคณิตศาสตร์
  3. บางขั้นตอนเช่นsleep()ใน Python มีประโยชน์สำหรับเอฟเฟกต์ (ด้าน) เท่านั้น สิ่งเหล่านี้มักถูกจำลองเป็นฟังก์ชันที่ส่งคืนค่าพิเศษNoneหรือunitหรือ()หรือ ... ซึ่งเพียงระบุว่าการคำนวณสิ้นสุดลงอย่างถูกต้อง

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

4

ผลข้างเคียงคือเมื่อการดำเนินการมีผลกับตัวแปร / วัตถุที่อยู่นอกการใช้งานที่ต้องการ

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

ฉันยอมรับว่าฉันมีปัญหาในการหาตัวอย่างง่ายๆที่ไม่ได้ดูอย่างสมบูรณ์แบบและตัวอย่างจากสิ่งที่ฉันได้ทำมานานเกินกว่าที่จะโพสต์ที่นี่ได้ (และเนื่องจากมันเกี่ยวข้องกับการทำงาน )

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


ตกลงดังนั้นเมื่อทุกคนให้ตัวอย่างตอนนี้ฉันคิดว่าฉันก็จะเหมือนกัน;)

/*code is PL/SQL-styled pseudo-code because that's what's on my mind right now*/

g_some_global int := 0; --define a globally accessible variable somewhere.

function do_task_x(in_a in number) is
begin
    b := calculate_magic(in_a);
    if b mod 2 == 0 then
        g_some_global := g_some_global + b;
    end if;
    return (b * 2.3);
end;

ฟังก์ชันdo_task_xมีผลกระทบหลักของการคืนผลลัพธ์ของการคำนวณบางอย่างและผลข้างเคียงของการปรับเปลี่ยนตัวแปรกลาง

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


2
ฉันไม่คิดว่านี่เป็นคำนิยามสากลที่ดี โปรแกรมเมอร์หลายคนตั้งใจใช้โครงสร้างเฉพาะสำหรับผลข้างเคียงของพวกเขา
CB Bailey

@Charles: ยุติธรรมเพียงพอ ในกรณีนั้นคุณจะกำหนดอย่างไร
FrustratedWithFormsDesigner

2
ฉันคิดว่า @KristopherJohnson มีคำจำกัดความที่ชัดเจนที่สุด สิ่งใดก็ตามที่เปลี่ยนแปลงสถานะของโปรแกรมหรือสภาพแวดล้อมหรือสร้างผลกระทบในโลกแห่งความเป็นจริงเช่นการสร้างผลผลิต
CB Bailey

@Charles Bailey: นั่นไม่ได้เปลี่ยนความหมาย ใช้สิ่งต่าง ๆ สำหรับผลข้างเคียงได้ดี ตราบใดที่คุณเข้าใจว่ามีผลข้างเคียง ไม่ได้เปลี่ยนแปลงอะไรเกี่ยวกับคำจำกัดความนี้
S.Lott

1
@SLott: คำจำกัดความในคำตอบนี้ (เช่นย่อหน้าแรก) รวมถึงข้อ: "นอกการใช้งานที่ตั้งใจ" ฉันคิดว่าความคิดเห็นของฉันยุติธรรม
CB Bailey

3

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

จากWikipedia - ผลข้างเคียง

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

ในระยะทั่วไปมากขึ้น, ผลข้างเคียงคือผลกระทบใด ๆ ที่ไม่ได้เป็นผลกระทบที่ตั้งใจของนักออกแบบของการก่อสร้าง

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

   public void SendBreakupTextMessage() {
        Messaging.send("I'm breaking up with you!")
   }

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

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

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

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

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

เหตุใดจึงสำคัญทั้งหมดนี้

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

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

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

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

ในที่สุด idempotent หมายถึงการเรียกใช้ฟังก์ชั่นนี้หลายครั้งด้วยอินพุตเดียวกัน (ไม่สำคัญว่ามาจากไหน) จะส่งผลเหมือนกันเสมอ (ผลข้างเคียงหรือไม่)


ฉันคิดว่าปัญหาใหญ่กับการอธิบายผลข้างเคียงคือจนกว่าคุณจะใช้ภาษาอย่าง Ocaml หรือ Haskell มันอาจยากที่จะให้เหตุผลเกี่ยวกับการเขียนโปรแกรมฟรี (เกือบ!) ผลข้างเคียง
Jamie Strauss

2

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

เท่าที่ฉันรู้ไม่มีผลข้างเคียงภายในและภายนอก


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

ฉันคิดว่าภาษาการเขียนโปรแกรม pre-gui บางอย่างเช่น MS-BASIC และ QBasic อาจใกล้เคียงกับภาษา 'ผลข้างเคียงเท่านั้น' ที่คุณจะได้รับ และใช่คุณสามารถมีผลข้างเคียงทั้งภายในและภายนอก
James K

0

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

int _totalWrites;
void Write(string message)
{
    // Invoking this function has the side effect of 
    // incrementing the value of _totalWrites.
    _totalWrites++;
    Debug.Write(message);
}

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


แต่ถ้าข้อความเข้ามาเป็นข้อมูลอ้างอิงและคุณเปลี่ยนข้อความในวิธีการของคุณที่อาจมีผลข้างเคียง ฉันถูกไหม?
Amir Rezaei

ความจริงที่ว่านิพจน์x++แก้ไขตัวแปรxนั้นโดยทั่วไปถือว่าเป็นผลข้างเคียง ค่าของนิพจน์นั่นคือค่าก่อนเพิ่มขึ้นx; นี่เป็นส่วนที่ไม่ใช่ผลข้างเคียงของการแสดงออก
CB Bailey

@Charles - ฉันเห็นด้วยแม้ว่าตัวอย่างดั้งเดิมจะไม่ชัดเจนเหมือนตัวอย่างในปัจจุบัน
ChaosPandion

@Amir - ดีขึ้นอยู่กับภาษา หากนี่คือ C # สิ่งนี้จะไม่ถือว่าเป็นผลข้างเคียง
ChaosPandion

@ChaosPandion: โดยส่วนตัวแล้วฉันไม่เห็นด้วย ตัวอย่างดั้งเดิมนั้นง่ายกว่าและชัดเจนกว่ามาก
CB Bailey

-2

ผลข้างเคียงคือสิ่งที่เกิดขึ้นในรหัสที่ไม่ชัดเจน

ตัวอย่างเช่นสมมติว่าคุณมีคลาสนี้

public class ContrivedRandomGenerator {
   public int Seed { get; set; }

   public int GetRandomValue()
   {
      Random(Seed);
      Seed++;
   }
}

เมื่อคุณสร้างชั้นเรียนคุณจะให้เมล็ด

var randomGenerator = new ContrivedRandomGenerator();
randomGenerator.Seed = 15;
randomGenerator.GetRandomValue();

คุณไม่ทราบว่าภายในคุณแค่คาดหวังว่าจะได้รับค่าสุ่มและคุณคาดหวังว่า randomGenerator.Seed จะยังคงเป็น 15 ... แต่ก็ไม่ได้

การเรียกใช้ฟังก์ชันมีผลข้างเคียงของการเปลี่ยนแปลงค่า Seed


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

1
การพิมพ์ไปยังคอนโซลเป็นผลข้างเคียง มันไม่ได้ซ่อน จากวิกิพีเดีย : "ในวิทยาการคอมพิวเตอร์ฟังก์ชั่นหรือการแสดงออกว่ามีผลข้างเคียงถ้านอกเหนือจากการคืนค่ามันก็ปรับเปลี่ยนบางรัฐหรือมีปฏิสัมพันธ์ที่สังเกตเห็นได้กับฟังก์ชั่นการโทรหรือโลกภายนอก "

ผลข้างเคียงคือฟังก์ชั่นที่ไม่ทำงาน (เช่นโพรซีเดอร์) ทำงานได้อย่างไร X = 1; X = Y (10) เป็นฟังก์ชันบริสุทธิ์สองฟังก์ชัน เมื่อคุณก้าวออกจากอาณาจักร "x = อะไรก็ตาม" ไม่ว่าจะเขียนผลลัพธ์ไปยังหน้าจอ | ไดรฟ์ | เครื่องพิมพ์ | นำหรืออ่านอินพุตนอกรูปแบบ "x = y" หรือเพียงแค่เปลี่ยนค่าของตัวแปรจากสิ่งหนึ่งไปยังอีก มันเป็นผลข้างเคียง
James K

ฉันคิดว่าโดย 'ซ่อน' เขาหมายถึงไม่ชัดเจน เช่นเดียวกับใน x = f (y, z) x สามารถสันนิษฐานได้ว่าขึ้นอยู่กับ y และ z ในขณะที่ proc (x, y, z) ไม่ได้บอกอะไรคุณเกี่ยวกับสิ่งที่เกิดขึ้น ทุกตัวแปรสามารถเปลี่ยนแปลงได้หรือไม่มีเลย Proc อาจเป็นแบบอะนาล็อกถึง f หรือไม่เกี่ยวข้องอย่างสมบูรณ์ ฟังก์ชั่นที่บริสุทธิ์มีคำตอบเดียว: 'x' ยิ่งไปกว่านั้นมันเป็นผลข้างเคียง ตั้งใจทั้งหมด แต่ผลข้างเคียง
James K

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