Is setting software flags an effective use of interrupts?
To talk efficiency you need to identify what it means for you.

Your design is all right, but as you guess there're other options available like putting execution into ISR rather than in main loop. Let's consider the following:


in your current design when interrupt happens only flag is set; execution, related to the "next" flag will be performed only when main thread finishes processing current flag, and your application will remember that there will be at least one related interrupt (flag is set = related interrupt occur at least once). This is more or less linear approach, which logically and physically separates processing of flags;
now consider you put flag/interrupt processing into ISR. Then you should take very precise care about interrupt enable/disable. If new interrupt comes, it may interrupt service of current "flag" and start servicing new "flag". What (external) process, attached to service of first flag, will think about it? Next, if two same interrupts occur while previous servicing did not finish, will processing overlap and external device malfunction?


You see - there're a number of choices (we see 2 above), and you must select the strategy which best fits the attached device protocols and their timing. There're no wrong ways of doing things, there're ways which lead you into situations when (a) you just can not implement what you want specific way and (2) solution is not scalable (in time or capacity).