Nice article. Thank you for sharing your thoughts. I have spent a lot of time throughout my career thinking about this topic, and implementing both approaches.
I would like to share another look at the exception throwing approach. Using exceptions definitely produces less code than the result pattern. In most cases this is a strong enough argument to choose this option.
We often presume that it is slower because of the performance hit of throwing exceptions. But is this really the case? Exceptions happen when we try to do something that we should not be able to. In most cases we should not worry about this, and try to do proper validation. Or better put, do better action flow.
Hear me out. Let's say we want to delete something. We do this through some UI. We need to load entities (so they exist), and then choose delete action.
If we are trying to delete something that we should not be able to delete, we should not ask ourselves how we will inform FE that this is not allowed. Real question is: How did we find ourselves in this situation?
There are two possible scenarios:
- FE have bug
- our user has malicious intentions and purposely tries to do something that should not be possible
Both cases should be looked at as exceptions that need to be addressed. Now, if we think about all internal company software, or web pages that require login to use API… using exceptions is a completely valid choice because in most cases (almost all) we will have only a happy path. Or we will get an exception because we have a use case that we did not cover.
So, my conclusion is: use exceptions until you need to use the result pattern. I would never use exceptions for something like signing users to the system, because I expect users to mistype their password often. But in most cases… exception it is.