Successfully reported this slideshow.
POOProgramação Orientada aObjetos no C# .NET usandoPadrões de ProjetoMARCELO SANTOS DAIBERT E MARCO ANTÔNIO PEREIRA ARAÚJO...
mudanças na economia, interface com o usuário, operações em rede, tempo de disponibilização parao mercado (time to market ...
caso apresenta um fragmento de um sistema maior, representado aqui pela relação entrefuncionários e departamentos de uma e...
Figura 2. Camadas do Estudo de caso.      No contexto do estudo de caso, o View é representado pelas classes de interface ...
18.         private String nome;19.         private String cpf;20.         private Departamento departamento;21.22.       ...
o nome de polimorfismo, que é a capacidade de um método de mesma assinatura comportar-se demaneira diferente, em uma mesma...
38.            public override Boolean Persistir(){39.                FuncionarioHoristaDAO objFunHoristaDAO = new Funcion...
33.              DepartamentoDAO objDepartamentoDAO = new DepartamentoDAO();34.              if (objDepartamentoDAO.atuali...
Figura 4. Classes de Interface.                           Figura 5. Interface Principal do Sistema - frmPrincipal.      As...
9.      class cntrFuncionario{10.         public cntrFuncionario(){11.         }12.         public static ArrayList Recupe...
4. using System.Text;5. using Empresa.Model;6.7. namespace Empresa.Controller{8.      class cntrFuncionarioHorista{9.     ...
responsabilidade da interface, pegar os dados digitados pelo usuário no formulário e montar essevetor.       O método entã...
NumHorasDiaTrabalhado int NOT NULL, ValorHora int NOT NULL,)ALTER TABLE Funcionario ADD CONSTRAINT fk_DPTOOID   FOREIGN KE...
configurando o servidor, o catálogo, forma de autenticação, e o atributos objConexao, este do tipoSqlConnection que é o re...
30.                        while (objLeitor2.Read()){31.                            objFuncionarioHorista = new Funcionari...
86.                    return listFuncionarios;87.               }88.          }89.           public static IList recupera...
142.                  Console.Write(strErro);143.                  return false;144.             }145.         }146.      ...
excluir. Este recebe o atributo identificador do funcionário como parâmetro e o excluir da base dedados, retornando verdad...
Buscando exemplificar o funcionamento da arquitetura do sistema proposto, é apresentado deforma detalhada a funcionalidade...
Esse, por sua vez, instancia um novo objeto do tipo FuncionarioHorista, e atribui os valoresdo vetor ao objeto. Com o obje...
Upcoming SlideShare
Loading in …5
×

Artigo c#

917 views

Published on

  • Be the first to comment

  • Be the first to like this

Artigo c#

  1. 1. POOProgramação Orientada aObjetos no C# .NET usandoPadrões de ProjetoMARCELO SANTOS DAIBERT E MARCO ANTÔNIO PEREIRA ARAÚJOMarcelo Santos Daibert (marcelo@daibert.net) é professor do Curso de Bacharelado em Ciênciada Computação da FAGOC - Faculdade Governador Ozanam Coelho na graduação e pós-graduação (especialização), Mestrando e Especialista em Ciência da Computação pelaUniversidade Federal de Viçosa e Bacharel em Sistemas de Informação pela Faculdade MetodistaGranbery. Gerente técnico da Optical Soluções em Informática.Marco Antônio Pereira Araújo (maraujo@granbery.edu.br) é professor do Curso de Bachareladoem Sistemas de Informação da Faculdade Metodista Granbery, Doutorando e Mestre emEngenharia de Sistemas e Computação pela COPPE/UFRJ, Especialista em Métodos EstatísticosComputacionais e Bacharel em Informática pela UFJF, Analista de Sistemas da Prefeitura de Juizde Fora.Este artigo discute Este artigo usa as seguintes tecnologias • Orientação a Objetos; Visual Studio 2008, C#, SQL Server 2005. • Padrões de Projeto; • Mapeamento Objeto-Relacional; • Criação de classes; • Programação em camadas; • Persistência de objetos. Com o passar dos anos foi possível observar uma profunda evolução na utilização decomputadores. Hoje graças a esta evolução, juntamente com fenômenos como a globalização, épossível estar em sincronia com as notícias de todas as partes do mundo. Nunca se utilizou tantoquanto atualmente recursos computacionais, firmando assim esta tecnologia como necessária para avida moderna atual. Neste sentido, várias evoluções foram necessárias para se alcançar o atualpatamar e novas outras evoluções se fazem necessárias para alcançar novos patamares que sereservam no futuro. Na área da engenharia de software não foi diferente. O desenvolvimento de software seamadureceu e ainda deve amadurecer com o passar dos anos. Para autores da área, fatores chavespara que houvesse mudanças e evolução no desenvolvimento de software nos últimos anos são:
  2. 2. mudanças na economia, interface com o usuário, operações em rede, tempo de disponibilização parao mercado (time to market - TTM), problemas com o modelo em cascata, tecnologia de objetos (OO– Orientação a Objetos) e computação em desktops. A qualidade de software passou a ser um tema muito discutido. O foco para a qualidade dossistemas desenvolvidos dentro de uma organização ganhou papel principal entre as discussões dosengenheiros. Assim, várias são as abordagens de desenvolvimento que buscam garantir estaqualidade. Neste contexto, o C# é uma linguagem de programação que une o poder e a flexibilidade dalinguagem C/C++ com a produtividade de linguagens e ambientes de desenvolvimento rápido(RAD - Rapid Application Development). Quando aplicadas técnicas da programação orientada aobjetos, com padrões de desenvolvimento de software, a linguagem se mostra uma poderosaferramenta para desenvolvimento de software, com suporte as mais novas tecnologias do mercado. Este artigo tem o objetivo de abordar de forma prática o desenvolvimento de uma aplicação,usando a linguagem C# do Visual Studio .NET 2008, utilizando os recursos da ProgramaçãoOrientada a Objetos (POO), do .NET, contextualizando a utilização de alguns padrões de projeto,em especial o padrão DAO (Data Access Object) para persistência e manipulação dos objetos daaplicação. Para armazenar os dados da aplicação desenvolvida é utilizado o banco de dados MS-SQL Server 2005. Toda a aplicação é desenvolvida com o conceito de programação em camadas,também discutido no artigo. Um dos desafios no desenvolvimento de aplicações orientadas a objetos é a persistência deobjetos. Os bancos de dados puramente orientados a objetos são de fato os mais adequados para apersistência, mas a indisponibilidade atual desses, seja devido ao custo, diversidade eprincipalmente amadurecimento, faz com que seja necessária uma busca por alternativas para arealização dessa tarefa. Uma das soluções encontradas para o problema é a utilização de camadas de persistência paraa manipulação dos objetos utilizando bancos de dados relacionais. Essa abordagem vem sendoamplamente utilizada no mercado, principalmente para o desenvolvimento de sistemas de médio agrande porte. Basicamente une a rapidez e o amadurecimento das bases de dados relacionais com osbenefícios da programação orientada a objetos (POO). A função principal de uma camada depersistência é portal transparentemente os objetos de uma aplicação para a base de dados relacionalde forma genérica. Para isso, são utilizas principalmente técnicas de mapeamento objeto-relacional com o intuitode mapear as classes e associações para tabelas e relacionamentos. A utilização de uma camada depersistência, embora pareça trivial inicialmente, se mostra complexa na prática, uma vez que sãovárias as configurações que devem ser feitas para que a camada funcione corretamente, além deoutros fatores que dificultam sua utilização. A edição 34 da revista .NET Magazine, antes chamadade MSDN Magazine, foi dedicada a esta abordagem, onde o estudo de caso apresentou a utilizaçãode um framework de persistência chamado nHibernate. Utilizando esse mesmo raciocínio, outra solução, a abordada neste artigo, apresenta o mesmoestudo de caso apresentado na edição 34, mas com uma diferença: A própria aplicação faz omapeamento objeto-relacional e a conexão com o banco de dados. Para isso, é apresentado o padrãode projeto DAO, que se apresenta como outra camada do sistema, com a responsabilidade deconectar no banco de dados, persistir e manipular os objetos da aplicação. Padrões de Projeto (Design Patterns): são soluções elegantes e reutilizáveis para problemasrecorrentes do processo de desenvolvimento de software Orientado a Objetos.Estudo de Caso Como já apresentado, o estudo de caso deste artigo é o mesmo apresentado na edição 34 destarevista, mas com a diferença de utilizar outra abordagem na persistência de objetos. O estudo de
  3. 3. caso apresenta um fragmento de um sistema maior, representado aqui pela relação entrefuncionários e departamentos de uma empresa, através das classes Departamento, Funcionario eFuncionarioHorista. A classe Funcionario é abstrata, servindo para a definição dos elementoscomuns às suas subclasses através da herança. Todos os funcionários devem estar lotados em um Departamento, que pode ter váriosfuncionários. A Figura 1 representa o diagrama de classes do nosso sistema. Funcionario codigo : String nome : String cpf : String 0..* 1 calcularSalario : float() Departamento codigo : String Descricao : String FuncionarioHorista numDiasTrabalhados : int numHorasDiaTrabalhado : int valorHora : int Figura 1. Diagrama de Classes do estudo de caso. Através desse estudo de caso, são abordados temas como classes, objetos, métodos, atributos,persistência de objetos, herança, polimorfismo, herança, diálogos, associações e programação emcamadas MVC (Model-View-Controller), além de temas pertinentes ao ambiente dedesenvolvimento, como utilização de componentes, classes e controles disponibilizados pelo VisualStudio 2008 e o framework .NET. O estudo de caso propõe o desenvolvimento em camadas, utilizando o padrão de projetoestrutura MVC, composto por três camadas fundamentais. Esta abordagem busca, entre outrascoisas, o desacoplamento de funções da aplicação, facilitando assim o desenvolvimento egarantindo maior manutenibilidade da aplicação. Além das três camadas do MVC, é aindaapresentada uma outra camada, a responsável pela persistência dos dados. Esta camada, aquichamada de camada de persistência tem a responsabilidade de comunicar com o banco de dados ede persistir e manipular os objetos neste banco. A Figura 2, representa as camadas do estudo decaso e como é feita a comunicação entre elas. Classes de Interface com usuário (View)  Modelo Classes de Controle (Controller)  MVC Classes de Negócio (Model)   Camada de Persistência (Classes DAO) Banco de  Dados SQL
  4. 4. Figura 2. Camadas do Estudo de caso. No contexto do estudo de caso, o View é representado pelas classes de interface com ousuário. Estas se comunicam com os controladores de das classes de domínio. As classescontroladoras (Controller) têm a finalidade de ser um elo entre o Model e o View, ou seja, entre asclasses de domínio da aplicação e a interface, garantindo assim o desacoplamento. Já o Model érepresentado pelas classes de domínio, e que neste estudo de caso são as classes Funcionario,FuncionarioHorista e Departamento. O Model faz acesso às classes de persistência DAO parapersistir e manipular os seus objetos. E esta, por sua vez, faz acesso ao banco de dados eefetivamente faz a tarefa de persistir e manipular os objetos.Classes do Modelo, Propriedades e Métodos Para iniciar o desenvolvimento do estudo de caso, foi criado um projeto no Visual Studiochamado Empresa. Este projeto será divido em cinco namespaces, como pode ser visualizado naFigura 3. O namespace View, para armazenar as classes de interface, o Controller, para as classescontroladoras, o Model, para as classes de domínio, o Persistence para as classes DAO de acesso aobanco de dados e por fim, o namespace Resources, para armazenar as imagens utilizadas nasinterfaces. Figura 3. Namespaces do projeto do estudo de caso. As listagens 1, 2 e 3 apresentam o código-fonte de definição das classes Funcionario,FuncionarioHorista e Departamento, respectivamente, do estudo de caso proposto, todas dispostasno namespace Model e com os nomes: Funcionario.cs, FuncionarioHorista.cs e Departamento.cs.Listagem 1. Definição da Classe Funcionario1. using System;2. using System.Collections.Generic;3. using System.Collections;4. using System.Text;5. using Empresa.Persistence;6.7. namespace Empresa.Model{8. public abstract class Funcionario{9. public Funcionario(String pNome, String pCPF){10. this.Nome = pNome;11. this.CPF = pCPF;12. this.Departamento = new Departamento();13. }14. public Funcionario(){15. }16.17. private String codigo;
  5. 5. 18. private String nome;19. private String cpf;20. private Departamento departamento;21.22. public String Codigo{23. get { return this.codigo; }24. set { this.codigo = value; }25. }26. public String Nome{27. get { return this.nome; }28. set { this.nome = value; }29. }30. public String CPF{31. get { return this.cpf; }32. set { this.cpf = value; }33. }34. public Departamento Departamento{35. get { return this.departamento; }36. set { this.departamento = value; }37. }38. public abstract float calcularSalario();39. public abstract Boolean Persistir();40. public abstract Boolean Atualizar();41. public static Funcionario RecuperaObjeto(String pID){42. Funcionario objFuncionario = FuncionarioDAO.recuperaObjeto(pID);43. return objFuncionario;44. }45. public static IList RecuperaObjetos(){46. IList listFuncionarios = FuncionarioDAO.recuperaObjetos();47. return listFuncionarios;48. }49. public static IList RecuperaObjetosPorDepartamento(String pOID){50. IList listFuncionarios =FuncionarioDAO.recuperaObjetosPorDepartamento(pOID);51. return listFuncionarios;52. }53. public static Boolean Excluir(String pID){54. return FuncionarioDAO.excluir(pID);55. }56. }57. } Na Listagem 1, a linha 8 exibe a assinatura da classe abstrata Funcionario. Ela é abstrata pornão instanciar objetos, tendo por objetivo definir os elementos comuns às suas subclasses. Entre aslinhas 17 e 20 são apresentados os atributos codigo, nome, cpf e departamento da classe. Todos comvisibilidade privada, sendo acessados pelas propriedades definidas entre as linhas 22 e 37. Aspropriedades, nesse caso, agem como métodos gets e sets, mantendo, portanto, o encapsulamento daclasse. Nota: Encapsulamento é a prática de limitar o acesso às informações de um objeto, fazendocom que somente os seus métodos tenham acesso aos dados e à manipulação dos atributos. Oencapsulamento disponibiliza o objeto com toda sua funcionalidade sem a necessidade de saberinternamente o funcionamento, aumentando assim a manutenibilidade do sistema. Das linhas 9 a 15 são apresentados os métodos construtores da classe, onde temos dois: umcom passagem de parâmetros dos atributos na sua construção e outro sobrecarregando o anteriorsem parâmetros, usado para instanciar um objeto sem informações para seus atributos. O métodosobrecarregado (overload) é definido quando a assinatura do mesmo, difere do anterior na passagemde parâmetros. Uma classe pode ter quantos métodos sobrecarregados forem necessários. Na linha 38 é exibido a assinatura do método abstrato calcularSalario. Ele é abstrato, pois éredefinido nas subclasses, de acordo com a necessidade específica de implementação. A isso é dado
  6. 6. o nome de polimorfismo, que é a capacidade de um método de mesma assinatura comportar-se demaneira diferente, em uma mesma hierarquia. Exemplificando o uso, o método calcularSalario possui a mesma assinatura em toda ahierarquia, no entanto, ele se comporta de maneira diferente na subclasse FuncionaoHorista, umavez que o algoritmo para calcular salário é diferente nessa subclasse. O fato do método ser definidocomo abstrato (abstract) em sua assinatura, obriga suas subclasses a implementá-lo. Entre as linhas 39 e 55 são definidos os métodos responsáveis pela persistência e manipulaçãodos objetos do tipo Funcionario. Observe que todos esses métodos fazem acesso às classes DAO,que é importado para a classe pela linha 5 (using Empresa.Persistence). Como já apresentado, asclasses DAO são as responsáveis pela conexão com o banco de dados e pela persistência emanipulação dos objetos. De acordo com a programação em camadas, estes métodos serãochamados pelos controladores da classe para finalmente, a classe fazer as chamadas para as classesDAO como apresentado acima. Observe que são definidos algum métodos com o modificador static, como por exemplo, nalinha 45. Este indica que o método é um método de classe e não é necessário instanciar objeto paraque o mesmo seja invocado. Nota: Método de Classe é um método que não há a necessidade se instanciar um objeto daclasse para poder acessá-lo. Diferentemente do método de instância, que como o próprio nome diz,é necessário a instanciação do objeto para sua invocação.Listagem 2. Definição da Classe FuncionarioHorista1. using System;2. using System.Collections.Generic;3. using System.Collections;4. using System.Text;5. using Empresa.Persistence;6.7. namespace Empresa.Model{8. class FuncionarioHorista : Funcionario{9. public FuncionarioHorista(String pNome, String pCPF, int pValorHora, intpNumDiasTrabalhado, int pNumHorasTrabalhada)10. : base(pNome, pCPF){11. this.valorHora = pValorHora;12. this.numHorasDiaTrabalhado = pNumHorasTrabalhada;13. this.numDiasTrabalhados = pNumDiasTrabalhado;14. }15. public FuncionarioHorista(){16. }17.18. private int numDiasTrabalhados;19. private int numHorasDiaTrabalhado;20. private int valorHora;21.22. public int NumDiasTrabalhados{23. get { return this.numDiasTrabalhados; }24. set { this.numDiasTrabalhados = value; }25. }26. public int NumHorasDiaTrabalhado{27. get { return this.numHorasDiaTrabalhado; }28. set { this.numHorasDiaTrabalhado = value; }29. }30. public int ValorHora{31. get { return this.valorHora; }32. set { this.valorHora = value; }33. }34.35. public override float calcularSalario(){36. return this.valorHora * this.numHorasDiaTrabalhado *this.numDiasTrabalhados;37. }
  7. 7. 38. public override Boolean Persistir(){39. FuncionarioHoristaDAO objFunHoristaDAO = new FuncionarioHoristaDAO();40. if (objFunHoristaDAO.persistir(this)){41. return true;42. }else{43. return false;44. }45. }46. public override Boolean Atualizar(){47. FuncionarioHoristaDAO objFunHoristaDAO = new FuncionarioHoristaDAO();48. if (objFunHoristaDAO.atualizar(this))49. {50. return true;51. }52. else53. {54. return false;55. }56. }57. }58. } Já na Listagem 2, é definida a classe FuncionarioHorista, com seus atributos, propriedades emétodos. Importante observar nas linhas 8 e 16, no método construtor da classe, a utilização dapalavra reservada base. Essa é utilizada para invocar o método construtor do pai, passando osparâmetros referentes à super classe. Deve sempre suceder a assinatura do método separado por dois pontos. Lembrando que aordem dos parâmetros deve ser a mesma da assinatura, assim como em qualquer chamada demétodo. A linha 35 apresenta a definição do método calcularSalario. Como esse método remete aométodo abstrato do pai, o mesmo deve ser definido como override. Esse sim com implementaçãoem sua definição.Listagem 3. Definição da Classe Departamento1. using System;2. using System.Collections.Generic;3. using System.Collections;4. using System.Text;5. using System.Windows.Forms;6. using Empresa.Persistence;7.8. namespace Empresa.Model{9. public class Departamento{10. public Departamento(){11. }12.13. private String codigo;14. private String descricao;15.16. public String Codigo{17. get { return this.codigo; }18. set { this.codigo = value; }19. }20. public String Descricao{21. get { return this.descricao; }22. set { this.descricao = value; }23. }24. public Boolean Persistir(){25. DepartamentoDAO objDepartamentoDAO = new DepartamentoDAO();26. if (objDepartamentoDAO.persistir(this)){27. return true;28. }else{29. return false;30. }31. }32. public Boolean Atualizar(){
  8. 8. 33. DepartamentoDAO objDepartamentoDAO = new DepartamentoDAO();34. if (objDepartamentoDAO.atualizar(this)){35. return true;36. }37. else{38. return false;39. }40. }41. public static Departamento RecuperaObjeto(String pID){42. Departamento objDepartamento = DepartamentoDAO.recuperaObjeto(pID);43. return objDepartamento;44. }45. public static IList RecuperaObjetos(){46. IList listDepartamentos = DepartamentoDAO.recuperaObjetos();47. return listDepartamentos;48. }49. public static Boolean Excluir(String pID){50. return DepartamentoDAO.excluir(pID);51. }52. }53. } Por fim, na Listagem 3 é apresentada a classe Departamento, com seus atributos,propriedades e métodos. Na linha 10 é exibido o método construtor do objeto. Entre as linhas 13 e23 são exibidos os atributos e propriedades da classe. Nas classes apresentadas nas listagens anteriores são definidos os métodos Persistir (persisteum objeto), Atualizar (atualiza um objeto já persistido), RecuperaObjeto (recupera um único objetoespecificado), RecuperaObjetos (recupera todos os objetos da classe referenciada) e Excluir (excluium objeto especificado). Esses são os métodos responsáveis pela persistência e manipulação dosobjetos no sistema. Observe que todos fazem acesso às classes DAO, do namespace Persistence. Aclasse Funcionario possui ainda o método RecuperaObjetosPorDepartamento. Este métodorecupera todos os funcionários de um determinado departamento especificado.Classes de Interface e Controladores Dentro do namespace View estão dispostas as classes com as interfaces, como visualizado naFigura 4. São definidas as seguintes interfaces: frmPrincipal (a interface principal do sistema,apresentada na Figura 5), frmSplashScreen (com a interface de inicialização da aplicação), frmSobre(interface sobre do sistema), frmListarTemplate (define um template para reutilização de interfaces,baseando-se no conceito de herança de interfaces), frmListarFuncionario (herda defrmListarTemplate e apresenta a interface de visualização de todos os funcionários),frmListarDepartamento (também herda de frmListarTemplate e apresenta a interface devisualização de todos os departamentos), frmNovoFuncionarioTemplate (define o template para ainterface de novos funcionários), frmNovoFuncionarioHorista (interface para criar um novofuncionário horista), frmNovoDepartamento (interface para criar um novo departamento nosistema), e por fim a interface frmFuncionariosDepartamento (lista todos os funcionários de umdeterminado departamento).
  9. 9. Figura 4. Classes de Interface. Figura 5. Interface Principal do Sistema - frmPrincipal. As classes de interface definem as interfaces da aplicação (View). Estas, por sua vez, fazemacesso às classes controladoras (Controller), que então fazem acesso às classes do modelo (Model),já definidas. E as classes do modelo fazem acesso às classes de persistência DAO (PersistenceDAO). As classes controladoras são definidas dentro do namespace Controller. As Listagens 4 e 5apresentam respectivamente os controladores cntrFuncionario e cntrFuncionarioHorista. Todospossuem a mesma funcionalidade: elo de ligação entre o model e o view. A estrutura também émuito semelhante em todas essas classes. Elas basicamente possuem um atributo do tipo da classeque gerenciam, menos para a cntrFuncionario, já que esta gerencia uma classe abstrata. Os métodostambém possuem a mesma estrutura e todos fazem acesso ao modelo. Basicamente existe o métodoSalvar, responsável por persistir ou atualizar um objeto, o método RecuperaObjeto, para recuperarum determinado objeto, o RecuperaObjetos, para recuperar todos os objetos da classe persistidos eo método Excluir, responsável por excluir um determinado objeto.Listagem 4. Definição da Classe cntrFuncionario1. using System;2. using System.Collections.Generic;3. using System.Collections;4. using System.Text;5. using Empresa.Model;6. using Empresa.Persistence;7.8. namespace Empresa.Controller{
  10. 10. 9. class cntrFuncionario{10. public cntrFuncionario(){11. }12. public static ArrayList RecuperaObjetos(){13. ArrayList vetEnviaFuncionarios = new ArrayList();14. IList listFuncionarios = Funcionario.RecuperaObjetos();15. for (int i = 0; i < listFuncionarios.Count; i++)16. {17. Funcionario objBuffer = (Funcionario)listFuncionarios[i];18. String[] vBuffer = new String[4];19. vBuffer[0] = objBuffer.Codigo;20. vBuffer[1] = objBuffer.Nome;21. vBuffer[3] = objBuffer.Departamento.Descricao;22. if (objBuffer is FuncionarioHorista)23. {24. vBuffer[2] = "Horista";25. }26. vetEnviaFuncionarios.Add(vBuffer);27. }28. return vetEnviaFuncionarios;29. }30. public static ArrayList RecuperaObjetosPorDepartamento(String pOID){31. ArrayList vetEnviaFuncionarios = new ArrayList();32. IList listFuncionarios =Funcionario.RecuperaObjetosPorDepartamento(pOID);33. for (int i = 0; i < listFuncionarios.Count; i++)34. {35. Funcionario objBuffer = (Funcionario)listFuncionarios[i];36. String[] vBuffer = new String[3];37. vBuffer[0] = objBuffer.Codigo;38. vBuffer[1] = objBuffer.Nome;39. vBuffer[2] = Convert.ToString(objBuffer.calcularSalario());40. vetEnviaFuncionarios.Add(vBuffer);41. }42. return vetEnviaFuncionarios;43. }44. public static Boolean Excluir(String pID){45. return Funcionario.Excluir(pID);46. }47. public static int ContabilizaFuncionariosPorDepartamento(StringpIDDepartamento){48. returnFuncionarioDAO.ContabilizaFuncionariosPorDepartamento(pIDDepartamento);49. }50. }51. } Na Listagem 4, a classe cntrFuncionario apresenta três métodos estáticos, responsáveis pelamanipulação genérica de objetos de toda a hierarquia da classe Funcionario. O primeiro é oRecuperaObjetos responsável por retornar à interface, um vetor aninhado com todos os objetos dotipo Funcionario da base de dados. Para isso, é invocado o RecuperaObjetos da classe Funcionario, que retorna uma coleção deobjetos. Com essa coleção, é então montado o vetor com os dados de cada funcionário, que seráretornado à interface. O método RecuperaObjetosPorDepartamento faz ação semelhante aoRecuperaObjetos, mas filtrando os funcionários por um determinado departamento. Para isso, ométodo recebe por parâmetro o OID (Object Identification – Atributo identificador) dodepartamento. Desta forma, o método invoca então o método da classe FuncionarioRecuperaObjetosPorDepartamento. Já o método Excluir se responsabiliza em receber comoparâmetro uma string representando o OID do objeto que a interface deseja excluir e aciona oExcluir da classe Funcionario.Listagem 5. Definição da Classe cntrFuncionarioHorista1. using System;2. using System.Collections.Generic;3. using System.Collections;
  11. 11. 4. using System.Text;5. using Empresa.Model;6.7. namespace Empresa.Controller{8. class cntrFuncionarioHorista{9. private FuncionarioHorista objFuncionarioHorista;10. public cntrFuncionarioHorista(){11. }12. public Boolean Salvar(ArrayList pLista){13. if (pLista[0] == null){14. //Criar um Novo15. this.objFuncionarioHorista = new FuncionarioHorista();16. this.objFuncionarioHorista.Codigo = System.Guid.NewGuid().ToString();17. this.objFuncionarioHorista.Nome = Convert.ToString(pLista[1]);18. this.objFuncionarioHorista.CPF = Convert.ToString(pLista[2]);19. this.objFuncionarioHorista.Departamento =Departamento.RecuperaObjeto(Convert.ToString(pLista[3]));20. this.objFuncionarioHorista.NumDiasTrabalhados =Convert.ToInt16(pLista[4]);21. this.objFuncionarioHorista.NumHorasDiaTrabalhado =Convert.ToInt16(pLista[5]);22. this.objFuncionarioHorista.ValorHora = Convert.ToInt16(pLista[6]);23. if (objFuncionarioHorista.Persistir()){24. return true;25. }26. else{27. return false;28. }29. }30. else{31. //Atualização32. this.objFuncionarioHorista =(FuncionarioHorista)Funcionario.RecuperaObjeto(pLista[0].ToString());33. this.objFuncionarioHorista.Nome = Convert.ToString(pLista[1]);34. this.objFuncionarioHorista.CPF = Convert.ToString(pLista[2]);35. this.objFuncionarioHorista.Departamento =Departamento.RecuperaObjeto(Convert.ToString(pLista[3]));36. this.objFuncionarioHorista.NumDiasTrabalhados =Convert.ToInt32(pLista[4]);37. this.objFuncionarioHorista.NumHorasDiaTrabalhado =Convert.ToInt32(pLista[5]);38. this.objFuncionarioHorista.ValorHora = Convert.ToInt32(pLista[6]);39. if (objFuncionarioHorista.Atualizar()){40. return true;41. }42. else{43. return false;44. }45. }46. }47. public ArrayList RecuperaObjeto(String pOID){48. ArrayList vetEnvia = new ArrayList();49. this.objFuncionarioHorista =(FuncionarioHorista)Funcionario.RecuperaObjeto(pOID);50. vetEnvia.Add(this.objFuncionarioHorista.Codigo);51. vetEnvia.Add(this.objFuncionarioHorista.Nome);52. vetEnvia.Add(this.objFuncionarioHorista.CPF);53. vetEnvia.Add(this.objFuncionarioHorista.Departamento.Codigo);54. vetEnvia.Add(this.objFuncionarioHorista.NumDiasTrabalhados);55. vetEnvia.Add(this.objFuncionarioHorista.NumHorasDiaTrabalhado);56. vetEnvia.Add(this.objFuncionarioHorista.ValorHora);57. return vetEnvia;58. }59. }60. } Na Listagem 5 é apresentada a classe cntrFuncionarioHorista. O primeiro métodoapresentado é o Salvar, que é invocado pela interface quando o usuário aciona essa opção noformulário. Ele recebe como parâmetro um ArrayList com os dados do FuncionarioHorista. É de
  12. 12. responsabilidade da interface, pegar os dados digitados pelo usuário no formulário e montar essevetor. O método então verifica se é uma operação de atualização ou de criação. Caso seja deatualização é invocado o Atualizar (linha 39) do objeto. Para o outro caso, é acionado o métodoPersistir (linha 23). No caso de criação de um novo funcionário, é atribuído ao código do objeto,um novo OID, usando a estratégia do GUID (linha 16). O segundo método apresentado é o RecuperaObjeto, que recebe como parâmetro uma string,representando o OID do objeto que a interface deseja recuperar. O método então invoca oRecuperaObjeto da classe FuncionarioHorista e monta um vetor com os seus dados e o devolvepara a interface. A interface então pode tratar da forma que lhe for conveniente. A classe controladora do Departamento, a cntrDepartamento possui definição semelhante asjá apresentadas e por isso não esta sendo definida. Nota: O código-fonte completo da aplicação esta disponível para download.Mapeamento Objeto-Relacional e Banco de Dados O mapeamento objeto-relacional é uma abordagem que permite a construção de sistemasutilizando o paradigma Orientado a Objetos com a persistência desses objetos em bancos de dadosrelacionais. Utilizando-se de técnicas e estratégias específicas, é possível mapear classes com seusatributos e associações para o modelo relacional. Utiliza-se uma abstração bastante intuitiva no sentido de que uma classe pode ser mapeadapara uma tabela no banco de dados relacional e atributos da classe para campos da tabela. Porém,algumas diferenças entre os dois modelos, como o OID, tipos de dados, herança e associações,demandam um estudo mais detalhado das estratégias de mapeamento. Para o estudo de caso, a construção da base de dados seguiu esse raciocínio. A classeDepartamento foi mapeada para a tabela Departamento, com seus atributos sendo os campos databela e a hierarquia Funcionario e FuncionarioHorista sendo mapeada para as tabelas Funcionarioe FuncionarioHorista, cada uma com os seus respectivos atributos sendo os campos das tabelasPara estabelecer a hierarquia, a chave primária da tabela FuncionarioHorista é a mesma chaveprimária da tabela Funcionario, estabelecendo assim uma relação de chave primária estrangeira. Existem outras duas possíveis alternativas para se mapear uma hierarquia: criar uma únicatabela, com todos os atributos como campos da tabela, com um campo adicional chamado tipo, querepresenta a classe que instanciou cada objeto ou criar uma nova tabela para cada classe concreta,contendo os seus atributos, mais os atributos da classe abstrata. Assim, a Listagem 6 apresenta o script para criação do banco, resultante do mapeamentoobjeto-relacional realizado com as classes do estudo de caso. A base de dados utilizada para oestudo de caso é o SQL SERVER 2005 Express Edition. No entanto, qualquer outra base seriasuportada nesta arquitetura.Listagem 6. Script para criação das tabelas no banco de dadosCREATE TABLE Departamento( ID varchar(38) NOT NULL PRIMARY KEY, Descricao varchar(50) NOT NULL,)CREATE TABLE Funcionario( ID varchar(38) NOT NULL PRIMARY KEY, Nome varchar(50) NOT NULL, CPF varchar(14) NOT NULL, DepartamentoOID varchar(38) NOT NULL,)CREATE TABLE FuncionarioHorista( ID varchar(38) NOT NULL PRIMARY KEY, NumDiasTrabalhados int NOT NULL,
  13. 13. NumHorasDiaTrabalhado int NOT NULL, ValorHora int NOT NULL,)ALTER TABLE Funcionario ADD CONSTRAINT fk_DPTOOID FOREIGN KEY(DepartamentoOID) REFERENCES Departamento(ID)ALTER TABLE FuncionarioHorista ADD CONSTRAINT fk_DPTOOID FOREIGN KEY(ID) REFERENCES Funcionario(ID)Classes de Persistência e Manipulação de Objetos Conforme já apresentado, o namespace Persistence constitui uma importante parte daaplicação. A parte que é responsável pela persistência e manipulação dos objetos no banco de dadosrelacional. Neste são definidas as classes que representam um padrão de projeto chamado DAO –Data Access Object – que, basicamente, define o encapsulamento do acesso aos dados por meio declasses especificamente construídas para essa tarefa. Assim, para cada classe persistente do modeloexiste uma classe DAO correspondente. No entanto, antes de se utilizar os métodos das classes DAO, é necessário se conectar eautenticar no banco de dados e configurar o catálogo correspondente no SQL SERVER que possui aestrutura de tabelas já apresentadas. Para isso, dentro do namespace Persistence, foi criada umaclasse com o nome FabricaConexao, com objetivo de centralizar a conexão com a base de dadosem um único lugar e certificando que ela será feita somente uma única vez ao carregar a aplicação. Essa classe é a implementação de um padrão de projeto criacional chamado Singleton, quegarante que uma classe possua apenas uma única instância fornecendo um ponto global de acessopara a mesma, através de atributos e definições estáticas (static). Com isso é disponibilizado àclasse um ponto global e único de conexão à base de dados, necessário para a persistência emanipulação dos objetos de forma eficaz e eficiente. A Listagem 7 apresenta a definição dessaclasse (crie um arquivo CS - FabricaConexao.cs - semelhante aos exemplos anteriores dentro donamespace Persistence).Listagem 7. Definição da Classe FabricaConexao1. using System;2. using System.Collections.Generic;3. using System.Text;4. using System.Data.SqlClient;5.6. namespace Empresa.Persistence{7. public class FabricaConexao{8. private String stringconnection = "Data Source=NOTEBK-DAIBERTSQLEXPRESS;Initial Catalog=Empresa;Integrated Security=SSPI;MultipleActiveResultSets=True";9. private static SqlConnection objConexao = null;10.11. public FabricaConexao(){12. objConexao = new SqlConnection();13. objConexao.ConnectionString = stringconnection;14. objConexao.Open();15. }16. public static SqlConnection getConexao(){17. if (objConexao == null){18. new FabricaConexao();19. }20. return objConexao;21. }22. public static void fecharConexao(){23. objConexao.Close();24. }25. }26. } A Listagem 7, define a classe FabricaConexao. Esta classe faz uso, para este caso de uso, daclasse SqlConnection, disponibilizada em System.Data.SqlClient (linha 4). Ela possui dois atributos:stringconnection, que armazena em uma string a string de conexão para o banco de dados,
  14. 14. configurando o servidor, o catálogo, forma de autenticação, e o atributos objConexao, este do tipoSqlConnection que é o responsável por realizar a conexão com o banco de dados com os dadosdefinidos na stringconnection. Entre as linhas 11 e 15 é definido o método construtor da classe. Esteinstancia um objeto SqlConnection no atributo objConexao, configura a string de conexão e acionao método Open. Este se conecta no banco de dados e mantém um ponteiro na base de dadosautenticada para que aplicação faça uso. Entre as linhas 16 e 21, é definido o método getConexao.Este disponibiliza o objConexao à aplicação. Observe que este método verifica se o objConexao énull. Se for, ele invoca o método construtor que por sua vez, como definido, irá instanciarobjConexao. Desta forma, garante-se que esta instancia é única em toda a aplicação. Todasolicitação de conexão ao banco de dados é centralizada nesta classe a sempre feita através destemétodo getConexao. Por fim, na linha 22, é definido o método fecharConexao. Este tem comoobjetivo fechar a conexão com o banco de dados, utilizada somente quando a aplicação se finalizano estudo de caso. Com isso, é possível analisar as definições das classes DAO. Como já apresentado, cadaclasse do modelo (Funcionario, FuncionarioHorista e Departamento) possui o seu DAOcorrespondente. Desta forma, tem-se: FuncionarioDAO, FuncionarioHoristaDAO eDepartamentoDAO. Todos definidos de forma autônoma, cada um em uma classe dentro donamespace Persistence. As Listagens 8 e 9 definem as classes FuncionarioDAO eFuncionarioHoristaDAO respectivamente. Observe que as classes DAO recebem as chamadas dasclasses do modelo (classes de domínio) e são as únicas da aplicação que acessam o banco de dados,respeitando assim o que fora definido referente à programação em camadas. Diferentemente comoobservado quando se é utilizado um framework de persistência, como o nHibernate, nestaabordagem, as classes DAO manipulam os objetos com SQL diretamente em seus métodos. Novamente, para fins do estudo de caso, é omitida a classe DAO correspondente aoDepartamento, pois esta possui definição muito semelhante às apresentadas.Listagem 8. Definição da Classe FuncionarioDAO1. using System;2. using System.Collections;3. using System.Text;4. using System.Data.SqlClient;5. using Empresa.Model;6. using Empresa.Controller;7.8. namespace Empresa.Persistence{9. class FuncionarioDAO{10. public FuncionarioDAO(){11. }12. public static Funcionario recuperaObjeto(String pID){13. SqlConnection objConexao = FabricaConexao.getConexao();14. String strQuery = "SELECT ID, Nome, CPF, DepartamentoOID FROMFuncionario WHERE ID = "+pID+"";15. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);16. cntrDepartamento objControllerDepartamento = new cntrDepartamento();17. SqlDataReader objLeitor2;18. Funcionario objFuncionario = null;19. FuncionarioHorista objFuncionarioHorista;20. try{21. objCommand.ExecuteNonQuery();22. SqlDataReader objLeitor = objCommand.ExecuteReader();23. while (objLeitor.Read()){24. //Verificar Tipo do Funcionário e Recuperar o Restante doFuncionário25. //Tentar em Todos os Filhos, até encontrar a Chave PrimáriaEstrangeira Igual26. strQuery = "SELECT ID, NumDiasTrabalhados,NumHorasDiaTrabalhado, ValorHora FROM FuncionarioHorista WHERE ID = " + objLeitor[0] +"";27. objCommand = new SqlCommand(strQuery, objConexao);28. objCommand.ExecuteNonQuery();29. objLeitor2 = objCommand.ExecuteReader();
  15. 15. 30. while (objLeitor2.Read()){31. objFuncionarioHorista = new FuncionarioHorista();32. objFuncionarioHorista.NumDiasTrabalhados =Convert.ToInt32(objLeitor2[1]);33. objFuncionarioHorista.NumHorasDiaTrabalhado =Convert.ToInt32(objLeitor2[2]);34. objFuncionarioHorista.ValorHora =Convert.ToInt32(objLeitor2[3]);35. objFuncionarioHorista.Codigo =Convert.ToString(objLeitor[0]);36. objFuncionarioHorista.Nome = Convert.ToString(objLeitor[1]);37. objFuncionarioHorista.CPF = Convert.ToString(objLeitor[2]);38. objFuncionarioHorista.Departamento =objControllerDepartamento.RecuperaObjetoObjeto(Convert.ToString(objLeitor[3]));39. objFuncionario = (Funcionario)objFuncionarioHorista;40. }41. //Fim Tentativas de Descobrir Tipo Funcionário42. }43. objLeitor.Close();44. return objFuncionario;45. }catch (SqlException err){46. String strErro = "Erro: " + err.ToString();47. Console.Write(strErro);48. return objFuncionario;49. }50. }51. public static IList recuperaObjetosPorDepartamento(String pOID){52. IList listFuncionarios = new ArrayList();53. SqlConnection objConexao = FabricaConexao.getConexao();54. String strQuery = "SELECT ID, Nome, CPF, DepartamentoOID FROMFuncionario WHERE DepartamentoOID = "+pOID+"";55. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);56. cntrDepartamento objControllerDepartamento = new cntrDepartamento();57. SqlDataReader objLeitor2;58. try{59. objCommand.ExecuteNonQuery();60. SqlDataReader objLeitor = objCommand.ExecuteReader();61. while (objLeitor.Read()){62. //Verificar Tipo do Funcionário e Recuperar o Restante doFuncionário63. //Tentar em Todos os Filhos, até encontrar a Chave PrimáriaEstrangeira Igual64. strQuery = "SELECT ID, NumDiasTrabalhados,NumHorasDiaTrabalhado, ValorHora FROM FuncionarioHorista WHERE ID = " + objLeitor[0] +"";65. objCommand = new SqlCommand(strQuery, objConexao);66. objCommand.ExecuteNonQuery();67. objLeitor2 = objCommand.ExecuteReader();68. while (objLeitor2.Read()){69. FuncionarioHorista objFuncionario = newFuncionarioHorista();70. objFuncionario.NumDiasTrabalhados =Convert.ToInt32(objLeitor2[1]);71. objFuncionario.NumHorasDiaTrabalhado =Convert.ToInt32(objLeitor2[2]);72. objFuncionario.ValorHora = Convert.ToInt32(objLeitor2[3]);73. objFuncionario.Codigo = Convert.ToString(objLeitor[0]);74. objFuncionario.Nome = Convert.ToString(objLeitor[1]);75. objFuncionario.CPF = Convert.ToString(objLeitor[2]);76. objFuncionario.Departamento =objControllerDepartamento.RecuperaObjetoObjeto(Convert.ToString(objLeitor[3]));77. listFuncionarios.Add(objFuncionario);78. }79. //Fim Tentativas de Descobrir Tipo Funcionário80. }81. objLeitor.Close();82. return listFuncionarios;83. }catch (SqlException err){84. String strErro = "Erro: " + err.ToString();85. Console.Write(strErro);
  16. 16. 86. return listFuncionarios;87. }88. }89. public static IList recuperaObjetos(){90. IList listFuncionarios = new ArrayList();91. SqlConnection objConexao = FabricaConexao.getConexao();92. String strQuery = "SELECT ID, Nome, CPF, DepartamentoOID FROMFuncionario";93. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);94. cntrDepartamento objControllerDepartamento = new cntrDepartamento();95. SqlDataReader objLeitor2;96. try{97. objCommand.ExecuteNonQuery();98. SqlDataReader objLeitor = objCommand.ExecuteReader();99. while (objLeitor.Read()) {100. //Verificar Tipo do Funcionário e Recuperar o Restante doFuncionário101. //Tentar em Todos os Filhos, até encontrar a Chave PrimáriaEstrangeira Igual102. strQuery = "SELECT ID, NumDiasTrabalhados,NumHorasDiaTrabalhado, ValorHora FROM FuncionarioHorista WHERE ID = "+objLeitor[0]+"";103. objCommand = new SqlCommand(strQuery, objConexao);104. objCommand.ExecuteNonQuery();105. objLeitor2 = objCommand.ExecuteReader();106. while (objLeitor2.Read()){107. FuncionarioHorista objFuncionario = newFuncionarioHorista();108. objFuncionario.NumDiasTrabalhados =Convert.ToInt32(objLeitor2[1]);109. objFuncionario.NumHorasDiaTrabalhado =Convert.ToInt32(objLeitor2[2]);110. objFuncionario.ValorHora = Convert.ToInt32(objLeitor2[3]);111. objFuncionario.Codigo = Convert.ToString(objLeitor[0]);112. objFuncionario.Nome = Convert.ToString(objLeitor[1]);113. objFuncionario.CPF = Convert.ToString(objLeitor[2]);114. objFuncionario.Departamento =objControllerDepartamento.RecuperaObjetoObjeto(Convert.ToString(objLeitor[3]));115. listFuncionarios.Add(objFuncionario);116. }117. //Fim Tentativas de Descobrir Tipo Funcionário118. }119. objLeitor.Close();120. return listFuncionarios;121. }122. catch (SqlException err){123. String strErro = "Erro: " + err.ToString();124. Console.Write(strErro);125. return listFuncionarios;126. }127. }128. public static Boolean excluir(String pID){129. SqlConnection objConexao = FabricaConexao.getConexao();130. //Criar query para deletar o funcionario associado. Criar query paratodos os tipos.131. String strQuery = "DELETE FROM Funcionario WHERE ID = " + pID + "";132. strQuery = strQuery + "; DELETE FROM FuncionarioHorista WHERE ID = "+pID +"";133. //Caso tivesse mais tipos, adicionar a query para todos os tipos, porexemplo FuncionarioDiarista caso existisse:134. //strQuery = strQuery + "; DELETE FROM FuncionarioDiarista WHERE ID = "+ pID + "";135. //Desta forma todo tipo de funcionário seria deletado, sem que sejanecessário descobrir o seu tipo específico. A query não retorna erro quando não encontrao objeto na clausula WHERE136. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);137. try{138. objCommand.ExecuteNonQuery();139. return true;140. }catch (SqlException err){141. String strErro = "Erro: " + err.ToString();
  17. 17. 142. Console.Write(strErro);143. return false;144. }145. }146. public static int ContabilizaFuncionariosPorDepartamento(StringpIDDepartamento) {147. SqlConnection objConexao = FabricaConexao.getConexao();148. String strQuery = "SELECT COUNT(*) FROM Funcionario WHEREDepartamentoOID = "+pIDDepartamento+"";149. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);150. int vRetorno = 0;151. try{152. objCommand.ExecuteNonQuery();153. SqlDataReader objLeitor = objCommand.ExecuteReader();154. while (objLeitor.Read())155. {156. vRetorno = Convert.ToInt32(objLeitor[0]);157. }158. return vRetorno;159. }catch (SqlException err){160. String strErro = "Erro: " + err.ToString();161. Console.Write(strErro);162. return vRetorno;163. }164. }165. }166. } Em toda a estrutura DAO, existem basicamente os seguintes métodos: recuperaObjeto(recupera um objeto em específico da classe referenciada), recuperaObjetos (recupera todos osobjetos da classe referenciada), persistir (persiste um objeto no banco de dados), atualizar (atualizaum objeto em específico com novas informações) e excluir (excluir um objeto especifico). Outrosmétodos são definidos, mas as chamadas operações CRUD (CREATE, RETRIEVE, UPDATE eDELETE) são feitas por estes apresentados. O CRUD representa todas as operações básicasnecessárias para a persistência e manipulação de objetos em uma base de dados relacional. A Listagem 8 inicia importando as bibliotecas e os namespaces que fará uso. Isso ocorreentre as linhas 1 e 6. Da linha 12 até a 50 é definido o método recuperaObjeto. Este método recebepor parâmetro o atributo identificador de um Funcionário que ao final do método é recuperado dabase de dados e disponibilizado à aplicação. Na linha 13 é feito a solicitação à classeFabricaConexao pelo objeto de conexão. Com este, é possível estabelecer consultar no banco dedados configurado. Na linha 14, é definida uma variável chamada strQuery. Esta variável armazenaa consulta SQL que será enviada para o banco de dados. Observe que neste caso esta sendo feito umSELECT, solicitando os campos ID, Nome, CPF, DepartamentoOID da tabela Funcionario quetenha o ID passado por parâmetro. Após, na linha 15, é instanciado um objeto do tipo SqlCommand,responsável por executar a consulta na base de dados, configurada pela conexão recebida peloFabricaConexao. Entre as linhas 23 e 44, é feito um esforço para recuperar as informações da basede dados e então popular um objeto, que é então retornado como retorno do método. Na linha 38, ésolicitado ao controlador de Departamento que recupere o objeto Departamento associado aoFuncionário, já que todo funcionário deve estar alocado em um departamento. O métodoRecuperaObjetoObjeto, da classe cntrDepartamento é um método de classe que retorna um objetoDepartamento de acordo com o parâmetro passado. A partir da linha 23 o método busca identificaro tipo do funcionário para recuperar todas as informações e que seja instanciado um objeto de formacorreta da hierarquia. Entre as linhas 89 e 127 é definido o método recuperaObjetos. Este recupera todos os objetosda base de dados. O seu funcionamento é semelhante ao recuperaObjeto, mas com uma diferença:não é retornado um objeto, mas sim uma lista de objetos – todos os persistidos na base de dados. Otipo de retorno do método é IList, que é a interface da classe Collections. O que permite a utilizaçãoda classe ArrayList, como definido na linha 90. Já entre as linhas 128 e 145 é apresentado o método
  18. 18. excluir. Este recebe o atributo identificador do funcionário como parâmetro e o excluir da base dedados, retornando verdadeiro em caso de sucesso e falso em caso de insucesso. Nas linhas 146 à 164 é definido o método ContabilizaFuncionariosPorDepartamento. Estemétodo faz uma contagem no banco de dados de quantos funcionários existem em um determinadodepartamento. Por fim, entre as linhas 51 e 88 é apresentado o métodorecuperaObjetosPorDepartamento. Este responsável por recuperar uma lista de funcionários de umdeterminado departamento. Para isso é feita uma consulta restritiva no campo DepartamentoOID,como pode ser observado na linha 54.Listagem 9. Definição da Classe FuncionarioHoristaDAO1. using System;2. using System.Collections.Generic;3. using System.Text;4. using Empresa.Model;5. using System.Data.SqlClient;6.7. namespace Empresa.Persistence{8. class FuncionarioHoristaDAO{9. public FuncionarioHoristaDAO(){10. }11. public Boolean persistir(FuncionarioHorista pFunHorista){12. SqlConnection objConexao = FabricaConexao.getConexao();13. String strQuery = "INSERT INTO Funcionario VALUES(" + pFunHorista.Codigo+ "," + pFunHorista.Nome + ","+ pFunHorista.CPF+","+pFunHorista.Departamento.Codigo+")";14. strQuery = strQuery + "; INSERT INTO FuncionarioHorista VALUES("+pFunHorista.Codigo+","+pFunHorista.NumDiasTrabalhados+","+pFunHorista.NumHorasDiaTrabalhado+","+pFunHorista.ValorHora+")";15. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);16. try{17. objCommand.ExecuteNonQuery();18. return true;19. }catch (SqlException err){20. String strErro = "Erro: " + err.ToString();21. Console.Write(strErro);22. return false;23. }24. }25. public Boolean atualizar(FuncionarioHorista pFunHorista){26. SqlConnection objConexao = FabricaConexao.getConexao();27. String strQuery = "UPDATE Funcionario SET Nome = " + pFunHorista.Nome +", CPF = "+pFunHorista.CPF+", DepartamentoOID = "+pFunHorista.Departamento.Codigo+"WHERE ID = " + pFunHorista.Codigo + "";28. strQuery = strQuery + "UPDATE FuncionarioHorista SET NumDiasTrabalhados ="+pFunHorista.NumDiasTrabalhados+", NumHorasDiaTrabalhado ="+pFunHorista.NumHorasDiaTrabalhado+", ValorHora = "+pFunHorista.ValorHora+" WHERE ID= "+pFunHorista.Codigo+"";28. SqlCommand objCommand = new SqlCommand(strQuery, objConexao);30. try{31. objCommand.ExecuteNonQuery();32. return true;33. }catch (SqlException err){34. String strErro = "Erro: " + err.ToString();35. Console.Write(strErro);36. return false;37. }38. }39. }40. } A classe FuncionarioHoristaDAO esta sendo apresentada pela Listagem 9. Em estruturasemelhante à classe FuncionarioDAO, esta apresenta dois métodos: persistir e atualizar. O persistiré responsável por salvar um objeto FuncionarioHorista no banco de dados e o atualizar poratualizá-lo. Em cada um dos métodos são definidos um SQL referente a cada operação. Em ambosos casos, é retornado verdadeiro em caso de sucesso e falso em caso de insucesso.
  19. 19. Buscando exemplificar o funcionamento da arquitetura do sistema proposto, é apresentado deforma detalhada a funcionalidade Cadastrar Funcionário Horista. A Figura 6 exibe o diagrama deseqüência, com o objetivo de nortear os passos realizados para esse cenário. Figura 6. Diagrama de Seqüência para a Funcionalidade Cadastrar Funcionário Horista Nota: O código-fonte completo da aplicação está disponível para download. O caso de uso inicia, quando o usuário acessa a interface e aciona a opção Adicionar NovoFuncionário Horista. Esse por sua vez acessa o controlador da classe Departamento(cntrDepartamento) para alimentar o ComboBox com todos os departamentos, invocando oRecuperaObjetos. Esse, por sua vez, aciona o RecuperaObjetos da classe Departamento, que acessao método recuperaObjetos da classe DepartamentoDAO para recuperar os departamentos da basede dados. Com o ComboBox montado, é exibido o formulário de criação de um novo funcionário comoexemplificado na Figura 7. Figura 7. Interface do formulário de um novo funcionário horista O usuário informa então os dados do novo funcionário e aciona o Salvar. Nesse ponto, oformulário (frmNovoFuncionarioHorista) monta um vetor (vetEnvia) com os dados do funcionárioe passa como parâmetro ao Salvar do controlador da classe FuncionarioHorista(cntrFuncionarioHorista).
  20. 20. Esse, por sua vez, instancia um novo objeto do tipo FuncionarioHorista, e atribui os valoresdo vetor ao objeto. Com o objeto montado, é invocado o seu método Persistir. Este faz o acesso àclasse FuncionarioHoristaDAO, que inicialmente resgata da classe FabricaConexao uma novaseção de conexão com o banco de dados (getConexao) e gera o SQL para inserir as novasinformações na base de dados. Este então executa o SQL na base de dados persistindo o objeto. Caso todas as operações tenham sido realizadas com sucesso, é retornado true para todos osmétodos até a interface. Caso tenha ocorrido algum erro, é retornado false para a interface que seresponsabiliza em emitir uma mensagem de erro ao usuário. Somente a interface tem acesso ao usuário nessa abordagem, portanto, somente ela podeenviar notificações de erros ou de sucesso. Após, uma consulta ao banco de dados pode verificar apersistência dos objetos.Conclusão Este artigo teve como objetivo abordar de forma prática a utilização do paradigma Orientadoa Objetos no contexto do desenvolvimento de software no ambiente do Visual Studio na linguagemC# .NET e de técnicas aliadas, como mapeamento objeto relacional e utilização de padrões dedesenvolvimento. Foi possível observar na prática como realizar de forma simples a persistência e manipulaçãode objetos utilizando um banco de dados relacional, apoiado por padrões de desenvolvimento, comoo padrão de projeto DAO (Data Access Object), que encapsula todo o contexto de conexão ecomunicação com o banco de dados. Atualmente, essa abordagem tem uma grande aceitação, uma vez que os bancos de dadosOrientados a Objetos ainda não são o padrão de mercado, tornando possível a união entre osconceitos da Orientação a Objetos, com o desempenho, maturidade e confiabilidade dos bancos dedados relacionais.

×