Arquivo para a categoria 'Todos'

EDWS – Sistema de Gerenciamento de Conteúdo

Em certa oportunidade um usuário me pediu para construir um site para o estabelecimento onde trabalha. Eu perguntei qual o objetivo do site. Ele simplesmente respondeu que a chefia dele quem solicitou e ele não sabia nem por onde começar. Ele não tinha a menor idéia do que ia colocar no site. Fiz algumas sugestões de conteúdos e disse que ele deveria, primeiro, conversar com os setores do estabelecimento e colher informações para alimentar o site com notícias, fotos, informações, artigos, textos, etc.

Mas surgiu um problema: quem iria dar manutenção no site? EU? Sem chances!!!!!!! Foi aí que surgiu a idéia de construir um sistema gerenciador de conteúdo onde ele mesmo pudesse criar e gerenciar as páginas do site. A criação das páginas deveria ser bem simples, como se fosse um editor de textos. Procurei na Internet sistemas de CMS (Content Management System ou Sistema Gerenciador de Conteúdo) prontos que pudessem ajudar nessa tarefa e achei alguns: Blogs gratuitos, EVA (100% brasileiro), XOOPS, etc. Todos muito bons porém, para usuários com pouca ou nenhuma experiência, são exageradamente cheio de recuros. É bom que se diga, bons recursos. Mas para o meu problema, possivelmente eu tivesse que “dar um curso” de alguma dessas ferramentas para o usuário e o pior: ficar tirando dúvidas, etc. Sem falar nos problemas com a instalação do banco de dados.

Decidi construi algo mais simples, levando em consideração que o usuário só queria ter um local na Internet para divulgar informações. Construi o EDWS – Edição Dinâmica de WebSite. Esta primeira versão era bem limitada. Uma versão light. Tinha uns 3 layouts prontos, menu superior e lateral e dois recursos pré-formatados: uma página “Fale conosco” e uma outra para localização do estabelecimento no Google Maps. Adicionei também um contador de visita além de uns links para alguns serviços últeis: consulta de CEP e previsão do tempo. A edição das páginas era feita utilizando o FCK Editor. Já falei dele em posts anteriores. Documentação sobre este editor pode ser facilmente encontrado na Internet.

O fato é que o usuário ficou satisfeito e eu também. Ele fez o site e está no ar até hoje. Eu também gostei do resultado e decidi desenvolver outra versão para o EDWS. Nasce, então, o EDWS – Sistema de Gerenciamento de Conteúdo. Adicionei inúmeros outros recursos pré-formatados: blog, álbum, notícias, novos layouts, YouTube, etc.

Além de tudo, decidi disponibilizá-lo para quem desejar utilizar em seus trabalhos. Acho que o maior diferencial deste sistema é a simplicidade e facilidade de uso. Quem desejar conhecer mais sobre este sistema e baixá-lo pode acessar o blog que criei especialmente para este projeto: http://edwsblog.wordpress.com. Não há necessidade de adiquirir licença para utilizar a versão gratuita. Porém quem desejar suporte ou os fontes do programa poderá entrar em contato comigo para fazer-mos alguma negociação. A única limitação dessa versão gratuita é a exibição de um link para o blog do EDWS.

É isso!

Sistema c/ fontes migrados do .NET 2.0 para .NET 3.5

Quando iniciei na plataforma .NET utilizei a versão 1.1 do framerwork no VS2003. Com o lançamento da versão 2.0 juntamente com o VS2005 migrei as aplicações para esta versão.

Hoje com o anúncio do VS2010 e do .NET 4.0 decidi migrar as minhas aplicações para a versão 3.5 e VS 2008. Preliminarmente tive dois problemas na migração:Editar posts ‹ Reginaldo Jr. Weblog — WordPress

  1. O Service Pack 1 do Visual Studio 2008 tinha uns bugs. Mas isso não foi problema por que no site da microsoft já havia a solução. Páginas com MasterPage, AJAX e componentes do AjaxControlToolkit geravam um erro durante a utilização do modo Design no VS 2008. O problema e a correção podem ser baixados aqui.
  2. O tratamento de excessão dentro do UpdatePanel do AJAX foi alterado em sua forma de utilização. Para utilizar a forma de tratar a excessão dentro de um UpdatePanel como era utilizada no .NET Framework 2.0 e VS 2005 tive que implementar um pequeno script em Javascript. Uma excessão dentro de um UpdatePanel na versão 2.0 do framework fazia surgir um ‘alert’ no browser. Na versao 3.5 surge um erro Javascript que precisa ser tratado em Javascript. Dá uma certa flexibilidade no tratamento de erros no lado do cliente. Mas com um pequeno script isso pode ser corrigido e o ‘alert’ pode ser exibido. Quem desejar ver este scrpit pode pedir por email que eu envio. Leia mais aqui.

No geral não tive problemas de adaptação ao novo ambiente já que é bem próximo da versão anterior. Porém achei pesado, ou seja, precisa de mais memória para uma boa performance. Mas indico a migração. Quem usa NHibernate como camada de persistência não vai ter maiores problemas, principalmente se utilizar o pacote NHibernate 2.0.1 GA. Tive um erro com uma query utilizando Criterion que, escrevendo em HQL, resolveu o problema.

Estou utilizando o VS2008 Pro SP1 desde o dia 28/06/2009 e “tudo bem também”; nada de mais. Espero não ter outros problemas. Se tiver possivelmente eu atualiza este post com o novo problema (não garanto). Quem conhecer outros incovenientes queram por gentileza deixar um comentário nesta página.

É isso. Ah, os sistemas com fontes que disponibilizo, agora, vai nessa nova versão da plataforma.

Validar Campos no Cliente com .NET e Javascript

Uma ponto importante para quem desenvolve sistemas é o tráfego de rede. Espera-se que os sistemas de informações utilizem o mínimo possível os recursos da rede. Evitar acessos desnecessários ao servidor de aplicação e banco de dados é uma das providências que os desenvolvedores devem tomar pra diminuir esse tráfego.

Em sistemas web não seria diferente. Afinal o acesso a páginas web pode ocorrer via intranet, ou seja, na rede local, ou pela internet passando por vários servidores, bandas, nós, comutadores, etc. É importante evitar submissões de páginas desnecessárias. Isso pode fazer com que a navegação seja bem mais rápida e produtiva. Por exemplo, se for definido na aplicação uma regra que somentes CPF´s válidos podem ser gravados no banco de dados, a aplicação deve validar o CPF antes de gravar no banco. Mas onde essa validação deve acontecer? Algumas sugestões:

  1. Triggers na tabela – Antes do INSERT a trigger pode validar o CPF. O uso de trigger é desaconselhável, principalmente para validações de campo;
  2. Procedures -  Se o sistema utilizar as procedures para implementar as regras de negócio, um ótimo lugar para validar o CPF é durante a execução da procedure;

Essa duas formas tem um problema em relação ao tráfego: os dados trafegaram a rede inteira apartir da tela do cliente até o banco de dados apenas para retornar “CPF inválido.”

Se utilizar um servidor de aplicação em uma arquitetura de n-camadas pode-se implementar a validação nos objetos de négocio. Isso já diminui um pouco o tráfego. Afinal o servidor de aplicação deve estar em uma camada acima, em relação a camada onde é feito o acesso ao banco de dados. O servidor de aplicação pode validar os dados e quando forem enviados à camada infeiror, os dados já foram validados na camada de regra de négocios.

Mas podemos subir camada ainda mais nessa validação. Podemos colocar a validação do CPF na camada de apresentação, exatamente no servidor web. Plataformas como PHP, ASP, ASP.NET, JSP podem utilizar essa forma. A página é submetida ao servidor web que faria a validação dos dados. Note que o servidor web deve ficar numa camada acima do servidor de aplicação.  Agora o tráfego é apenas entre o cliente e o servidor web que já é muito bom.

Mas tem certas validações que podem ser feitas diretamente no cliente; lá no navegador. Vejamos alguns exemplos:

  • campos que não podem ser nulos;
  • data, cpf, cns, cnpj, etc. inválidos;
  • comparação de dados entre dos campos.

Ou seja, se determinadas validações, também chamadas de pré-validações, forem checadas antes de submeter a página ao servidor web podemos evitar ao máximo tráfegos desnecessários em situações elementares. O campo CPF pode ser validado antes de o usuário enviar os dados ao servidor, ou seja, a página só seria enviada ou submetida ao servidor se o CPF fosse digitado corretamente, com os dois dígitos verificadores válidos. O mesmo podemos pensar com datas, horas e outros valores. Assim a diminuição do tráfego seria total. A gravação do CPF, ao ser validado no navegador do cliente, quando fosse enviado ao servidor certamente seria gravado já que o CPF sempre estaria correto ao chegar no servidor. Isso vale para vários outros tipos de campos: data, hora, data e hora, cnpj, cns, números, campos com dígitos verificadores, entre outros.

Essa validação no cliente pode ser feita com Javascript. Uma problema: “E se o navegador não suportar Javascript?” Realmente. Aí a validação deverá também ser feita em alguma das camadas inferiores citadas acima. Foi dito que essas validações seriam um tipo de pré-validações. Nenhuma aplicação deve ser feita apenas com validações no navegador do cliente. Algum outro local deve fazer a validação principal. Os objetos de negócio devem implementar as validações dos campos. Em programação orientada a objetos isso passa a ser um requisito técnico. Se a validação no navegador do cliente não funcionar, a verificação em outra camada inferior deverá ser feita.

O fato é que validar no navegador do cliente utilizando Javascript é um boa prática para qualquer sistema web. Em ASP.NET existe alguns componentes que realizam essa tafera com muita qualidade.

  • RequiredFieldValidator: usado quando um campo não pode ser vazio;
  • RangeValidator: usado para verificar se o conteúdo do campo está dentro de uma determinada faixa;
  • RegularExpressionValidator: usado para validar campos utilizando expressões regulares;
  • CompareValidator: usado para comparar dois campos;
  • CustomValidator: usado para preparar uma verificação personalizada;

Todos esses validadores fazem verificações diretamente no navegador do cliente e só deixa os dados serem enviados ao servidor se os dados estiverem de acordo com as condições definidas nos validadores. Existe mais um componente chamado ValidatorSummary que é capaz de exibir mensagens de erro durante a validação. Leia mais sobre esses validadores neste link.

Gostaria de destacar a utilidade do CustomValidator. Ele permite utilizar validações personalizadas em Javascript. O desenvolvedor pode criar alguma validação de acordo com sua necessidade.  Para utilizar este validador genérico a função em Javascript segue uma padronização na sua definição. O script para validação pode vir entre tags <scripts></scripts> na própria página ou em arquivos .js e vinculados a página. A função de validação pode ter qualquer nome sendo que os parâmetros de entrada devem ser source e arguments.  Veja o exemplo:

<script language=”Javascript”>

function valida_vazio(source, arguments)

{

// O campo não pode ser vazio

if (arguments.Value!=”")

{

arguments.IsValid = true;

return true;

}

else

{

arguments.IsValid = false;

return false;

}

</script>
O exemplo acima faz a mesma coisa que o RequiredFieldValidator: valida campos que não podem ser vazio. O CustomValidator faz referência a esta função na propriedade ClientValidationFunction. Voce pode também combinar validators. Por exempo: O RequiredFieldValidator pode ser usado para verificar que um campo não pode ser vazio e o CustomValidator para verificar se o campo foi preenchido com um CPF válido por exemplo.

Note que essas validações no cliente apenas verificam a qualidade dos dados digitados. Elas não verificam, por exemplo, se o CPF está ou não cadastrado no banco. Esse tipo de validação tem que ser feita do lado do servidor.

Diversos tratamentos e validações pode ser feitos utilizando Javascript e o CustomValidator. Veja alguns exemplos:

  • CEP
  • CNPJ
  • CNS
  • CPF
  • Data
  • Data/Hora
  • Números decimal
  • Dígito verificador
  • Email
  • Hora
  • Números
  • PIS/PASEP

Essas validações são comumente utilizadas na maioria das aplicações. Eu implementei cada uma delas em Javascript e construi uma página em ASP.NET que demonstra a utilização de cada uma delas com o CustomValidator.  Se desejar ver ou ter todas ou alguma dessas validações clique aqui.

Então é isso.

Relatórios em .NET: ReportViewer e NHibernate

Quem utiliza sistemas de informações sabe da importância dos relatórios. Eles são tão importantes quanto o próprio banco de dados. Listagens, gráficos, resumos, sumários, formulários são alguns exemplos de resultados que essas ferramentas devem ser capazes de fornecer. Claro que dada tipo de resultado será aplicado em um contexto. Cada sistema precisa emitir relatórios de acordo com a necessidade do trabalho onde for utilizado. Por exemplo, os gráficos são normalmente utilizados para avaliação e gestão. As listagens são utilizadas para buscas, levantamentos, etc. O fato é que relatórios são de vital importância para quem utiliza algum sistema de gerenciamento de dados.

Por outro lado, os desenvolvedores de sistemas sabem da dificuldade de se construir um relatório. Isso sem falar das alterações que possam surgir posteriormente. Todos procuram alguma ferramenta que possa minimizar o desgaste natural causado pelo processo de construção e manutenção de relatórios. A situação tende a se agravar quando falamos de relatórios para sistemas web. Isso por que os navegadores trabalham com HTML. A situação natural é montar relatórios utilizando esta linguagem diretamente e isso não é tão trivial assim. Mesmo utilizando alguma outra linguagem que rode do lado do servidor o resultado final deve ser em HTML que é o que os navegadores são capazes de exibir. Para aumentar o poder desses navegadores alguns recursos podem ser utilizados: ActiveX, Plugins, Flash, Applets, etc. Essas e outras tecnologias, além de dar maior poder aos navegadores, aumentam a produtividade dos desenvolvedores já que podem utilizar ferramentas mais completas para gerar os relatórios que serão vistos nos navegadores.

Em .NET não seria diferente. Montar relatórios é um processo muito delicado. A pergunta é qual a melhor forma? Qual a melhor ferramenta? Resposta: EU NÃO SEI. Mas será que existe uma forma dita “melhor”?! Mas, como todo programador, eu também tenho a minha forma que pode não ser a melhor nem a mais ortodoxa. Mas é a minha forma e é com ela que tenho resolvido a maioria dos problemas. Vou compartilhar com voces.

A minha primeira experência em .NET foi quando eu tive que migrar um sistema do Delphi para o Visual Studio 2003. Neste sistema existe inúmeros relatórios. Inicialmente fiz as telas de usuário. Como o sistema em delphi utiliza as procedures de banco como regras de negócio não tive muitos problemas. Tive apenas que refazer as telas que iriam chamar as procedures. O problema começou na hora dos relatórios. Inicialmente tentei utilizar o Crystal Reports. Não me identifiquei com ele. Achei muito complicado e etc. A primeira solução que me veio a cabeça foi a seguinte: já que os relatórios estavam todos prontos em Delphi utilizando views e procedures do banco de dados decidi criar em Delphi um servidor de relatórios. O funcionamento era +ou- assim:

  1. Um programa executavel criado em delphi e instalado no servidor encapsulava todos os meus relatórios. Este programa tinha a capacidade de exportar relatórios em PDF para a pasta web da minha aplicação.
  2. Este programa era chamado de dentro da minha aplicação asp.net passando alguns parâmetros:  id-relatorio, arq-pdf-saida, param-1, param-2, … , param-n. O id-relatório identificava o relatório que eu gostaria de imprimir. Os parêmetros, de 1 a n, eram passados de acordo com a necessidade da instrução SQL do relatório.
  3. O programa recebia estes parêmtros, conectava-se ao banco, extraia os dados do banco, montava o relatório e exportava para pdf em uma pasta com nome e path indicado pelo arq-pdf-saida.
  4. A aplicação aguardava o término do processo até um certo limite e redirecionava o browser para o arquivo pdf gerado. Com o Adobe Reader instalado o navegador baixava este pdf e exibia ao usuário.

Durante muito tempo este sistema funcionou assim. Principalmente por que eu não tinha muito tempo para refazer toda aplicação inclusive os relatórios em 100% .NET utilizando o Crystal.

Mas, novas versões deste sistema foram surgindo e com elas, a necessidade de utilizar uma forma 100% .NET de fazer relatórios. Fiz algumas buscas e achei algumas ferramentas muito interessantes:

  1. DevExpress
  2. Afalinasoft
  3. StimulSoft
  4. PerpetuumSoft
  5. (…)

Algumas eu testei e gostei. Todas são muito boas e integradas ao IDE do Visual Studio. Cada uma com suas características e diferenciais. Mas todas tem a principal limitação para o tipo de trabalho que eu faço:  não são gratuitas. Porém nada impede de utilizar a versão demo convivendo com algumas situações. Uma coloca o nome DEMO no meio de cada página impressa. Outra limita o número de páginas impressas. Outra coloca uma pequena propaganda no final da página. Enfim…. Pra mim era inviável.

Há também quem prefira fazer relatórios em HTML para exibir diretamente no navegador. Separei também um link para esses programadores: http://www.webly.com.br/tutorial/net/8861/aspnet-gerar-relatorio-em-html.htm.

Foi quando eu conheci o ReportViewer. Estudei um pouco sobre ele. Dê uma olhada nos endereços abaixo e conheça também um pouco mais:

  1. http://www.macoratti.net/aspn_grv.htm
  2. http://www.devmedia.com.br/articles/viewcomp.asp?comp=5371
  3. http://blog.adsystems.com.br/2009/04/10/tutorial-c-relatorios-master-detail-com-reportviewer/
  4. http://www.macoratti.net/08/03/vbn5_rpv.htm
  5. http://www.macoratti.net/08/03/vb8_rpv2.htm
  6. http://csharpbrasil.com.br/2008/09/11/criando-relatorio-com-reportviewer-em-aspnet/

Não vou entrar em detalhes do funcionamento. Os links acima são bem explicativos.  Mas duas novas questões surgem:

  1. Eu não gostaria de utilizar o visualizador padrão do ReportViewer. Gostaria de exportar os relatórios diretamente para pdf para utilizar o Adobe Reader como visualizador no prórprio navegador.
  2. Gostaria da utilizar o NHibernate como minha fonte de dados também. O natural é conectar o banco com algum DataSource. Gostaria que os dados viessem da minha camada de negócio (BO) e não conectando diretamente o banco. Principalmente pelo fato da independência de dados que já comentei e posts anteriores.  Sem falar no fato de obedecer as regras da arquitetura em camadas.

Graças a Deus, consegui resolver os dois problemas. Não pretendo construir um tutorial para cada solução.Vou passar a idéia da solução. A implementação da proposta fica como exercício para o leitor.  É necessário ter conhecimento intermediário de OOP, persistência com NHibernate, Visual Studio e arquitetura em camadas. Em posts atenteriores dou uma ajuda nessas questões. Vale a pena dar uma olhada.

Vamos ao que interessa.

  1. Os relatórios desenvolvidos com ReportViewer podem ter como fonte de dados os DataTables. Esses DataTables podem ser criados tanto em tempo de execução quanto em tempo de desenvolvimento. Para nossa proposta é legal criá-los em tempo de desenvolvimento. Isso irá facilitar a confecção do arquivo de relatório (.rdlc). Faça isso. Abra um projeto no VS e adicione um item DataSet. Neste DataSet adicione um DataTable. As colunas do DataTable serão os campos que vc irá imprimir. Adicione as colunas com seus respectivos nomes.
  2. Adicione um novo item ao seu projeto. Este item deve ser um Report (.rdlc). Agora voce deverá formatar o relatório de acordo com sua necessidade. Os links acima dão uma ideia de como trabalhar com a IDE. Uma coisa importante: as colunas do seu relatórios devem ser vindas do DataTable que voce criou no item anterior. Mas para que seja possível fazer essa associação voce deve vincular o relatório ao DataTable. No menu Report, selecione o DataSource. Na caixa suspenda selecione o DataTable que voce criou indicando-o como fonte de dados do relatório. A partir daí voce já pode adicionar colunas ao seu relatório.
  3. Talvez vc queria indicar algumas informações no cabeçalho do seu relatório, tais como: nome da empresa, período, setor, etc. Isso deverá ser passado ao relatório através de parâmetros. No menu Report->Report Parameters voce pode indicar todos os parêmetros que desejar e posicioná-los no cabeçalho do relatório.

Neste relatório voce pode definir: grupos, sumários, totais, gráficos, tabelas com números de linhas e colunas variáveis, etc. Consulte documentação do ReportViewer.  Com um pouco de prática tudo vai parecer muito natural. No início eu támbem demorei um pouco a me familiarizar com o ambiente. Há quem diga que no ReportViewer não dá pra fazer relatórios muito complexos. Para os relatórios do dia a dia tenho tido ótimos resultados. Sem falar no fato: ReportViewer é uma solução gratuita. Qualquer relatório mais complexo que sua empresa precise, posivelmente tenha que meter a mão no bolso. ;)

Mas, continuando… A questão agora é o Nhibernate. Sem problemas! No seu DAO e/ou BO voce deve ter um método que retorne para a camada de apresentação os dados que prentende utilizar no relatório. Esses dados podem ser retornados de diversas formas: IList, IList<> ou o próprio DataTable, inclusive utilizando a estrutura definida no DataSet/DataTable do relatório. Não aconselho usar DataTable nas camadas BO e DAO para retornar dados. Surigo utilizar sempre IList<> nessas camadas e deixar pra conversão em DataTable na camada de apresentação utilizando algum foreach. (Já notou que eu uso C#, não é?) O DataTable destino será aquele mesmo que formatou o relatório do ReportViewer.  Associe o DataTable o relatório, preencha os campos de parâmetros e mande exibir. Vc pode seguir um dos tutoriais que indico acima.

Mas se vc não quiser utilizar o visualizador padrão do ReportViewer? Eu sempre exporto o relatório para PDF e envio  os bytes do arquivo diretamente para o STREAM de tela. No browser do cliente o Adobe Reader captura isso e abre no browser como arquivo PDF. Não há necessidade de gerar arquivo em disco como eu fazia no início.

Mas como fazer esta exportação! Vou dar duas sugestões. A primeira é aprender como se faz consultando os seguintes links: Link 1 e Link 2. A outra opção é “use o que tá pronto”. Na página de Sistemas c/ Fontes deste blog eu disponibilizo uma aplicação que faz exatamente as coisas que eu descrevi aqui. A aplicação é Contas a Pagar on-line. Nele voce pode encontrar os arquivos .rdlc criados, o DataSet com os DataTables criados e o método de exportação em PDF em funcionamento.  Há métodos para exportão para Excel e PDF, em vetor de bytes ou arquivo. Fica a sua escolha. Inclusive mostra como passar parâmetros para o relatório. Esse parâmetros podem ser exibidos, por exemplo, no cabeçalho do relatório como o nome do estabelecimento ou perído. Uma dica: visite esta dica que lá mostra como exportar diretamente para PDF ou Excel sem ter que passar pelo processo de seleção no ReportViewer.

Adiquira o  projeto e veja uma aplicação prontinha utilizando esses conceitos. Além de estar investindo em seu aprendizado está contribuindo para meus estudos e pesquisas. A implementação completa dos métodos fazem parte da Regisoft Library que voce também pode adquirir.

Bom, é isso. Obrigado pela atenção e até a próxima.

    Conversão de documentos para PDF em .NET

    Um cliente me solicitou um sistema que permitisse receber documentos via web. O sistema deveria ter uma página que permitisse fazer upload de documentos (.doc, .ppt, .xls, .txt, .pps, .rtf). Até aí, tudo bem. O Visual Studio possui componente para realizar esta operação facilmente. Em consulta no Google é possível encontrar inúmeras sugestões de código e em diversas linguagens.

    Acontecesse que o cliente não queria armazenar no banco de dados os arquivos recebidos em seu formato original. Ele gostaria que os arquivos, ao chegarem, fossem convertidos em PDF e, então, fossem armazenados num campo BLOB de uma tabela do banco de dados. Aí começou o problema!

    Fiz algumas pesquisas na internet e descobri vários componentes pagos para realizar esta conversão. O cliente não estava disposto a contratar licensas do produto. E agora? Fiz, então, inúmeras pesquisas afim de encontrar algum componente de código aberto que pudesse fazer conversão de documentos do office. Não encontrei nenhum. Aproveito para solicitar a quem encontrar algum componente gratuito que realize esta operação não deixe de registrar aqui.

    Mas nem tudo foi perdido. Um componente .NET eu (ainda) não encontrei (me ajudem). Fui obrigado a apelar para outras soluções e encontrei uma bastante interessante. Vou descrevê-la aqui.

    Achei um programa muito interessante que permite converter qualquer documento imprimível no Windows para PDF utilizando uma impressora virtual: PDF Creator. Conheça mais detalhes da ferramenta no site da comunidade. Clique aqui e conheça mais sobre o formato PDF.

    Execute o programa de instalação, instalando também os exemplos (samples) quando for solicitado. Após instalado, na pasta de instalação do produto possui uma chamada COM (Isso mesmo. A solução foi usar COM/DCOM.) e nessa pasta possui exemplos de utilização do PDF Creator com várias linguagens, inclusive em .NET. Eu me inspirei no exemplo da pasta “C:\Arquivos de programas\PDFCreator\COM\Dot Net\VS2005\C#”. Voce pode abrir esse projeto no Visual Studio, compilar e tirar sua próprias conclusões.Tudo está muito bem explicado. Este exemplo faz uso do ActiveX para permitir a conversão de documentos.

    Quanto ao sistema do cliente devo informar que essa solução teve alguns inconvenientes: :(
    1) Deve ter instalado no servidor WEB o PDFCreator bem como o programa padrão para o arquivo que deseja converter.
    2) Nem todos os arquivos podem ser utilizados para impressão/conversão pelo processo. Pelo menos com os arquivos do Office 2003 (.doc, .ppt, .xls, .txt, .pps, .rtf) que eu testei, foram convertidos sem nenhum problema em um site.
    3) Arquivos com macros, links dinâmicos, etc. e arquivos que, quando aberto necessitem de alguma confirmação para continuar abertura no programa também são problemas. Por exemplo, a princípio não há como converter .html por causa da necessidade de escolha da impressora de saída. O esquema só é útil para arquivos que permitam impressão direta pela impressora padrão sem intervenção do usuário.
    4) O COM do PDF creator não permite abrir várias instâncias do programa. Isso pode ser um problema em sistema WEB onde vários usuários podem estar efetuando a conversão ao mesmo tempo. Caberá ao programador cuidar disso.
    5) As vezes pode ser necessário encerrar (kill) algum processo pendente do PDF Creator na memória. Sem isso outras conversões não poderão ser feitas por causa do motivo do item 4. Também caberá ao programador cuidar disso.
    6) Quando tentar executar um módulo web com acesso ao componente COM possivelmente dê esse erro: Retrieving the COM class factory for component with CLSID {3A619AE4-50EC-46C8-B19E-BE8F50DD2F22} failed due to the following error: 80070005. Pra isso também há solução. Clique aqui e veja como resolver o problema.
    7) Por último, não consegui converter arquivos pelo PDFCreator rodando diretamente em uma página hospedada no IIS. Tentei de tudo e nada. O programador deverá buscar formas de contornar essa situação. Eu consegui dar um jeito nisso também.

    Esses foram alguns dos problemas que enfrentei e acho que utilizei uma boa solução para alguns desses problemas. Claro que tem situações que, a princípio, não há o que ser feito. Aproveito para indicar um pequeno sistema web que construi baseado no PDF Creator. Ele permite o upload de arquivos e faz a conversão. Tratei alguns os problemas que comento acima (só os passíveis de solução). Quem desejar conhecer, o projeto se chama Convert2PDF e faz conversão via web de arquivos do Microsoft Office 2003. Cliqui aqui e veja mais detalhes.

    Quem tiver novidades sobre esse assunto não deixe de registrar aqui.

    É isso.

    Servidor de Aplicação em .NET

    A arquitetura em camadas tem sido amplamente adotada pelos analistas e desenvolvedores de sistemas computacionais. Isso porque esta arquitetura favorece a aplicação de vários conceitos envolvendo a engenharia de software como, por exemplo, modularidade, manutenibilidade, etc. O conceito que motivou a escrita deste post é a escalabilidade, ou seja, o desafio de construir sistemas preparados para “crescer”. Um sistema e dito escalável, por exemplo, quando seu desempenho aumenta com acréscimo de hardware. Não estou falando em ficar mais rápido por que agora ele está rodando em um servidor mais rápido do que o antigo. Estou falando em potencial de crescimento e adaptação a cenários de produção. Imagine a situação: Uma pequena empresa com poucos recursos financeiros requisitou da equipe de TI um sistema de gestão empresarial. Após levantamento de requisitos, avaliação das condições de infraestrutura, decidiu-se pela seguinte configuração: arquitetura cliente/servidor. Um servidor de banco de dados foi colocado na rede e a aplicação cliente faria solicitações a este servidor. A aplicação cliente implementava todas as regras de negócio do sistema de gestão e o servidor de banco de dados serviria apenas como repositório de dados. A princípio tudo funcionava bem: LAN com poucos usuários, poucos dados no banco… Mas a empresa cresceu. Mais usuários na rede, maior volume de dados, novas filiais, negócios via internet, novas regras de negócio, etc. Já está claro que o velho sistema precisaria ser reescrito. Talvez até em outra plataforma de desenvolvimento. Sem falar que, possivelmente, novos especialistas em TI precisarão ser contratados ou, pelo menos, os anteriores terão que passar por algum treinamento/reciclagem. Tudo isso porque não se pensou na possibilidade do sistema crescer em necessidades de regras de negócio juntamente com a necessidade de infraestrutura. A pequena empresa, hoje, tem condições para investir em mais computadores-servidores, internet, redes de longa distância. Ela tem alto volume de dados que precisam ser tratados com velocidade dentro e fora do ambiente da empresa. Eu pergunto: é qualquer sistema que pode se adaptar a esta nova realidade? O grande desafio é CONSTRUIR SISTEMAS PREPARADOS PRA CRESCER. O sistema não precisa nascer grande mas deve possuir características que, com pequenas adaptações, tenha seu potencial aumentado.

    Um bom começo para quem prentende trabalhar com escalabilidade é verificar se seu sistema admite a possibilidade de trabalhar utilizando um servidor de aplicação: as aplicações clientes (desktop ou web) fazem requisições a um servidor. Neste servidor estão implementados todas as regras de negócio e esse servidor faz acesso ao banco de dados para, então, responder às solicitações. Para utilizar essa proposta, que modificações voce teria que fazer no seu sistema?

    1. Teria que reescrever o sistema em outra plataforma?
    2. Teria que efetuar algumas mudanças sim. Voce acha que dá pra fazer? Em quanto tempo?
    3. Teria que, primeiro ser treinado em ambiente em camadas pra depois pensar nisso?
    4. Teria que, primeiro mudar sua forma de programar?
    5. Teria que colocar as regras de negócio da aplicação em um só lugar para depois pensar no servidor de aplicação?
    6. Teria que modelar o sistema primeiro em orientação a objetos?
    7. Outro “teria” qualquer….

    Veja que parece simples responder a esta pergunta mas não é tão imediato assim. Nem todos os sistemas são preparados para isso efetivamente. Outras respostas:

    1. Construimos o sistema com esta visão. Foi previsto que o projeto teria grande possibilidade de crescimento tanto em recursos quanto em necessidades.
    2. Sim. É só modificar o arquivo de configurações do sistema para que as aplicações clientes façam solicitações para o servidor.
    3. Sim. Só preciso modificar uma linha do sistema, recompila-lo e recoloca-lo em produção.
    4. Quantos servidores posso utilizar? Pelo menos um servidor para DAO´s e banco de dados e um outro servidor de regra. Poderiam ser mais servidores de aplicação espalhados pela rede. Depende apenas do nível de resposta que a empresa pretende ter e da disponibilidade de recursos físicos.
    5. O sistema permite dividir papéis facilmente.
    6. Outros “só se for agora” qualquer….

    Se voce puder utilizar alguma dessas respostas, parabéns. Voce já está no caminho certo. É essa linha que a engenharia de software moderna quer que os novos sistemas sigam. Para aqueles que aindam não perseguem estes objetivos vou tentar passar algumas dicas como roteiro inicial a seguir.

    Eu utilizava .NET 1.1 quando me fiz a seguinte pergunta: Em J2EE, pode-se configurar a utilização de um servidor de aplicação através dos EJB containers. JBoss é um exemplo de servidor de aplicação gratuito em Java. Qual o servidor de aplicação para .NET??? Há um tempo atrás fui a uma apresentação sobre .NET 2.0 com Visutal Studio 2005. Na saída fiz essa pergunta ao facilitador e ele me respondeu com uma palavra: “Remoting”. Ao chegar em casa me dediquei a pesquisar sobre o assunto. A seguir, deixo indicado um artigo que serviu de base para nossa trajetória sobre o assunto:

    .NET Remoting – Parte 1 – Acessando informações remotamente
    .NET Remoting – Parte 2 – Acessando informações remotamente

    Desde então temos trabalhado para que a construção dos nossos sistemas tenham carateríscas que viabilizem a arquitetura de acesso remoto. As pessoas que acompanharam em nosso blog os post entitulados NHIbernate + Visual Studio: Construindo aplicações em camadas devem ter notado em algumas partes dos códigos e da explanação a presença de flags para utilização de servidor de aplicação. Desenvolvemos uma solução chamada RemoteServer.NET em Visual Studio 2005 com 3 projetos que casa perfeitamente com esses indicadores:

    1. RemoteServerWin: Um servidor de aplicação utilizando .NET Remoting que roda como aplicação do windows.
    2. RemoteServerService: Um servidor de aplicação, também utilizando .NET Remoting que roda como serviço do windows.
    3. RemoteServerSetup: Um instalador dos projetos anteriores.

    Vamos entender o esquema abaixo numa proposta didática, porém bem próxima de uma arquitetura ideal:

    No ínicio do processo temos um usuário utilizando o seu computador para fazer solicitações ao servidor web através de um navegador. O servidor web é responsável apenas pela apresentação e desenho da página web. Qualquer necessidade de processamento de regras de négocio deverá ser enviada ao servidor de negócio. A linha usuario-navegador-servidor web-servidor de negócio poderia ser subistituida por outras configurações: celular-servidor web-servidor de negócio, aplicativo windows-servidor de negócio, etc. O fato é que o servidor de negócio precisa está preparado para receber e responder a requisições remotas. Neste servidor estaria configurado o RemoteServer.NET para responder solicitações da camada de apresentação. Algumas vezes o servidor de aplicação precisaria acessar dados do banco de dados. Esse acesso, de acordo com padrões de projetos e arquitetura em camadas deveria ser através de DAO´s. Logo poderiamos ter um servidor DAO para responder requisições feitas pelo servidor de negócio. Neste servidor DAO também teria instalado o RemoteServer.NET para responder requisições remotas. Por fim, temos uma máquina como servidor de banco de dados para acesso a dados.

    As possibilidades são inúmeras. Imagine um enorme volume de usuários fazendo acesso ao servidor de regra. Poderiamos colocar novos servidores de negócio pra dividir a carga ou mesmo, mais servidores de acesso a dados fazendo com que as requisições fossem aleatórias a estes servidores evitanto o engarrafamento de requisições no mesmo servidor. Poderiamos também fazer replicação sincrona de dados no banco ou mesmo, utilização de cluster para dividir a carga de acesso ao banco de dados. Tudo dependendo do potencial do parque de informática da empresa e necessidade de acesso rápido ás informações. Adicionemos a tudo isso uma dose de XML Web Service para que outra aplicações possam conectar-se diretamente a seu servidor de regras via web.

    As aplicações que voce desenvolve suporta essas possibilidades?  Isso é ESCALABILIDADE.

    Na nossa página de Sistemas c/ Fontes estamos disponbilizando a solução RemoteServer.NET para aqueles que desejarem adquirir e ampliar seus horizontes. Vale lembrar que o RemoteServer.NET sozinho não faz milagre. A aplicação como um todo deve ser pensada para suportar esses requisitos. O primeiro passo é repensar seus conceitos em desenvolvimento e pesquisar soluções que sejam multi-utilizáveis.

    Quem desejar adiquirir esse e outros produtos entre em contato. Teremos o maior prazer em responder. Voce estará contribuindo para manter nossas pesquisas bem como, a qualidade das nossas publicações.

    É isso.

    Visual Studio + NHibernate: Construindo aplicações em camadas – (cont. VI)

    No post anterior criamos as classes que vão dar suporte às regras de negócio da nossa aplicação. Neste post, que é o último desta série, vamos criar a nossa camada de apresentação. Não pretendo aqui esgotar o assunto sobre isso, nem mesmo desenvolver todas as telas do sistema. O que iremos fazer é dá uma idéia inicial sobre a comunicação entre as camadas e criar uma página web que possa servir de base para o trabalho do desenvolvedor.

    Até o momento tudo que fizemos foi puramente conceitual. E, de posse dos conceitos, utilizamos scripts para gerar os códigos. Destaque para algumas bibliotecas que encapsulam funcionalidades ligadas ao Hibernate, visando diminuir codificação e ganho em reaproveitamento de código. Daqui pra frente quem manda é a critatividade e a prática do programador para desenvolver a aplicação de acordo com os requisitos de sistemas definidos no projeto. Eu considero que é deste ponto que se inicia o trabalho de codificação efetivamente, visto que, até o momento, utilizamos geradores de código para criar as camadas que darão suporte a nossa aplicação. Eu utilizo essa prática em todo sistema corporativo que desenvolvo. Claro que a medida que vão surgindo outras necessidades, tanto as bibliotecas, quanto os scripts vão sofrendo adaptações. Por exemplo, desde quando comecei a escrever esta série algumas mudanças foram feitas nos scripts bem como na biblioteca. Isso é fácil de entender: a medida que vamos trabalhando, vamos aprendendo e aprimorando nossos hábitos e conceitos. Isso faz parte do ser humano: fazer hoje, melhor que ontém.

    Então vamos iniciar os trabalhos. Abra a nossa solução no Visual Studio e adicione um novo projeto. Uma vez me perguntaram se este projeto poderia ser em windows forms. Claro que sim. Pode ser qualquer projeto de GUI: web, windows forms ou console. A camada de apresentação é o local onde o usuário final irá interagir com seu sistema. Quem define isso é o documento de requisitos. No nosso caso será um projeto web. Adicione um web site ou um web application. Eu prefiro utilizar web application e com suporte a AJAX. Qual a diferença? Bom… Eu começei no VS 2003 e ele já utilizava o conceito de web application. Eu gostava porque os arquivos .cs não precisavam ser colocados no site em produção. Ele gerava uma única .dll que implementava todas as classes. No web site, temos que colocar em produção os arquivos .cs que serão compilados, gerando as dll’s, em tempo de execução. Vantagem e desvantagem: Na web application qualquer modificação precisa ser recompilada. No web site modificações podem ser feitas diretamente no arquivo em produção. A compilação será feita automaticamente. Por outro lado, na web application tem como evitar a ação de pessoas não autorizadas na sua aplicação, enquanto no web site não tem como impedir diretamente. Enfim, veja o que é melhor. Fiquei com web application… Adicionei projeto web application com nome “AgTel”. O Visual Studio gerou os arquivos.

    Primeira coisa a fazer é configurar o Hibernate. Vamos utilizar o web.config para isso. Essa configuração vai dizer ao NHibernate qual banco de dados estamos utilizando e onde ele está (usuario, senha, dialeto, tipo de banco, etc.). Uma outra informação que eu coloco neste arquivo é o nome do assembly O/R. Quem vai ler esta informação é a bilbioteca Regisoft.Camadas.dll para configurar o mapeamento do Hibernate.  Neste arquivo, em nossa aplicação e relacionado ao Hibernate, não mexeremos mais neste arquivo. A menos que desejemos fazer alguma mudança ou adicionar algum recurso novo, como por exemplo, se desejarmos trabalhar como servidor remoto. Mas isso é assunto de outros posts.

    Precisamos adicionar algumas referências em nossa aplicação web. Clique no botão direito do mouse sobre o nome do projeto que acabamos de adicionar e selecione “Add Reference…”. Selecione a guia project e, nessa guia, selecione os projetos BO, Interface e OR (não selecione o DAO) e clique em ‘OK’.. Lembre da obediência a hierarquia em cadamas que discutimos anteriormente. A camada de apresentação só pode fazer requisições à camada de negócio. Nunca à camada DAO. Lembra da biblioteca Regisoft.dll? Adicione ela também. Mas duas bibliotecas serão necessárias: Regisoft.web.dll e Regisoft.Web.UI.WebControls. A primeira possui recursos para manipulação de javascript, limpeza automática de campos da tela, atribuição automática de valores dos objetos O/R a campos da tela, etc. A segunda são alguns componentes da toolbox que eu adicionei alguns novos recursos.

    Clique aqui e baixe as bibliotecas. Vai junto também o web.config para quem tiver alguma dúvida. Após download e descompactação (renomei antes de descompactar para .ZIP), salve junto com as outras que utilizamos anteriormente. No projeto adicione as duas novas bibliotecas como referência no projeto. A Regisoft.Web.UI.WebControls.dll deve ser adicionada também na Toolbox do Visual Studio para facilitar. Para fazer isso clique com botão direito do mouse em qualquer lugar da Toolbox e selecione “Add Tab“. Dê um nome: “Regisoft”. Clique ainda com botão direito dentro da tab criada e selecione “Choose Items…“. Quando a janela aparecer clique em “Browse” e localize a biblioteca Regisoft.Web.UI.WebControls.dll. Confirme… Pronto! Os componentes foram adicionados. Abra a página Default.aspx e veja que na tab “Regisoft” possui alguns componentes. Inclusive essa é a maneira de adicionar webcontrols na Toolbox. Toda vez que voce baixar um componente visual pode adicioná-lo na toolbox dessa forma – Dica.NET ;)

    Se tudo foi feito corretamente teremos a seguinte tela:

    Já estamos com nosso ambiente preparado para iniciar os trabalhos. Vamos criar nossa primeira página web. Faremos uma página para inclusão de UF. Há quem ache que não precisa. Basta popular o banco de dados com essas informações, já que as UF não mudam constantemente. Eu concordo. Mas vamos construir para fins didáticos. Pra não perder a prática utilizaremos o MyGeneretion e um dos nossos scripts pra facilitar o trabalho. Não iremos nos preocupar com aparência da página fica como exercício para os interessados.

    Como não é uma tabela com muitos dados vamos utilizar o script “WebFormTabela.csgen“. Utilize este script no MyGeneration e gere os arquivos na pasta do projeto web. Selecione UF dentre as tabelas do banco.

    No Visual Studio, clique em “Show All Files“, selecione os dois arquivos gerados, clique em um deles com o botão direito do mouse e selecione “Include In Project“. Agora, clique em TabelaUf.aspx com o botão direito do mouse e selecione “Convert to Web Application“. Defina a página TabelaUf.aspx como “Set As Start Page” e execute a aplicação. Vamos ver se funciona…

    Pra variar, PROBLEMAS!!!!! Vamos as correções:

    1. Se voce baixou as atualizações dos scripts e bibliotecas do post anterior e está utilizando, terá que gerar os DAO´s novamente. ATENÇÃO: NÃO GERE POR CIMA. APAGUE-OS E GERE NOVAMENTE.
    2. No projeto AgTel adicione referencia à bilbioteca do Firebird (FirebirdSql.Data.FirebirdClient.dll) que pode ser conseguida diretamente no site do Firebird. Após a adição, clique com botão direito do mouse sobre a referência adicionada e selecione “Properties”. Modifique a propriedade “Copy Local” para true. Se voce utilizar outro banco deve fazer a mesma coisa: adicionar o client do seu banco ao projeto. Sendo SQL Server ou Oracle isso não será necessário. Na realidade, este passo depende do banco que voce está utilizando e a forma que voce configurou o Hibernate para acessar este banco.
    3. No projeto BO é necessário adicionar referência de duas bibliotecas: Regisoft.dll e Regisoft.Camadas.Interface.dll
    4. No projeto AgTel crie uma pasta chamada Diversos. Nesta pasta voce deve utilizar o MyGeneration com o script BOAccess Class for Nhibernate.csgen para gerar a classe de acesso aos DAO´s. Durante a geração da classe pelo MyGeneration: em using escreva AgendaTelefonica.OR e em namespace escre AgTel. No Visual Studio selecione o arquivo e “Include In Project“.  Mas este script possui alguns erros que só identifiquei enquanto preparava este post. No post anterior, os arquivos para download foram substituídos por versões corrigidas.
    5. No arquivo TabelaUf.aspx.cs adicione na seção de using: using AgendaTelefonica.BO;
    6. Substitua a linha 46 por IList<Uf> lst = BOAccess.getBOFactory().UfBO().Listar(“Sigla”);
    7. Substitua a linha 91 por o = bo.UfBO().InserirAlterar(o, op);
    8. Substitua a linha 129 por BOAccess.getBOFactory().UfBO().Excluir(lst); Essas 03 últimas modificação removem a informação de usuário dos parâmetros de entrada dos métodos. Essa informação serviria para que, na regra de negócio, houvesse validação de permissões do usuário. Removi apenas para fins de testes na página.
    9. Comente a linha 26, 27 e 28, também removendo informação de login de usuário. Eu guardo a informação de login na sessão. Quando a sessão expira o usuário deve efetuar login novamente.;
    10. Para nosso exemplo, foi necessário fazer modificações no script do banco. Um novo script foi substituído no primeiro post dessa série. Nada muito complexo. Apenas incluí dois Generator no banco: Um para auto-numeração do cadastro de cidades e outro para auto-numeração do cadastro de UF.

    Depois dessas modificações a página já pode ser testada. Note e a página é bem simples e complatemente funcional. Seria interessante adicionar alguns recursos visuais com CSS ou coisas do tipo. Mas não é objetivo deste material.

    A verdade é que os geradores de código não resolvem todos os problemas. Mas adiantam bastantes. Com algumas modificações podemos ter ótimos resultados. Imagine se tívessemos que escrever tudo do zero…

    Vamos agora ilustrar a adição de métodos de acesso a dados no DAO. Abra o UfDAO.cs e adicione as seguintes linhas:

    /// <summary>
    /// Selecionar uma UF através da sigla
    /// </summary>
    /// <param name=”sigla”>Sigla para pesquisa</param>
    /// <returns></returns>
    public Uf SelecionarPorSigla(string sigla)
    {
    ICriteria crit = getCriteria()
    .Add(Expression.Eq(“Sigla”, sigla));
    return crit.UniqueResult<Uf>();
    }
    /// <summary>
    /// Listar UF´s que iniciem por uma string
    /// </summary>
    /// <param name=”descricao”>Descrição inicial para filtro</param>
    /// <returns></returns>
    public IList<Uf> ListarPorDescricao(string descricao)
    {
    string hql = @”select uf from Uf uf
    where uf.Descricao like :descricao
    order by uf.Descricao”;
    IQuery query = getSession().CreateQuery(hql);
    query.SetAnsiString(“descricao”, descricao + “%”);
    return query.List<Uf>();
    }

    Veja que criamos dois métodos DAO´s comentados. Um com critéria e outro com HQL (Hibernate Query Language). Veja que o controle da sessão do Hibernate vem do getSession() e o critéria vem do getCriteria(). Ambos implementados no BaseDAO. Veja também que com a utilização da nossa bilbioteca a construção de métodos de acesso a dados com Hibernate é bem facilitada. Abra tambem a interface IUfDAO.cs e adicione as seguintes linhas:

    Uf SelecionarPorSigla(string sigla);
    IList<Uf> ListarPorDescricao(string descricao);

    Qualquer novo método que for adicionado nos DAO´s deverá também adicionar a declaração na interface correspondente. Agora abra o UfBO.cs e adicione as seguintes linhas:

    public Uf SelecionarPorSigla(string sigla)
    {
    if (sigla == string.Empty || sigla == null)
    throw new ExceptionRS(“Necessário informa a sigla”);
    return ufDAO.SelecionarPorSigla(sigla);
    }
    public IList<Uf> ListarPorDescricao(string descricao)
    {
    if (descricao == string.Empty || descricao == null)
    throw new ExceptionRS(“Necessário informa a descricao”);
    return ufDAO.ListarPorDescricao(descricao);
    }

    Na regra de negócio nos fazemos chamadas aos nóvos métodos do DAO. Adicionamos uma pequena regra que determina que os parêmetros de entrada não podem ser vazio ou nulos. Todas essas validações podem ser colocadas aqui. Eu diria que DEVEM. Mas há quem coloquem apenas na página web através dos componentes ASP.NET de validações. Eu costumo validar os dados de entrada tanto na tela com os componentes de validação, quanto no objeto de négocio. Isso por que caso eu esqueça de validar na tela de entrada certamente no objeto de negócio uma excessão será gerada.

    Como fizemos no IUfDAO.cs, vamos fazer com IUfBO.cs. Abra-o e adicione as seguintes linhas:

    Uf SelecionarPorSigla(string sigla);
    IList<Uf> ListarPorDescricao(string descricao);

    Note que algumas linhas já estão lá definidas assim como no UfBO.cs. Essas linhas foram adicionadas pelos scripts do MyGenerator.

    Após estes procedimentos os novos métodos já estão disponíveis para utilização na página. Fica como exercício: modificar a página para localizar dados por descrição. Dica: existe um script chamado WebFormCadastro.csgen que gera um outro layout de página que foi desenhado para utilizar essas pesquisas. Após a geração dos códigos algumas modificações como fizemos na nossa página serão necessárias.

    É possível modificar os arguivos gerados para que os DAO´s, BO´s e banco dados possam rodar em um servidor de aplicação, equanto que o servidor web e outros programas desktop possam rodar em outra máquinas fazendo solicitações ao servidor. Mas isso é assunto de posts futuro.

    CONCLUSÃO

    Desenvolver sistema é um trabalho desgastante. Mas este desgaste pode ser bem diminuido. Padrões de projetos, geradores de código, pesquisas e toda a engenharia de software podem ser aliados nessa tarefa de desenvolver bons programas.

    Aproveito para indicar nossa área de Sistemas c/ Fontes. Adiquira um projeto completo para auxiliar no seu estudo e contribuir em nossas pesquisas.

    Desde já agradeço a todos e até os próximos.

    Visual Studio + NHibernate: Construindo aplicações em camadas – (cont. V)

    No post anterior desta série discutimos sobre a criação da camada DAO. Geramos as classes e interfaces, além de preparar um DAOFactory que é o caminho por onde serão feitos acessos às funcionalidades dos DAO´s. Vimos também como utilizar uma classe abstrata BaseDAO que, combinada com o MyGeneration, pode facilitar bastante no uso dos recursos do Hibernate.

    Neste post vamos discutir sobre a camada de regras de negócio (BO). Vamos acessar os DAO´s através de um DAOAccess e criar um BOFactory para que a camada de apresentação possa utilizar este caminho para fazer acessos ou requisições às regras de negócio.

    Como o próprio nome já diz a camada de regras de negócio define as regras ou comportamentos que a aplicação terá durante o processamento de requisições oriundas da camada de apresentação. Esta camada pode ser formada por uma ou várias classes que serão responsáveis por controlar a entrada e saída de informações. Não acho legal criar uma única classe para controlar todas as regras de negócio da aplicação. Procuro agrupar em classes, separando as operações relacionadas. Dessa forma consigo ter melhor visão dos módulos da aplicação.

    Mas o que tem numa classe de negócio?! Como sabemos uma classe é formada basicamente por métodos e propriedades. Os métodos irão ser chamados na camada de apresentação para realizar as operações de negócio. As porpriedades irão formar parâmetros de entrada ou saída da classe para determinar algum comportamento do método. Vamos conhecer algumas métodos e propriedades que podemos colocar numa classe de negócio:

    1. Inclusão e alteração de dados. Esses métodos são os mais comuns em qualquer aplicação que utilize banco de dados. Eles serão chamados pela camada de apresentação para realizar a devida operação no banco de dados (através dos DAO´s); Nesses métodos podemos encontrar procedimentos comuns em operações de inclusões e alterações. E, por exemplo:
      • validação de permissões de usuário;
      • validação de campos;
      • verificações de relacionamentos entre tabelas do banco;
      • verificações de violação de índices ou chaves;
      • abertura e fechamento de transações;
      • inserções e/ou alterações em tabelas;
      • outros processos durante a operação.
    2. Exclusões. Esses métodos realizam operações de exclusão de dados do banco. Internamente também possui procedimentos comuns ao processo:
      • validação de permissões;
      • verificação de violação de relacionamentos;
      • verificações de violação de índices ou chaves;
      • abertura e fechamento de transações;
      • eliminações de dados em tabelas
      • outros processos durante a operação.
    3. Seleções de linhas da tabela. Esses métodos vão dar suporte a consultas e listagens que a camada de apresentação possa necessitar e também para outros objetos de negócio:
      • Seleção de uma linha da tabela por chave primária ou índice único;
      • Listagem de registros das tabelas controlada ou não por filtro;

    Acredito que, no mínimo, todas as aplicações realizam alguma ou todas as operações e sub-processos citados acima. Já que esses processos são comuns a maioria das aplicações em camadas e que fazem acesso a banco de dados, seria interessante que pudessemos automatizar a criação desses métodos. Foi exatamente o que eu fiz criando scripts no MyGeneration. Vamos utilizá-lo para gerar as classes da nossa camada de negócio.

    Os scripts que deverão ser utilizados neste processo são:

    • BO Interface for Nhibernate.csgen que irá gerar as interfaces das classes de negócio;
    • BO Class for Nhibernate.csgen que irá gerar as classes de negócio, com as funcionalidades principais já implementadas.

    Claro que, obedecendo a hierarquia em camadas, as classes de negócio fazem chamadas às classes DAO´s. E essas chamadas são feitas atravéz do DAOFactory por um DAOAccess. Parece complicado mas não é. Apenas estou determinando que nenhuma classe DAO seja instanciada com new diretamente na camada de negócio. Quem terá essa responsabilidade será o DAOAccess e quem irá responder a essas solicitações de instanciamento dos objetos é o DAOFactory.

    Acho que não preciso mais comentar sobre o processo de criação dos BO´s e das interfaces no MyGeneration. Inclusive sei que alguns leitores já se adiantaram e geraram essas classes por conta própria, através de nossa explicação anterior. ;) Só irei fazer alguns comentários sobre este processo:

    1. As intefaces devem ser geradas na pasta BO da biblioteca AgendaTelefonica.Interface.
    2. Os BO´s devem ser gerados na pasta da biblioteca AgendaTelefonica.BO.
    3. No Visual Studio, após ter sido gerado os arquivos, selecione as classes e, clicando com o botão direito do mouse em algum dos arquivos selecionados, selecione a opção “Include In Project“. Isso deve ser feito em cada biblioteca onde os arquivos foram gerados.
    4. Após a realização dos procedimentos o Solution Explorer estará assim:

    É importante conhecer o conteúdo dos arquivos gerados e entender seu funcionamento. Destaque para os arquivos

    • DAOAccess.cs, que se comunica com a camada DAO através do DAOFactory.cs;
    • BOFactory.cs que será a via de comunicação entre a camada de apresentação e a regra de negócio.
    • IBOFactory.cs que é a interface de exposição do BOFactory.cs

    Aproveite e olhe a estrutura dos arquivos BO´s gerados, por exemplo CidadeBO.cs. Veja que nele e em todos os outros BO´s existe uma estrutura inicial com aquelas funcionalidades principais e comuns a todos os arquivos de regra de negócio (valiação, inserção, exclusão, etc.).  Note também que no construtor do BO existe a ligação com o DAO correspondente e todos os métodos fazem uso desta instãncia do DAO.

    Não é necessário ter um BO para cada DAO correspondente. Voce pode agrupá-los em funcionalidades próximas na sua aplicação, criando assim uma visão de módulo. Por exemplo, voce pode embutir num único BO as funcionalidades para controlar endereços. Neste BO irá conter todos os métodos para gerenciar endereços: UF, Cidade, CEP, etc.  Assim, na camada de apresentação, voce pode fazer uso de um certo EnderecoBO e nele já possuir tudo que se precisa pra controle de endereço: seleções, inclusões, alterações, etc. de Uf’s, cidades, ceps, etc’s. Inclusive está é a atitude mais comum no que diz respeito a criação de BO’s.

    Certamente durante o desenvolvimento da camada de apresentação será necessário criar vários novos métodos para operações de seleção de dados e/ou persistência, tanto nos DAO’s quanto nos BO’s. Paralelamente, alterações nas respectivas interfaces também serão necessárias. Tudo para que os BO’s realizem com exatidão seu papel de controlar a regra do negócio. Montamos o esqueleto principal que dará suporte a aplicação. No próximo e último post estaremos criando o projeto do site para camada de apresentação. Vamos criar uma tela que servirá de base para entendimento do processo e criação das outras. Vamos criar também novos métodos em alguns DAO´s e BO´s para mostrar um pouco do potencial do Hibernate nesta questão.

    Fiquem a vontade para comentar. Espero que estejam gostando e até o próximo!

    Correções nos Scripts e Bibliotecas

    Para aqueles que fizeram download dos scripts no post sobre desenvolvimento ágil e/ou nas bibliotecas na parte IV do tutorial sobre Visual Studio + NHiberante; existiam alguns bugs que foram corrigidos. Os novos arquivos substituiram os antigos nas referidas páginas.

    Os scritps geradores de página .ASPX tiveram correções nas validações de campos. Nas bibliotecas, a classe BaseDAO tinha um problema de configuração do NHibernate. Como eu, até então, só estava usando no servidor de aplicação não tinha detectado este problema. No momento que eu precisei utilizar num programa sem servidor de aplicação, diretamente no IIS, o problema foi detectado e corrigido.

    Aproveito para citar que nos próximos dias estaremos dando continuidade ao estudo sobre Visual Studio + NHibernate e essas novas correções serão necessárias.

    É isso.

    Visual Studio + NHibernate: Construindo aplicações em camadas – (cont. IV)

    No post anterior criamos as classes e os mapeamento O/R do Hibernate. Vimos que essas classes farão o papel de transferir dados entre as camadas. Neste post vamos construir os DAO´s. Vamos definir os componentes que farão acesso ao banco de dados, ou seja, os DAO´s.

    Vamos falar um pouco sobre alguns detalhes importantes neste processo. No post anterior indicamos um material sobre conhecimentos preliminares em relação ao Hibernate. Importante ter lido antes de continuar.

    Nunca tive muita afinidade com a arquitetura cliente/servdor. Aquela onde existe um servidor de banco instalado em algum lugar da rede e as aplicações acessam diretamente este servidor fazendo requisições e persistindo dados. Esse processo é muito comum em Delphi e Visual Basic. Os programadores constroem um executável, embuntindo as regras de negócio e os comandos SQL no programa. Sempre achei isso meio complicado de gerenciar. E, de certa forma, é mesmo. Controle de transação, travamento de linhas, várias máquinas com o mesmo executável instalado e acessando o mesmo banco, etc. passam a ser preocupações do desenvolvedor que deve embutir soluções no programa. Mesmo usando o Delphi eu preferia separar alguns papéis. Eu fazia assim: a aplicação era responsável apenas por solicitar e exibir dados so servidor. As procedures do banco eram responsáveis para incluir, alterar e excluir dados (regras de negócio e DAO). Nenhuma aplicação poderia efetuar inserções, alterações ou deleções diretamente nas tabelas. Essas operações tinham que passar pelas procedures. As aplicações parametrizava dados e passava para a procedure. A aplicação permanecia aguardando o final da execução da procedure para saber se houve algum problema ou tudo foi realizado com sucesso. Nas procedures eram definidas regras da aplicação: validações, integridades, restrições, procedures paralelas (nada de triggers), etc. Inclusive acho isso muito bom. Não existe nada mais rápido pra banco de dados do que procedures. Eu disse NADA!!!!!!!!

    Como nada é perfeito, tem um problema: se mudar a aplicação para outro banco as procedures teriam que ser reescritas!!!! Eu tinha uma aplicação mediana em SQL Server com mais de 200 procedures que teria que migrar para Oracle. Sem chances reescrever as procedures novamente. E se tivesse que mudar pra outro banco? Reescrever tudo outra vez?.

    Neste cenário entrou o Hibernate! Com ele foi possível ganhar indepêndencia de banco de dados. Mas nem tudo são flores. As procedures do banco geram pouco tráfego de rede. O Hibernate gera auto nível de tráfego. Por isso é importante ter cuidado ao utiliza-lo. Sem falar em outras situações: gerenciamento de sessão, conectividade com outros bancos, HQL (o SQL do Hiberante), configurações, etc. Por tudo isso é importante planejar bem o seu uso. Dediquei um pouco do meu tempo a pesquisar e planejar. Construí uma biblioteca que gerencia inúmeras situações que acabam sendo repetitivas nas aplicaçãoes com Hibernate. Eu a chamei de Regisoft.Camadas. Ela faz parte de um pacote (Regisoft Library.NET) com outras bilbiotecas que utilizo no processo de desenvolvimento. Veja as classes que a biblioteca Regisoft.Camadas possui:

    1. NHibernateHelper – (Regisoft.Camadas.NHibernateHelper) Responsável por configurar e gerenciar o Hibernate dentro da aplicação. Inicialização das classes de mapeamento, gerenciamento da sessão, conectividade com um ou vários bancos de dados ao mesmo tempo são responsabilidades desta classe. Não precisa ser instanciada nem utilizada diretamente. Uma outra classe chamada BaseDAO fará uso desta classe internamente.
    2. BaseDAO – Todos os DAO´s devem herdar dessa classe abstrata. É um DAO genérico que é responsável por dar suporte, através de seus métodos e propriedades, ás operações envolvendo persistência: inserções, alterações, exclusões, transações, seleção de dados, validação de campos not-null, controle de objetos persistentes e transientes, verificação de integridade antes de uma exclusão e outras mais. Existe uma versão bem completa usando o Generic da versão .NET 2.0 (Regisoft.Camdas.Generic.BaseDAO<T,ID> ) e uma versão descontinuada sem Generic (Regisoft.Camadas.BaseDAO). A versão sem Genéric existe por compatibilidade retroativa. Aplicações desenvolvidas em Visual Studio 2003 utilizam esta versão (não valia a pena mudar).

    Eu utilizo esta biblioteca em TODAS as aplicações que desenvolvo. Ela me permite abstrair da problemática do Hibernate. Não será diferente na nossa aplicação de Agenda Telefônica On-Line. Vamos gerar nossos DAO´s herdando da classe abstrata dessa biblioteca. Quem desejar escrever seu próprio BaseDAO ou sua própria biblioteca fique a vontade. Tem um post aqui que fala sobre as funcionalidades básicas que todo DAO genérico tem que ter. Leia mais… Uma novidade: o nosso BaseDAO também pode ser configurado para trabalhar numa arquitetura que faz uso de um ou mais servidores de aplicações. Clique aqui e saiba mais sobre essa possibilidade.

    Clique aqui e baixe a bliblioteca. Vamos utiliza-lá em nosso projeto. ATENÇÃO: Voce deve renomear o arquivo baixado para .ZIP antes da descompactação. Não é um .DOC.

    Utilizando a biblioteca assima não precisaremos escrever manualmente um DAO para cada tabela do banco. Podemos utilizar o MyGeneration para gerar os arquivos necessários. E vamos fazer isso agora. No segundo post sobre nosso assunto disponibilizei os scripts que são utilizados neste projeto e também a explicação de como utilizar o MyGeneration. Neste vamos repetir o processo utilizando dois scripts: DAO Class for Nhibernate.csgen e DAO Interface for Nhibernate.csgen.

    Gerando as interfaces e os DAO´s

    Abra o MyGeneration, efetue as confiurações necessárias se for o caso, abra, primeiramente, o script das interfaces:DAO Interface for Nhibernate.csgen. Execute o script preenchendo os campos como mostrado abaixo. Na selecção da pasta voce deve apontar para o local do projeto AgendaTelefonica.Interface e na pasta DAO.

    Agora abra no MyGeneration o segundo script - DAO Class for Nhibernate.csgen. Vamos gerar os DAO´s. Note que a pasta destino deve ser a pasta onde o projeto AgendaTelefonica.DAO está hospedada. Quando executar o script voce deve entrar os dados da mesma forma que o fez para a geração das interfaces, modificando apenas a pasta destino. Veja a figura acima que é similar!!

    No Visual Studio

    Com os arquivos gerados nas suas respectivas pastas precisamos agora inclui-los em seus projetos. O Visual Studio precisa reconhece-los como parte do projeto. Os passos a seguir devem ser efetuados em cada projeto do Visual Studio, no local onde os arquivos foram gerados.

    1. Selecione o projeto. Se os arquivos gerados não tiverem aparecendo clique no botão “Show all Files“. Depois selecione os arquivos, clique em qualquer dos arquivos com o botão direito do mouse e selecione a opção “Include In Project“.

    Chegou a hora de utilizar a nossa biblioteca. Voce terá que adicionar as bibliotecas que voce baixou aos projetos.

    1. Projeto AgendaTelefonica.DAO: Clicando com o botão direito do mouse sobre o projeto selecione “Add Reference…“. Selecione a aba Browse e localize as bibliotecas Regisoft.Camadas.dll, Regisoft.dll e Regisoft.Camadas.Interface.dll no local onde foi descompactada. Selecione-as e clique em Ok.
    2. Proejto AgendaTelefonica.Interface: Clicando com o botão direito do mouse sobre o projeto selecione “Add Reference…“. Selecione a aba Browse e localize as bibliotecas Regisoft.dll e Regisoft.Camadas.Interface.dll (não inclua neste projeto Regisoft.Camadas.dll) no local onde foi descompactada. Selecione-as e clique em Ok.

    Se tudo foi feito como indicado o Solution Explorer estará como abaixo quando apresentar os projetos AgendaTelefonica.DAO e AgendaTelefonica.Interface.

    Tecle Ctrl+F5 para montar o projeto. Se nenhum erro ocorrer voce concluio com sucesso essa etapa. No máximo, voce receberá uma mensagem informando que não há nenhum projeto que possa ser executado.

    Vamos agora analisar os arquivos gerados.

    1. Abra primeiro o arquivo CidadeDAO.cs. Veja que não existe nada de extraordinário nele. Apenas 03 construtores diferentes na classe. O mais importante é a definição da classe que herda de uma BaseDAO<Cidade,long> e uma interface ICidadeDAO. A BaseDAO é a classe que implementa as funcionalidades de persistências que já estão prontas para serem usadas. Como é uma classe genérica estamos usando <Cidade,long> que diz que o DTO a que esta classe se refere é ‘CIDADE’ e diz também que possui um campo chave primária do tipo ‘long’. É provável que precisemos de algumas novas funcionalidades na classe CidadeDAO.cs mas iremos adiciona-la depois. O principal (inclusão, exclusão, alteração, seleções de dados, transações, ect.) já está disponível pela herança. Abra também a classe ICidadeDAO.cs e veja que lá também não existe nada de mais. Apenas as herança de outra interface genérica.
    2. Abra agora o arquivo DAOFactory.cs. Este será o arquivo por onde as regras de negócio farão acesso aos DAO´s. Voce entenderá isso melhor quando trabalharmos na geração dos BO´s. Veja que também possui uma inteface na sua declaração. Veja que seu construtor possui maneiras para acessar os DAO´s: com ou se servidor remoto. É possível planejar este sistema paraexecutar DAO´s e banco de dados numa máquina, regras de negócio em outra e servidor web em outra. Mas isso não faz parte do escopo do nosso projeto. Quem desejar conhecer mais sobre este assunto aguarde post posteriores ou registre algum comentário. Por hora voce deve entender que os DAO´s permitem flexibilidade de acesso graças a sua estrutura e o factory dos DAO´s sabe disso, permitindo que o programador escolha a forma de acesso que deseja trabalhar. Mas abaixo no arquivo voce vê exatamente os construtores dos DAO´s sendo chamados de acordo com aqueles construtores que mostramos no item 1, na classe CidadeDAO.cs que usamos como exemplo. O mais importante na nossa arquitetura é saber que os chamados aos DAO´s serão feitos através deste Factory (um padrão de projeto).

    Estude bem este processo e os arquivos gerados. No próximo post vamos gerar os BO´s com suas interfaces. O procedimento é similar ao utilizado na geração dos DAO´s e suas interfaces. Estamos abertos a dúvidas e sugestões.

    Se voce gostou e deseja ter os fontes dessas bibliotecas clique aqui. Conheça uma forma de adquirir ajundando a manter nossas pesquisas.

    Até o próximo.

    Próxima Página »


    Calendário

    Novembro 2009
    D S T Q Q S S
    « Jul    
    1234567
    891011121314
    15161718192021
    22232425262728
    2930  

    Desde (04/11/07)

    • 43,583 visitas