Word constituents: ‘w’
Parts of words in human languages. These are typically used in variable and command names in programs. All upper- and lower-case letters, and the digits, are typically word constituents.
Symbol constituents: ‘_’
Extra characters used in variable and command names along with word constituents. Examples include the characters ‘$&*+-_<>’ in Lisp mode, which may be part of a symbol name even though they are not part of English words. In standard C, the only non-word-constituent character that is valid in symbols is underscore " _ ".
Courtesy of gnu.org
When should I use each? For example, given a programming language that writes variables in snake case foo_bar, should _ be part of a word or symbol?
It depends one what you want to achieve. I'll say, '_' should be part of word. That way, foo_bar will be treated as one word.
Please throw an eye to that question, there is an interesting answer talking about superword-mode and subword-mode