Arquitetura do BIS
O BIS (ou BISERP) é um sistema focado em atender de forma ampla as necessidades de uma empresa. Com esse objetivo a arquitetura do BIS precisa ter uma organização que permita escalabilidade a medida que sua abrangência se torna mais ampla, o desenvolvimento e organização do código não devem ser comprometidas. Com isso em mente o BIS foi dividido seguindo principalmente 2 'patterns': Modularidade e Camadas.
Para entender de maneira mais fácil, a princípio imagine o BIS como sendo uma 'coisa' única:

Modularidade
A primeira divisão a entender é quanto a modularidade. O pattern de modularidade define que o sistema deve ter o código dividido em 'blocos' para que permitam: sua reutilização, a centralização do código facilitando a manutenção, tempo e praticidade de desenvolvimento. A modularidade é aplicada no projeto em diferentes níveis. O primeiro nível a se entender é a separação do BIS é por suas funcionalidades. Essa primeira divisão compõe o BISKernel e o BISPlugin.

Essa divisão permite que concentremos no BISKernel os códigos que são usados por toda a aplicação, e serve de base para o desenvolvimento dos BISPlugin que oferecem funcionalidades distintas para o BISERP. Cada Plugin pode ser colocado ou tirado da aplicação para incluir ou não a funcionalidades que aquele Plugin implementa, devendo-se apenas observar as dependências entre Plugins na documentação de cada Plugin.
O principal BISPlugin em desenvolvimento atualmente é o BISModules.
Camadas
O desenvolvimento por camadas, permite que o sistema seja dividido conceitualmente. O patter define que deve-se separar o código de acordo com sua finalidade. No BIS usamos praticamente 3 camadas de separação: persistencia, lógica e apresentação.

As camadas tem a seguinte função:
- persistência - Camada responsável por ter o código usado para salvar os dados recebidos. Nada além disso! Não testa se os dados são válidos, não faz formatações nem conversões além do que for necessário para salvar/persistir os dados.
- lógica - muitas vezes chamada de CRUD é onde toda a lógica do programa é colocada. Entende-se por lógica do programa o código que processa e 'cumpre' o que fora definido como requisitos do sistema. Por exemplo as validações, os cálculos, processamentos, manipulação de dados, etc. Aqui não teremos lógicas de formatação de dados para a localidade do usuário nem manipulamos controles de UI.
- apresentação - esta camada é a responsável por interagir com o usuário, ou mesmo com outros sistema no caso de integração. Aqui mantemos o código que habilita/desabilita controles, traduz mensagens e códigos de erro para a língua do usuário (i18n), etc. É possível, por exemplo termos mais de uma classe de apresentação ao mesmo tempo, por exemplo: uma para exibição de aplicação desktop, outra para mobile, alguma para visualização web, e ainda alguma camada que seja usada para integrar com algum sistema legado ou de outro fabricante. Todas essas diferentes implementações da camada de apresentação acionam a camada de lógica para realizar as funcionalidades do sistema.
Módulos do Plugin
Aqui vamos tomar cuidado para não confundir a 'modularidade' citada acima, com o que o projeto chama de 'módulos'. O módulo é uma divisão interna ao Plugin, que tem mais a função organizacional e lógica do que de implementar o conceito do pattern de modularidade. Essa divisão não é obrigatória, mas normalmente ocorre de acordo com as funcionalidades que o Plugin vai oferecer. Por exemplo, um Plugin desenvolvido para gerenciar compras de uma empresa. Pode ter um módulo de cadastro dos produtos, um módulo para fazer cotação, outro módulo para gerenciar o cadastro dos fornecedores e assim por diante. Os módulos de um plugin não são destacáveis, andam sempre junto do plugin!

No BISCore essa divisão lógica é chamada de serviços, já que em geral eles não tem uma grande funcionalidade se não servir e centralizar funções comuns a toda a aplicação.