O Transaction Script é um padrão arquitetural de software que organiza a lógica de negócio da sua aplicação em procedimentos onde cada procedimento lida com uma única solicitação da apresentação.

Cada transação da sua aplicação terá um Transaction Script, embora subtarefas comuns possam ser separadas em procedimentos.

Funcionamento do Transaction Script

Toda lógica do Transaction Script é organizada primariamente pelas transações que você executa usando o sistema. Todos os procedimentos necessários para executar a lógica da sua aplicação ficam dentro de um único procedimento encarregado de fazer toda a transação. Por exemplo, digamos que você queira retirar um material de um estoque, nesse caso a verificação se o material se encontra em estoque, se há o número necessário de materiais em estoque para satisfazer a necessitada solicitada, e a retirada do material do estoque fazem parte de um único procedimento.

Quando utilizar Transaction Script

O grande beneficio do Transaction Script é a sua simplicidade. Organizar uma aplicação através do Transaction Script é natural quando se tem pouca quantidade de lógica na sua aplicação, além de envolver pouco overhead, tanto em termos de desempenho quanto em compreensão do funcionamento da aplicação. Você começa a perceber que não é mais hora de utilizar Transaction Script quando sua aplicação começa a ter muita duplicação de código entre as transações. Refatorações podem melhorar a situação, porém a melhor forma de organizar o seu código é partir para um Modelo de Domínio que é uma outra forma alternativa ao padrão Transaction Script para organizar o seu código. O padrão Modelo de Domínio será discutido no próximo artigo.

Um exemplo de utilização de Transaction Scripts são os Web Services que em grande parte utilizam este padrão para a sua organização.

Formas de Organizar um Transaction Script

Basicamente temos duas formas de organizar o Transaction Script:

  • Vários Transaction Scripts numa classe, onde cada classe implementa uma fase diferente dos seus scripts. Essa forma de organização é mais intuitiva.
  • Uma classe para cada Transaction Script, onde define-se uma superclasse que especifica um método de execução. Essa forma de organização permite controlar as instancias de scripts em memória em run time.

Exemplo de Utilização do Transaction Script

Nos exemplos abaixo é demonstrado como um projeto corporativo decidiu organizar os testes da sua aplicação. Será demonstrado abaixo como foi utilizado o Transactrion Script para testar a inclusão e exclusão de pacientes usando Java e Junit. O padrão Transaction Script é bastante utilizado para organizar os testes de software automatizados pela razões já citadas anteriormente. Também é muito mais simples dos desenvolvedores entenderem como funciona a aplicação apenas olhando os testes através dos Transaction Scripts que são simples e muito intuitivos. Não esqueçamos que os testes são as fontes mais valiosas, atualizadas e precisas de documentação de como sua aplicação realmente funciona.

Procurou-se mostrar o teste mais simples feito numa aplicação real para dar a ideia mais clara ao leitor de como é utilizado o Transaction Script no sistema sem dispersar a atenção em regras que não são o objetivo de estudo aqui.

A forma de organização escolhida é uma classe para cada Transaction Script conforme foi discutido anteriormente.

Primeiramente no código abaixo se definiu a interface padrão que será utilizada por todas as classes de teste.


package com.meu.sistema.teste.acoes;

public interface Acao {
	public Integer execute();
}
Listagem 1. Interface padrão para todas as classes

Abaixo tem-se uma implementação da inclusão de um paciente no sistema. Repare a implementação da interface comum Acao.


package com.meu.sistema.teste.acoes;

public class AcaoIncluiPaciente implements Acao {

	//Contem toda a lógica para a inclusão do paciente e verificação se ele foi incluido	
	public Integer execute() {

    	//Inclui Paciente
    	Log.log("Incluindo um paciente no Sistema..."); 
    
	//Chama a segunda camada que faz a inserção do paciente no sistema real
    	PacienteRN paciente = new PacienteRNImpl();
	//DadosPaciente.getED() contem gets e sets com informações do paciente a 
	//ser inserido com todos os dados necessários já configurados
    	paciente.inclui(DadosPaciente.getED() );

    	Log.log("Paciente incluído com sucesso: " + 	DadosPaciente.getED().getNomePac()); 

    	//Consulta Paciente
    	Log.log("Consultando um paciente no Sistema...");
	//PacienteED contém gets e sets com dados do paciente que foi retornado da consulta, 
	//os dados foram preenchidos na pesquisa ao banco de dados
    	PacienteED pacienteED = paciente.consulta(DadosPaciente.getED());

	//Verifica se o paciente que foi passado é o mesmo que foi inserido e consultado anteriormente
    	Assert.assertEquals( pacienteED.getNomePac(), 	DadosPaciente.getED().getNomePac());
    
    	Log.log("Paciente consultado com sucesso: " + 	DadosPaciente.getED().getNomePac());
	
	//Retorna o número interno do paciente inserido para ser usado em outros pontos da aplicação 
	//como por exemplo uma inserção de tratamento que necessitaria de um paciente já incluído 
	//no banco de dados
	return pacienteED.getNroIntPaciente;
    }
	
}
Listagem 2. Implementação da interface Acao

Abaixo mais uma funcionalidade sendo implementada com Transaction Script. Novamente implementa-se a interface padrão e sobrescreve-se o método execute().


package com.meu.sistema.teste.acoes;

public class AcaoExcluiPaciente implements Acao {

	public Integer execute() {

    	//Exclui o Paciente
    	Log.log("Excluindo o paciente do Sistema..."); 
    
	//Chama o método exclui da lógica de negócio da aplicação para excluir 
	//o paciente previamente incluído no sistema.
    	paciente.exclui(DadosPaciente.getED() );

    	Log.logLast("Paciente excluído com sucesso: " + DadosPaciente.getED().getNomePac()); 
		
		return null;
	}
}
Listagem 3. Sobrescrevendo o método execute

Abaixo uma demonstração de como é simples a chamada ao Transaction Script criado anteriormente.


package com.meu.sistema.teste.suites.paciente;

public class TesteIncluiPaciente extends TestCase{
	
	//Este método sempre será chamado quando executar o teste, sua função é chamar 
	//o Transaction Script que contem a lógica para a inclusão do paciente.
	public void testExecute() {

		//Insere
	    Integer nroInt = new AcaoIncluiPaciente().execute();
	    
		//guarda o número interno do paciente que será utilizado em outras transações
	    DadosPaciente.setNroIntPac(nroInt);	    
	}
Listagem 4. Chamada ao Transaction Script criado

Nesta aplicação decidiu-se por criar uma funcionalidade para cada classe, que é a forma mais utilizada, lembre-se do que diz o padrão em que deve-se organizar a lógica de negócios por procedimentos, onde cada procedimento lida com uma requisição da camada de apresentação. Aqui a camada que chama a lógica do teste é a classe TesteIncluiPaciente acima que esta se comportando como uma classe de apresentação que faz a requisição e o procedimento neste caso é o execute na classe AcaoIncluiPaciente e da classe AcaoExcluiPaciente que deve lidar com a requisição e toda a lógica necessária.

Conclusão

Neste artigo procurou-se demonstrar na prática como este padrão simples mas muito utilizado é implementado nas aplicações. A sua forma simples e intuitiva é uma das suas grandes vantagens para ser adotado em diversos tipos de aplicações.

Bibliografia: