Exceptions Are Your Friends
Do not affraid of
throw new XYZException.
Yazının Türkçe versiyonuna bu link ile ulaşabilirsiniz.
In this article, we will talk about creating exceptions and their advantages. We will also talk about the difference in approach between creating an exception and returning an operation result within a method.
When We Throw Exception
1 — Changing the Exception Type
Suppose we write a method called
Split. Suppose we send the total amount to be paid and the list of people who will share the bill as parameters in this method. Let’s imagine that our method results in returning the amount a person has to pay. If there is nobody to participate in the payment, the division operation executed in C# language creates an exception of the
DivideByZeroException type. In this case, by changing the exception type, we can both write our own explanation and choose a more appropriate error type. In our example scenario, although the reason for the error is that the number cannot be divided by zero, we can better represent the situation with an exception type indicating that the parameter given to the method is not valid.
2 — Unprocessable State
Let’s say we write a calculator as a desktop program. Suppose we return a result by summing the values in the TextBox when the add button is pressed. If the values we have received are not numbers, we are not able to continue the operation. In such cases where we cannot continue the process, we can create an exception and terminate the process.
3 — Unexpected Situation
In some cases, we may not be able to execute the operation even if the parameter we get is in the appropriate format and value range. Such exceptional situations will also be one of the scenarios that we create exceptional cases.
Let’s say you have a resource with cities. The user gives an
Id value and wants to get the information of this city. In a normal situation, the expectation is to have the information of this value in the source. In exceptional cases, when we look at the data source, we may not find a record with the requested
Id value. In this case, we can use the existing exception structures as well as terminate the process by using the exception types that we will define.
You can find more information about exception scenarios from the link below.
Throwing Exception vs Returning Operation Result
Throwing exceptions or returning operation results with an error code are two scenarios that we can use interchangeably. Both of these scenarios have some disadvantages. In this part of the article, we will address these disadvantages.
Note: You can access the sample code snippets in this section via the GitHub link.
Disadvantages of Returning Operation Result
1 — Code Length
In the first code snippet below, we can see the situation where we designed the
Proxy classes that throw an exception when the city depending on the
Id value cannot be found or the air temperature value related to the city name cannot be reached. In this case, let’s assume that the errors are caught by
GlobalExceptionHandler and the appropriate error codes are returned to the user. We can see that the service layer is very simple and very easy to read.
On the other hand, in case we do not manage the exception and return from
OperationResult type, the code block that performs the same function is below. The checks as to whether the response from the calls made to the
Proxy classes contains the result we want, causes the code to stretch and also significantly reduces the legibility.
2 — Missing Operation Result Status Check
In the example above, we saw that after making a method call from the
Proxy class, the return value needs to be checked every time.
NullReferenceException will occur when this check is skipped, ie when the Result value is tried to be used without checking that the
OperationResult operation is completed successfully. This is a situation that we do not want in our practice.
Disadvantages of Throwing Exception
1 — Increased Response Time
In case we create
OperationResult, we consider the response as failed or successful. This situation is no different in terms of software. For this reason, there is no performance difference. Creating an exception is a costly process. For this reason, when we execute an operation that will result in failure, the running time of the code increases.
- When we work with an existing city (CityId = 1), our service structure that uses exception works with a slightly better performance. This is because it deals with less control blocks.
- When we make a transaction with a city that does not exist (CityId = 0), it takes much more time to complete our transaction due to the cost of throwing an exception object.
The issue that lies at the basis of software development is also encountered here. By comparing the pros and cons between the two solutions, we need to find the best solution for our situation.
I ignore the disadvantage in terms of performance because I expect exceptions to be much less than the total number of operations. Considering the advantage of increasing code readability and reducing the possibility of unexpected errors, the method I use more frequently is the error generation method.