Wednesday, November 21, 2012

Proxy Pattern



Proxy Pattern

Esta semana comecei a trabalhar em um projeto que implementa o padrão Proxy para acesso aos serviços expostos pelo domínio. Segue abaixo os detalhes deste padrão que é realmente muito útil, principalmente em sistemas que apresentam arquitetura orientada a serviços.

Descrição do pattern:

"O Pattern Proxy é um pattern Estrutural definido pelo 'Gang of Four'. O seu objetivo principal é encapsular um objeto através de um outro objeto que possui a mesma interface, de forma que o segundo objeto, conhecido como “Proxy”, controla o acesso ao primeiro, que é o objeto real."




Objetivos principais do pattern:

·         Fornecer um placeholder para acesso controlado a um determinado objeto
·         Usar uma camada extra que permite um acesso inteligente, controlado e distribuído aos recursos do sistema.
·         Usar um wrapper e delegate para encapsular o componente real que está sendo acessado.

Tipos de Proxy:

·         Virtual Proxy:  Placeholder para objetos cuja construção é complexa. Geralmente, o objeto real só é criado na primeira vez que o cliente faz a requisição.
·         Remote Proxy: Permite acesso a um representante local de um objeto que reside em um outro espaço de endereçamento.
·         Protective Proxy:  Permite acesso a um objeto assim como o Remote proxy, ou o virtual porém ele confere se o cliente que fez a requisição tem as devidas permissões para acessar o recurso.
·         Smart Proxy: Contém regra de negócios adicionais para controle de acesso ao recurso.


Exemplo Simples de Implementação:

Suponha a arquitetura abaixo, aonde temos aplicações front end que dependem dos serviços espostos pelo domínio.



Imagine que por algum motivo os serviços precisam ser alterados. Caso a arquitetura acima esteja implementada, será necessário atualizar a dependência entre cada um dos projetos front ends com cada um dos serviços acessados.

Quando implementamos o padrão Proxy, nossa estrutura muda para algo parecido com a figura abaixo (retirando as interfaces implementadas pelo serviço):


Usando este padrão, todas as camadas de front-end vão depender do proxy, no caso de precisarmos atualizar as dependências, apenas o proxy será alterado, como cada uma das aplicações faz referência a este proxy elas serão atualizadas indiretamente.


Principais vantagens do pattern:

·         Permite deixar transparente o local (endereço) do objeto real. O cliente não precisa conhecer se o objeto é remoto ou não, este tipo de proxy é conhecido como Remote Proxy.

·         Útil para realizar otimizações, como cache de objetos, rotinas de logs e controle de acesso (segurança). Este tipo de proxy é conhecido como Virtual Proxy.



Exemplo Simples de código C#:

using System;

  // MainApp test application
  class MainApp
  {
    static void Main()
    {
      // Create proxy and request a service
      Proxy proxy = new Proxy();
      proxy.Request();

      // Wait for user
      Console.Read();
    }
  }

  // "Subject"
  abstract class Subject
  {
    public abstract void Request();   
  }

  // "RealSubject"
  class RealSubject : Subject
  {
    public override void Request()
    {
      Console.WriteLine("Called RealSubject.Request()");
    }
  }

  // "Proxy"
  class Proxy : Subject
  {
    RealSubject realSubject;

    public override void Request()
    {
      // Use 'lazy initialization'
      if (realSubject == null)
      {
        realSubject = new RealSubject();
      }

      realSubject.Request();
    } 
  }


Good Stuff:

Tuesday, October 30, 2012

S.O.L.I.D.


SOLID é uma sigla que apresenta 5 princípios básicos da programação orientada a objetos:


Estes princípios básicos servem como guias para o desenvolvimento de um código sustentável e eficiente. Para projetos que implementam o TDD e metodologias ágeis de gerenciamento estes princípios são essenciais.

Abaixo, temos uma introdução de cada um dos princípios

Single Responsibility:

"Every class should have a single resposibility. It should have a single puprpouse in the system, and there should be only one reason to change it." - Michael C feathers

Este é o princípio da responsabilidade única, cada classe no sistema deve ter um único objetivo. É um princípio que prega a coesão do sistema:

Coesão
A coesão Mede o quanto que uma classe e seus métodos fazem sentido;
Uma classe com alta coesão possui responsabilidades bem definidas e são difíceis de serem desmembradas em outras classes;
Uma classe com baixa coesão possui muitas responsabilidades, geralmente que pertencem a outras classes, e podem ser facilmente desmembradas em outras classes;

Open Closed:

Introduzido por Bertrand Meyer no seu livro Object Oriented Software Contruction - http://en.wikipedia.org/wiki/Object-Oriented_Software_Construction, este princípo diz que o código do sistema deve ser extensível (voltamos a coesão) e fechado para modificação. Ou seja, uma entidade deve permitir que o seu comportamento se modifique sem que o código seja alterado.

A idéia mais importante é que uma classe só deve ser alterada para correção de erros. Funcionalidades alteradas e novas devem ser criadas em classes novas que implementam o conceito de herança. Evitando modificações, reduzimos a carga de revisão, testes unitários, integrados,  etc..

Liskov substitution principle

"Objects of subclasses should be substitutabe for objects of their superclasses througout our code. If they are not, we could have silent errors in our code."

Princípio da substituição de Liskov. Se um objeto B implementa herança do objeto A, então o sistema deve permitir que o objeto A seja substituído por B. Por exemplo:

public class Nota {

int valor;

}

public class DezReais: Nota {

public DezReais()
{
this.valor = 10;
}

}

public class VinteReais: Nota {

public VinteReais()
{
this.valor = 20;
}

}

Neste caso temos as classes DezReais e VinteReais que implementam herança da classe Nota. Podemos então ter uma lista de objetos do tipo Nota, que são substituídos por objetos do outro tipo.

var notas = new List<Nota>();
notas.Add(new DezReais());
notas.Add(new VinteReais());

Interface Segregation principle



O princípio da segregação de interfaces diz que os clientes não devem depender de interfaces que não são usadas por eles, ou seja, nossas interfaces devem ser o mais coesas possível, minimizando o aclopamento do sistema.

O conceito foi introduzido por Robert Martin   (vulgo uncle bob), e apresentado através do exemplo de um projeto de software desenvolvido para uma impressora da Xerox.

Neste projeto, os clientes dependiam de uma única classe gigante de job. Para resolver este problema, foi criada uma camada de interfaces entre a classe gigante e os clientes, usando o princípo de inversão de dependência. Agora cada cliente faria acesso a sua própia interface, que é implementada pela classe gigante, escondendo os métodos que não dizem respeito a este cliente.



Dependency inversion principle

O princípio de inversão de dependência diz que as classes do nosso projeto devem depender de abstrações e não de implementações concretas.

Por exemplo:

public class CartaDeBaralho()
{

}

public class Ordenador()
{
   public void Ordena( List<CartaDeBaralho>) {}

}

No exemplo de código acima, a classe Ordenador depende da implementação de CartaDeBaralho.

O ideal seria a classe Ordenador depender de uma interface. Isto evita duplicação de código através da reutilização, deixando a lógica de comparação para cada uma das entidades que implementarem a interface (de volta a coesão). Por exemplo:

public interface IOrdenavel()
{
void Compara();

}
public class CartaDeBaralho(): IOrdenavel
{
public void Compara()
{

}
}
public class Ordenador()
{
   public void Ordena( List<IOrdenavel>) {}

}


Good stuff:
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
http://www.slideshare.net/ydarias/solid-principles-9721480

Wednesday, October 24, 2012

Introdução ao Domain Driven Design

O que é Domain Driven Design?

Domain Driven Design significa Projeto Orientado a Domínio. É um conjunto de práticas e padrões de desenvolvimento de software que foram apresentados no livro "Domain-Driven Design: Tackling Complexity in the Heart of Software" de Eric Evans, que pode ser obtido gratuitamente no link http://books.google.com.br/books?id=7dlaMs0SECsC&printsec=frontcover&redir_esc=y#v=onepage&q&f=false

Geralmente quando desenvolvemos um software estamos automatizando processos ou solucionando problemas que existem no mundo real. Esses problemas e processos podem ser considerados como o domínio do software. É muito importante compreendermos que o software é originado e extremamente relacionado a este domínio.

Por exemplo: Se vamos construir um sistema web que controla a matrícula dos alunos em uma faculdade, podemos enxergar a faculdade como o nosso domínio. Ele vai refletir todas as regras de negócio e processos que existem na faculdade. Os desenvolvedores não possuem conhecimento dessas regras e para isso precisam entrar em contato com os especialistas do domínio que seriam os diretores, coordenadores, professores e secretários.

Ao iniciar um projeto de desenvolvimento de software não podemos simplesmente sentar e programar. Pode até ser que isto funcione em alguns casos mais simples e triviais, mas para desenvolvermos sistemas complexos, sentar e progamar é condenar o projeto ao fracasso.

Nós devemos manter em foco o domínio ao qual o sistema está relacionado. O software precisa incorporar os principais conceitos e elementos do domínio e os relacionamentos que existem entre estes elementos, ou seja: O Software precisa ser um modelo do domínio.

Quando um sistema é bem desenhado, uma pessoa sem conhecimentos específicos do negócio consegue aprender bastante sobre o domínio através da leitura do modelo. Isso é essencial. Sistemas que não estão fortemente ligados ao domínio não reagem bem a mudança com o passar do tempo.

Quando usamos DDD, o primeiro passo que tomamos em um projeto de software é criar uma abstração do domínio. Nós precisamos aprender o máximo possível sobre este domínio através de entrevistas e conversas com os especialistas do negócio. Esse conhecimento não se transforma em código e elementos do software de maneira simples, é preciso primeiro criar uma abstração que define o modelo do domínio.

O modelo de um domínio não é um diagrama, nem um tipo de documento em particular. Na verdade o modelo do domínio é a idéiaexpressada por N diagramas e documentos do projeto.  O modelo de domínio é uma parte essencial do design de software, nós precisamos dele para podermos lidar com a complexidade do sistema.

Quando nós temos um modelo definido, podemos começar a definir o design do código. Não devemos confundir design do código com arquitetura do software. A arquitetura consiste nas coisas que são difíceis de sere alteradas, os componentes principais do sistema enquanto o design de código trata de coisas mais específicas, detalhes pequenos e que provavelmente serão alterados a todo momento. Sem um design de código eficiente, o produto final não vai ser bom nem fácil de manter. Design patterns e boas práticas de progamação são essenciais para se obter um design de código eficiente.

Domain driven design combina design e desenvolvimento e mostra como eles devem trabalhar em conjunto para criar uma solução melhor. Um bom design vai acelerar o desenvolvimento, enquanto o feedback dos desenvolvedores fará com que sejam aplicadas melhorias ao design.

A necessidade de uma linguagem única

Conforme dito acima, é essencial definirmos um modelo de domínio. Este trabalho é feito pelos especialistas de software que trabalham em conjunto com os especialistas do negócio. Geralmente os especialistas do negócio possuem seus própios jargões e gírias enquanto a equipe técnica possui uma linguagem totalmente diferente (vivem pensando em classes, herança, polimorfismo, etc..) Problemas sérios acontecem quando estes dois times não conseguem se comunicar, ou se comunicam em linguagens distintas.

Um dos principios fundamentais do Domain Driven Design é fazer o time se comunicar em uma linguagem única, que é definida a partir do modelo do domínio. Esta linguagem única pe chamada de Linguagem Ubíqua e deve estar presente nas reuniões, documentos e no código do projeto. Ela conecta todas as partes do design e permite que os analistas, desenvolvedores e especialistas do domínio se comuniquem sem que haja ambiguidades, falha de interpretação ou falta de entendimento entre as partes.

Segue abaixo uma lista de sites muito bons para quem quer começar a aprender DDD:

Friday, October 19, 2012

Enviando email através de webservices


Vou demonstrar neste post um exemplo de aplicação ASP.NET MVC que permite o envio de emails a partir de servidores SMTP previamente cadastrados no sistema.

O interessante desta aplicação é que vamos tirar a responsabilidade do envio de email da aplicação web e transferi-la para serviços WCF, que utilizam o mesmo modelo de domínio da aplicação. Misturando DDD e SOA, o sistema adota alguns padrões conhecidos como o Repository, Unity of Work, Abstract Factory, REST...

A topologia da arquitetura é demonstrada abaixo :



  • Presentation Layers:  Camadas responsáveis pela interface com o usuário.
  • Application Control Layer: Camada responsável por fazer a ponte entre as camadas de apresentação e a camada de serviços, delegando o trabalho solicitado pelo usuário aos serviços necessários.
  • Services Layer:  Realiza o trabalho de fato. Dividida em duas camadas que possuem a mesma finalidade, porém são implementadas de maneira diferentes. (SOAP x REST)
  • Data Access Layer: Responsável pela persistência de dados.
  • Domain Model Layer: Responsável pela definição dos objetos e regras de negócio do domínio. Possui as entidades mapeadas abaixo:



Resumo do código para envio de email:

1 - Presentation Layer (Web):

2 - Application Control Layer:

3 - Services Layer:

4 - Domain Model Layer (Entidade Mensagem):



Para acessar o sistema web e simular o envio de mensagens, use o link:
http://comprasonline.intcom.com.br/LogIn/
Para o login use email = teste@intcom.com.br e senha = teste


Para download dos arquivos da solução, use o link:
http://comprasonline.intcom.com.br/EmailServicesSample.rar

(Necessários: Visual Studio 2010, ASP NET MVC 3 e Sql Server Compact Edition - O URL estranho é devido a falta de tempo para registrar subdomínios)

Wednesday, October 17, 2012

Como especificar uma porta específica para o deploy de uma Web Application

Estou trabalhando em uma solução de N camadas com arquitetura orientada a serviços Restful. Algo parecido com:





Cada um dos serviços implementa uma injeção de dependência no construtor, para chamar o serviço é necessário um código parecido com:

  using( var service = BusinessService.Factory.Service1(string URI))
 {
     //Do stuff

  }
 
A aplicação web por sua vez, tem no arquivo de configuração a declaração de todas as URIs necessárias, algo parecido com:

<appSettings>
  <add key="DataService1" value="http://localhost:1429/Service1/"/>
  <add key="BusinessService1" value="http://localhost:2573/Service1/"/>
</appSettings>

Um problema foi encontrado quando o projeto era iniciado em outras máquinas, no ambiente de desenvolvimento: O URI do serviço era alterado e invalidava os dados do arquivo de configuração.

Isso acontecia por quê o Visual Studio definia uma porta aleatória para a aplicação que disponibiliza os serviços. Pesquisando na MSDN, descobri que existe uma maneira de configurar uma porta fixa para cada um dos projetos WEB na solução:

  1. In Solution Explorer, right-click the name of the Web application project for which you want to specify a Web server, and then click Properties.
  2. In the Properties window, click the Web tab.
  3. To choose the Visual Studio Development Server, under Servers, click Use Visual Studio Development Server.
  4. To use a specific port number with the Visual Studio Development Server, select Specific port and enter the port number. By default, the Auto-assign Port option is selected, and the port number that has been assigned to your application appears.

Segue o Link, que também contém outras dicas: http://msdn.microsoft.com/en-us/library/ms178108(v=vs.100).aspx



Friday, October 5, 2012

Levando o Controle de Alterações na Base de Dados para o Código

Um dos maiores problemas em um projeto de software é o controle de publicação de novas versões. Esse trabalho envolve um longo processo de revisão de código, atualização dos ambientes no qual faremos a publicação, (que pode incluir novos plugins) e um dos maiores problemas: as alterações feitas no modelo de dados da aplicação.

Caso você não esteja usando um framework de persistência que se encarregue de manter o equilíbrio entre o modelo de domínio e a base de dados, você vai precisar adotar algum processo exclusivo para manter o controle das alterações. Como por exemplo:



Hoje em dia é comum vermos equipes pequenas desenvolvendo aplicações orientadas a dados sem a presença de um recurso específico para manter o controle da base e das alterações (o DBA). Geralmente as alterações são documentadas em algum tipo de repositório na rede, ou até mesmo compartilhada por email entre os desenvolvedores (Caso estejam comitando o código e trabalhando com bases locais).

Acontece que a maioria dos processos estabelecidos são sujeitos a falhas e o controle pode se perder, principalmente quando um sistema muito antigo precisa ser atualizado para a última versão (do 1.0 pro 3.4, por exemplo). Pensando nesse problema resolvi passar o controle de documentação e execução das alterações de um determinado projeto para o código, me baseando no EntityFramework Migrations.

O conceito que eu tirei do Migrations é muito simples: Cada alteração feita na base de dados, gera uma nova migration. Essa migration recebe um número sequencial de versão e contém dois scripts diferentes:
               Up: Script para publicação da alteração. (Por exemplo, criar uma tabela nova)
               Down: Script para desfazer uma alteração. (Por exemplo, um drop de coluna. O script 'Down' é muito importante caso alguma publicação de release precise ser revertida. Ele funciona como um Recovery Plan da alteração)


Abaixo segue o diagrama do processo baseado em código:



Abaixo segue a implementação do código.

Primeiro, as classes que servem de base para as alterações adicionadas.



Sempre que um desenvolvedor da "commit" em uma alteração do banco, ele deve ao invés de encaminhar para o DBA, criar uma nova classe no projeto, com base nesta classe abaixo:


 * o maior problema da implementação é que o número da alteração é gerado em hardcode. O desenvolvedor precisa estar atento para não haver duplicidade, mas isso pode ser facilmente resolvido com um pouco mais de capricho.

O namespace também disponibiliza um controlador para acionar a verificação automática de versão da base:



Agora na aplicação web, adicionamos ao arquivo Global.asax a chamada ao controlador, passando as dependências necessárias, a aplicação checa por um número de versão no web.config da aplicação, caso não encontre ele atualiza a base para a última versão com base nas classes adicionadas ao framework DataBaseMigrations.Versoes :


Wednesday, October 3, 2012

O papel do arquiteto de softwares

Hoje estava lendo um artigo escrito por Martin Fowler entitulado "Who needs an architect?" e gostaria de destacar alguns conceitos que pude retirar do texto.
Estes conceitos nos ajudam a compreender qual é o papel de um arquiteto de softwares em um projeto de desenvolvimento e também nos ajudam a definir melhor o conceito "arquitetura de softwares".

O que é arquitetura de software?

De acordo com o RUP (Rational Unified Process) podemos definir arquitetura de softwares da seguinte maneira:

"O conceito de mais alto nível de um sistema. A arquitetura de um sistema de software  é a sua organização ou a estrutura dos componentes mais importantes interagindo através de interfaces, sendo que esses componentes, por sua vez, são compostos de componentes e interfaces sucessivamente menores."


Ralph Johnson (http://pt.wikipedia.org/wiki/Ralph_Johnson) se mostra contrário a essa definição pois ele acredita que não existe um conceito de nível mais alto em um sistema, pois esse conceito depende do seu ponto de vista.
Clientes possuem um conceito totalmente diferente dos desenvolvedores do sistema, eles não se importam com a estrutura dos componentes em si, e sim com as funcionalidades do sistema. Tendo isso em mente, ele  prefere definir arquitetura da seguinte maneira:

"Na maioria dos projetos de software bem sucedidos os desenvolvedores mais experientes do projeto compartilham um entendimento único do design do sistema. Esse entendimento compartilhado é chamado de 'arquitetura' e inclui a maneira na qual o sistema se divide em componentes interagindo através de interfaces, sendo que esses componentes, por sua vez, são compostos de componentes e interfaces sucessivamente menores.".

Outra boa definição levantada:

"Arquitetura é um grupo de decisões de design que devem ser feitas no início do projeto."  

O problema desta última definição é o fato de que é muito difícil acertar todas essas decisões. Então se é muito difícil tomar essas decisões acertadas no início do projeto, por quê que a maioria dos analistas continuam tentando?

A resposta é bastante óbvia. Essas decisões são tomadas pois vão gerar componentes de software que são difíceis de serem alterados. Por exemplo: Se você optou por persistir os dados no SQL Server, e mapeou as entidades com LINQ to SQL, uma vez que  a aplicação esteja toda escrita baseada nesse mapeamento objeto-relacional , você provavelmente nunca mais vai se livrar dele.

Tendo isso em mente podemos definir arquitetura como:

 "Componentes do software que são muito difíceis de se alterar."

Qual é o papel do arquiteto de softwares?

Uma das tarefas mais importantes de um arquiteto é  encontrar maneiras de eliminar irreversibilidade e reduzir a complexidade de um determinado projeto de software. Ele deve ser muito ciente do que está acontecendo no projeto,olhando para questões importantes e deve abordá-las antes que se tornem um problema sério.

A parte mais visível do trabalho de um arquiteto de softwares é a colaboração intensa com os outros recursos do projeto. Pela manhã,  um arquiteto pode estar programando junto com um desenvolvedor, enquanto na parte da tarde, o arquiteto participa de uma reunião de requisitos junto aos StakeHolders e clients, ajudando a explicar o impacto e consequência técnica das decisões que estão sendo tomadas.


O arquiteto é um dos mais experientes membros da equipe, e deve atuar como um guia. Responsável por ensinar outros recursos a tomar as melhores decisões e adotar boas práticas para evitar problemas futuros além de ajuda-los tecnicamente em tarefas mais complexas.







Fonte: http://martinfowler.com/ieeeSoftware/whoNeedsArchitect.pdf

Wednesday, September 26, 2012

Microsoft Office Excel Corrupted File

Hoje tivemos mais um problema de configuração de ambientes que foi um pouco chato de resolver por quê o erro não acontecia na nossa aplicação.

Descrição do Cenário:

Implementamos nosso sistema em uma empresa que possui um ERP e deseja que este sistema ERP atualize os dados de cadastro dos funcionários automaticamente no nosso sistema, todos os dias.

Para isso, disponibilizamos um serviço web através do qual a atualização dos dados seriam publicadas no nosso sistema a partir de arquivos .XLS exportados do sistema ERP.

O problema da abordagem adotada era que o ERP não gerava arquivos .XLSX e sim arquivos do tipo BIFF ou Excel 2. Descritos abaixo




Quando os arquivos eram publicados acontecia um erro de leitura dos dados através do provider Microsoft.ACE.OLEDB que não suporta esses tipos de arquivo.

A solução mais rápida foi adotar um novo processo antes de fazer a leitura das planilhas:

1 - Salvar arquivo BIFF/Excel 2 recebido pelo webservice.
2 - Abrir arquivo com o Microsoft Excel
3 - Salvar arquivo como .XLS (2007)
4 - Continuar leitura dos dados a partir do novo arquivo.

Quando publicamos em um dos nossos ambientes de homologação, a solução não funcionava, embora nos testes em desenvolvimento não tenha aparecido nenhum tipo de problema.

Investigando um pouco mais, no passo 2 descobrimos que o seguinte erro acontecia:


Neste momento, identificamos que o erro não estava na nossa aplicação, mas sim no Excel que não conseguia abrir o arquivo BIFF/Excel2.  Investigando o Log da aplicação no windows, conseguimos identificar a fonte do problema através da mensagem abaixo:


Para resolver a situação, foi necessário alterar algumas configurações de segurança no Microsoft Excel.

Abrindo o programa, clicamos em File > Options > Trust Center > Trust Center Settings > File Blocking Settings

Devemos desmarcar as opções Open e Save para os arquivos que precisamos, conforme mostrado na figura abaixo:




Wednesday, September 19, 2012

Operation is not valid due to the current state of the object

Hoje tratamos de um problema em uma aplicação asp.net que pode ser um pouco complicado já que não temos como detectar o erro através do debug comum Visual Studio.

Acontece que em uma das páginas um relatório é gerado dinâmicamente, com base na pesquisa feita pelo usuário (Mês / Ano).

Cada registro deste relatório gera novos controles ASP.NET na página, (caixas de texto para que o usuário possa adicionar ou modificar informações).



O relatório gerava mais de 300 linhas, logo o número de controles .NET adicionados ultrapassava o limite suportado pela aplicação. Quando qualquer postback era feito na página, o erro abaixo acontecia:



Com um pouco de pesquisa podemos encontrar referências da microsoft a respeito desta restrição:
http://support.microsoft.com/kb/2661403

"Microsoft security update MS11-100 limits the maximum number of form keys, files, and JSON members to 1000 in an HTTP request. Because of this change, ASP.NET applications reject requests that have more than 1000 of these elements. HTTP clients that make these kinds of requests will be denied, and an error message will appear in the web browser. The error message will usually have an HTTP 500 status code. This new limit can be configured on a per-application basis. Please see the "Resolution" section for configuration instructions."

* O limite de chaves em um form, arquivos e membros JSON é, por default, 1000 em um request HTTP .
 Para modificar este limite podemos adicionar ao web.config da aplicação:


<configuration>
  <appSettings>
    <add key="aspnet:MaxHttpCollectionKeys" value="1000" />
  </appSettings>
</configuration>

Caso você esteja usando ASP.NET 1.1, ajuste o limite adicionando um valor DWORD para a seguinte chave de registro:


HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\1.1.4322.0\MaxHttpCollectionKeys

Para modificar o limite de membros JSON adicione o seguinte código:

<configuration>
  <appSettings>
    <add key="aspnet:MaxJsonDeserializerMembers" value="1000" />
  </appSettings>
</configuration>

O problema dessa abordagem é que um limite muito alto pode aumentar a possibilidade do seu servidor ter vulnerabilidade a ataques do tipo Denial of Service.




Tuesday, September 18, 2012

Desenvolvimento para Android com C#



Quando pensamos em como construir aplicativos para IOS e Android , a maioria das pessoas pensam que as linguagens nativas (Objectice-C e Java repectivamente) são as únicas opções. Entretanto, nos últimos anos um novo ecosistema de plataformas para construção de aplicaçãoes surgiu. Entre as novas soluções podemos citar: PhoneGap, Appcelerator, CellSDK e Xamarin. 
Neste artigo iremos fazer uma introdução ao desenvolvimento de aplicativos para Android a partir do Framework da Xamarin: Mono.Android

Xamarin é uma empresa de softwares baseada em Boston, Massachussetts que foi fundada em Maio de 2011. A Xamarin oferece como seus produtos principais os frameworks Xamarin.IOS e Xamarin.Android, também conecidos como MonoTouch e Mono for Android respectivamente.
Ambas as plataformas são construídas em cima da biblioteca Mono, uma versão open-souce do .Net Framework que foi baseada nos padrões ECMA(http://www.ecma-international.org). Esta biblioteca é quase tão antiga quanto o própio .Net Framework e  está presente em várias plataformas como Linux, Unix, FreeBSD e Mac OSX.

Um dos diferenciais da Xamarin é que ela oferece uma única linguagem (C#) e uma biblioteca de classes que funcionam em todas as 3 plataformas: Android, IOS e Windows Phone.

No Android, o código é compilado para uma linguagem intermediária que por sua vez será compilada para o assembly nativo da plataforma quando a aplicação for lançada (Just in time compilation of an Intermediate Language). As aplicações utilizam um runtime que manipula automaticamente problemas clássicos como alocação de memória, garbage collector, interoperabilidade de plataformas subjacentes, etc..

Outras features do framework apontados pelo site da Xamarin são (em inglês):

Complete Binding for the Indigenous SDKs – Xamarin contains bindings for nearly the entire underlying platform SDKs in both iOS and Android. Additionally, these bindings are strongly typed, which means that they’re easy to navigate and use, and provide robust compile-time type checking and auto completion during development. This leads to fewer runtime errors and higher quality applications.

    Objective-C, Java, C, and C++ Interop – Xamarin provides facilities for directly invoking Objective-C, Java, C, and C++ libraries, giving you the power to use a wide array of 3rd party code that has already been created. This lets you take advantage of existing iOS and Android libraries written in Objective-C, Java, or C/C++. Additionally, Xamarin offers binding projects that allow you to easily bind native Objective-C and Java libraries by using a declarative syntax.

    Modern Language Constructs – Xamarin applications are written in C#, a modern language that includes significant improvements over Objective-C and Java such as Dynamic Language Features, Functional Constructs such as Lambdas, LINQ, Parallel Programming features, sophisticated Generics, and more.

    Amazing Base Class Library (BCL) – Xamarin applications use the .NET BCL, a massive collection of classes that have comprehensive and streamlined features such as powerful XML, Database, Serialization, IO, String, and Networking support, just to name a few. Additionally, existing C# code can be compiled for use in your applications, which provides access to thousands upon thousands of libraries that will let you do things that aren’t already covered in the BCL.
    Modern Integrated Development Environment (IDE) – Xamarin uses MonoDevelop on Mac OSX, and also MonoDevelop or Visual Studio 2010 on Windows. These are both modern IDE’s that include features such as code auto completion, a sophisticated Project and Solution management system, a comprehensive project template library, integrated source control, and many other options.

Considerações Importantes para Desenvolvimento de Aplicativos Mobile:

Multitasking
Em aparelhos mobile apenas uma aplicação pode estar em foreground. Isso se deve principalmente às limitações de memória e espaço em tela. Outro ponto importante é que ter muitas aplicações abertas ao mesmo tempo consomem rapidamente a bateria do aparelho.

No android Multitasking pode ser dividido em 2 componentes:  

Activity Lifecycle: Cada tela em uma aplicação android é representada por uma atividade. Existe um grupo de eventos específicos que são acionados sempre que uma atividade vai para background ou foreground.

Services: Serviços são processos geralmente longos que existem independentemente da aplicação e são executados quando a aplicação está em background.

Padrões e tamanhos de tela

Telefones e tables são os dois tipos principais de aparelhos mobile. Alguns aparelhos acabam caindo em categorias intermediárias à essas duas. Desenvolver aplicações para esses tipos de aparelhos pode ser muito diferentes devido ao pouco espaço em tela quando comparados a um laptop ou PC. Por esse motivo, os controles responsáveis pela interface com o usuário devem ser desenhados especificamente para serem efetivos nesses aparelhos e menores em tamanho.

No IOS temos um pequeno número de dispositivos para atender, no Windows Phone 7 existem restrições impostas pela Microsoft que padronizam os aparelhos e estabelecem requisitos mínimos a serem atendidos para que o dispositivo seja aprovado. Já no Android , a Google não estabelece limites e restrições para os dispositivos o que aumenta muito o universo de ambientes ao quais a nossa aplicação precisa se adaptar, isso inclui diferentes tamanhos de tela, especificações de hardware, features, capabilities, etc... Devido a esse universo abrangente, a maioria das equipes de desenvolvimento escolhem 5 ou 6 aparelhos top e focam os testes para esses aparelhos.

Dispositivo e fragmentação do SO

Conceitualização e planejamento – Devido às grandes diferenças entre o hardware e features de cada aparelho, você precisa ter em mente que uma aplicação que depende de algumas features podem não funcionar corretamente em todos os dispositivos. Por exemplo, nem todos os smartphones tem câmeras. Esse tipo de fator é muito importante para o seu planejamento inicial.

Design – Ao desenhar o controle de experiência e usabilidade do usuário (UX), tamanos diferente de tela, teclados e interfaces de controle (touch-screen ou voz) devem ser levados em consideração.  Ao desenharmos a interface do usuário (UI) devemos ter em mente diferentes tipos de resolução.
Desenvolvimento – Quando usamos alguma feature do dispositivo (a câmera, por exemplo) esta feature deve ser sempre testada primeiro. (Pergunte ao SO se a feature está disponível)
Testes – É muito importante testar a sua aplicação nos dispositivos atuais (e na maioria deles). No android, mesmo aparelhos com especificações de hardware idênticas podem apresentar diferenças de comportamento.

Recursos Limitados

Os dispositivos móveis estão cada vez mais poderosos, porém ainda possuem capacidades limitadas se comparados a notebooks e computadores. Por isso devemos sempre adotar boas práticas de programação que limitem o consumo de memória e tempo de CPU das nossas aplicações. 

Considerações de Segurança

Cada aplicação no Android OS roda sob uma identidade isolada e distinta cujas permissões são limitadas. Por default, aplicações tem permissão para quase nada. Por exemplo, sem permissões especiais uma aplicação não consegue enviar mensagens de texto ou até mesmo acessar a internet. Para poder acessar essas features, as aplicações precisam especificar no arquivo de manifesto quais permissões serão utilizadas. Quando a aplicação é instalada essas permissões são listadas para o usuário que deverá aprovar, ou cancelar a intalação.

Distribuição

Todas as aplicações android devem ser assinadas digitalmente antes de serem distribuídas. Os desenvolvedores devem assinar suas aplicações usando seus própios certificados protegidos por uma chave privada. Ao contrário das outras plataformas, Android tem uma abordagem muito aberta quanto a distribuição de aplicativos. Os dispositivos não são restritos a uma única app store, desse modo um canal muito mais largo e complexo existe para distribuição dos aplicativos.

Starting Guide:

Para começar a desenvolver para android, entre no site da Xamarin e faça o download do framework e dos plugins para IDE (Visual Studio). A empresa fornece todo o material necessário para iniciantes, como exemplos de código e documentação da biblioteca de classes além de tutorias relacionados a permissões, distribuição, etc..

Site da Xamarin: http://www. xamarin.com
Download das ferramentas:   http://xamarin.com/androidbeta/setup.exe

Após instalar a solução, observe os novos tipos de projeto que você pode criar:

Tuesday, September 11, 2012

GoDaddy Failure

Ontem tivemos problema de acesso nos nossos servidores devido ao outage do serviço de dns do Godaddy. Hoje, dia 11/09 o serviço já foi restaurado e podemos ver a repercussão através das notícias da web:

http://bits.blogs.nytimes.com/2012/09/10/member-of-anonymous-takes-credit-for-godaddy-attack/
http://mashable.com/2012/09/10/godaddy-gone-recover-its-reputation/
http://techcrunch.com/2012/09/10/godaddy-outage-takes-down-millions-of-sites/

Monday, September 3, 2012

Criando User Controls em ASP.NET


User Controls são componentes nos quais você inclui Tags html e um ou mais controles web, podendo tratá-los como uma unidade com suas propriedades e métodos particulares. Ou seja, pode ser visto como uma página ASP.NET que assume o comportamento de um Controle encapsulado.

Tem como grande vantagem a praticidade da utilização e reutilização de código e ganho de agilidade na manutenção.

Os User Controls são baseados na classe System.Web.UI.UserControl e difere de uma página ASP.NET nos seguintes itens:

  • A extensão do arquivo de um  User Control  é ".ascx";
  • Ao invés de usar a diretiva @page, um  User Control  contém uma diretiva @Control que define suas propriedades;
  • Um  User Control não pode ser executado diretamente, somente quando incluído em uma página ASP.NET;
  • Um  User Control  não possui os elementos html, body ou form no seu interior.


O exemplo mais comum que temos de User Controls são páginas web que permitem a navegação do usuário não autenticado. Enquanto este usuário não estiver autenticado, um controle de Login estará disponível em todas as páginas do site e algumas ações (geralmente ações de compra e download) estão desabilitadas.

Não seria esperto neste caso escrevermos o código do controle de login em todas as páginas.  Nós poderíamos usar um User Control. Cada vez que você procurar a sua Toolbox por um controle específico e ele não existir, você mesmo pode criar o seu controle e adicionar a toolbox.

Abaixo, temos um exemplo prático de como criar um User Control para input de datas no sistema. Este controle associa ao textbox aonde a data será digitada: Um controle de calendário, um controle de validação do formato de acordo com a cultura do usuário e um controle de range de datas de acordo com a base de dados com a qual estamos trabalhando.

01- Clique com o botão direito no seu projeto web e vá em Adicionar Novo item. Adicione uma nova pasta com o nome UserControls
02- Clique com o botão direito nesta pasta e vá em Adicionar novo Item. Adicione um novo  User Control com o nome "DateControl" conforme mostra a figura abaixo.


03- Abra o arquivo DateControl.ascx que foi adicionado e escreva o seguinte código para adicionar os controles necessários:

04 - Agora vamos adicionar o codebehind deste controle no arquivo "DateControl.ascx.cs":



========================================================================

using System;
using AjaxControlToolkit;

namespace WebApplication1.UserControls
{
    public partial class DateControl : System.Web.UI.UserControl
    {
        public enum DateRange
        {
            Aspnet,
            SqlServer,
            Oracle
        }
        private bool _isValid = false;
        public bool IsValid()
        {
            if (_isValid)
                return true;
            return false;
        }
        private DateTime _minimumRange;
        private DateTime _maximumRange;
        public string Text
        {
            get { return tbDate.Text; }
            set { tbDate.Text = value; }
        }

        public DateRange Range { get; set; }
        protected void Page_Load(object sender, EventArgs e)
        {
            SetRange();
            SetMask();
        }
        protected void Validate(object sender, EventArgs e)
        {
            ValidarData();
        }
        /// <summary>
        /// Retorna o valor da data já convertido
        /// </summary>
        /// <returns></returns>
        public DateTime? GetDate()
        {

            if (_isValid)
                return Convert.ToDateTime(tbDate.Text);
            return null;

        }
        /// <summary>
        /// Tenta converter a data e compara com o range. Em caso de falha limpa o texto.
        /// </summary>
        private void ValidarData()
        {
            try
            {
                var date = Convert.ToDateTime(tbDate.Text);
                //Check  range
                if (date < _minimumRange)
                {
                    Clear();
                }
                else if (date > _maximumRange)
                {
                    Clear();
                }
                _isValid = true;
            }
            catch
            {
                Clear();
            }

        }
        /// <summary>
        /// Determina o mínimo e máximo suportado pela estrutura de dados
        /// </summary>
        private void SetRange()
        {
            switch (Range)
            {
                default:
                    _minimumRange = System.DateTime.MinValue;
                    _maximumRange = System.DateTime.MaxValue;
                    break;
                case DateRange.Aspnet:
                    _minimumRange = System.DateTime.MinValue;
                    _maximumRange = System.DateTime.MaxValue;
                    break;
                case DateRange.Oracle:
                    //4712 antes de cristo não é suportado pelo .Net?
                    _minimumRange = System.DateTime.MinValue;
                    _maximumRange = new DateTime(9999, 12, 31, 23, 59, 59);
                    break;
                case DateRange.SqlServer:
                    _minimumRange = new DateTime(1753, 01, 01);
                    _maximumRange = new DateTime(9999, 12, 31, 23, 59, 59);
                    break;
            }
        }
        private void SetMask()
        {
            var mke = new CalendarExtender();
            mke.TargetControlID = tbDate.UniqueID;
            mke.Format = System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern;

            upDateControl.ContentTemplateContainer.Controls.Add(mke);

        }
        /// <summary>
        /// Limpa o conteúdo da caixa e marca o estado como inváido
        /// </summary>
        private void Clear()
        {
            tbDate.Text = "";
            _isValid = false;
        }
    }
}

========================================================================
05 - Para usar o controle, crie uma nova página Default.aspx e adicione o seguinte código:


Vamos agora fazer um outro controle que desta vez valide uma data de início e uma data de fim de um determinado período. Este controle aplica todas as regras do DateUsercontrol porém valida se a data de fim é maior que a data de início.

01 - Clique com o botão direito na pasta UserControls e vá em Adicionar novo Item. Adicione um novo User Control com o nome "DateFromToControl" e adicione o código ao arquivo .ascx, conforme mostra a figura abaixo.


02 - Adicione o CodeBehind:

using System;
using System.Web.UI.WebControls;
using AjaxControlToolkit;

namespace WebApplication1.UserControls
{
    public partial class DateFromToControl : System.Web.UI.UserControl
    {
        public enum DateRange
        {
            Aspnet,
            SqlServer,
            Oracle
        }
        private bool _isValidTo = false;
        private bool _isValidFrom = false;
        private bool _isValid = false;
        private DateTime _minimumRange;
        private DateTime _maximumRange;
        public DateRange Range { get; set; }

        public string FromText{ get; set; }
        public string ToText { get; set; }
       
        protected void Page_Load(object sender, EventArgs e)
        {
            lblFrom.Text = FromText;
            lblTo.Text = ToText;
            SetRange();
            SetMask();
        }
        protected void Validate(object sender, EventArgs e)
        {
            _isValid = false;
            ValidarTo();
            ValidarFrom();
            if (_isValidTo & _isValidFrom)
            {
                if (Convert.ToDateTime(tbDate.Text) > Convert.ToDateTime(tbDate2.Text))
                {
                    var tb = (TextBox)sender;
                    if(tb.UniqueID == tbDate.UniqueID)
                        ClearTo();
                    else
                    {
                        ClearFrom();
                    }
                }
                else
                    _isValid = true;
            }
        }
        public DateTime? GetToDate()
        {

            if (_isValidTo)
                return Convert.ToDateTime(tbDate.Text);
            return null;

        }
        public DateTime? GetFromDate()
        {

            if (_isValidFrom)
                return Convert.ToDateTime(tbDate.Text);
            return null;

        }
        private void ValidarTo()
        {
            try
            {
                var date = Convert.ToDateTime(tbDate.Text);
                //Check  range
                if ((date < _minimumRange) || (date > _maximumRange))
                {
                    ClearTo();
                }
                else
                _isValidTo = true;
            }
            catch
            {
                ClearTo();
            }

        }
        private void ValidarFrom()
        {

            try
            {
                var date = Convert.ToDateTime(tbDate2.Text);
                //Check  range
                if ((date < _minimumRange) || (date > _maximumRange))
                {
                    ClearFrom();
                }
                
                else
                _isValidFrom = true;
                
            }
            catch
            {
                ClearFrom();
            }
        }
        private void SetRange()
        {
            switch (Range)
            {
                default:
                    _minimumRange = System.DateTime.MinValue;
                    _maximumRange = System.DateTime.MaxValue;
                    break;
                case DateRange.Aspnet:
                    _minimumRange = System.DateTime.MinValue;
                    _maximumRange = System.DateTime.MaxValue;
                    break;
                case DateRange.Oracle:
                    //4712 antes de cristo não é suportado pelo .Net?
                    _minimumRange = System.DateTime.MinValue;
                    _maximumRange = new DateTime(9999, 12, 31, 23, 59, 59);
                    break;
                case DateRange.SqlServer:
                    _minimumRange = new DateTime(1753, 01, 01);
                    _maximumRange = new DateTime(9999, 12, 31, 23, 59, 59);
                    break;
            }
        }
        private void SetMask()
        {
            var mke = new CalendarExtender
                          {
                              TargetControlID = tbDate.UniqueID,
                              Format = System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern
                          };
            var mke2 = new CalendarExtender
                           {
                               TargetControlID = tbDate2.UniqueID,
                               Format = System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern
                           };

            upDateControl.ContentTemplateContainer.Controls.Add(mke);
            upDateControl.ContentTemplateContainer.Controls.Add(mke2);

        }
        private void ClearTo()
        {
            tbDate.Text = "";
            _isValidTo = false;
            _isValid = false;
        }
        private void ClearFrom()
        {
            tbDate2.Text = "";
            _isValidFrom = false;
            _isValid = false;
        }
    }
}

03 - Para finalizar, abra a página Default.aspx e adicione o seguinte código: