Get consistent on events: Either Action or event, not both
See original GitHub issueFirst, I’ll point out that none of this really matters. I’m investing blood & sweat into this project because it’s fun. It’s a low-risk project that potentially 10s of others will use 😉. I don’t really care about these topics because I’m not a professional developer. I just play one on TV.
That said, I’d love to have people using Terminal.Gui
and say “wow, this thing is really easy to use and work great! The people who worked on it sure were thoughtful.”. Of course, 99% of the credit for that will always go to @migueldeicaza.
To this end: This project has become confused on whether the idiom for events is based on Action
or event
. In addition there’s gross inconsistency between naming of events. E.g.
- Recently we added
static public Action OnResized
toApplication
. - Meanwhile most
View
derived events useevent
as inpublic event EventHandler Enter
. - Some event handlers use “On” and some don’t. E.g.
public event EventHandler OnOpenMenu
vs.public event EventHandler TextChanged
.
I’m guilty of contributing to this myself. I hereby commit that moving forward, no more. I will do better.
The best guidance on naming event related things I’ve seen is this: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-type-members?redirectedfrom=MSDN
Events always refer to some action, either one that is happening or one that has occurred. Therefore, as with methods, events are named with verbs, and verb tense is used to indicate the time when the event is raised.
✔️ DO name events with a verb or a verb phrase.
Examples include Clicked, Painting, DroppedDown, and so on.
✔️ DO give events names with a concept of before and after, using the present and past tenses.
For example, a close event that is raised before a window is closed would be called Closing, and one that is raised after the window is closed would be called Closed.
❌ DO NOT use “Before” or “After” prefixes or postfixes to indicate pre- and post-events. Use present and past tenses as just described.
✔️ DO name event handlers (delegates used as types of events) with the “EventHandler” suffix, as shown in the following example:
public delegate void ClickedEventHandler(object sender, ClickedEventArgs e);
✔️ DO use two parameters named sender and e in event handlers.
The sender parameter represents the object that raised the event. The sender parameter is typically of type object, even if it is possible to employ a more specific type.
✔️ DO name event argument classes with the “EventArgs” suffix.
I found this article to be especially clarifying: https://www.codeproject.com/Articles/20550/C-Event-Implementation-Fundamentals-Best-Practices
We are not consistent along these lines in Terminal.Gui
at all. This leads to friction for adopters and bugs.
Because I’m so familiar with WinForms and classic .NET event
I have a bias for the event/EventHandler
model. Action
seems well suited for internal APIs, but event/EventHandler
seems to scale better for public APIs. I’d like us to minimize use of Action
.
I would like to take on fixing this (it speaks to my OCD). There’s no way to do this without breaking changes, I’m afraid. But the longer it waits, the harder it will be.
My proposed Event rules for Terminal.Gui
moving forward:
- We follow the naming advice provided in https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-type-members?redirectedfrom=MSDN
- We only use the
Action<T>
idiom for internal APIs, not for public APIs. For public APIs we use theevent/EventHandler
model. - For public APIs, the class that can raise the event will implement:
- A
virtual
event raising function, named asOnEventToRaise
. Typical implementations will simply do aEventToRaise?.Invoke(this, eventArgs)
. - An
event
as inpublic event EventHandler<EventToRaiseArgs> EventToRaise
- Consumers of the event can do
theobject.EventToRaise += (sender,, e) => {};
- Sub-classes of the class implementing
EventToRaise
can overrideOnEventToRaise
as needed.
- A
- Where possible, a subclass of
EventArgs
should be provided and the previous state should be included.
At the very minimum, can we agree that moving forward we will follow the above rules?
You’ll note that my toplevel_ready
PR attempts to follow these rules: https://github.com/migueldeicaza/gui.cs/pull/446
What enhancements, changes would you make to these rules?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:10
Top GitHub Comments
If an
Action
is not added to it, it will not perform properly threadingTasks
, unless the invoke get called from inside anAction
that was previously added to theApplication.MainLoop.AddIdle()
.This was mostly taken care of as part of the push to 1.0. Closing.