Это расширенный ответ, как и было обещано.
В 2000 году мы начали писать приложение с использованием Delphi. Это был один EXE и несколько DLL, содержащих логику. Это была киноиндустрия, так что были клиенты DLL, DLL бронирования, касса DLL и биллинг DLL. Когда пользователь захотел выставить счет, он открыл соответствующую форму, выбрал клиента из списка, затем логика OnSelectItem загрузила театры клиентов в следующее поле со списком, затем после выбора театра следующее событие OnSelectItem заполнило третье поле со списком информации о фильмах, которая не была выставлено еще. Последней частью процесса было нажатие кнопки «Сделать счет». Все было сделано как процедура мероприятия.
Тогда кто-то решил, что у нас должна быть обширная поддержка клавиатуры. Мы добавили обработчики событий вызова из других четных обработчиков. Рабочий процесс обработчиков событий начал усложняться.
Через два года кто-то решил внедрить другую функцию - чтобы пользователю, работающему с данными о клиентах в другом модуле (модуле клиентов), была представлена кнопка с названием «Выставить счет этому клиенту». Эта кнопка должна запустить форму счета и представить ее в таком состоянии, как если бы пользователь вручную выбирал все данные (пользователь должен был иметь возможность просмотреть, внести некоторые изменения и нажать волшебную кнопку «Сделать счет»). ). Так как данные клиента были одной DLL, а биллинг - другой, это был EXE, который передавал сообщения. Таким образом, очевидная идея заключалась в том, что разработчик данных клиента будет иметь одну подпрограмму с одним идентификатором в качестве параметра, и что вся эта логика будет внутри модуля биллинга.
Представь, что случилось. Поскольку вся логика была внутри обработчиков событий, мы потратили огромное количество времени, пытаясь на самом деле не реализовывать логику, а пытаться имитировать пользовательскую активность - например, выбирать элементы, приостанавливать Application.MessageBox внутри обработчиков событий с использованием переменных GLOBAL и т. Д. Представьте себе - если бы у нас были даже простые логические процедуры, вызываемые внутри обработчиков событий, мы бы смогли ввести логическую переменную DoShowMessageBoxInsideProc в сигнатуру процедуры. Такая процедура могла быть вызвана с параметром true, если вызван из обработчика события, и с параметрами FALSE, когда вызван из внешнего места.
Так вот, что научило меня не помещать логику непосредственно в обработчики событий GUI, за возможным исключением небольших проектов.