A resposta para a sua pergunta (e que costuma ser a mesma para a maioria das situações) é: "Depende".

No caso, este código usa querySelector para buscar vários elementos da página. Mas o que acontece se o script rodar antes da página carregar, ou seja, quando os elementos ainda não estiverem disponíveis?

Por exemplo, se estiver assim:

<html>
  <head>
    <script type="text/javascript">
      function meuPrograma() {
        const nome = document.querySelector('.nome');
        alert('Nome: ' + nome.value);
      }
      meuPrograma();
    </script>
  </head>
  <body>
    <input type="text" class="nome" value="Fulano">
  </body>
</html>

Neste caso dará erro, porque ele tenta buscar por um elemento que ainda não existe (o script roda antes do HTML referente ao input ser carregado). E mesmo se não usarmos a função, continuará dando erro:

<html>
  <head>
    <script type="text/javascript">
      const nome = document.querySelector('.nome');
      alert('Nome: ' + nome.value);
    </script>
  </head>
  <body>
    <input type="text" class="nome" value="Fulano">
  </body>
</html>

Em vez disso, eu poderia fazer assim:

<script type="text/javascript">
function meuPrograma() {
    const nome = document.querySelector('.nome');
    alert('Nome: ' + nome.value);
}
document.addEventListener('DOMContentLoaded', meuPrograma);
</script>

No caso, o evento DOMContentLoaded só chamará a função quando o HTML for completamente carregado.

É claro que eu poderia fazer assim também:

<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
    const nome = document.querySelector('.nome');
    alert('Nome: ' + nome.value);
});
</script>

Ou seja, uso uma função anônima e coloco tudo que preciso lá dentro.


Mas suponha que a função está em um arquivo .js próprio. Então no HTML eu poderia fazer:

<html>
  <head>
    <script type="text/javascript" src="arquivo_que_tem_a_funcao.js"></script>
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', meuPrograma);
    </script>
  </head>
  <body>
    <input type="text" class="nome" value="Fulano">
  </body>
</html>

Ou seja, separo a definição da função do seu uso, e assim fica mais organizado (pode ser que outro arquivo precise da função em outras circunstâncias, por exemplo, ao clicar em um botão, etc).

Enfim, colocar tudo em uma única função é algo que pode fazer sentido, dependendo do caso. Mas tem vezes que pode ser um exagero, por exemplo, se for algo que precise rodar imediatamente e não vai ser reusado em lugar nenhum, aí talvez não justifique.

Com a tag script podemos usar o atributo defer e o prefer. O defer serve para renderizar todo conteúdo estático e só depois os scripts, muito útil para pessoas que gostam dos scripts na tag head como eu. Segue o link da documentação: https://developer.mozilla.org/pt-BR/docs/Web/HTML/Element/script#defer