Sua consulta está quase certa e é a maneira certa de fazer isso (e a mais eficiente)
SELECT books.*, count(orders.book_id) as number_of_orders
from books
left join orders
on (books.book_id = orders.book_id)
group by
books.book_id
COUNT(*)
poderia incluir valores NULL na contagem porque conta todas as linhas, enquanto COUNT(orders.book_id)
não porque ignora valores NULL no campo fornecido.