Let try to answer this briefly... if you are talking about the back-end that is.
What are the best practices? Alternative ways of changing Umbraco behavior?
Angular & Plugins
Best way by far is to write plug-ins. Plug-ins can be in the first place property editors. But it could also be used to interfere with the complete backend. But you can go much further.
Almost everything can be extended, custom dashboards, custom sections, custom trees, ... you name it and it probably is possible to extend in the backend.
Everything is powered by angular. Nothing stops you from doing very funky stuff. Packages like Nexu intercept every angular http call and then run their own logic.
From .net Code
A lot of the umbraco logic (like the complete request pipeline) can be replaced by your own implementation. Nothing stops you from run your own UrlProvider.
And what about the events (doing things after somethings happens). E.g. after a save.
Best practices
I think a best practice is to leave umbraco as is. Do not change it if you don't really need to. Use all extension points where you can.
And use the default Umbraco stuff. Don't reinvent the wheel. Use things which already exists in Umbraco. It will give you the possiblity to build better websites for content editors, and faster for the users.