Make your Models Error Friendly

Don’t make your model spew nonsense error messages. You’re missing out on the benefit of abstraction layers.

pancy
Code Zen
2 min readOct 26, 2019

--

If you have programmed in Go for a while, you know that one of its distinct characters is its error handling, for better or worse. Some people like it because it is very explicit, some people hate it because it is (“I want to catch it rather deal with it!”).

This post is not about that, but it’s about how handling errors the human way from the depth of the model layer can make life easier for yourself and the users.

Just because your model talks to the database does not mean it should bypass its job of making errors more personal and abstract. My good rule of thumb (in Go, at least) is if a function or method is exported, it should return graceful error messages.

For example, if your model has this:

package modeltype User struct {
id int
Name string
Email string
}
func GetUserByEmail(email string) (*User, error) { var user User err := db.QueryRow("SELECT * FROM user_table").Scan(
&user.id,
&user.Name,
&user.Email,
)
// This is bad
if err != nil {
return nil, err
}
return &user, nil
}

Then it’s bad because now the caller (from the controller, route, or any other package) can’t possibly know the error and how to handle it. Yourself won’t even know what this error looks like until it bubbles up to the caller and you might have to spend time debugging.

Be bold and decisive. Make the model creates an error of its own and decide what it is. Don’t miss out on the benefit of abstraction layers. Do this:

if err != nil {
return nil, fmt.Errorf("Error getting user %s\n", email)
}

Now you will have an easier time locating the error. You can choose to print out the original error to help you understand the underlying cause.

One more thing to add is if your functions or methods are exported, don’t panic or crash the program there. They are meant to be used by others, so be courteous. Only log.Fatal inside unexported ones. In fact, most of the time, you want to only do that in a controllable environment, like in the main function where the program really runs (and crashes). Other layers shouldn’t get to decide whether to run or crash the program.

Happy crashing.

--

--

pancy
Code Zen

I’m interested in Web3 and machine learning, and helping ambitious people. I like programming in Ocaml and Rust. I angel invest sometimes.