A escolha entre uma biblioteca e um arquivo executável é relativamente simples: faz sentido executar o código que você deseja colocar em um executável como um programa independente? Caso contrário, provavelmente deve ser uma biblioteca. Em geral, eu preferiria uma camada executável fina sobre quantas bibliotecas forem necessárias, pois isso facilita a reutilização dessas bibliotecas de back-end posteriormente e elas não estão vinculadas a um programa específico.
Quanto a decidir como dividir seu código entre bibliotecas, você pode achar útil o artigo sobre granularidade do tio Bob Martin .
Nele, ele fala sobre a estrutura OO e define vários princípios que podem ajudá-lo a empacotar seu código adequadamente. Estes também são abordados com mais detalhes em seu livro Princípios, padrões e práticas ágeis em C # .
Vou resumir os princípios abaixo:
O Princípio da Equivalência de Reutilização / Liberação (REP)
O grânulo de reutilização é o grânulo de liberação. Somente componentes liberados por meio de um sistema de rastreamento podem ser efetivamente reutilizados. Este grânulo é o pacote.
O tio Bob define a reutilização como capaz de vincular estaticamente ou dinamicamente a biblioteca reutilizada ao seu programa e nunca ter que procurar seu código-fonte. Quando uma nova versão da biblioteca é lançada, ele pode simplesmente integrá-la ao seu sistema.
Tratar bibliotecas dessa maneira leva apenas a manter as coisas relacionadas juntas no mesmo pacote. Caso contrário, os consumidores da biblioteca talvez precisem atualizar para uma nova versão sem motivo ou ficar algumas versões atrasadas.
O Princípio Comum de Reutilização (CRP)
As classes em um pacote são reutilizadas juntas. Se você reutilizar uma das classes em um pacote, reutiliza todas elas.
Este princípio suporta o acima. Se você tem classes no mesmo pacote que não estão relacionadas entre si, pode estar forçando os usuários da sua biblioteca a atualizar desnecessariamente.
O princípio comum de fechamento (PCC)
As classes em um pacote devem ser fechadas contra os mesmos tipos de alterações. Uma alteração que afeta um pacote afeta todas as classes nesse pacote.
Este princípio fala sobre manutenção. A idéia aqui é agrupar classes com base em como elas podem precisar mudar. Dessa forma, suas alterações podem ser localizadas em uma parte do aplicativo e não se espalhar por todo o lado.
Princípio das Dependências Acíclicas (ACP)
A estrutura de dependência entre pacotes deve ser um gráfico acíclico direcionado (DAG). Ou seja, não deve haver ciclos na estrutura de dependência.
A exclusão de dependências cíclicas permite que cada pacote seja desenvolvido independentemente e "liberado" para o restante da empresa quando novas alterações estiverem prontas. Dessa forma, você não acaba com duas equipes em conflito, esperando uma para a outra terminar um trabalho.