.Net Remoting – Pizzaria
1º Trabalho PráticoTecnologias de Distribuição e Integração
4º Ano do Mestrado Integrado em Engenharia Informática e Computação
João Carlos Figueiredo Rodrigues Prudêncio – [email protected] Seraphin Rodrigues Miranda – [email protected]
Faculdade de Engenharia da Universidade do Porto Departamento de Engenharia Informática Rua Roberto Frias, s/n, 4200-465 Porto, Portugal
2
Índice
1. Introdução ... 3 2. Descrição Problema ... 3 3. Visão Geral ... 4 3.1 Arquitectura... 4 3.2 Descrição Módulos ... 6 4. Interface Gráfica ... 8 5. Testes ...11 6. Conclusão ...12 7. Bibliografia ...12Índice de figuras
Ilustração 1 - Arquitectura geral ... 4Ilustração 2 - Arquitectura específica do sistema ... 5
Ilustração 3 - Página ASP ... 9
Ilustração 4 - Lista de pedidos página ASP ... 9
Ilustração 5 - Interface Gráfica Kitchen ...10
3
1. Introdução
Este projecto foi realizado no âmbito da Unidade Curricular Tecnologias de Distribuição e Integração, pertencente ao 4º ano do Mestrado Integrado de Engenharia Informática e Computação.
O principal objectivo deste trabalho é explorar a tecnologia .NET Remoting. Esta API permite ter acesso a objectos remotos. Usou-se como ambiente de trabalho o Visual Studio 2010, e como linguagem de programação C# e ASP.
Pretende-se implementar um sistema para gerir uma Pizzaria. Tendo em conta que existem diferentes processos desde o pedido até à entrega de uma Piza, implementou-se um sistema que gerisimplementou-se os vários terminais.
Neste documento irá ser feita uma descrição pormenorizada do problema no capítulo 2. De seguida, aborda-se aspectos arquitecturais da implementação, tendo em conta a divisão em diferentes módulos. Posteriomente é feita uma abordagem à interface gráfica implementada. Finalmente, apresenta-se a metologia de testes usada, assim como, as conclusões gerais do trabalho.
2. Descrição Problema
O problema proposto consiste na implementação de um sistema de gestão de encomendas para uma pizzaria. A pizzaria deve ter uma interface online que permite aos clientes poderem encomendar pizzas. Essas pizzas podem ser de vários tipos e tamanhos diferentes. O utilizador deverá poder adicionar ingredientes extras à pizza. Com base nas escolhas do cliente, o sistema deverá calcular o custo da respectiva pizza. Para facilitar a transacção o cliente deverá pagar a encomenda através do seu cartão de crédito. Após efectuar a encomenda o sistema deverá enviar o pedido de encomenda à cozinha que confeccionará a pizza segundo o pedido recebido.
Depois da pizza ser confeccionada deve ser entregue ao cliente. Para o efeito a cozinha deverá lançar, através do sistema, um pedido de entrega às equipas de entrega de pizzas, para a morada do cliente. Note-se que cada equipa de entregas encontra num terminal diferente. Após uma equipa escolher um pedido, apenas essa equipa conseguirá visualizar o pedido.
4
3. Visão Geral
3.1 Arquitectura
Perante o problema descrito anteriormente, optou-se por uma solução onde existe um objecto remoto num Servidor. Esse objecto conterá a lista de pedidos, e poderá ser acedido remotamente por outros terminais. A figura seguinte ilustra a arquitectura geral do sistema, onde possível analisar a interacção entre os diferentes módulos.
Ilustração 1 - Arquitectura geral
Após a estruturação geral do sistema, foram feitas algumas opções num nível mais baixo da arquitectura. Na figura seguinte ilustra-se os diferentes módulos que foram desenvolvidos.
5
Ilustração 2 - Arquitectura específica do sistema
Existe o módulo relativo ao servidor, que contém o objecto remoto. Este objecto remoto é uma instância da classe OrderCentral. Note-se que este objecto extende de
MarshalByRefObject, de forma a permitir que este seja invocado remotamente. Este objecto contém uma lista com todas as ordens.
De forma aos restantes módulos, que podem estar em locais remotos, conseguirem aceder a ao objecto OrderCentral, foram criadas três interfaces diferentes para cada um desses módulos. Esta solução é bastante elegante e segura, porque assim não é necessário disponibilizar ao cliente, o código-fonte da classe OrderCentral. Assim sendo, apenas se disponbilizam os cabeçalhos das funções e atributos, espefícicos, que queremos dar acesso.
Note-se que estas Interfaces encontram-se num ficheiro específico, denominado Shared. Como o nome indica, é um ficheiro que será partilhado por todos os módulos. Relativamente ao módulo de Cliente, criou-se então a interface IOrderClient, dando acesso apenas a funções que permitem criar novas ordens, e visualizar a listagem das mesmas. Além disso existe uma página desenvolvida em ASP, onde o utilizador pode efectuar os pedidos.
Além disso, é importante realçar que quando uma nova ordem é criada, é lançado um evento do tipo NewOrderEvent.
6
questões. Para isto acontecer, é necessário que a Kitchen recebe as novas ordens criadas. Assim, existe a subscrição a um evento denominado NewOrderEvent. Sempre que uma nova ordem for criada, a Kitchen vai ser notificada através da classe intermédia NewOrderRepeater.
Por fim, a Delivery Room possui também uma interface específica, IOrderDeliver, que permite ter acesso à camada relativa às entregas. Desta forma, subscreve-se a vários eventos. Consoante cada tipo de evento, irá tomar acções diferentes. Novamente, usa-me uma classe intermédia UpdateOrderRepeater para tratar estas actualizações.
3.2 Descrição Módulos
3.2.1 Módulo Kitchen (Cozinha)
O módulo Kitchen, desenvolvido na aplicação KitchenGUI, contém a interface gráfica que permitirá a interacção do utilizador com o sistema. A aplicação KitchenGUI trata dos pedidos recorrendo ao objecto remoto que implementa a interface IOrderKitchen. Deste modo, garante-se que a aplicação KitchenGUI aceda exclusivamente às funcionalidades e estruturas de dados previamente identificadas na interface do objecto remoto. Esta abordagem estrutural garante alguma segurança no controlo de acesso aos dados.
3.2.2 Módulo DeliveryRoom (Sala de entregas)
O módulo DeliveryRoom, tem um Form que permite ao utilizador visualizar os pedidos. Sempre que há uma actualização de um pedido na Kitchen assinalando que o pedido já está pronto, esse pedido aparece na lista de pedidos na Delivery Room. A nível de implementação, existe a subscrição do evento IsReadyEvent, sendo existir um handler para esse evento.
Cada Delivery Room pode escolher um pedido da lista para entregar. Após seleccionar esse pedido ficará alocado apenas a essa Delivery Room. Isto significa portanto que novamente há uma subscrição a um evento do tipo DeliverEvent, sempre que este evento acontecer, o pedido deixa de aparecer na lista de pedidos gerais às equipas, e ficará visível apenas na equipa específica.
7
3.2.1 Módulo Server (Servidor)
O servidor é responsável pela activação do objecto remoto. Optou-se por uma activação do tipo Singleton, em que apenas existirá uma instância do objecto. Esta opção é óbvia, no sentido em que é necessário manter o estado do objecto ao longo do tempo, e passar esse estado a outros módulos remotos.
Note-se que o servidor não tem interface gráfica, tendo apenas uma aplicação do tipo consola, onde não é possível qualquer interacção.
A nível de configurações, apenas é necessário alterar o ficheiro de configuração, caso se queira alterar a porta ou o URI, não sendo necessário qualquer processo de compilação.
3.2.1 Módulo OrderCentral (objecto remoto)
Relativamente a este módulo, vai existir um objecto do tipo OrderCentral, que como já foi referido extende de MarshalByRefObject, e além disso implementa as várias interfaces.
Este módulo contém uma lista de objectos do tipo OrderBasic. A definição desta classe encontra-se no módulo Shared.
Como implementa todas as interfaces, irá ter a definição de todas as funções que permitem interargir com os pedidos e lançar os diferentes eventos.
Além disso existem também funções para persistir as ordens para ficheiro, assim como a lista de pagamentos efectuados.
É de realçar a metodologia para invocar os eventos, percorrendo todos os subscritores, e tentar enviar o evento para cada um individualmente. Caso não se consiga estabelecer a ligação, é retirado da lista de subscritores, e nada é enviado. Desta forma, o sistema pode continuar a correr naturalmente, mesmo que alguns subscritores já não estejam activos. De seguida, ilustra-se o algoritmo adoptado.
private void callEvent(AlterOrderHandler ev, OrderBasic ord) {
if (ev != null) {
Delegate[] invList = ev.GetInvocationList(); foreach (AlterOrderHandler handler in invList) {
try {
IAsyncResult ar = handler.BeginInvoke(null, ord, null, null); }
catch (Exception ex) {
8
} } }
3.2.1 Módulo Shared (Partilhado/Comum)
Como já foi referido anteriormente, este módulo será partilhado por todos os outros. Contém as várias interfaces e as classes intermédias. Além disso contém as classes OrderBasic e Payment, ambas Serializable uma vez que vão ser enviadas de um módulo para o outro.
Pensamos que esta é a maneira mais robusta de partilhar o código entre vários módulos, dando acesso apenas ao que é realmente necessário.
4. Interface Gráfica
O módulo Kitchen, contém a interfaces gráfica, na qual se pode visualizar todos os pedidos nos estados “Ordered” e “In Preparation”. O estado “Ordered” corresponde a uma encomenda de uma pizza que chegou à cozinha mas que ainda não foi tratado. O estado “In Preparation” corresponde a uma encomenda de uma pizza que está a ser confeccionada.
De seguida, mostra-se algumas imagens da interface gráfica, ilustrando também o fluxo de dados desde que um pedido é feito até ser entregue.
9
Ilustração 3 - Página ASP
Após efectuar o pedido, pode também visualizar todos os pedidos que já efectuou, através da opção “See Orders”.
Ilustração 4 - Lista de pedidos página ASP
10
Após terminar a confecção, deverá novamente alterar o estado para “Ready”, e esse pedido deixará de estar presente na lista.
Ilustração 5 - Interface Gráfica Kitchen
11
Ilustração 6 - Interface Gráfica Delivery Room
É visível na parte superior da Form, que este terminal está associado a um ID. Quando se abre uma nova Delivery Room, é gerado automaticamente um ID. Caso o utilizador quiser recuperar outras encomendas que estava a processar, deverá indicar o ID que lhe foi atribuído inicialmente.
O estafeta analisa toda a informação do pedido, e pode escolher entregá-lo. Após a selecção de um pedido, esse pedido apenas aparecerá na lista relativa aos pedidos em entrega, e apenas aparecerá neste terminal.
5. Testes
Para determinar o correcto funcionamento da aplicação foram realizados alguns testes que comprovam o correcto funcionamento da aplicação. Estes testes têm o intuito de validar as funcionalidades desenvolvidas, relativamente aos requisitos determinados na análise dos requisitos da aplicação.
Durante a fase de testes, foi testada a aplicação em rede a qual funcionou correctamente.
12
enviando só para os subscritores activos, a aplicação manteve-se estável em todos os testes.
Também se teve o cuidado de proteger as zonas críticas do código. Um desses casos é quando duas equipas de entregas, em simultâneo, efectuam uma mudança de estado do pedido. Essa mudança deve ser persistida num único ficheiro, o que poderia levar à ocorrência de bloqueios ou mesmo erros. Para evitar isso, usamos o mecanismo do C#, critical section.
A abordagem utilizada no desenvolvimento do sistema foi a abordagem incremental. No fim de implementar e integrar cada funcionalidade, tivemos o cuidado de testar exaustivamente essas funcionalidades. Nesta mesma abordagem, inicialmente tinhamos a aplicação a funcionar em modo consola. Quase no final da implementação, convertemos as nossas aplicações em modo consola em interfaces gráficas.
6. Conclusão
Foram atingidos todos os objectivos inicialmente definidos para a elaboração do projecto. As funcionalidades definidas inicialmente também foram concretizados com sucesso.
Durante o desenvolvimento foram discutidas várias arquitecturas para a aplicação. Acreditamos que a nossa arquitectura, discutida anteriomente, seja adequada ao ambiente na qual se insere.
Na arquitectura desenvolvida tivemos o cuidado de garantir o controlo de acesso aos dados, através da implementação de interfaces, garantido alguma segurança.
Este projecto foi essencial para a aplicar os conhecimentos adquiridos sobre C# e .NET Remoting.