Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking Change: Remove Unneeded Interfaces #9495

Closed
grokys opened this issue Nov 21, 2022 · 5 comments · Fixed by #9553
Closed

Breaking Change: Remove Unneeded Interfaces #9495

grokys opened this issue Nov 21, 2022 · 5 comments · Fixed by #9553

Comments

@grokys
Copy link
Member

grokys commented Nov 21, 2022

We currently have many interfaces in Avalonia which mirror concrete classes, for example (list is not exhaustive):

  • IAvaloniaObject -> AvaloniaObject
  • IControl -> Control
  • IInteractive -> Interactive
  • ILayoutable -> Layoutable
  • IPanel -> Panel
  • IStyledElement -> StyledElement
  • ITemplatedControl -> TemplatedControl
  • IVisual -> Visual

These interfaces were added at the beginning of the project at a time where the prevailing fashion in unit testing was "create an interface for each concrete class in order to make it easier to mock".

This turned out to be a mistake because:

  • Using interfaces instead of concrete classes means that every method call is a virtual method call. This degrades performance in large applications and can be particularly noticeable when profiling on slower embedded and mobile hardware
  • We still target netstandard2.0 which includes platforms such as .NET framework where default interface implementations are not supported, meaning that we can't even add methods to these interfaces without breaking API compatibility
  • Mocking is unnecessary in the unit tests anyway: it's much better to use concrete classes
  • Implementing these interfaces in user code isn't supported by much of the code anyway

For 11.0 we should remove these interfaces to improve performance. This will be a large breaking change, but we feel it's necessary, and the fix should be reasonably straightforward - remove a bunch of I characters.

@grokys grokys added the feature label Nov 21, 2022
@grokys grokys self-assigned this Nov 21, 2022
@wieslawsoltes
Copy link
Collaborator

wieslawsoltes commented Nov 21, 2022

+1 for removing interfaces, it's especially confusing when creating libraries and deciding what to use (concrete class or interface). Also performance is a feature especially on wasm and mobile.

@grokys
Copy link
Member Author

grokys commented Nov 22, 2022

One of the more tricky interfaces here might be IStyleable. This could be removed in favor of just using StyledElement, the only problem being that the current method of overriding a control's style key is to provide an explicit interface implementation of IStyleable.StyleKey.

Would people be comfortable with removing IStyleable and having to change their code to override the style key by overriding e.g. a protected method/property?

@kekekeks
Copy link
Member

BTW, why aren't we using the WPF approach with DefaultStyleKeyProperty?
Also, the current way of handling StyleKey override is highly counterintuitive: it's set to the type itself automatically unless you have some base type that overrides it.

@grokys
Copy link
Member Author

grokys commented Nov 22, 2022

BTW, why aren't we using the WPF approach with DefaultStyleKeyProperty?

Historical reasons really: back in 2015 when I didn't know anyone would ever use this project, I decided to implement it like that. Mostly because in WPF, I always forgot the step of setting a new default value for DefaultStyleKeyProperty and it annoyed me because 90% of the time "of course I want a new style for this new control I'm writing".

However if we want to change it to match WPF/UWP etc then now would be the time to do it. Bear in mind though that reading the default value of a styled property is a lot slower than reading a virtual CLR property, and we'd be potentially reading the property a lot more than WPF does due to our CSS-like styling system.

@amwx
Copy link
Contributor

amwx commented Nov 22, 2022

I think just making it a virtual read-only property on StyledElement would be best solution. Overridable things also show up in intellisense so probably more intuitive this way. Would be to simple fix in existing code too:
Type IStyleable.StyleKey => typeof(MyControl); --> public override Type StyleKey => typeof(MyControl)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants