You only need to use the special variable $? when you need its value across several invocations of other utilities. For example, you may want to output it in a diagnostic message and then return it from a function. Outputting something with printf would reset $? to the exit-status of printf, so you wouldn't be able to do return "$?" (or return) directly afterward to return the original exit-status. Notice that even testing something with [ ... ] resets $?. You would probably instead assign $? to some other variable and use that.
You might want to consider using $? in an if statement if that is the style used in the rest of the project. In that case, remember to quote the expansion, as technically, $IFS might contain digits, which means the unquoted expansion of $? would potentially disappear entirely or partially.
utility
# shellcheck disable=SC2181
if [ "$?" -eq 0 ]; then
echo ok
else
echo fail
fi
However, this makes for much typing and makes the code slightly obfuscated and a bit unnecessarily tricky to follow. Note that the invocation of utility above is not connected to the if statement following it in any immediate way.
There is additionally a bit of extra redundancy here since the if statement is now examining the exit-status of the [ utility to test whether a variable is zero or not. The variable is the exit-status of another utility, which we could have used with if directly.
if utility; then
echo ok
else
echo fail
fi
Here it's clear that the invocation of utility is an integral part of the if statement.
See also the rationale behind the SC2181 warning in the ShellCheck wiki.
if findmnt /dev/sda1 >/dev/null; then echo 1; else echo 0; fiwould be a more direct equal of the first one. Using!there flips the sense of the test.findmnt.