quinta-feira, 29 de dezembro de 2011

O javascript não sabe fazer conta??

Essa foi a minha primeira impressão ao fazer uns cálculos um pouco mais complexos no javascript. Depois de resolver a maior parte dos erros de contas com o parseInt e o parseFloat, eu descobri outra faceta bem chata deles: se vc digitar um zero à esquerda no valor a reconhecer, ele vai passar pra octal e a sua conta vai ficar mais bonita ainda.

Pra resolver esse problema, basta atribuir a base numérica na própria função parseInt ou parseFloat. Então o código vai ficar assim:

var x = parseInt(y, 10) + parseInt(z, 10); // Assim o javascript vai converter pra um número na base 10, e conseguiremos efetuar nossos cálculos sem problemas. O parseFloat é a mesma coisa.

Agora vem a minha pergunta: por que o javascript não assume a base 10 como default?? Por que ao digitar um zero à esquerda mudamos a base numérica da variável?

Javascript: ruim com ele, mas muito pior sem ele...

segunda-feira, 8 de agosto de 2011

Múltiplas implementações de uma mesma camada

Olá a todos,

Neste post eu vou dar um exemplo de como fazer um modelo de implementação que mantenha a mesma camada de negócios, mas que utilize uma camada de dados que só é conhecida pela camada de interface com o usuário.

É muito comum um programa ter mais de uma implementação específica, principalmente quando os usuários finais podem estar geograficamente em locais de difícil conexão, etc. Enfim, às vezes é necessário fazer o mesmo programa praticamente duas vezes. Somente o fato de pensar em reescrever o mesmo programa já me dá frio na espinha, então estava eu aqui pensando com os meus botões: "Será que não dá pra deixar pelo menos a camada de negócio intocada e eu mudo somente a parte em volta??". Depois de alguns ensaios eu vi que dá sim e não é tão complicado quanto parece.

A idéia aqui é basicamente a clássica implementação em 3 camadas (interface com o usuário, regra de negócio e persistência), mas adicionaremos duas camadas intermediárias que farão o trabalho de seleção e carga da camada de persistência, de acordo com as configurações do programa via web.config ou app.config.


Ok, vamos aos detalhes:

- Camada de interface com o usuário: Sem novidades aqui, você vai implementar do mesmo jeito de sempre, deixando-a com o mínimo de regras de negócio possível (num mundo perfeito, nenhuma regra de negócio...), mas adicionando uma chave ao seu arquivo de configuração, conforme abaixo:







Deste jeito, a camada de factory vai abrir a camada de persistência pelo seu nome de assembly, onde o único trabalho que teremos será o de ajustar a versão do assembly.

- Camada de negócio

Aqui também há pouco a adicionar, mas é importante que todas as classes tenham um objeto privado fazendo referência ao acesso a dados. Então fica praticamente como um cabeçalho das classes de negócio a implementação abaixo:

DLInterface.IDL assemblyToRun = new DLFactory.Factory().getDataLayer("Class1");

DLInterface é o meu namespace para identificar a interface de acesso a dados. Como serão implementações separadas, eu preciso deixar algo em comum entre elas, portanto essa intersecção será feita por uma interface.

- Factory

Aqui é uma novidade: Muita gente simplesmente referencia a camada de dados na camada de negócio e a persistência de dados está resolvida. Sim, em aplicações normais isso funciona muito bem, obrigado. O detalhe aqui é que a camada de dados tem mais de uma implementação. Portanto eu vou colar o código inteiro da minha factory e explicar melhor depois.

Parece confuso, mas é só aparência:










No método getDataLayer cria uma instância de um assembly (previamente criado por você, óbvio) e retorna a classe passada no parâmetro. Essa classe é referenciada pelo nome mesmo, por isso o método recebe uma string.

O método getAssemblyType é somente uma centralização de código para buscar a chave no web.config (ou app.config). Se você quiser ignorar, sem crise, mas precisará implementar o conteúdo dele mesmo assim.

Os dois últimos métodos fazem parte de um POG (Programação Orientada a Gambiarra) para contornar uma característica bem chata que eu acabei enfrentando. Se a classe não tem nenhuma referência em código das camadas que ela acessa, o Assembly.Load não toma conhecimento do assembly (mesmo que esteja referenciado certinho...)

- Acesso a dados

As camadas de acesso a dados devem ser implementadas com os mesmos métodos, mesmo que alguns não sejam necessários. Isso porque a interface força a implementação do método e a sua camada de negócios vai precisar conhecer uma estrutura mínima para poder acessar ambas as classes sem conhecê-las completamente.

No meu exemplo aqui, eu defini uma interface bem boba, com apenas um método para teste:














O método showMe simplesmente vai mostrar qual é a camada que está sendo acessada.

No final das contas, a arquitetura desta implementação fica assim:






















Esta dica foi testada utilizando o Visual Studio 2010.


Até a próxima!

quarta-feira, 27 de julho de 2011

Um modelo simples de implementação em camadas

Depois de alguns meses sem postar nada, segue abaixo mais uma dica que pode simplificar a sua vida ao desenvolver uma aplicação em camadas, mas o tamanho da aplicação não justifica utilizar Design Patterns, DDD ou qualquer outra técnica mais avançada.
A idéia é implementar 3 camadas separadas e sequenciais e uma camada de elementos visuais, que é usada pelas outras 3 como transporte de dados. Fica algo mais ou menos assim:

Inteface com o usuário
- Nesta camada, não existem regras de negócio, no máximo um ou outro controle de visibilidade ou enable/disable de componente. Toda a validação é passada para a camada abaixo. A única inteligência que a interface de usuário precisa ter é saber quais campos são vinculados a quais propriedades do objeto visual.

Regras de Negócio
- Aqui moram as regras de validação e tratamento dos dados. Tudo o que a tela faz, essa camada valida e retorna se está ok. Ela não sabe qual a tecnologia de persistência de dados que você tem, portanto passa essa responsabilidade para a próxima camada.

Acesso a Dados
- Essa camada sabe qual o seu banco de dados e quais são as queries que você está utilizando para persistência de dados. Adicionalmente é ela quem sabe como preencher o seu objeto visual, que será transportado entre as camadas.

Objetos Visuais
- Essa é a camada que contem as classes que serão transportadas entre as outras camadas. Todas a conhecem e sabem como utilizar suas propriedades e métodos para cumprir suas tarefas, mas aqui só tem métodos de conversão de dados (por exemplo, converter o peso de um atleta de Kg para Libras). Essa classe não sabe se validar, nem se carregar. Quem faz esse trabalho são as outras camadas.

Essa forma de desenvolver programas não é a melhor do mundo, mas ajuda bastante ao desenvolver um sistema de pequeno a médio porte com uma organização de código bastante satisfatória. Deixe cada camada como um projeto na sua Solution de forma a garantir que somente as camadas certas se conheçam (neste caso, Interface de Usuário e Acesso a Dados não podem saber uma da existência da outra).

Para esta dica, eu tenho usado o Visual Studio 2010, mas ela pode ser aplicada em diversas tecnologias.

terça-feira, 11 de janeiro de 2011

Cuidado com datetime na PK

Olá a todos.

Estou reformulando este blog e este é o meu novo primeiro tópico.

Uma coisa que eu vejo muitos teóricos comentarem é a criação de certas tabelas no SQL Server com um campo Datetime na primary key.
Em tese, tudo certo, mas tem um porém: Quando voce tem entradas de dados muito rápidas e consecutivas, a PK não considera o datetime completo. O SQL faz o favor de arredondar em alguns segundos as entradas de dados, sabe-se lá porque. O importante deste post é: NÃO CRIE PRIMARY KEYS COM CAMPOS DATETIME, não dá pra garantir que o SQL Server vai respeitar o conteúdo completo (como milissegundos, por exemplo).

Essa dica foi testada no SQL Server 2005 Express e no Enterprise Edition.

Até a próxima!