There are many design constraints that can drive the decision. My app has a combination of interrupt and polling:
External and internal clock sources trigger interrupts - it's critical to
timestamp both accurately so we can synchronize them.
Incoming serial messages trigger interrupts. The recieve FIFOs must be serviced before they overflow.
Outgoing messages trigger interrupts when the FIFO is partially empty - it must be refilled before it underflows.
The ISR's set semaphores that are polled for in the background. This has 2 advantages:
The computation needed to handle incoming events can be lengthy; if it were left in the ISR it could delay other ISRs beyond their service deadlines.
Events can be sequenced. For instance, a polling loop can ensure that calculation X always occurs between ADC data collection and incoming message parsing, even if sometimes the message arrives a little earlier than expected.