Em resposta à sua primeira pergunta, o maior problema ao verificar se um usuário tem uma função e não uma permissão específica é que as permissões podem ser mantidas por várias funções. Como exemplo disso, um desenvolvedor pode ter acesso para ver o portal do desenvolvedor na intranet da empresa, que provavelmente também é uma permissão mantida por seu gerente. Se um usuário estiver tentando acessar o portal do desenvolvedor, você terá uma verificação semelhante a:
if(SecurityUtils.hasRole(developer)) {
// Grant them access to a feature
} else if(SecurityUtils.hasRole(manager)) {
// Grant them access to a feature
} else if...
(Uma switch
declaração no seu idioma de escolha seria melhor, mas ainda não particularmente organizada)
Quanto mais comum ou amplamente realizada uma permissão, mais funções de usuário você precisa verificar para garantir que alguém possa acessar um determinado sistema. Isso também levaria ao problema de que toda vez que você modificar as permissões de uma função, será necessário modificar a verificação para refletir isso. Em um sistema grande, isso se tornaria muito difícil de manejar muito rapidamente.
Se você simplesmente verificar se o usuário tem a permissão que lhes permite acessar o portal do desenvolvedor, por exemplo, não importa qual a função que eles desempenham, eles terão acesso concedido.
Para responder à sua segunda pergunta, o motivo pelo qual você tem funções é que elas agem com a facilidade de modificar e distribuir "pacotes" de permissões. Se você possui um sistema com centenas de funções e milhares de permissões, a adição de um novo usuário (por exemplo, um novo gerente de RH) exigiria que você passasse e concedesse a ele todas as permissões que outros gerentes de RH possuem. Isso não seria apenas entediante, mas também propenso a erros se feito manualmente. Compare isso simplesmente adicionando a função "Gerente de RH" ao perfil de um usuário, o que concederá a eles o mesmo acesso que qualquer outro usuário com essa função.
Você pode argumentar que pode simplesmente clonar um usuário existente (se o seu sistema oferecer suporte a isso), mas, embora isso conceda ao usuário as permissões corretas para esse momento, tentar adicionar ou remover uma permissão para todos os usuários no futuro pode ser difícil. Um exemplo de cenário para isso é se, talvez no passado, a equipe de RH também estivesse encarregada da folha de pagamento, mas mais tarde a empresa se tornasse suficientemente grande para contratar pessoal especificamente para lidar com a folha de pagamento. Isso significa que o RH não precisa mais acessar o sistema de folha de pagamento, para que a permissão possa ser removida. Se você possui 10 membros diferentes de RH, precisará passar manualmente e remover a permissão correta, que introduz a possibilidade de erro do usuário. O outro problema com isso é que ele simplesmente não escala; À medida que você ganha mais e mais usuários em uma determinada função, torna muito mais difícil a modificação de uma função. Compare isso com o uso de funções, onde você precisaria modificar apenas a função abrangente em questão para remover a permissão, que seria refletida por todos os usuários que possuem essa função.