Тёмный

The hidden cost of Exceptions in .NET 

Nick Chapsas
Подписаться 309 тыс.
Просмотров 34 тыс.
50% 1

Become a Patreon and get source code access: / nickchapsas
Check out my courses: dometrain.com
Hello everybody I'm Nick and in this video I am going to talk about the hidden cost of Exceptions in C# and .NET in general. Exceptions are a great feature but when misused they can lead to unexpected performance issues. By no means should you go and change your applications but it is good to be aware of the shortcoming and take a look at potential alternatives.
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasG...
Follow me on Twitter: bit.ly/ChapsasT...
Connect on LinkedIn: bit.ly/ChapsasL...
Keep coding merch: keepcoding.shop
#csharp #dotnet #exceptions

Опубликовано:

 

10 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 143   
@PelFox
@PelFox 3 года назад
Personally I just find it cleaner with exceptions than passing result objects or OneOf. It's a clean way to make sure every endpoint returns the same pattern for status codes and response models. If I have performance issues, those 20 μs from replacing exceptions with result objects is most likely the last thing I would do. This also adds a new dependency in your code base to this OneOf library.
@Mr.Thompson
@Mr.Thompson 3 года назад
I agree that the OneOf conecpt wouldn't be my favorite. Typescript has native support for this by pipe-concatenating type like so: type1 | type2 | undefined .... The point where you need to distinguish between these types then usually becomes messy. But still I wouldn't use exceptions allthe way for expected/common errors.
@chadiusmaximus9350
@chadiusmaximus9350 3 года назад
I don't throw errors in my domain logic. I just return a custom result interface like action methods do.
@rafaelrosa3841
@rafaelrosa3841 2 года назад
if 20us makes difference on the application, we probably shouldn't even use C# to build it from the start.
@PelFox
@PelFox 2 года назад
@@Qrzychu92 You catch them in a global exception handler which logs the exception then map it to an appropriate status code and response to the client. It's not hard to add a summary tag on your methods which defines which exceptions it may throw and when it does it.
@PelFox
@PelFox 2 года назад
@@Qrzychu92 I use a pipeline that wraps all requests in a try/catch and logs any exception and throws it. If it's not something expected to be handled within the global handler it's returned as a 500.
@Thial92
@Thial92 3 года назад
I usually just create a Result object using an IResult or IResult interfaces which can either hold the value or a custom exception object (which builds minimalistic stack trace using the Caller attributes) and then I provide properties for checking the actual result like IsFail IsSuccess isNull IsFailOrNull IsFailOrNullOrEmpty etc. Then I only use trycatch on things like http calls, json (de)serialization, EF queries etc (basically only the obvious failure points) and my every method uses IResult as the return type which effectively converts all methods into easily manageable contracts where you can easily check if they have fulfilled their purpose or not.
@nickchapsas
@nickchapsas 3 года назад
A Result object is also a perfect alternative. I’ve been bouncing back and forth between Result and OneOf
@mahdyberriri5742
@mahdyberriri5742 3 года назад
This channel is really underrated! I learned a lot from your channel keep it up :)
@matrim
@matrim 3 года назад
This is interesting, and as you say by the end, this is a very small change in executing time, and in most (not all) cases that execution means very little, specially on an API level due to the other factors that will consume the time. It could potentially save you some processing time in large scale processing, such as large data validation. If we could get a native implementation of this I could see scenarios where I would change to use this
@MyNisDavid
@MyNisDavid 3 года назад
Сontent is a piece of gold, succinctly, straight to the point. This is the first time I immediately liked and subscribed after watching a video. I am just now writing a service for work and using exceptions. I didn't even know the filter trick. But here I have a question, what if there are not 2 but 20 different exceptions?
@SCHCOMM
@SCHCOMM 3 года назад
Moreover - what if we throwing exceptions wwwaay way deeper? We will have to disfugure all our domain-level code with these clumsy signatures and returns..
@namhoang5550
@namhoang5550 2 года назад
I always know that exceptions are quite expensive but I haven't been able to come up with any better solution yet. Your solution seems promising, I would definitely give it a try. Thanks!
@BrankoDimitrijevic021
@BrankoDimitrijevic021 2 года назад
Exceptions are only expensive when thrown. At long as exceptions are truly exceptional (i.e. rare) that’s not a problem.
@Phroggster
@Phroggster 3 года назад
Exceptions are perfectly fine to use for exceptional circumstances, which I've always interpreted as programming or implementation errors. For everything else, OneOf does a very good job, but I tend to find it easier long-term to return a class capable of holding a bool or enum indicating pass/fail or validity of result object, a result class/struct/value object, and a string with the error message if the pass/fail bool should ever be false.
@RohitMoni0
@RohitMoni0 3 года назад
Interesting video, I'm not sure if I'll use this approach though. One of the main advantages of exceptions as a form of error handling (at least to me) is that exceptions can throw through multiple steps of the stack without having to write explicit handling code for each step along the way. I don't know if the OneOf approach would be anywhere near as clean if your service logic was deeper and had different sets of exceptions thrown for different types of errors. I think it would quickly get very messy. One thing I do like about the OneOf approach is that the function signature tells you what errors can exist (which is nice). Might use that kind of thing for some specific use cases.
@nickchapsas
@nickchapsas 3 года назад
You don't need to handle failed responses explicitly in the OneOf approach. In the same way that you generically handle exceptions when they extend a specific Exception and you map that to a response, you can use the interface in OneOf to map a "Bad action" to a bad response. You can still have the exception handling in there, but for things that are truly "exceptions", not just normal domain behavior masked as something that it isn't
@awmy3109
@awmy3109 3 года назад
Nice idea and a good alternative to consider sometimes. The issue is exeptions are straight forward and easy to implement and reason about. When they occur, they occur because it is impossible to continue execution. If they don't occur, it means everything is right. That means clear separation of valid execution (get a return value or null or void) and invalid execution (exception occurs) and even have context, why and at what point in execution it occurred (stack trace). OneOf doesn't give you any of that separation. Correct me if am wrong.
@gbjbaanb
@gbjbaanb 3 года назад
the mistake is thinking that situations such as an empty data field is an exception is where the problem lies. Such errors are not exceptional, they are part of normal error handling (though obviously it depends in practice what data you mean - open a file and read 0 bytes is not an exception, open a file and fail to read because its been deleted from under you, is). Too often exceptions are used for ordinary error conditons that should simply be a null or error code - but throwing is just easier, then its someone else's problem. And quite possibly major performance issue.
@manishjhamaster
@manishjhamaster 3 года назад
OneOf and matching is very similar to rust enums and pattern matching. neat!
@Mr.Thompson
@Mr.Thompson 3 года назад
I usually follow a simple rule when deciding to use exceptions or another type of error handling: Only if an error is literally exceptional, then use exceptions. If it is a more common error, then handle it differently. It's a rule thumb, not a dogma but mostly works.
@GeorgiGeorgiev-sm3lx
@GeorgiGeorgiev-sm3lx 3 года назад
Nick, isn't the OneOf approach bad for domain logic, where buisness rules are ever changing. I mean, every new business validation would require to change the contract? Please share your opinion
@nickchapsas
@nickchapsas 3 года назад
The contract is on the API level not the domain. The domain can change but the contract stays the same. Remember you only have one "Good" response in OneOf, the first one, which represents your core contract for that endpoint. All the others are the potential "bad responses" that will get mapped to the "ErrorResponse" contract, which will be static.
@diego_samano
@diego_samano 3 года назад
I guess the WebApplicationFactory deserves a video as well (if no one yet). Referring to OneOf video, you mentioned that it was not your preferred approach. So, this is a video for "I changed my mind" or is still something better for handling Exceptions.
@nickchapsas
@nickchapsas 3 года назад
I have a video on the WebApplicationFactory on the integration tests video. In terms of returning I was using Result at the time which return the good object or an exception and then I was handling the exception based on the type, but it was returned not thrown. The reason why I moved away was because it does t feel appropriate to use an exception to represent a bad state in the domain.
@kj2w
@kj2w 3 года назад
So question, in your OneOf you have to add a new type for every possible return? Wouldn't that be a violation for the O of SOLID (Open/Closed Principle for those not familiar)? New requirements come along from business, new possible error is concieved, now you have to modify the OneOf CreateUser(). But again, love your videos, VERY fun to watch. Ps. moving from Visual Studio to Rider is rather difficult, so different! :)
@nickchapsas
@nickchapsas 3 года назад
By your explanation, the exception approach also violates the O in SOLID because somewhere something has to be modified. Open/closed doesn't mean that you should never edit your code. If your method needs to also handle something new, but still falls under the concerns of that single method, hanse the return type change, then there is nothing wrong with that. Requirements change. The point of O is that if you need to add something new in your system you should be able to do that without mofifying existing code. Your requirement doesn't fall under that.
@PticostaricaGS
@PticostaricaGS 3 года назад
It's funny, it has always been known that throwing exceptions will slow a little bit the code execution, but nowadays everyone throws exceptions pretty much everywhere, instead of doing pre-validation. As for the Filters, I usually rather use a Global Exception Handler instead.
@PticostaricaGS
@PticostaricaGS 3 года назад
@@ericnewton5720 yeah, sometimes, it all depends on the project really
@vpsrj
@vpsrj 3 года назад
It’s totally true but when you want to deal with duplicated keys on database (and not querying before insert, leaving for the db index to work for you with only one connection) I thought the best approach is to handle the db exception and return OneOf error!
@nickchapsas
@nickchapsas 3 года назад
Agreed. This isn’t about database lever concerns but rather domain level. A database isn’t really a concept of the domain but domain validation is
@fotofoxes2255
@fotofoxes2255 2 года назад
Exceptions are good if you wanna keep the context of failure [for possible analysis], so I’d say within the internal APIs. For the public APIs you simply cannot expose them, as this gives a potential attacker some info about application internals.
@BryanTheYeti
@BryanTheYeti 2 года назад
Liked this video. Would also have liked to see performance impact of using a try/catch when no exception was thrown. Also curious if the compiler does something behind the scenes to handle the potential for a thrown exception even when the exceptional branch is never taken, which could possibly hurt performance. example: a game's update loop that does a check and throws if needed, but that branch is never taken. does this hurt performance?
@MichaelMiller-rg6or
@MichaelMiller-rg6or 3 года назад
This is a really good video. I am guilty of misusing exceptions on occasion in my code.
@BrankoDimitrijevic021
@BrankoDimitrijevic021 2 года назад
Sure, you can change the controller method, but what about the code it depends on? 1. That code might be reused in multiple places or not be under your control (such as database driver), making it impractical to modify. 2. And even if you could, would you really want to, considering the C# compiler will not force you to handle return values, making it extremely easy to silently ignore an error encoded in a return value. I think what you showed was simply a good practice of not using exceptions for non exceptional errors, but this is not a way to altogether avoid the exception filter (because of 1), or structure the error handling in general (because of 2) unless the performance impact is compelling.
@DeViLvs
@DeViLvs 3 года назад
Absolutely brilliant explanation. I knew that I'm doing it right (preferring error results over exceptions) but now you gave me the proof!
@TerenceHancock
@TerenceHancock 2 года назад
Exceptions are for scenarios that are not the happy path. They are by definition exceptions to the rule. So using them for errors or bad input is a correct usage. If the exception never is thrown it won't perform worse
@danku1013
@danku1013 3 года назад
In the big applications, people try to minimize as much as possible references to the externals libraries. That's one of the main reasons to use exceptions.
@vpsrj
@vpsrj 3 года назад
You can handle with monad (OneOf is a good example) to not tie results with libraries!
@jeffgamedev
@jeffgamedev 3 года назад
Thanks Nick. Great topic as usual!
@noelfrancisco5778
@noelfrancisco5778 3 года назад
great demo! may i request for a better method interceptor (e.g. logging, catching error) demo? TIA :)
@buriedstpatrick2294
@buriedstpatrick2294 3 года назад
It looks pretty neat, but I have to question whether it's a flat out "better" approach. Because we are adding yet another third party library to the code base which, although it isn't the biggest problem in the world in this instance, adds to the complexity and learning curve of the application's development. I think it's important to point that out, because this is also a contextual thing. Say you have a massive application, doesn't matter if it's a monolith or a bunch of microservices. And you've gone with the traditional Exception filter approach. Now you essentially have to rewrite and test a huge part of your application's surface. Depending on code base that might not be straight forward. Suddenly that "free" performance comes at a significant development cost. That being said, definitely considering OneOf for future projects. Although I feel like something like it will be baked into the language in the near future.
@nickchapsas
@nickchapsas 3 года назад
It's not one or the other. Some people opt in to use a Result object instead of OneOf that returns either a "good" object or an exception but it returns it, it doesn't throw it. The OneOf approach is definately harder to manage in a monolith application, in which case the Result version is better. In microservices I have found that OneOf is perfectly managable but this ofc depends on the complexity of your domain.
@buriedstpatrick2294
@buriedstpatrick2294 3 года назад
@@nickchapsas It's true that it's not one or the other. But if you don't commit to one or the other, you will end of with a Frankenstein solution in my opinion.
@nickchapsas
@nickchapsas 3 года назад
@@buriedstpatrick2294 Yeah sorry I mean, not one or the other in the grand scheme of things. In a single solution you should pick one and use that one consistently whatever it is.
@Layarion
@Layarion 3 года назад
Hey I'm a noob, no idea what this "domain" you keep mentioning is. I have a very rough idea, but I don't really understand it. Do you have a video for that?
@mohammedehsan4368
@mohammedehsan4368 3 года назад
Generally, I would not care about optimization and performance until it becomes a problem, or I have early indicatora that it will be in the near future. I've been writing defencive code for quite a time and it's time consuming and unnecessary in most cases.
@nickchapsas
@nickchapsas 3 года назад
This isn't about optimizing anything. It is about using a language feature properly and better designing your application's code.
@williamfleetwood4612
@williamfleetwood4612 3 года назад
You kinda did make it about optimizing, showing several tests highlighting the cost in execution time when using error codes vs exceptions vs OneOf, and even naming the video "hidden cost". But in the end, the cost differences were so slight, that yeah this isn't really about optimizing anymore and becomes more about how cleanly can you manage "exceptional" or error states in your code/service.
@tiggerbiggo
@tiggerbiggo 3 года назад
@@williamfleetwood4612 slight cost differences can become big ones in certain circumstances. I still learned something from this video.
@mohammedehsan4368
@mohammedehsan4368 3 года назад
@@AlbertoMonteiro I think exceptions are not really named well. In my opinion, it's not about exceptional events, rather it shows that the method is not behaving as expected.
@mohammedehsan4368
@mohammedehsan4368 3 года назад
@@AlbertoMonteiro Usually, I create all sort of custom exceptions to meaningfully show what is failing and why. At the end, all it matters is to be consistent across your code base to make the code behaving in the expected way. All these topics are highly opinionated and subjective, and the diversity in opinions what makes it beautiful.
@vassilispanos
@vassilispanos 3 года назад
The list of OneOf dependencies seems to be excessive. I had great success with FluentResults library.
@WojtaZy1996
@WojtaZy1996 3 года назад
I can recommend CSharpFunctionalExtensions
@RandalGJunior
@RandalGJunior 3 года назад
I generaly using a Tuple approach, with a nullable returning type and a struct error with boolean success and a error message. Do you think that there is something terrible wrong with this approach?
@nickchapsas
@nickchapsas 3 года назад
Yeah I find the Tuple approach faulty because it requires extra logic to properly handle the response. Also tuples don't force you to handle every possible scenario. OneOf does. It's way safer IMO.
@john-gd3tj
@john-gd3tj 3 года назад
Hi guys I am thinkng of learning new programming language. Which one would you suggest? Or should I stick with dot net?
@GameMuse
@GameMuse 3 года назад
Clicked this link ASAP. You do find some very interesting topics. I'll call them 'Thinking' Topics :)
@JonWoo
@JonWoo 3 года назад
This is just demonstrating 2 different techniques of doing something. Wouldn't a hidden cost of exceptions video explain what is happening under the hood when you throw an exception such that so many more cpu cycles are used.
@farabikurmanshady8486
@farabikurmanshady8486 3 года назад
This channel is brilliant! Your code examples is elegant! But can you make your speech more slowly and not monotonic, giving attention to your accent! Thanks!
@ianfoster6601
@ianfoster6601 Год назад
Also hanging out for discrimiated unions natively supported in C#. They've been promising it since version 8...
@vladimirseven777
@vladimirseven777 3 года назад
TLDR: use exceptions for exceptional cases if you cannot resolve something by using params and results. In case of throwing/catching exception it will be handled at CPU level because it designed to break execution flow.
@the.ledbetter
@the.ledbetter 3 года назад
In the past, I have made a bool method and had an out variable that functioned as the "error" messages if it returned false. Not sure if there's real harm in doing it that way. Thoughts?
@KeyboardKrieger
@KeyboardKrieger 3 года назад
Doing the same. The frontend itself should check the inputs and give the user a response. If my API checks it and the input is wrong it doesn't have to be catched and shown to the user. A possible log entry is more than enough xD
@tiggerbiggo
@tiggerbiggo 3 года назад
A lot of the old business apps i work on use that same pattern, I think it's ok but does require you to have an errorMsg variable floating around whenever you need to call something
@berylliosis5250
@berylliosis5250 3 года назад
So basically... Rust Result style API for domain logic. Neat. Plus you get the benefit of more explicit type signatures and making it harder to ignore errors on the caller side. I am missing _why_ exceptions are so slow - is there any particular reason?
@nickchapsas
@nickchapsas 3 года назад
It's not exceptions in general but rather the throwing part of exceptions. It just interrupts the flow in a way that is costly for the flow. I haven't dived into the JIT to investigate exactly why.
@berylliosis5250
@berylliosis5250 3 года назад
​@@nickchapsas Yeah, that's what I figured. You'd expect a similar/higher cost on every virtual method call if it were just a CPU thing though
@stefanbogdanovic590
@stefanbogdanovic590 3 года назад
Could you explain Special case patrern for error handling instead of throwing Exceptions?
@FranchevandenBerg
@FranchevandenBerg 3 года назад
Hi Nick, hope you find my comment. Just a quick question. Would this method support generating correct swagger responses? Meaning that if you used something like ReDoc, would the resulting model match just the one models structure or potentially define the structure for each status code that would possibly be returned? Hope my question makes sense. Thanks for the nice nugget by the way. Like you videos!
@nickchapsas
@nickchapsas 3 года назад
I prefer to have my swagger responses driven by “Produces” attributes and not leave it up to chance to see what it can figure out.
@udayughareja
@udayughareja 3 года назад
how did you set toolbars to the right side and aligned with navigation bar on the same line?
@michaelspahr3815
@michaelspahr3815 3 года назад
First of all, I really appreciate your work and brilliant videos! In order to prevent the additional complexity of "OneOf", how do you think about providing a (single), more extended return type of the service methods. Similar to the IActionResult, where you can check for an error in the valid response. Or (in my opinion) even more elegant: Providing an Action-Callback-Argument?
@jez9999
@jez9999 3 года назад
I left a comment about the fact that Microsoft recommend against returning error codes instead of throwing exceptions, and it seems to have been deleted.
@nickchapsas
@nickchapsas 3 года назад
I don't delete any comments. If you linked something then the spam filter might have caught it. This is NOT returning error codes. This is the exact same behavior as exceptions, but you are no longer actually throwing exceptions and you are using a domain object to represent the validation error instead. Both the Exception and the validation object will be mapped to a BadRequest. It's the same behavior just faster, and in my opinion, cleaner.
@jez9999
@jez9999 3 года назад
@@nickchapsas It's not the same behaviour as exceptions, because it doesn't interrupt code flow, and the calling code is able to ignore the return value. Code written after the invocation of the method cannot assume that the data is in an acceptable state to continue without a manual check of the return value.
@nickchapsas
@nickchapsas 3 года назад
@@jez9999 But you will need at some point in your request pipeline to do a manual check to see if an exception is of a specific type. You don't just randomly convert any exception to a 400 error. You check for specific types and you map the appropriately. If you do map any exception blindly then that's even worse.
@CatalinTomescu
@CatalinTomescu 3 года назад
Where is the repo link!? Hard to follow without the code!
@trongphan6197
@trongphan6197 3 года назад
can you try the benchmark with the release mode instead of debug?
@nickchapsas
@nickchapsas 3 года назад
All the benchmarks are in release mode. Benchmarks cannot run in debug mode.
@sujoyinnovates
@sujoyinnovates 3 года назад
What methods signature does IValidationError has?
@steve-wright-uk
@steve-wright-uk 3 года назад
I think your approach of returning multiple values instead of throwing exceptions is correct IF your code is the first place that does the validation. If the validation is done further up the call stack so that only valid values SHOULD be passed into your method then throwing exceptions is the better way to go
@nickchapsas
@nickchapsas 3 года назад
There are many ways to skin a cat. Domain validation wouldn't happen higher than the service that the controller calls. Now whether that "service" is a mediator and validation is part of the pipeline pre-execution, or whether you explicitly call a validator's validate method that's a different story, but even then the validation logic should not throw IMO. It should return an object of some sort capturing the error and then bubble it up appropriately all the way to the controller.
@williamfleetwood4612
@williamfleetwood4612 3 года назад
Isn't OneOf basically Rust response handling in C#? At a quick glance it even appears to have the syntax and semantics
@nickchapsas
@nickchapsas 3 года назад
Yeah it's trying to replicate Discriminated Union behavior
@pilotboba
@pilotboba 3 года назад
How would you eliminate using exceptions for domain validation failures in Jason Taylor architecture. IIRC his template uses exceptions within the mediatr fluent validations. From what I see, mediatr wouldn't allow me to change the return types to OneOf. I think his template also uses an exception filter to return the errors back out of the API.
@nickchapsas
@nickchapsas 3 года назад
You kinda don’t, at least not with the core design. Those clean code architecture templates are linked to the idea that an exception can be thrown from anywhere, especially the domain from value objects. Unless you re architect it a bit, you are stuck
@mohammadmahditalachi9211
@mohammadmahditalachi9211 3 года назад
Thanks for your video But according to clean code book it's better to "Use Exceptions Rather Than Return Codes" If something goes wrong in one of low level module, we have to return that error code in every higher level modules
@nickchapsas
@nickchapsas 3 года назад
This isn't about return codes but rather responses. Also define "Goes wrong". Does a user trying to sign in with an existing email fall under "goes wrong"? I would say no. It's just normal domain behavior which can be represented with a domain object, not with an arbitrary exception. You should still have a "catch-all" middleware for actual exceptions that is from stuff you don't expect or can't control but I wouldn't use them to map into responses.
@paulkoopmans4620
@paulkoopmans4620 3 года назад
I agree with Nick. Notice his clear distinction about early validation and being able to return these validation errors. Whether you return them as OneOf, plain string messages, ValidationResults, etc., anything is better than using exceptions for general code flow. The underlying message is: do not throw exceptions for simple validation or code flow. If you own both the frontend and backend then doing more or even all validation in the front end is desired. Don't make your front end make unnecessary calls to your back end that you know will fail. now if you are only writing a backend api, something you are selling or does not have a single frontend, so therefore many outside clients are using.. you have no choice then to put validation into your backend api. Don't let your api code go way down a call stack and let it fail with an exception if you could have caught it with simple validation. the advice from clean code is definitely true and should also be used. If you would have done your pre-emptive validation and all data seems fine and then only deeper in your method call stack something seems to "go wrong" unexpectedly, for example retrieving a file by passed in file name and you check whether the file exists, then if it doesn't then just use exceptions. Do not try to get tempted into writing code where every method returns some arbitrary integer codes meaning things. Place yourself in the user perspective; if you would be consuming an api and your result code is 0 for the last weeks or months and all of a sudden you'll get a vague 0x00040592 code, that's terrible! I'll hope that you would favour an exception with a descriptive message and possible other data hinting to what is the problem. The clean code advice is also more geared to usage within the language itself, api's on code level, like a dll/package that you are using. WebApi's in that sense have an extra challenge, especially when consumed by different frontend technologies.
@kalleguld
@kalleguld 3 года назад
How does the OneOf version compare to the exception version when there are no exceptions? Is exception handling "free" when no exceptions are thrown?
@nickchapsas
@nickchapsas 3 года назад
It performs the same on the happy path for both approaches. Your code isn't slower for using exceptions. Only throwing them is.
@carlosl8832
@carlosl8832 2 года назад
👍👍
@moreira551
@moreira551 3 года назад
This is an interesting approach but if you have an API that fails 50% of the time you have bigger issues than the cost of exceptions, and if your exception rate is low like 1% 5%, or even 10%, I think the cost is negligible, so it's interesting in theory but maybe not so much in practice, considering that in my opinion exception make the code look cleaner
@Cristian-ek7xy
@Cristian-ek7xy 2 года назад
@@ericnewton5720 Where is it written you shouldn't? Exception means something abnormal has just happened and you won't be able to handle the user's request. Hence it makes total sense to throw an exception.
@JakeAndDaddy
@JakeAndDaddy 3 года назад
Uncle Bob advocates using exceptions to “clean up” code on one of his tomes. There’s a lot he’s written that I don’t agree with. Not convinced he’s ever written anything that needs to perform quickly.
@parlor3115
@parlor3115 3 года назад
Why not use the Go method of returning a tuple which the second element is an error or null? You won't need a third party library this way as well. Win win!
@nickchapsas
@nickchapsas 3 года назад
2 reasons. First tuples need all typle values returned to have the tuple itself returned. If you are forced to return some value or null for the other objects then that's really bad. Also tuples don't force the consumer to handle every possible tuple value. Discriminated unions do.
@protox4
@protox4 3 года назад
Dangit, RU-vid, stop deleting my comments! Yes, exceptions are expensive and should only be thrown in unexpected situations. I made an issue on the CSharpLang github for improving the performance of canceling async functions, you should check it out! (#4565)
@jensingels5958
@jensingels5958 3 года назад
Throwing exceptions in the WebApiServiceLayer is a code smell on itself, to be honest.
@roflex2
@roflex2 3 года назад
Why not just return an enum? And use a switch statement? I'll admit if does look very clever your solution. Good work
@nickchapsas
@nickchapsas 3 года назад
Because enums don't contain the object's data that you might need. Switches don't force you to handle every case. OneOf does.
@roflex2
@roflex2 3 года назад
@@nickchapsas after viewing it a second time I really like it. I think I'll give it a crack.
@ciberman
@ciberman 2 года назад
I think the "performance impact" is responsibility of the compiler and JIT and should not affect the design of the application. Exceptions are by definition anomalous behaviours in the application.
@zabustifu
@zabustifu 2 года назад
True, but should bad requests be considered "exceptional"? I don't think so. Throwing an exception is synonymous with _crashing_ to me, and I don't like my applications to crash because of something like bad input. Anyway, unless you barely have anything to validate, you'd usually use something like FluentValidation to handle this, which does not push you toward relying on exceptions.
@Serotonindude
@Serotonindude 2 года назад
so exceptions are not for free? wow... use them for error cases what they are for... and in those cases the timing doesn't matter... but don't use them for regular flow control... anything new?
@rajm1976
@rajm1976 3 года назад
Basically don't use Exception as a control flow mechanism.
@asdfuzdah
@asdfuzdah 2 года назад
This feels like returning response codes instead of throwing an exception, which directly goes against Clean Code principles for error handling
@DF-ov1zm
@DF-ov1zm Год назад
I can see this approach as some sort of optimization where they are really needed. But common use... it is just a potential catastrophe. Exceptions are not just errors; it is a native way to stop your code from making the situation even worse and maybe rollback the changes you already made before this happened. You can say just use them in critical cases and so on.. but you are just splitting your code in two totally different paradigms of errors handling, which makes tons of potential problems making a totally disaster quite inevitable.
@zerosugarmatcha7348
@zerosugarmatcha7348 3 года назад
You don't call 50% chance "exception".
@simonbaxter8001
@simonbaxter8001 3 года назад
Hate programs that throw exceptions with a passion. I think it's lazy programming and performance wise it's a killer. The number of commercial application that (if you hook up the debugger to the process) throw and 'don't' handle exceptions is getting concerning. The sad thing is that programmers don't even handle the exception s that are thrown and just continue to the point of the crash! Lazy, lazy, lazy ... did I already mention that!?
@navjotsingh1081
@navjotsingh1081 3 года назад
Oneof can lead to verbose method signatures. I guess a simple Result class is enough.
@nickchapsas
@nickchapsas 3 года назад
Yeah Result is a perfect alternative. OneOf can also be encapsulated in its own class to hide the length
@omuleanu
@omuleanu 2 года назад
you could just return bool, or enum, or an object containing whatever you need at the other end
@10199able
@10199able 3 года назад
F# vibes
@lordicemaniac
@lordicemaniac 3 года назад
problem is the OneOf approach will take always same time doesn't matter if response was OK or ERROR, but exception way will take more time only if response is ERROR, in real application you have many more times OK result than ERROR, 50% would be rly bad, i wonder if you would use 20% ERROR in your test, if you still get better time with OneOf
@nickchapsas
@nickchapsas 3 года назад
Without any errors the performance is the same for both speed an allocations. ExceptionVersion | 89.95 us OneOfVersion | 89.97 us You can calculate the offset in performance difference since it will be almost linear since the cost of the exception is pretty much static.
@lordicemaniac
@lordicemaniac 3 года назад
@@nickchapsas you are saying that returning some string in case of using exceptions when no error is same speed as using OneOf construct? how come then the first test without use of any exceptions was so much faster, not just some 20% faster?
@nickchapsas
@nickchapsas 3 года назад
​@@lordicemaniac Because the first test was only focusing on the Exception case. The last tests look at the problem form an external end-to-end perspective and a lot of those concerns are getting load leveled by other stuff that happened in the flow
@lordicemaniac
@lordicemaniac 3 года назад
@@nickchapsas i see... btw i love your videos, keep them coming :)
@feitan8745
@feitan8745 3 года назад
When you realise that exceptions are already a point of failure...
Далее
Don't throw exceptions in C#. Do this instead
18:13
Просмотров 260 тыс.
What is Span in C# and why you should be using it
15:15
How to rate limit (throttle) your ASP.NET Core API
16:41
Making async code run faster in C#
10:28
Просмотров 106 тыс.