События используются только для программирования GUI?

57

События используются только для программирования GUI?

Как вы справляетесь в обычном бэкэнд-программировании, когда что-то происходит с этим другим?

user3093620
источник
6
Кстати, Event Source - это совершенно ортогональная концепция для Event-Programming. Основная концепция Event Sourcing заключается в том, что вы сохраняете «события» или «изменения» в вашей системе вместо того, чтобы сохранять «состояние» вашей системы. Например, вы можете смоделировать свой банковский счет как a) Ваш баланс (STATE) или b) серию транзакций (EVENTSOURCE).
Артс
4
В зависимости от использования, «событие» - это обычно просто обратная связь, завернутая в сахар. Обратные вызовы используются повсеместно - если вам интересно, это, вероятно, хорошее ключевое слово для начала поиска.
J ...
10
Я также отметить, что даже если вы идете как низкий уровень , как микроконтроллер, вы найдете аппаратные прерывания полезную и спорные существенную особенность. Отлично подходит для систем управления или базового ввода-вывода, например кофеварки. Эти аппаратные прерывания на самом деле существенно не отличаются от событий.
Дан
Нет! Практический пример: события Nodejs
сампатрисрис
2
Вы на Windows? Проверьте Просмотрщик событий. Веселиться.
23 марта

Ответы:

106

Нет. Они действительно удобны для реализации 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);
}

Это делает наш код чистым и гибким. Одна из часто игнорируемых частей ООП заключается в том, что классы отправляют сообщения друг другу. События - это сообщения.

Резиновая утка
источник
37
Я читаю это и думаю о нашем коде «создать бронирование», и я плачу некоторое время и жажду лучшего места: '(
sara
1
+1, отличный ответ. Просто тангенциальный вопрос (меня это немного беспокоило): есть ли у вас особая причина, чтобы вы начинали названия методов (Зарегистрироваться, Сохранить и Отправить) заглавными буквами? Конечно, это не влияет на полезность этого ответа.
Педро А
14
@Hamsteriffic Я в основном разработчик C #, и это общепризнанное соглашение. Нет другой причины.
RubberDuck
6
@Hamsterifficas, как дополнение, то, что вы называете lowerCase, но в верхнем регистре он содержит заглавные буквы, часто называется camelCase, потому что в середине у него горбы. Это отличает его от snake_case, где строчные слова разделяются символами подчеркивания, что является знакомым для python и большинства языков оболочки, чтобы назвать несколько.
Аарон
5
События - это один из типов этих сообщений, я бы сказал. Вызовы методов также должны рассматриваться как передача сообщений.
jpmc26
53

Нет.

Классическим примером событий, используемых в логике без графического интерфейса, являются триггеры базы данных.

Триггеры - это код, который выполняется, когда происходит данное событие (INSERT, DELETE и т. Д.). Похоже, событие для меня.

Это определение события из Википедии:

В вычислениях событие - это действие или событие, распознаваемое программным обеспечением, которое может обрабатываться программным обеспечением. Компьютерные события могут быть сгенерированы или инициированы системой, пользователем или другими способами. Как правило, события обрабатываются синхронно с потоком программы, то есть программное обеспечение может иметь одно или несколько выделенных мест, где обрабатываются события, часто цикл событий. Источник событий включает в себя пользователя, который может взаимодействовать с программным обеспечением посредством, например, нажатия клавиш на клавиатуре. Другим источником является аппаратное устройство, такое как таймер. Программное обеспечение также может запускать свой собственный набор событий в цикле событий, например, для сообщения о завершении задачи. Программное обеспечение, которое изменяет свое поведение в ответ на события, называется управляемым событиями, часто с целью быть интерактивным.

Не все события генерируются пользователем. Некоторые генерируются таймером, подобным crontab, из INSERT базы данных, как я упоминал ранее.

В определении также говорится, что некоторые программы или системы являются «управляемыми событиями, часто с целью быть интерактивными» , из чего можно сделать вывод, что цель или полезность событий не только, но довольно часто, обеспечивают интерактивность (например, GUI). хотя не обязательно GUI, так как программы CLI также могут быть интерактивными).

Тулаинс Кордова
источник
2
Я всегда думаю об этом, когда слышу о триггерах базы данных: thecodelesscode.com/case/42
Almo
Как бывший разработчик DBA, теперь разработчик, я смущаюсь каждый раз, когда слышу, как люди говорят об использовании триггеров без учета более широкой производительности БД.
Логика трех значений
27

Программирование на основе событий фактически также используется для высокопроизводительного программирования сервера.

При типичной рабочей нагрузке на сервер большая часть времени обработки результата фактически поступает из операций ввода-вывода. Например, извлечение данных с жесткого диска (7200 об / мин) может занять до 8,3 мс. Для современного процессора ГГц это будет равняться ~ 1 миллиону тактов. Если бы процессор каждый раз ждал данных (ничего не делая), мы бы потеряли МНОГО тактов.

Традиционные методы программирования позволяют обойти это путем введения нескольких потоков . Процессор пытается запустить сотни потоков одновременно. Однако проблема, с которой сталкивается эта модель, заключается в том, что каждый раз, когда процессор переключает поток, ему требуются сотни тактов для переключения контекста . Переключение контекста происходит, когда ЦП копирует локальную память потока в регистры ЦП, а также сохраняет регистр / состояние старого потока в ОЗУ.

Кроме того, каждый поток должен использовать определенный объем памяти для хранения своего состояния.

Сегодня был толчок для серверов, которые имеют один поток, который работает в цикле. Затем части работы переносятся на насос сообщений , который выступает в качестве очереди для одного потока (так же, как в потоке пользовательского интерфейса). Вместо того, чтобы ждать окончания работы, CPU устанавливает событие обратного вызова для таких вещей, как доступ к жесткому диску. Что уменьшает переключение контекста.

Лучшим примером такого сервера является Node.js , который, как было показано, способен обрабатывать 1 миллион одновременных подключений с помощью скромного оборудования, в то время как сервер Java / Tomcat будет бороться с несколькими тысячами.

иСКУССТВ
источник
2
«Скромное железо» немного вводит в заблуждение. Вам понадобится 8GB + для Node, в дополнение к тому, что использует ОС. А если у вас так много памяти, Tomcat легко справится с несколькими тысячами соединений. Конечно, есть большая разница, но она не в 1000 раз.
Пол Дрейпер
@PaulDraper нет, не может. И нет, это не так. Вам нужно 8 ГБ + только для стека на 8000 потоков. Это большая разница.
АрЦ
3
@PaulDraper, кроме 8GB, очень скромен по стандартам сервера. Я работал на машинах с 128 ГБ оперативной памяти, и они даже не полностью загружены. Тараны стоят дороже, чем вся ваша машина.
АрЦ
это зависит от размера вашего стека. Oracle / OpenJDK по умолчанию составляет 1 МБ на большинстве платформ для 64-разрядных и 512 КБ для 32-разрядных. Если вы просто примете значения по умолчанию, вы будете правы. Но по умолчанию это не то, как вы добираетесь до соединений 1M Node;) В любом случае, 128K - это достаточно; Вы можете уйти с еще меньшим количеством. Это было бы 1 ГБ стекового пространства для 8000 потоков.
Пол Дрейпер
6
Вы ошибаетесь Даже при размере стека по умолчанию вам потребуется всего 8 ГБ виртуальной памяти. Память передается на лету по мере необходимости. Как правило, вам нужна только одна страница на стек, если вы на самом деле не используете дополнительную память. И на практике большинство потоков в такой системе имеют только эти (обычно) стеки по 64 КБ. Использование виртуальной памяти имеет большое значение в 32-битных ОС, но не так сильно в 64-битных. Вы сталкиваетесь с другими ограничениями гораздо раньше - например, с исчерпанием TCP-порта :) А где, по вашему мнению, хранятся эти "псевдостеки" узла? Это верно, в куче.
Луаан
10

События также активно используются в сетевом программировании (например, Nginx), чтобы избежать дорогостоящих циклов ожидания и вместо этого обеспечивают чистый интерфейс, чтобы точно знать , когда доступна определенная операция (ввод-вывод, срочные данные и т. Д.). Это также решение проблемы C10k .

Основная идея состоит в том, чтобы предоставить ОС набор сокетов (то есть сетевых подключений) для мониторинга событий, всех из них или только тех, которые вас особенно интересуют (например, данные, доступные для чтения); когда такая активность обнаружена операционной системой в одном из сокетов в списке, вы получите уведомление о событии, которое вы искали с помощью API, и вам нужно будет разобраться, откуда оно происходит, и действовать соответствующим образом. ,

Теперь, это низкоуровневое и абстрактное представление, более того, сложно правильно масштабировать. Однако существует множество высокоуровневых фреймворков, которые справляются с этим даже кроссплатформенным образом: Twisted для Python, Boost.Asio для C ++ или libevent для C.

edmz
источник
+1 «дорогие циклы занятости-ожидания»: другими словами, это полезно в любых параллельных процессах, которые включают некоторую неактивность (ожидание), а также синхронизацию между такими процессами (сообщениями или событиями). Как много в реальном мире работает.
fr13d
Интересно выяснить, что сокеты изначально разрабатывались как форма IPC на одной машине, до того, как существовала сеть.
5

Встроенные системы почти всегда по своей сути управляются событиями, даже если они не запрограммированы как таковые.

Эти события происходят от таких вещей, как аппаратные прерывания, нажатия кнопок, периодические аналого-цифровые показания, истечение таймера и т. Д.

Встраиваемые системы с низким энергопотреблением еще более подвержены влиянию событий; они проводят большую часть своего времени в спящем режиме (процессор спит в режиме пониженного энергопотребления), ожидая, что что-то произойдет (это «что-то» является событием).

Одна из наиболее распространенных и популярных платформ для встраиваемых систем, управляемых событиями, - это Quantum Platform (QP) (QP также работает под Linux, Windows и любой unix-подобной ОС.) Конечные машины естественным образом подходят для программирования, управляемого событиями, поскольку программа не является «последовательной» в типичном смысле, это скорее набор «обратных вызовов», которые вызываются в зависимости от состояния системы и текущего события.

радиан
источник
3

Сообщения о событиях Gregor Hohpe.

Событийно-управляемая архитектура Грегора Хопе.

SEDA архитектура , валлийский, каллер, пивовар.

как вы справляетесь в обычном бэкэнд-программировании, когда что-то происходит, делаете это иначе?

Конечный автомат - один из распространенных подходов

Given(State.A)
When(Event.B)
Then(State.C)
    .and(Consequences.D)
VoiceOfUnreason
источник
2
1, это не совсем последовательный ответ, и 2, FSM не являются хорошими примерами использования событий.
whatsisname
1
FSM. Я уверен, что пастафарская религия наблюдает ряд событий ;-)
fr13d
0

Во встроенных системах события происходят во время прерываний. Существует много источников прерываний, от таймеров до ввода-вывода.

Кроме того, RTOS также может иметь события. Один пример - ожидание сообщения от другой задачи.

Томас Мэтьюз
источник
0

Для не встроенной системы, но то, что я делал в C #, было системой SCADA. Было много событий, связанных с тем, что происходило на складе, когда загрузка была выгружена, часть сгенерированного системой события, а другая часть записывала новое состояние в базу данных. Конечно, у нас был клиент с графическим интерфейсом, но он просто показывал состояние базы данных, которая отражала состояние хранилища. Так что это было серверное программное обеспечение на основе событий и потоков. Довольно сложно развиваться.

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

Матеуш
источник