Padrão de Projeto State

Documentos relacionados
Programação Orientada a Objetos. Vagner Luz do Carmo - Vluzrmos

Herança. Prof. Fernando V. Paulovich 23 de agosto de 2010

Computação II Orientação a Objetos

Recapitulando. Construtores: (Overload assinatura) public Circle() {...} public Circle(double x, double y, double r) {... }

PROCESSO SELETIVO PARA ESTÁGIO REMUNERADO NO TRIBUNAL DE CONTAS DO ESTADO DO MARANHÃO ENSINO SUPERIOR - INFORMÁTICA

Enums em Java: utilização e persistência

Classe Abstrata e Interface

PROGRAMAÇÃO ORIENTADA A OBJETOS II -TÉCNICAS DE OO. Prof. Angelo Augusto Frozza, M.Sc.

UML (Linguagem Modelagem Unificada) João Paulo Q. dos Santos

INF1013 MODELAGEM DE SOFTWARE

Singleton e Adapter. Professor: Nazareno Andrade (baseado no material de Hyggo Almeida e Jacques Sauvé)

Paradigmas de Programação. Java First-Tier: Aplicações. Orientação a Objetos em Java (I) Nomenclatura. Paradigma OO. Nomenclatura

Introdução à UML. Prof. Jesus José de Oliveira Neto

Carlos S. Rodrigues Leonardo Lino Vieira Eric Felipe Barboza Antonio Vasconcellos

Modelagem Usando Orientação à Objetos (Programação Orientada a Objetos) Prof. Responsáveis Wagner Santos C. de Jesus

Linguagem de Programação. Diagrama de classes

Requisitos de sistemas

PROGRAMAÇÃO ORIENTADA A OBJETOS: OCULTAR INFORMAÇÕES E ENCAPSULAMENTO

Tipos, Literais, Operadores

Tipos, Literais, Operadores

Construtores e Especificadores de Acesso

Computação II Orientação a Objetos

Computação II Orientação a Objetos

INF1013 MODELAGEM DE SOFTWARE


PROJETO DE DADOS PROJETO ARQUITETURAL BÁSICO. Projeto de Programas PPR0001

Computação II Orientação a Objetos

Computação II Orientação a Objetos

Linguagem de Programação II Implementação

UML. Modelando um sistema

Universidade Federal de Uberlândia Faculdade de Computação Programação Orientada a Objetos II Prof. Fabiano Dorça. Padrão Observer (Observador)

Definição. Em POO, a abstração é o processo de esconder os detalhes de implementação de uma aplicação.

INF1013 MODELAGEM DE SOFTWARE

GRASP. Nazareno Andrade (baseado em Hyggo Almeida e Jacques Sauvé)

Computação II Orientação a Objetos

PROGRAMAÇÃO ORIENTADA A

Desenvolva de qualquer sistema operacional para qualquer sistema operacional. Sem limites.

Palavras Reservadas da Linguagem Java

JUnit. Alexandre Menezes Silva Eduardo Manuel de Freitas Jorge

PADRONIZAÇÃO 10. INTERFACES PADRONIZAÇÃO CONTRATOS

Aula 5 POO 1 Encapsulamento. Profa. Elaine Faria UFU

Namespaces, Classes e Métodos.

Model Driven Development (MDD)

Orientação a Objetos Parte I. Introdução a POO (Programação Orientada a Objetos)

Encapsulamento e Métodos (Construtores e Estáticos) João Paulo Q. dos Santos

Lógica de Programação para Jogos

Padrões Fábrica. Simple Factory Factory Method

Programação Orientada a Objetos

FAURGS HCPA Edital 06/2010 PS 51 ANALISTA DE SISTEMA I Fábrica de Aplicativos Pág. 1

Visões Arquiteturais. Visões Arquiteturais

Implementar um exemplo de relacionamento entre classes um para muitos (1:N) e um para um (1:1). Sistema para uma Promotora de Evento Agenda Anual

Esta categoria mais geral, à qual cada objeto pertence, denominamos de classe; IFSC/POO + JAVA - prof. Herval Daminelli

1 Introdução e Conceitos básicos

Linguagem de Programação Orientada a Objeto Polimorfismo, Classes Abstractas e Interfaces

Computação II Orientação a Objetos

Introdução à Análise e Projeto de Sistemas

Injeção de Dependências e Spring

ANÁLISE DE SISTEMAS. Diagrama de atividades. por. Antônio Maurício Pitangueira

Classes e Objetos INTRODUÇÃO À ORIENTAÇÃO A OBJETOS COM JAVA - MÓDULO II. Classes. Objetos. Um modelo para a criação de objetos

Tema da aula Introdução ao paradigma de programação: Orientado a Objetos

Televisao tamanho tela emitirsom. conectarperifericos

A classe ArrayList. IFSC/Florianópolis - Programação Orientada a Objetos com Java - prof. Herval Daminelli

Universidade de Mogi das Cruzes Implementação Orientada a Objetos - Profª. Danielle Martin. Guia da Sintaxe do Java

Herança Tiago Eugenio de Melo

Engenharia de Software

Aula 3 POO 1 Classe e Objeto. Profa. Elaine Faria UFU

Classes, Métodos e Propriedades

Instituto Superior de Engenharia de Lisboa

INF1404 MODELAGEM DE SISTEMAS

Para entender o conceito de objetos em programação devemos fazer uma analogia com o mundo real:

Linguagem de Programação III

Padrões de Projeto. Padrões de Projeto. Além dos 23 Padrões GoF. Os 23 Padrões de Projeto. Documentação de um Padrão. Classificação dos Padrões

Java para Desktop. Programação Orientada à Objetos 2 JSE

Atribuições: Valores, Ponteiros e Referências

Computação II Orientação a Objetos

Compiladores Análise Semântica

POO UML e Outros Conceitos. Prof. Vicente Paulo de Camargo

Organizando seus Testes Funcionais AUMENTANDO A MANUTENIBILIDADE DE TESTES FUNCIONAIS ATRAVÉS DA ORIENTAÇÃO A OBJETOS.

Técnicas para Reutilização de Software

UML Diagramas Estruturais Diagrama de Componentes

Collections Framework

PMR Computação para Automação. PMR Computação para Mecatrônica. Exercício Programa 2 - Versão Package BancoDeDados

Programação Orientada a Objetos

Introdução Diagrama de Classes Diagrama de Seqüência Diagrama de Atividades. Diagramas UML. Classe, Seqüência e Atividades. Marcio E. F.

Ciência da Computação. Análise e Projeto Orientado a Objetos UML. Anderson Belgamo

POO29004 Programação Orientada a Objetos

Programação Orientada a Objetos 2 Flávio de Oliveira Silva, M.Sc.

Análise e Projeto Orientados por Objetos

15/04/2013. Pensar Orientado a Objetos. Projeto Orientado a Objetos. Características de Objetos. Classe de Objetos. Comunicação entre Objetos

Padrão de projeto de software

INE 5612 Professor: Frank Siqueira. Leonardo Silva Jean Ercilio Thiago

Computação II Orientação a Objetos

Programação Orientada a Objetos

Composite. Pronunciação americana: compósit Pronunciação canadense (Britânica): cómposit

Linguagem de Programação IV Introdução

Engenharia de Software e Gerência de Projetos Prof. Esp. André Luís Belini Bacharel em Sistemas de Informações MBA em Gestão Estratégica de Negócios

Pacotes Organizando suas classes e bibliotecas

Lógica de Programação e Algoritmos com exemplos na linguagem JAVA

Polimorfismo. PARTE II: Java e OO. Polimorfismo. Polimorfismo. Polimorfismo. Polimorfismo

Transcrição:

padrão state_ cinto de utilidades MÁQUINAS DE ESTADO COM O Padrão de Projeto State Desenvolver software é trabalhar com abstrações o tempo todo, pois estas nos ajudam a gerenciar a complexidade nos sistemas que desenvolvemos. Uma das abstrações mais poderosas que podemos empregar são as máquinas de estado. Com elas, é possível até complexos autômatos para uso em compiladores máquina de estados é extremamente interessante por ser de fácil construção, sucinto e altamente comunicativo, facilitando bastante a comunicação com os usuários do sistema e especialistas de domínio. No entanto, o que acontece é que muitos utilizam a modelagem de máquinas de estados apenas em nível conceitual, perdendo-o de vista no momento da implementação. Muitos até fazem a modelagem em máquina de estados de uma maneira mais formal usando algo como UML1, mas apenas para propósitos de documentação de requisitos e comu- estados é convertida em diversos ifs, que se espalham por variadas partes do sistema, aumentando as lacunas sintática e semântica entre o modelo de domínio discutido pelas pessoas e o modelo de representar um conceito da linguagem do domínio explicitamente em código, como advogado pelo Domain-driven Design 2. Mas não precisa ser assim! 1. Máquinas de estados são um recurso de modelagem também previsto 2. Para mais detalhes sobre Domain-driven Design, recomendo fortemente Neste artigo, mostraremos como implementar máquinas de estado por meio do padrão de projeto State. Primeiramente, faremos um resumo do padrão e, em seguida, ilustraremos seu uso por meio de um exemplo prático associado com o uso da Java Persistence API. Ressaltamos que este artigo assume que o leitor já possui um conhecimento básico do funcio- desejam mais informações, ver seção de referências). O padrão State O padrão State é um dos 23 padrões de projeto da Gang of Four (GoF), já velho conhecido da comunidade (o livro foi publicado em 1994). Apesar de alguns desses padrões hoje serem até meio controversos (como é o padrão Singleton, por exemplo), o padrão State (juntamente com seu irmão gêmeo Strategy) continua sendo de elevada aplicabilidade nos sistemas desenvolvidos atualmente. A ideia do State é representar os estados de uma máquina de estados por meio de classes que implementam uma interface comum, a qual contém as regras de transição. Cada classe implementa, então, a ação devida quando a transição é acionada por essa interface. O outro elemento do padrão é o chamado contexto, que é a classe da qual o estado faz parte e também é a classe com a qual o restante do sistema interage. Quando uma regra de negócio é acionada a leitura do livro homônimo de Eric Evans. / 26

Alexandre Gazola alexandregazola@gmail.com @alexandregazola Bacharel em Ciência da Computação pela Universidade Federal de Viçosa (UFV) e mestre em Informática pela PUC-Rio. Traba- e editor-técnico da revista MundoJ, além de manter um blog em http://alexandregazola.wordpress.com. Bacharel em Ciências da open source, como KDE e Mentawai, e é da equipe de arquitetura da CodeIT Solutions, uma empresa especializada na prestação de serviços de desenvolvimento de software para as indústrias de seguros. Máquinas de estados são uma construção extremamente comum para se modelar requisitos de diversos sistemas. Normalmente, são fáceis de desenhar (em forma de modelos) e interessantes instrumentos para comunicação e validação com os usuários por serem de simples entendimento. No entanto, muitos desenvolvedores perdem artigo, abordamos o padrão de projeto State, bastante útil para modelagem de máquinas de estado em código. Como sempre, damos uma ênfase mais prática e direta, mostrando uma opção de implementação do padrão em Java usando Enums e a Java Persistence API. ção de uma transição de estado, o contexto dispara do de realizar a ação correspondente e determinar passado como parâmetro ao estado para que o estado possa decidir o estado seguinte, setando um obje- estrutura geral do padrão State. Vamos à seção seguinte, na qual utilizaremos um exemplo concreto para o qual aplicaremos o padrão. Aplicando o padrão State na prática Como ilustração, imaginemos uma aplicação e publicação de artigos para um periódico qualquer. Neste exemplo, estamos interessados em modelar os estados e transições de um artigo. Após discussão CONTEXT + REQUEST ( ) STATE.HANDLE ( ) CONCRETESTATE A Figura 1. Estrutura geral do padrão State. STATE com os usuários, chegamos ao diagrama de estados O modelo apresentado é bastante autoexplicativo. Os estados são representados pelos retângulos e as transições por setas. Tudo começa quando um artigo é submetido pelo sistema. Quando isso acontece, ele vai para o estado Recebido. A partir desse estado, o sistema realiza algumas validações automáticas no artigo, como, por exemplo, ortogra- automática determina se o artigo irá para o estado Aceito para revisão ou Recusado. No estado Recusado, o usuário pode fazer alterações à vontade e realizar uma nova submissão. Uma vez que um artigo esteja Aceito para revisão, um humano fará a leitura e revisão do artigo, determinando se o mesmo está satisfatório, se apresenta erros básicos ou se, simplesmente, foi recusado. Cada um desses eventos faz com que o artigo vá, respectivamente, para os estados Aceito para publicação, Aceito com correções e Recusado. CONCRETESTATE B Implementação tradicional do padrão Agora, vamos ao que interessa: o código! A Listagem 1 apresenta a interface para os estados do nosso modelo, contendo as possíveis transições da máquina. Na Listagem 2 trazemos 27 \

INÍCIO ACEITO PARA REVISÃO satisfatório ACEITO PARA PUBLICAÇÃO validado com sucesso apresenta erros básicos satisfatório ACEITO COM CORREÇÕES submetido RECEBIDO validado sem sucesso submetido recusado recusado RECUSADO FIM Figura 2. Modelagem da máquina de estados para o sistema de publicação de artigos. um exemplo simples de implementação da interface para o estado Recebido. Repare que o código é bastante simples, apenas cabendo ao estado em questão decidir qual é o estado seguinte. As transições que não fazem sentido para um dado estado lançam a exceção não checada UnsupportedOperationException. Listagem 1. Interface para os estados possíveis de um artigo. public interface EstadoArtigo { void submetido(artigo artigo); void validadocomsucesso(artigo artigo); void validadosemsucesso(artigo artigo); void satisfatorio(artigo artigo); void apresentaerrosbasicos(artigo artigo); void recusado(artigo artigo); Listagem 2. Implementação do estado recebido. public class Recebido implements EstadoArtigo { public void submetido(artigo artigo) { throw new UnsupportedOperationException( O artigo está em um estado inválido para a ocorrência do evento submetido : + this); public void validadocomsucesso(artigo artigo) { artigo.setestado(new AceitoParaRevisao()); public void validadosemsucesso(artigo artigo) { artigo.setestado(new Recusado()); /* lançando UnsupportedOperationException igual a submetido()... */ A Listagem 3 exibe o código da classe principal (o contexto do padrão State), por meio da qual o restante da aplicação interage (por isso, os estados podem ter visibilidade restrita apenas ao pacote em que está a classe de contexto). Repare que a classe artigo não precisa ter conhecimento de qual é o estado seguinte ao do evento ocorrido, isso passa a ser uma responsabilidade do estado com que o artigo está atualmente plementação tradicional, provavelmente não haveria os métodos de transição na classe Artigo, e a lógica mente por outras partes do sistema (com os estados modelados talvez até como constantes inteiras, acredite se quiser!). A Listagem 4 mostra um exemplo de como poderia ser esse código sem o padrão. Listagem 3. Classe Artigo (faz o papel de contexto no padrão State). public class Artigo { private EstadoArtigo estado; public void setestado(estadoartigo estado) { this.estado = estado; / 28

public void submetido() { estado.submetido(this); public void validadocomsucesso() { estado.validadocomsucesso(this); public void validadosemsucesso() { estado.validadosemsucesso(this); Listagem 4. Exemplo de implementação tradicional sem usar o padrão State. public class RevisaoArtigoService { /* mais código aqui */ public void revisar(artigo artigo) { /* mais código aqui */ if (artigo.getestado().equals( ACEITO_PARA_REVISAO)) { if (estasatisfatorio(artigo)) { artigo.setestado(aceito_para_publicacao); else if (correcaopodeserfeita(artigo)) { artigo.setestado(aceito_com_correcoes); else { artigo.setestado(recusado); Implementação do padrão com Enum e JPA Uma forma interessante de se implementar os estados é por meio do uso dos tipos enumerados (Enums) oferecidos pelo Java. A ideia é simples: cria-se uma enum com métodos para cada transição e constantes que implementem esses métodos de acordo com suas respectivas lógicas. Normalmente, numa aplicação real, precisaremos armazenar os dados dos artigos e seus estados em um banco de dados. Vamos assumir que queremos usar a Java Persistence API (JPA) com Hibernate para armazenar os objetos no banco de dados, incluindo aí os estados da máquina. O problema, neste caso, é que o Hibernate não oferece um suporte adequado à persistência de enums (existe anotação para isso, mas existem problemas para seu uso usar strings para mapeamento de chaves etc.). Mesmo numa implementação de máquina de estados sem enums, questão dos objetos transientes que já existem dentro do banco (quando um estado necessita realizar uma transição, ele criaria uma nova instância de um estado já existente). Para contornar esse problema, podemos representar as constantes em duas partes, usando uma classe principal (esta, mapeada via Hibernate), a qual delega para um enum que representa o estado da máquina de estados propriamente dito. A Listagem 5 mostra um exemplo de como poderia ser esse código. Desta forma, é possível utilizar as constantes da classe EstadoArtigo (a lógica da máquina de estados também das facilidades de persistência oferecidas pelo Hibernate. Repare que implementamos no contexto da enum todos os métodos de transição, mas com uma implementação default (como se fosse uma classe abstrata). Dessa forma, as constantes enume- zerem sentido. Lembramos que a classe de contexto, Artigo, permanece com o mesmo código. Listagem 5. Implementação do padrão State com Enums e suporte de JPA/Hibernate. @Entity public class EstadoArtigo { public static EstadoArtigo RECEBIDO = new EstadoArtigo(1, EstadosMaquinaEstados. RECEBIDO); public static EstadoArtigo RECUSADO = new EstadoArtigo(2, EstadosMaquinaEstados. RECUSADO); public static EstadoArtigo ACEITO_PARA_REVISAO= new EstadoArtigo(3, EstadosMaquinaEstados. ACEITO_PARA_REVISAO); public static EstadoArtigo ACEITO_PARA_PUBLICACAO=new EstadoArtigo(4, EstadosMaquinaEstados.ACEITO_PARA_PUBLICACAO); public static EstadoArtigo ACEITO_COM_CORRECOES = new EstadoArtigo(5, EstadosMaquinaEstados.ACEITO_COM_CORRECOES); @Id private int private EstadosMaquinaEstados estadomaquina; private EstadoArtigo(int EstadosMaquinaEstados estadomaquina) { this this.estadomaquina = estadomaquina; protected void submetido(artigo artigo) { estadomaquina.submetido(artigo); protected void validadocomsucesso(artigo artigo) { estadomaquina.validadocomsucesso(artigo); protected void validadosemsucesso(artigo artigo) { estadomaquina.validadosemsucesso(artigo); 29 \

protected void satisfatorio(artigo artigo) { estadomaquina.satisfatorio(artigo); protected void apresentaerrosbasicos(artigo artigo) { estadomaquina.apresentaerrosbasicos(artigo); protected void recusado(artigo artigo) { estadomaquina.recusado(artigo); private static enum EstadosMaquinaEstados { void satisfatorio(artigo artigo) { lancarexcecaodefault( satisfatorio ); void apresentaerrosbasicos(artigo artigo) { lancarexcecaodefault( apresentaerrosbasicos ); private void lancarexcecaodefault(string evento) { throw new UnsupportedOperationException( O artigo está em um estado inválido para a ocorrência do evento + evento + : + this); RECEBIDO { void validadocomsucesso(artigo artigo) { ACEITO_PARA_REVISAO); void validadosemsucesso(artigo artigo) { RECUSADO);, ACEITO_PARA_REVISAO { void satisfatorio(artigo artigo) { ACEITO_PARA_PUBLICACAO); void apresentaerrosbasicos(artigo artigo) { ACEITO_COM_CORRECOES); void recusado(artigo artigo) { RECUSADO);, /* implementacao das transicoes omitidas para os seguintes estados... */ RECUSADO, ACEITO_PARA_PUBLICACAO, ACEITO_COM_CORRECOES; Máquinas de estados são uma abstração recorrente em diversos tipos de sistema, constituindo um poderoso instrumento de modelagem e comunicação para usuários e desenvolvedores. Neste artigo, vimos como podemos levar as vantagens desse modelo até o nível do código por meio do padrão State, evitando- -se, assim, o espalhamento das lógicas de transição por diferentes partes do sistema. Destacamos também uma possibilidade de implementação particular para o caso em que é necessária a persistência dos es- Procura conhecer o estado das tuas ovelhas; cuida bem dos teus rebanhos. (Pv 27:23) Gazola /para saber mais /referências void submetido(artigo artigo) { lancarexcecaodefault( submetido ); void validadocomsucesso(artigo artigo) { lancarexcecaodefault( validadocomsucesso ); void validadosemsucesso(artigo artigo) { lancarexcecaodefault( validadosemsucesso ); void recusado(artigo artigo) { lancarexcecaodefault( recusado ); / 30