A camada de apresentação
A camada de apresentação é responsável pela interacção com utilizador. É esta camada que é responsável por apresentar os dados ao utilizador e recolher os dados inseridos pelo utilizador. Esta camada é totalmente suportada pela framework po-uilib.
O tipo de interacção suportado por esta framework pode ser visto como um conjunto de menus, em que cada menu é composto por um determinado conjunto de opções. Cada opção vai pedir para realizar uma dada funcionalidade da aplicação ou para apresentar um novo menu. Para representar um menu, o programador da aplicação terá que instanciar a classe Menu da framework po-uilib ou desenvolver uma sub-classe de Menu e instanciar esta subclasse. As duas opções são correctas. Cada opção de um menu é represemtada por uma instância de uma sub-classe da classe Command da framework po-uilib. Estas sub-classe pertencem à camada de serviços.
Esta camada já está concretizada pela framework po-uilib pelo que o programador da aplicação a desenvolver não tem que concretizar qualquer entidade desta camada. A única coisa que o programador da aplicação tem que realizar é indicar a composição de cada menu da aplicação é qual é o fluxo de navegação entre os vários menus da aplicação.
A camada de serviços
A camada de serviços é a camada intermédia entre a camda de lógica de negócio e a camda de apresentação. A camada de serviços é uma camada cujas entidades são relativamente simples. Esta camada é responsável pela definição da interacção com o utilizador que deve ser suportada pela aplicação. Cada funcionalidade que se quer oferecer ao utilizador deve ser concretizada por uma sub-classe de Command a desenvolver pelo programador da aplicação. A classe abstracta Command fornecida pela framework po-uilib é uma abstracção que representa genericamente uma funcionalidade sobre a aplicação que se quer disponibilizar ao utilizador. Por exemplo, no contexto de uma aplicaçãoo bancária, se quisermos que o utilizador possa criar uma conta bancária no banco ou ver o saldo o de uma dada conta bancária, então teremos que ter duas sub-classes de Command, cada uma responsável por uma destas funcionalidades. Cada sub-classe de Command é responsável por pedir os dados ao utilizador necessários para realizar a funcionalidade pretendida e também por apresentar o resultado que resulta da execução da funcionalidade pretendidada.
A leitura e escrita de dados a realizar em cada comando deve ser realizada através das entidades Form e Display da framework po-uilib, respectivamente.
Genericamente, cada funcionalidade a disponibilizar ao utilizador concretizada por um comando deve primeiro pedir os dados necessários para a realização da funcionalidade, depois deve invocar uma entidade do domínio que sabe realizar a funcionalidade pretendida (passando-lhe os dados inseridos pelo utilizador) e depois deverá apresentar ao utilizador o resultado desta execução. Pode não ser necessário pedir dados ao utilizador e pode também não ser necessário apresentar qualquer resultado. No caso da criação de uma conta bancária, o comando que concretiza esta funcionalidade deverá primeiro pedir os dados necessários para a criação da conta (saldo inicial da conta e identificador do titular da conta), depois deverá pedir à entidade do domínio que representa o banco para criar uma conta bancária com os dados inseridos pelo utilizador e, finalmente, deverá apresentar o identificador da conta criada (caso a criação da conta tenha tido sucesso).
Existe um caso particular de comando que não obedece a esta comportamento geral e que acontece quando se tem uma funcionalidade que corresponde a apresentar um sub-menu. Neste caso, o comando que concretiza esta funcionaldiade apenas deverá criar o menu com as opções pretendidas e apresentá-lo.
Estas sub-classes de Command não devem concretizar lógica de negócio como dito anteriormente. Desta forma, teremos um melhor desenho da aplicação e evitaremos estar a concretizar a mesma regra de negócio em diferentes comandos. Por exemplo, suponha que existe a regra de negócio que uma conta bancária nunca pode ter saldo negativo, quem deve verificar se a regra é verificada ou não quando se cria uma conta (ou se levanta dinheiro da conta) é a entidade conta bancária da camada de domínio e não o próprio comando.
A camada de domínio
Esta cama (também designada como camada de lógica de negócio ou o a camada core) contém a realização de todas as entidades que são responsáveis pela lógica de negócio da aplicação desenvolvida. Esta camada é assim constituída por um conjunto de classes que modela e concretiza o domínio da aplicação a desenvolver. Por exemplo, numa aplicação bancária, as entidades do domínio incluiriam as classes Banco, Cliente e Conta as quais concretizariam as funcionalidades inerentes às entidades do mundo real modeladas por estas classes.
Por forma a ter um bom desenho da aplicação, a lógica de negócio associada a cada entidade do domínio deve estar concretizada na própria entidade em causa. Isto permite ter um desenho da aplicação com uma boa qualidade. Por exemplo, a legibilidade da aplicação melhora. É mais fácil perceber a semântica de cada entidade, dado que esta ? concentrada na classe que representa a entidade e não espalhada por várias classes da aplicação. Esta concentração facilita ainda a manutenção do código e a sua evolução. Ao mesmo tempo, evita-se que a mesma funcionalidade acabe por ser replicada em várias classes do domínio da aplicação.
Relativamente à última vantagem, o núcleo de uma aplicação é o conjunto de classes que modela e realiza o problema proposto. A interface com o utilizador dá um aspecto visível possível através do qual se podem realizar pedidos ao núcleo. Uma aplicação pode suportar diferentes interfaces com o utilizador. Por esta razão, o núcleo nunca deve aceder à interface utilizador. Da mesma forma, a interface utilizador não deve realizar operações que representam lógica de negócio relacionada com o núcleo mas apenas recolher dados, passá-los a um ou mais métodos do núcleo, e apresentar os resultados obtidos do núcleo. A lógica de negócio da aplicação a desenvolvida deve estar completamente concretizada nas várias classes do núcleo da aplicação. Desta forma, temos reutilização de código pelas várias interfaces com o utilizador que existam, não sendo necessário estar a repetir código pelas várias interfaces com o utilizador.