Exceptions Are Extremely Expensive… Do This Instead

preview_player
Показать описание

How should you handle errors in your code? This has been a topic of many discussions, and I want to share my opinion. One school of thought suggests using exceptions for flow control. This is not a good approach because it makes the code harder to reason about. The caller must know the implementation details and which exceptions to handle. Exceptions are for exceptional situations. Exceptions are also costly and degrade performance. If you don't believe me, we'll prove it in this video.

Functional Error Handling in .NET With the Result Pattern

Check out my courses:

Read my Blog here:

Join my weekly .NET newsletter:

Chapters
0:00 Are exceptions expensive?
3:14 Exceptions for flow control
7:38 Performance testing exceptions
10:23 Handling errors with Result pattern
14:11 Performance testing Result pattern
15:30 Result pattern drawbacks
Рекомендации по теме
Комментарии
Автор

Like everything, exceptions are a trade-off. In one codebase, we went from Exceptions to success/failure wrappers, then back to Exceptions after about 2 years. Exceptions were waaaay simpler, and the code was drastically reduced when we removed the success/failure wrappers. The code was easier to follow and find bugs when we used exception because there was less of/else/switch control flow, and the return types were simpler. The apps were also easier to debug because breakpoints, and stepping through code was simpler when using exceptions as there was less indirection.

brnto
Автор

I think the gained performance won't matter as much in a real world enterprise solution and I'll explain why. The selected premise is invalid, it sets up an application to fail hundreds of thousands of times per minute in order to be true. I understand that was done to highlight how expensive they are, but an application is not expected to fail like that. We generaly see a couple of exceptions once in a while, just like you said, they are for exceptional cases. If the application is failing like that, it means something is wrong with the caller or the application. Adding so much boilerplate for that is not worth it and will only polute the code.

reginaldo
Автор

As you mentioned in your final remarks if we are doing client-side validation, the number of server-side exceptions should be minimal. With result objects, we have
1. Arguably less readable/maintainable code. Having result checks on each layer is way less fun than having a middleware that handles all exceptions in one place and returns the appropriate result to the user.
2. More memory allocations, since ALL happy paths are now boxed with the Result object. Try testing with a 5% failure rate, and compare memory allocations. In my benchmark, using ErrorOr, resulted in 10x memory allocations.
3. Lost stack trace

daneel_olivaw
Автор

00:02 Exceptions are meant for exceptional situations
02:06 Instead of exceptions, consider using the result pattern for error handling
04:07 Handling validation errors with exceptions
06:10 Handling exceptions using an IExceptionHandler interface in .NET 8.
08:03 Performance test using k6 for API requests
10:02 Implement alternative error handling method without throwing exceptions
12:05 Utilize existing libraries or create custom abstractions for handling exceptions efficiently
14:10 Using result pattern is faster than exceptions for flow control
16:12 Consider using result object instead of exceptions for performance

mohammedelrasheed
Автор

Great video! however one thing to note: All these stats about requests per hour (800, 000 vs 15 million) are still not realistic in a real-world scenario, because this means that ALL these requests fail. In a true setting though, a percentage of requests might fail, and some will succeed.
Therefore the gap between the two situations isn't as big as we think in the first place, and the 800, 000 r/s might be more toward a few-million r/s (depending on the api consumer behavior of course).

ajdinhusic
Автор

Im not sure where I saw it, but congrats on being MVP again.

bogella
Автор

Great video! In my case, most applications I write are in a controlled environment, so exceptions are really exceptions and a tiny portion of our responses. So, in my case, I find it hard to defend using results in every method on the chain.

gfantin
Автор

I use exceptions in most of my methods. If an action needs to be attempted without throwing an exception, then I create a separate "Try..." method. I don't see the point of using the Result type everywhere, as it adds dozens of checks to the code after each operation. But I agree that an exception should not control the flow of execution. When an exception occurs, it should reach the top of the call stack and return the result to the user (if possible).

anton-ivanchenko
Автор

and how many applications go behond 1k request a second? Does the applications you built do 1/2k/s? Be pragmatic and default to exception handling first. There are many other ways (infrastructure) to increase request/s very cheaply, and if, somehow, this really gets to be a problem, then c# was probably a bad choice.

pedroferreira
Автор

Great Video !
Almost my code using Exception to bypass all code after error occurs, then handle it by try..catch . We don't consider receiving request speed because the number of users arenot so many. Now the code is live production. Better not touching it anymore as long as it is not broke :D

Rizkiaqa
Автор

I would love to see a follow up video on this that goes deeper into using exceptions for handling invariants and other validation checks in a DDD Domain Layer. In this case I prefer exceptions because I don't want to dirty my whole domain layer return types with a Result type. DDD states that the domain layer should use domain objects as arguments and return types. So in my eyes, (domain) exceptions are the only way to go.

CreativeBST
Автор

The biggest problem of this video is that the author misleads the audience that "you should not use exceptions because they slow down your app". This completely incorrect statement!
Exceptions cost a lot, but the result in k6 depends on your app arch+tech solutions. In the same way I can prove that the SIMD instructions slow down your app by testing app using double and SIMD to sum and mul numbers in the "calculator app"
It is important to tell what solution/technique is better to use in which cases/scenarios

vunder
Автор

For this example in the video, I totally agree with not using exceptions, but for domain classes, I'm totally against using result, for me it has to be exception.

If used for domain classes, the consumer of the class will have to do ifs all the time, this is hell, and I think it's unnecessary, normally input validations are done in higher layers, like controllers for web api. If you reached the domain class, it is understood that the inputs are ok, and if for some reason, the inputs arrived at the domain class with invalid data, an exception must be thrown, this applies to the class constructor, the methods within and etc...

juniorzucareli
Автор

No, exceptions are for what they are, they bubble up to ensure some one catch and manages the exception. Result pattern doesn't. Exceptions for everything that needs to be handled or the application crahses

sokka
Автор

Well done, exposing real pors and cons

chanep
Автор

A simple alternative to a Result type might be to return a tuple like (T? Value, string? Error) where either of the elements is null. This can be simply checked with a switch expression and pattern matching.

krccmsitp
Автор

I'm not sure if that minimal performance gain for very rare cases is worth the effort and extra dependency. Also logging will become complexer with the shown concept.

DanielOpitz
Автор

Great video. I've always known that exceptions were expensive, but never imagined the difference would be that huge. What are your views on Tuples (containing an error) as simple return types rather than the complexity of Result types? Similar to Go's error handling methodology?

helshabini
Автор

If your service in 99% of time returns bad responses than yes - do not use exceptions. Otherwise there is no point to spend a time for fighting with exception because it is a rare case and performance issues will be in some another places - like slow db requests, caching, pools etc. And better to spend your time there.

yatsuk
Автор

Hi, Milan Jovanović. What is your opinion about exceptions in parameter validation during object initialization? Since there is a trend that says you should not create an object with an invalid state.

By not using the exceptions approach, you would have to use something like FluentValidation. Which, in short, creates an object with a possible invalid state and then checks whether or not it is invalid.

eu.jeanoliveira