There are a lot of duplicates for this question, many of which have a slightly simpler usage scenario where you don't want to capture stderr and stdout and the exit code all at the same time.
if result=$(useless.sh 2>&1); then
stdout=$result
else
rc=$?
stderr=$result
fi
works for the common scenario where you expect either proper output in the case of success, or a diagnostic message on stderr in the case of failure.
Note that the shell's control statements already examine $?
under the hood; so anything which looks like
cmd
if [ $? -eq 0 ], then ...
is just a clumsy, unidiomatic way of saying
if cmd; then ...