# Assignment 1 part 1 Notes
- Don't throw an exception and catch it in the same place, e.g.
```cpp=
try
{
if(!something) throw std::runtime_error("some error happened");
}
catch(std::runtime_error &e)
{
std::cout << "I caught exception with message " << e.what() << std::endl;
}
```
`try`/`catch` blocks should be used to check for exceptions being thrown inside functions that you are calling. Throwing exceptions should be done if you need to pass the error handling up a level (to the calling function); if you can handle the error inside the same function then there is no need to throw an exception.
- Functions should have error handling if errors are possible. For example, a function which is valid for all positive numbers should have error handling if it takes `int` as input, since `int` can be negative. However, if it takes a `uint` (unsigned integer, which is always positive), then the function may not have any error cases which need to be handled.
- Writing a function with no error handling on the assumption that you (and anyone _else_ who uses it) will never provide it with invalid inputs is not sufficient.
- Error handling can also mean consistency checks: some functions may complete but leave your program in an invalid state. For example, what happens if you load a game of life grid file where the rows are different lengths? If the rest of your code assumes that the grid is rectangular, so all rows are the same length, then this would be an invalid state which would need to be checked for upon loading.
- Unit tests should be written for each of your functions, and they should test the function thoroughly for both valid _and_ invalid inputs. Unit tests are frequently:
- Missing for some functions
- Fail to check multiple cases or edge cases
- Do not check for failure / invalid inputs