รูปแบบการออกแบบ“ แก้ไขทุกอย่าง” คืออะไร?


74

ในปี 2003 บทความนี้โดย Stephen Figgins บน linuxdevcenter.com BitTorrent ของ Bram Cohen ถูกอธิบายว่าใช้รูปแบบการออกแบบ "แก้ไขทุกอย่าง"

วิธีการทั่วไปที่น้อยกว่าซึ่งทั้งสองทำให้ BitTorrent ยากที่จะเข้าใจ แต่ควรค่าแก่การศึกษาคือการใช้ idempotence ของโคเฮน กระบวนการเป็น idempotent เมื่อใช้มากกว่าหนึ่งครั้งทำให้ไม่มีการเปลี่ยนแปลงเพิ่มเติม Cohen กล่าวว่าเขาใช้รูปแบบการออกแบบที่เรียกว่า "แก้ไขทุกอย่าง" ซึ่งเป็นฟังก์ชั่นที่สามารถตอบสนองต่อการเปลี่ยนแปลงจำนวนมากโดยไม่ได้สังเกตสิ่งที่มันอาจเปลี่ยนแปลง เขาอธิบายว่า“ คุณสังเกตเห็นเหตุการณ์ที่เกิดขึ้นจากนั้นเรียกใช้ฟังก์ชันแก้ไขทุกอย่างที่เขียนในลักษณะที่ไม่คุ้นเคยนี้และทำความสะอาดทุกสิ่งที่อาจเกิดขึ้นและคำนวณใหม่ทั้งหมดตั้งแต่เริ่มต้น” ในขณะที่ idempotence ทำให้การคำนวณยากขึ้นง่ายขึ้น แต่ก็ทำให้สิ่งต่าง ๆ มีความซับซ้อน ไม่ชัดเจนว่าการโทรกำลังจะเปลี่ยนแปลงหากมีสิ่งใดอยู่เสมอ คุณไม่จำเป็นต้องรู้ล่วงหน้า คุณมีอิสระที่จะเรียกใช้ฟังก์ชั่น

เสียงนี้ค่อนข้างดีบนใบหน้าของมัน

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

ฉันไม่สามารถพูดได้ว่าฉันเคยใช้มาก่อน ฉันยังไม่สามารถหาแหล่งที่มาสำหรับการใช้งานออนไลน์ของเขา ( แต่ฉันไม่พบคนนี้ที่อ้างว่าจะขึ้นอยู่กับมัน.) หรือฉันสามารถหาอ้างอิงถึงมันนอกของบทความนี้ (และผมคิดว่า google-Fu ของฉันจะสวยดี) แต่ฉันไม่พบรายการสำหรับ"idempotent ความสามารถ" ใน SOApatterns.org

ความคิดนี้เป็นที่รู้จักกันดีในชื่ออื่นหรือไม่?

รูปแบบการออกแบบ "แก้ไขทุกอย่าง" คืออะไร? ข้อดีและข้อเสียของมันคืออะไร?


4
ฉันสงสัยว่าชื่อนี้ยังอ้างอิงถึงแนวคิดของจุดคงที่ของฟังก์ชั่น, x = f (x) ไม่ว่าคุณจะใช้fกับxกี่ครั้งผลลัพธ์ก็เหมือนกัน เมื่อคุณบรรลุผลลัพธ์ที่ถูกต้องแล้วการประมวลผลผลลัพธ์ที่ถูกต้องจะส่งกลับผลลัพธ์ที่ถูกต้องเหมือนเดิม
9000

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

1
สิ่งนี้เตือนให้ฉันทราบว่ามีการใช้งานกิจกรรมหลักวนบน Mac OS อย่างไร มันเป็นฟังก์ชั่นเดียวที่ตอบสนองต่อกิจกรรมใด ๆ และโดยทั่วไปมีโครงสร้างเพื่อทดสอบสถานะของการควบคุมทั้งหมดและอัปเดต UI ทั้งหมดตามต้องการ Idempotent แน่นอน
Lucas

3
This sounds quite nice on the face of it. จริงๆ? มันฟังดูน่ากลัวสำหรับฉัน!
Michael

3
@Michael คุณไม่ชอบผู้จัดการแพคเกจ? มันทำงานโดยใช้แนวคิดเดียวกันในระดับที่เล็กกว่า: ทำเครื่องหมายสิ่งที่คุณต้องการให้ระบบดูเหมือนว่ารัน "แก้ไขทุกอย่าง" มันจะติดตั้ง / ลบ / อัปเกรดตามความเหมาะสม แต่มีอะไรที่ต้องทำเมื่อมีการเปลี่ยนแปลง
Izkata

คำตอบ:


100

สมมติว่าคุณมีหน้า HTML ที่ค่อนข้างซับซ้อน - หากคุณเลือกบางสิ่งในหนึ่งดรอปดาวน์การควบคุมอื่นอาจปรากฏขึ้นหรือค่าในการควบคุมที่สามอาจเปลี่ยนไป มีสองวิธีที่คุณสามารถเข้าถึงสิ่งนี้:

  1. เขียนตัวจัดการแยกต่างหากสำหรับตัวควบคุมแต่ละตัวที่ตอบสนองต่อเหตุการณ์บนตัวควบคุมนั้นและปรับปรุงตัวควบคุมอื่น ๆ ตามต้องการ

  2. เขียนตัวจัดการเดียวที่มีลักษณะที่สถานะของการควบคุมทั้งหมดบนหน้าเว็บและเพียงแค่แก้ไขทุกอย่าง

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

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

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

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

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

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


9
สำหรับฉันแล้วดูเหมือนว่า MVC จะเป็นเรื่องปกติของ "แก้ไขทุกอย่าง": เมื่อคุณแก้ไขโมเดลแล้ววาดมุมมองใหม่ตั้งแต่เริ่มต้นมุมมองจะถูกวาดใหม่ทั้งหมดโดยไม่ต้องพยายามทำนายว่าส่วนใดของการกระทำที่อาจส่งผลกระทบ
Matthieu M.

3
สิ่งนี้ฟังดูคล้ายกับหลักการที่อยู่เบื้องหลังระบบเช่น Saltstack, Ansible และ Nix ด้วยคำอธิบายของการกำหนดค่าในทางทฤษฎีคุณสามารถนำระบบที่หลากหลายหลายระบบเข้าสู่สถานะสิ้นสุดเดียวกัน
kojiro

1
@MatthieuM Reactซึ่งค่อนข้างได้รับความนิยมในการพัฒนา frontend นั้นเป็นแบบนั้นยกเว้นมันจะเป็น virtual dom diffing ดังนั้นมันจะอัพเดท Dom จริงด้วยการเปลี่ยนแปลงที่เกิดขึ้นจริงเท่านั้น
Izkata

2
@Izkata ยิ่งกว่า React คำตอบนี้ทำให้ฉันคิดถึง Redux
เควิน

2
มันอาจมีประโยชน์ที่จะชี้ให้เห็นว่า "แก้ไขทุกอย่าง" และ idempotent นั้นแตกต่างกัน: "แก้ไขทุกอย่าง" มักจะเป็น idempotent (แต่ไม่จำเป็นต้องเป็น) และการดำเนินงาน idempotent ไม่จำเป็นต้องแก้ไขทุกอย่างหรือแม้กระทั่งประสิทธิภาพ การลงโทษ - เพียงแค่ให้ผลลัพธ์เดียวกันเมื่อดำเนินการสองครั้ง
Hans-Peter Störr

15

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

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

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

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

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


2
ฉันค่อนข้างแน่ใจว่า Excel ตั้งใจจะคำนวณเฉพาะเซลล์ที่ขึ้นอยู่กับการเปลี่ยนแปลงใหม่อีกครั้งซึ่งเป็นสาเหตุที่มีวิธีที่จะกระตุ้นให้เซลล์ทั้งหมดคำนวณใหม่: superuser.com/questions/448376/ … (ซึ่งฉันคิดว่าน่าจะเป็น "แก้ไขทุกอย่าง" )
แอรอนฮอลล์

@AaronHall ถ้าเป็นเช่นนั้นมันเป็นการใช้งานที่ไม่ดีจริงๆ ฉันดูเป็นประจำกินซีพียู 7% เป็นเวลา 15-30 นาทีเพื่อคำนวณเช่น 60,000 เซลล์ การคำนวณไม่ซับซ้อน ฉันมักจะเขียนโปรแกรม Python ที่สามารถทำทุกอย่างในแผ่นงานในไม่กี่วินาทีรวมถึงการเริ่มต้น Python นี่คือการคาดเดาที่ดีที่สุดของฉันว่าจะใช้เวลานานขนาดไหน อาจเป็นอย่างอื่นที่ฉันคิด นอกจากนี้ยังมีข้อบกพร่องจำนวนมากใน Excel ซึ่งอาจเป็นสาเหตุของคุณลักษณะนั้น
JimmyJames

1
@AaronHall ก็เป็นไปได้ที่ผู้ใช้นั้นปิดการคำนวณอัตโนมัติบนแผ่นงาน ฉันมักจะทำสิ่งนี้ในสมุดงานขนาดใหญ่เพราะฉันไม่มีเวลาว่าง 15 นาทีทุกครั้งที่ฉันเข้ามา
JimmyJames

@ AaronHall ฉันคิดอีกเล็กน้อยและคุณมีจุด สมมติฐานของฉันมีแนวโน้มกว้างเกินไป ฉันปรับปรุงคำตอบให้กับฉันมากขึ้นโดยเน้นที่สิ่งที่ฉันมั่นใจมากขึ้น
จิมมี่เจมส์

2
@JimmyJames: จุดที่ฉันตั้งใจจะทำคือวิธีการที่ดีที่สุดอาจแตกต่างกันมากขึ้นอยู่กับสถานการณ์และ "สามารถแก้ไขทุกสิ่งทุกอย่าง" สามารถแบ่งย่อยเป็น "กระตือรือร้นแก้ไขทุกอย่างในการเปลี่ยนแปลงแต่ละครั้ง" และ "ขี้เกียจแก้ไขทุกอย่างหลังจากการเปลี่ยนแปลงทั้งหมดเสร็จสมบูรณ์ "
supercat

4

ไม่แน่ใจว่าเป็น "รูปแบบการออกแบบ" แต่ฉันจะจัดประเภทของพฤติกรรมดังกล่าวเป็นการกำหนดค่าสถานะสิ้นสุดหรือการกำหนดค่าสถานะที่ต้องการในเส้นเลือดของ Puppet, Chef หรือ Powershell DSC

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


1

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

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


0

เสียงเหมือนหลักการเขียนโปรแกรมปฏิกิริยา "แก้ไขทุกอย่าง" ดูที่สถานะ "คอร์" ปัจจุบันและเผยแพร่ทุกอย่างที่ควรได้รับผลกระทบ - "สถานะที่คำนวณ" หากคุณเพิ่มประสิทธิภาพการสืบทอดนี้อาจมีประสิทธิภาพสูง a-la React หากการปฏิบัติที่ไร้เดียงสาอาจไม่ดีที่สุดแม้ว่าจะยังเร็วพอก็ตาม

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