กิจกรรมใช้สำหรับการเขียนโปรแกรม GUI เท่านั้นหรือไม่


57

กิจกรรมใช้สำหรับการเขียนโปรแกรม GUI เท่านั้นหรือไม่

คุณจัดการกับการเขียนโปรแกรมแบ็กเอนด์ปกติอย่างไรเมื่อมีบางอย่างเกิดขึ้นกับสิ่งอื่นนี้


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

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

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

Nope! ตัวอย่างการปฏิบัติ: เหตุการณ์
Nodejs

2
คุณอยู่บน Windows หรือไม่ ตรวจสอบตัวแสดงเหตุการณ์ มีความสุข.
Marc.2377

คำตอบ:


106

Nope มันมีประโยชน์จริง ๆ สำหรับการใช้ Observers และตรวจสอบให้แน่ใจว่าคลาสนั้นใกล้เคียงกับการดัดแปลง

สมมติว่าเรามีวิธีการที่ลงทะเบียนผู้ใช้ใหม่

public void Register(user) {
    db.Save(user);
}

จากนั้นมีคนตัดสินใจว่าควรส่งอีเมล เราสามารถทำสิ่งนี้:

public void Register(user) {
    db.Save(user);
    emailClient.Send(new RegistrationEmail(user));
}

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

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

public void Register(user) {
    db.Save(user);

    RaiseUserRegisteredEvent(user);
}

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


37
ฉันอ่านสิ่งนี้และคิดถึงรหัส "สร้างการจอง" ของเราและฉันร้องไห้ไปพักหนึ่งและนานเพื่อที่ที่ดีกว่า: '(
sara

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

14
@Hamsteriffic ฉันเป็น C # dev ส่วนใหญ่และเป็นแบบแผนที่ยอมรับกันโดยทั่วไป ไม่มีเหตุผลอื่น
RubberDuck

6
@Hamstercifficas นอกจากนี้สิ่งที่คุณเรียก lowerCase แต่มีตัวพิมพ์ใหญ่ตรงกลางมักจะเรียกว่า camelCase เพราะมันมี humps อยู่ตรงกลาง ซึ่งแตกต่างจาก snake_case ซึ่งคำตัวพิมพ์เล็กคั่นด้วยเครื่องหมายขีดล่างซึ่งคุ้นเคยกับภาษาไพ ธ อนและภาษาเชลล์ส่วนใหญ่เพื่อตั้งชื่อให้สองสามคำ
แอรอน

5
เหตุการณ์เป็นข้อความประเภทหนึ่งฉันอยากจะบอกว่า การเรียกใช้เมธอดควรถูกพิจารณาว่าเป็นการส่งผ่านข้อความเช่นกัน
jpmc26

53

Nope

ตัวอย่างคลาสสิกของเหตุการณ์ที่ใช้ในตรรกะที่ไม่ใช่ GUI เป็นทริกเกอร์ฐานข้อมูล

ทริกเกอร์คือรหัสที่ถูกเรียกใช้งานเมื่อมีเหตุการณ์เกิดขึ้น (INSERT, DELETE, ฯลฯ ) ดูเหมือนว่าเหตุการณ์สำหรับฉัน

นี่คือนิยามของวิกิพีเดียของเหตุการณ์:

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

ไม่ใช่ทุกเหตุการณ์ที่ผู้ใช้สร้างขึ้น บางอย่างถูกสร้างขึ้นโดยตัวจับเวลาเช่นเดียวกับ crontab ของฐานข้อมูล INSERT อย่างที่ฉันพูดถึงก่อนหน้านี้

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


2
ฉันมักจะคิดถึงสิ่งนี้เมื่อฉันได้ยินเกี่ยวกับทริกเกอร์ของฐานข้อมูล: thecodelesscode.com/case/42
Almo

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

28

การเขียนโปรแกรมตามเหตุการณ์นั้นใช้สำหรับการเขียนโปรแกรมเซิร์ฟเวอร์ที่มีประสิทธิภาพสูง

ที่ปริมาณงานเซิร์ฟเวอร์ทั่วไปเวลาส่วนใหญ่ในการประมวลผลผลลัพธ์มาจาก I / O ตัวอย่างเช่นการดึงข้อมูลออกจากฮาร์ดดิสก์ไดรฟ์ (7200 RPM) อาจใช้เวลานานถึง 8.3 ms สำหรับโปรเซสเซอร์ GHz ที่ทันสมัยซึ่งจะเท่ากับ ~ 1 ล้านรอบนาฬิกา หาก CPU ต้องรอข้อมูลในแต่ละครั้ง (ไม่ทำอะไรเลย) เราจะสูญเสียวงจรนาฬิกาจำนวนมาก

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

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

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

ตัวอย่างที่ดีที่สุดของเซิร์ฟเวอร์ดังกล่าวคือNode.jsซึ่งแสดงให้เห็นว่าสามารถจัดการการเชื่อมต่อพร้อมกัน 1 ล้านกับฮาร์ดแวร์ที่ใช้งานง่ายในขณะที่เซิร์ฟเวอร์Java / Tomcatจะต่อสู้กับคนไม่กี่พันคน


2
"ฮาร์ดแวร์ที่เรียบง่าย" เป็นสิ่งที่ทำให้เข้าใจผิดเล็กน้อย คุณจะต้องมี 8GB + สำหรับ Node นอกเหนือจากสิ่งที่ระบบปฏิบัติการใช้ และถ้าคุณมีหน่วยความจำมากพอสมควร Tomcat สามารถรองรับการเชื่อมต่อได้สองสามพัน ได้รับมีความแตกต่างใหญ่ แต่ไม่ใช่ 1,000x
พอลเดรเปอร์

@ PaulDraper ไม่สามารถทำได้ และไม่มีมันไม่ได้ คุณต้องการ 8GB + เพียงแค่สแต็คสำหรับ 8000 เธรด นั่นคือความแตกต่างที่ยิ่งใหญ่
ArTs

3
@ PaulDraper นอกเหนือจาก 8GB นั้นมีความสุภาพตามมาตรฐานเซิร์ฟเวอร์ ฉันทำงานกับเครื่องที่มี RAM ขนาด 128GB และยังไม่โหลดเต็มที่ ram sticks มีราคาสูงกว่าเครื่องจักรทั้งหมดของคุณ
ArTs

ขึ้นอยู่กับขนาดสแต็กของคุณ Oracle / OpenJDK มีค่าเริ่มต้นเป็น 1MB สำหรับแพลตฟอร์มส่วนใหญ่สำหรับ 64- บิตและ 512K สำหรับ 32- บิต หากคุณเพิ่งเริ่มต้นคุณจะถูกต้อง แต่ค่าเริ่มต้นไม่ใช่วิธีที่คุณจะได้รับการเชื่อมต่อ 1M Node;) อย่างไรก็ตาม 128K นั้นมีมากมาย คุณสามารถหนีไปได้แม้แต่น้อย นั่นคือพื้นที่สแต็ค 1GB สำหรับ 8000 เธรด
พอลเดรเปอร์

6
คุณเข้าใจผิด แม้จะมีขนาดสแต็กเริ่มต้นคุณก็ต้องการหน่วยความจำเสมือน 8 GiB เท่านั้น หน่วยความจำมีความมุ่งมั่นในการบินได้ตามต้องการ โดยปกติแล้วคุณต้องการเพียงหน้าเดียวต่อสแต็คเว้นแต่ว่าคุณจะใช้หน่วยความจำเพิ่มเติม และในทางปฏิบัติเธรดส่วนใหญ่ในระบบดังกล่าวจะมีสแต็ค 64 บิต (kiB) เหล่านั้นเท่านั้น การใช้หน่วยความจำเสมือนเป็นเรื่องใหญ่ในระบบปฏิบัติการ 32 บิต แต่ไม่มากใน 64- บิต คุณพบข้อ จำกัด อื่น ๆ เร็วกว่าเช่นพอร์ต TCP หมดตัวอย่างเช่นคุณคิดว่า "pseudo-stack" ของโหนดถูกเก็บไว้ที่ไหน? ถูกต้องแล้วบนกอง
Luaan

10

เหตุการณ์ยังถูกใช้อย่างมากในการเขียนโปรแกรมเครือข่าย (เช่น Nginx) เพื่อหลีกเลี่ยงการวนลูปที่ยุ่งและมีค่าใช้จ่ายสูงและให้อินเทอร์เฟซใหม่ที่จะรู้ว่าเมื่อการดำเนินการบางอย่างพร้อมใช้งาน (I / O ข้อมูลเร่งด่วน ฯลฯ ) และนี่ก็เป็นวิธีการแก้ที่ปัญหา C10k

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

ตอนนี้เป็นมุมมองในระดับต่ำและเป็นนามธรรม อย่างไรก็ตามมีกรอบระดับสูงกว่ามากมายที่จัดการกับสิ่งนั้นในรูปแบบข้ามแพลตฟอร์ม: Twisted for Python, Boost.Asio สำหรับ C ++ หรือ libevent for C เข้ามาในใจของฉัน


+1 "ลูปที่ยุ่งรอแพง": ในคำอื่น ๆ มันมีประโยชน์ในกระบวนการแบบขนานใด ๆ ที่เกี่ยวข้องกับการไม่ใช้งาน (รอ) รวมทั้งการซิงค์ระหว่างกระบวนการดังกล่าว (ข้อความหรือเหตุการณ์) โลกแห่งความจริงทำงานได้มาก
fr13d

เป็นที่น่าสนใจที่จะพบว่าซ็อกเก็ตได้รับการออกแบบมาเป็นรูปแบบของ IPC ในเครื่องเดียวก่อนที่จะมีเครือข่าย

5

ระบบฝังตัวมักขับเคลื่อนเหตุการณ์โดยเนื้อแท้แม้ว่าจะไม่ได้โปรแกรมอย่างชัดเจน

เหตุการณ์เหล่านี้มาจากสิ่งต่าง ๆ เช่นการขัดจังหวะฮาร์ดแวร์การกดปุ่มการอ่านแบบอะนาล็อกเป็นดิจิตอลการหมดเวลาของตัวจับเวลา ฯลฯ

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

หนึ่งในกรอบทั่วไปที่ได้รับความนิยมมากที่สุดสำหรับระบบฝังตัวที่ขับเคลื่อนด้วยเหตุการณ์คือQuantum Platform (QP) (QP ยังทำงานภายใต้ Linux, Windows และระบบปฏิบัติการยูนิกซ์ใด ๆ ที่คล้ายกัน) เครื่องจักรของรัฐนั้นเหมาะอย่างยิ่งสำหรับการเขียนโปรแกรมเชิงเหตุการณ์ เนื่องจากโปรแกรมไม่ได้ "เรียงตามลำดับ" ในความหมายทั่วไป แต่เป็นชุดของ "การเรียกกลับ" ที่ถูกเรียกขึ้นอยู่กับสถานะของระบบและเหตุการณ์ปัจจุบัน


3

ข้อความเหตุการณ์ Gregor Hohpe

สถาปัตยกรรมที่ขับเคลื่อนด้วยเหตุการณ์ Gregor Hohpe

สถาปัตยกรรม SEDA , เวลส์, Culler, Brewer

คุณจัดการกับการเขียนโปรแกรมแบ็คเอนด์ปกติอย่างไรเมื่อมีบางอย่างเกิดขึ้นทำสิ่งอื่นนี้

เครื่องจักรสถานะ จำกัดเป็นวิธีการหนึ่งที่ใช้กันทั่วไป

Given(State.A)
When(Event.B)
Then(State.C)
    .and(Consequences.D)

2
1 นี่ไม่ใช่คำตอบที่สอดคล้องกันและ 2, FSM ไม่ใช่ตัวอย่างที่ดีของการใช้เหตุการณ์
whatsisname

1
เอฟเอส ฉันแน่ใจว่าศาสนา pastafarian สังเกตเหตุการณ์ต่าง ๆ ;-)
fr13d

0

ในระบบฝังตัวเหตุการณ์เกิดขึ้นระหว่างการขัดจังหวะ มีแหล่งขัดจังหวะมากมายตั้งแต่ตัวนับถึง I / O

นอกจากนี้ RTOS ก็สามารถมีกิจกรรมได้เช่นกัน ตัวอย่างหนึ่งกำลังรอข้อความจากงานอื่น


0

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

https://en.wikipedia.org/wiki/SCADA

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