- Design Patterns na prática – Parte 1
- Design Patterns na prática – Parte 2
- Design Patterns na prática – Parte 3
Se você leu a terceira parte desta série, você aprendeu o quanto é importante criar classes que tenham apenas uma única responsabilidade. Também aprendeu a identificar as responsabilidades de uma classe e como fazer para separá-las. Agora está na hora de criar o banco de dados da aplicação. É claro que o resultado deve ser um código flexível o suficiente para que o SGBD possa ser alterado com pouco esforço.
Na última parte desta série o agendador sofreu grandes modificações. O comportamento do sistema continua o mesmo, pois nenhuma nova função foi adicionada. Porém internamente muita coisa mudou. Em outras palavras, o agendador continua fazendo a mesma coisa, mas de maneira diferente. O principal problema que foi corrigido na segunda versão (parte 3) era o acúmulo de responsabilidades sobre a classe do formulário, pois esta classe possuía todas as regras de negócios da aplicação. Após identificar este problema, o que fizemos, foi separar estas responsabilidades em mais classes e o design do sistema ficou como o apresentado na Figura 1.
Uma vez que a maioria dos problemas de engenharia foi corrigida, está na hora de implementar uma das funções mais importantes: salvar as informações no banco de dados. Até agora o aplicativo não persiste as informações, ao invés disto, cada tarefa é adicionada a uma variável do tipo List e é claro que quando o sistema é fechado esta lista é perdida. Agora que o sistema já está mais maduro é possível implementar a persistência dos objetos.
O objetivo da alteração
É preciso retirar da classe do formulário toda a responsabilidade referente ao ato de salvar informações. Como você pode ver na Listagem 1, o código para salvar uma tarefa é muito simples, basta adicionar a nova tarefa na variável utilizada como banco de dados temporário da aplicação – veja linha 10 da Listagem 1. Normalmente é necessário mais código para salvar um registro como, por exemplo, abrir uma conexão, criar a tabela caso não exista, verificar se já existe um registro com o mesmo nome e somente depois salvar a tarefa. O que atualmente no agendador é representado apenas por uma linha, na vida real seriam várias linhas de códigos. O objetivo é separar toda essa lógica em classes que sejam responsáveis exclusivamente por persistir os objetos.
01 private void SalvarTarefa_Click(object sender, EventArgs e)
02 {
03 var Tarefa = new Tarefa();
04 Tarefa.Comando = Comando.Text;
05 Tarefa.Nome = Nome.Text;
06 Tarefa.Parametros = Parametros.Text;
07 Tarefa.IniciarEm = IniciarEm.Text;
08 Tarefa.Comentario = Comentarios.Text;
09
10 Lista.Add(Tarefa);
11
12 MostrarTarefas();
13 }
Quando dizemos persistir os objetos, nos referimos à ação de salvar as informações de todas as propriedades de um objeto no banco de dados e quando necessário for, buscar e colocar essas informações de volta em um objeto do mesmo tipo. Fazer isto de forma manual é possível, mas muito cansativo e o resultado não será bom, pois cada objeto possui diferentes propriedades. Por este motivo é óbvio que isso deve ser feito de modo automático.
Persistência de objetos
Salvar objetos que estão na memória para um meio físico pode ser trabalhoso, principalmente se optarmos por nós mesmos fazer essa tarefa. Existem frameworks que tiram esse trabalho de nossas costas, como o NHibernate e o Entity Framework. Contudo, estes são frameworks que fazem o chamado mapeamento objeto relacional, ou seja, transformam objetos em registros de um banco relacional, ou vice-versa. Mesmo sendo práticos, esses frameworks exigem que façamos esse mapeamento. Nosso projeto não exige um banco de dados relacional para armazenar os dados. Como faremos então?
Existe uma terceira opção. Os bancos de objetos. Estes são bancos de dados que salvam os objetos tal qual eles são no código fonte. Não há necessidade de se fazer mapeamento, agilizando assim o processo como um todo. No mercado temos algumas opções como o MongoDB, Caché, db4o e outros. Vamos optar pelo db4o, mas, sinta-se livre para experimentar outro banco.
Vamos organizar agora nosso modelo de classes, criando uma classe base, o que permitirá na sequência a criação de um repositório genérico.
Classe Bean
Esta classe será a base para as outras já existentes. Teremos nela apenas uma única propriedade, Id do tipo string. Essa propriedade servirá apenas como um identificador único para o objeto. No construtor da classe vamos instanciar um objeto Guid e passar seu valor para essa propriedade. Veja seu código na ...