Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add errors concept #686

Merged
merged 8 commits into from
Aug 12, 2024
Merged

Conversation

meatball133
Copy link
Member

No description provided.

@@ -0,0 +1,5 @@
{
"blurb": "Crystal has modules which can be used for namespacing and organizing code. It can also be used to create mixins and to extend classes.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a copy paste error

raise "This is an error"
```

There are several built-in exceptions in Crystal, like `ArgumentError`, `IndexError`, `KeyError`, `IOError`, `SystemCallError`, `TypeError`, `ZeroDivisionError` and many more, these require you to pass a message to the exception.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
There are several built-in exceptions in Crystal, like `ArgumentError`, `IndexError`, `KeyError`, `IOError`, `SystemCallError`, `TypeError`, `ZeroDivisionError` and many more, these require you to pass a message to the exception.
There are several built-in exceptions in Crystal, like `ArgumentError`, `IndexError`, `KeyError`, `IOError`, `SystemCallError`, `TypeError`, `ZeroDivisionError` and many more.
These require you to pass a message to the exception.

raise ArgumentError.new("This is an argument error")
```

## Handle exceptions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Handle exceptions
## Handling exceptions

Comment on lines 27 to 29
We wouldn't want our program to crash when an exception is raised.

Therefore, when we know a piece of code is error prone, we can wrap it in a `begin` block and rescue the exception with a `rescue` block.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
We wouldn't want our program to crash when an exception is raised.
Therefore, when we know a piece of code is error prone, we can wrap it in a `begin` block and rescue the exception with a `rescue` block.
We wouldn't want our program to crash when an exception is raised.
Therefore, when we know a piece of code is error prone, we can wrap it in a `begin` block and rescue the exception with a `rescue` block.


## Method convention

If you have checked, specific methods have two versions, one with `!` and the other without.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If you have checked, specific methods have two versions, one with `!` and the other without.
Some methods have two versions, one with `!` and the other without.

## 2. Check the number of cows

- `ValidateInputAndDivideFood` has the same function signature as `DivideFood`.
- Since you want to return early in case of an error in Go, you first check whether the number of cows is less or equal than 0 with an if-statement.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Since you want to return early in case of an error in Go, you first check whether the number of cows is less or equal than 0 with an if-statement.
- Since you want to return early in case of an error, you first check whether the number of cows is less or equal than 0 with an if-statement.

Luckily, you don't need to work out all the formulas for calculating fodder amounts yourself.
You use some mysterious external library that you found on the internet.
It is supposed to result in the happiest cows.
The library exposes a class that fulfils the following interface.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The library exposes a class that fulfils the following interface.
The library exposes a class that fulfills the following interface.

"Fulfil" is used in British English and "fulfill" is used in American English.


## 3. Improve the error handling

Checking the number of cows before passing it along was a good move but you are not quite happy with the unspecific error message.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Checking the number of cows before passing it along was a good move but you are not quite happy with the unspecific error message.
Checking the number of cows before passing it along was a good move but you are not quite happy with the vague error message.

Checking the number of cows before passing it along was a good move but you are not quite happy with the unspecific error message.
You decide to do better by creating a custom error class called `InvalidCowsError`.

The custom error should hold the number of cows (`Int32`) and a custom message (`String`) and the `Expection` method should serialize the data in the following format:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The custom error should hold the number of cows (`Int32`) and a custom message (`String`) and the `Expection` method should serialize the data in the following format:
The custom error should hold the number of cows (`Int32`) and a custom message (`String`), and the `Expection` method should serialize the data in the following format:

Some methods raise an exception by default but also have a version ending with `?` which returns `nil` instead of raising an exception.

This is ideal when you want to avoid an error being raised.
This can benefit performance since it doesn't have to create a stack trace and, if setup correctly, could make the code safer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, how would not using an error/exception improve safety?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of that text is based of: https://crystal-lang.org/reference/1.13/syntax_and_semantics/exception_handling.html#alternative-ways-to-do-error-handling.

But using for example nil instead of throwing errors, so will the compiler make you handle nil meanwhile if you have code which throws error the compiler will not make you handle that instead if you are unlucky could make your application just halt execution.

@ryanplusplus ryanplusplus merged commit d7c3b0a into exercism:main Aug 12, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants