David Anderson Lino (Developer's Blog)

7Out/115

Quem disse que Programador não deveria usar Windows?

Praticamente todo dia, vejo escrito em algum lugar, ou ouço alguém falar que "Programador não deveria usar Windows". Mas quando pergunto por quê nunca vejo um argumento forte.

Antes que venham me mandar usar Linux de verdade, já trabalhei com desenvolvimento em ambiente Linux por mais de 3 anos, e o resto da vida com Windows. Programei/programo com Java, C#, Python e mais recentemente Ruby. Então tenho exp. como dev nos dois lados, com todas estas linguagens.

Outra coisa, sempre que falo sobre este assunto, muitos entendem que eu estou falando que Windows é melhor que Linux pra desenvolver ou pior: que estou dizendo que só deveríamos usar Windows para desenvolver. Ou estou me expressando mal, ou os extremistas não querem parar pra ver o outro lado. Basicamente, não vejo bom argumento para evitarmos o Windows como ambiente de desenvolvimento (E até mesmo como usuário final).

Após este disclaimer, vamos ao primeiro argumento:

O bash do Linux é muito melhor.

Acho que não há muito o que discutir. SIM, o bash do linux é melhor. Mas isso não quer dizer que só por que o shell do Windows é fraco programadores não deveriam usar Windows. Então pergunto: O que vocês ganham com o poder do bash? Você utiliza esse ganho? Maioria das pessoas com quem conversei só usam o trivial, que o cmd do Windows faz muito bem. Caso você realmente precise, no Windows existem ótimas alternativas, como o Console2, o TakeCommand. E caso precise de mais algum poder, existe o PowerShell, que não uso por quê não preciso, mas o pouco que conheço e leio sobre vejo que é possível fazer muito com ele. Alguns reclamam que no Linux tem alguns utilitários como cat, grep, awk etc. Pra quem realmente precisa disso, e quer um ambiente unix-like sempre é possível instalar o Cygwin. Acho sensato concluir que este então não é um bom motivo pra abandonar o Windows.

Outro argumento que vejo com frequência é:

Eu posso baixar o código do Linux e customizar a meu favor.

90% das pessoas que vem me dizer que eu deveria usar o Linux usa este argumento. Quando pergunto  "Você já baixou o código alguma vez? Já alterou? Já compilou?" 99% respondem não às 3 perguntas (Ok, inventei os números mas estão próximos da minha realidade =) Acho que posso parar por aqui;

Mais um:

No Linux eu aprendo a usar SSH, uso svn através de linha de comando, no windows eu não preciso usar isto.

Para quem não sabe, existe tudo isto no Windows, e pode-se viver muito bem sem usar estas ferramentas (sinal que nem sempre são necessárias), e mais! Nada impede que você no Windows use ou aprenda a usar estas ferramentas, visto que todas elas estão disponíveis no mundo Windows.

E o último do dia:

Os grandes sistemas são feitos em Linux e rodam em Linux. Servidor bom roda Linux.

As empresas que conheço, a maioria delas seus usuários usam Windows. E usa servidor de AD rodando num Windows. Pra quem quiser argumentar que não conheço empresas 'realmente grandes' ou coisas do gênero, a página de cases mostra quem está usando no momento, empresas do naipe da Ford e Dell. Outro case notável é o StackOverflow que a maioria de vocês usa.

Estes são os motivos pelo qual dizem que não devemos usar o Windows e minha opnião sobre eles.
Agora: Por quê eu acho que deveríamos usar Windows?

  • Se o objetivo é desenvolver pra Desktop, use Windows!

Windows ainda é o mais popular, possui mais de 80% do market share hoje em dia. Então, as chances de seu cliente estar usando o windows, e você está desenvolvendo um app desktop, você deveria usar Windows, só assim você vai está desenvolvendo e tendo feedback real sobre o ambiente de produção. Não vejo sentido desenvolver um sistema 100% no linux quando vai ser usado 80%+ no Windows.

  • Se vai desenvolver para Web, tanto faz, visto que a escolha do SO só impacta na escolha do servidor, por quê não usar?

Acho que o StackOverflow é um bom exemplo que dá pra criar sites grandes, com milhares de visitas e centenas de usuários simultâneos num ambiente 100% Microsoft. Sinal que SIM, é possível fazer algo grandioso no windows. Por quê não dar uma chance então?

  • Praticamente tudo que você consegue fazer no Windows. Pode ser mais fácil ou não.

Meio que já comentei sobre isso nos argumentos do pessoal do Linux.

Dado o que falei, e que já trabalhei nos dois, mesmo tendo prática em Linux e sabendo me virar no mesmo escolho o Windows. Por quê?

Simples: Eu sou mais produtivo lá. E também gosto mais dele :)

E vocês, o que acham?

19Set/111

Implementando MVVM em WPF

Comecei a trabalhar com WPF, e procurei alguma forma para conseguir uma melhor Separation of Concerns(SoC).

Um dos padrões que possibilitam isto é o MVVM. O Elemar escreveu um ótimo post sobre a parte teórica do padrão, então decidi utilizar este padrão e esta é a forma que o implementei.

Eu tenho uma classe Pessoa com o atributo "Nome" e uma tela onde desejo alterar o Nome, e salvar esta pessoa em algum lugar.

Minha classe pessoa é a seguinte:

public class Person {
   public string Name {get;set;}
   public int Age {get; set;}
}

Porém nesta minha tela só preciso utilizar o atributo pessoa, crio então um ViewModel que vai ser uma representação dessa classe do meu modelo, para esta view específica, o ViewModel fica assim:

public class PersonVM: INotifyPropertyChanged
{
    private string nameValue;
 
    public string Name
    {
        get{
            return nameValue;
        }
        set
        {
            if (value != this.nameValue)
            {
                this.nameValue= value;
                NotifyPropertyChanged("Name");
            }
        }
    }
 
	//You probably would cache this command, remeber this is just an example...
    public ICommand ChangeName{ get { return new ChangeNameCommand(); } }
 
    #region INotifyPropertyChanged Members
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
 
    #endregion
}

 

Percebam que minha classe implementa a interface INotifyPropertyChanged . Esta interface é usada para notificar clientes que uma certa propriedade teve seu valor alterado. Neste caso, o cliente vai ser a tela propriamente dita.

A ViewModel também encapsula o comportamento necessário para executar a lógica, este comportamento é exposto através de Comandos. Comandos são classes que implementam a interface ICommand. Este comando será ligado à view através de Bindings, e a classe ChangeNameCommand é:

public class ChangeNameCommand: ICommand
{
    #region ICommand Members
 
    public bool CanExecute(object parameter)
    {
        return (parameter as PersonVM) != null;
    }
 
    public event EventHandler CanExecuteChanged;
 
    public void Execute(object parameter)
    {
            PersonVM person = parameter as PersonVM;
            if(person != null)
                //Actually Save the person...
    }   
 
    #endregion
}

 

Ok, como vou usar isto? Aqui está a minha tela:

    <button name="Salvar">Save</button>

 

No meu TextBox eu digo que ele estará ligado (Binding) à propriedade Name. Han? Propriedade Name? Sim! Em WPF,  a propriedade informada no atributo Binding é procurada no objeto que está no DataContext desta classe. Ou seja, se meu DataContext possuir uma propriedade 'Name' ela estará ligada à este controle.

Isto quer dizer que, qualquer alteração no conteúdo do controle (neste caso, digitar algo), será refletida no objeto armazenado no DataContext. Se o DataContext implementa INotifyPropertyChanged então qualquer mudança no objeto será refletida no controle (O valor da propriedade aparece como texto).

Ok?

Outro Binding realizado é o Binding com o comando ChangeNameCommand. O controle, quando acionado, irá executar o comando passado presente no Binding, como o controle é um botão, o comando será invocado ao clicar no mesmo. Vale ressaltar que também é passado um parâmetro para o comando, neste caso o parâmetro é o próprio objeto no DataContext.

Como instanciar esta tela? Antes de a exibirmos, setamos o DataContext para o objeto adequado da seguinte forma:

PersonVM viewModel = //get View Model from Model
ChangeNameScreen screen = new ChangeNameScreen();
screen.DataContext = viewModel;
screen.Show();

 

E como isso tudo funciona no fim das contas?

  1. Instancia-se / carrega um objeto do tipo Pessoa de algum lugar (banco/memória)
  2. A tela ChangeName é criada;
  3. A pessoa obtida anteriormente é atribuída à propriedade DataContext da tela;
  4. A tela é exibida;
  5. Ao digitarmos qualquer coisa no TextBox, este valor é setado na nossa pessoa;
  6. Ao clicarmos no botão, a tela verifica se é possível verificar o comando, para aquele parâmetro;
  7. O comando verifica se o parâmetro é realmente do tipo do nosso ViewModel e retorna;
  8. Com a confirmação, a view executa o comando passando o DataContext como parâmetro;
  9. A alteração é tratada pelo nosso modelo;
  10. A tela retoma o controle da execução.

Simples não? Desta forma temos a nossa lógica de interface apenas no code-behind da view, completamente isolada da lógica de negócio, que está no nosso modelo, e é acessado através dos comandos.

Surgiram alguns padrões para facilitar a aplicação deste padrão como o RelayCommand e o DelegateCommand. Bem como alguns frameworks, como o Caliburn, Cinch e Prism. Ainda não tive a necessidade de usar nenhum deles, alguém aí tem algo a comentar?

 

1Set/1158

Não faltam profissionais qualificados em TI, mas empresas qualificadas!

Esta semana no Twitter, me inspirei para fazer meu primeiro post não técnico do blog.
A motivação veio deste twit: "Cadê a reportagem no Fantástico sobre profissionais que tem dificuldade de encontrar empresas qualificadas?".

Nos últimos meses, regularmente vejo reportagens com título similar a: "Faltam pessoas qualificadas no mercado de TI". Se você procurar por esta frase numa engine de busca qualquer, com certeza irá encontrar várias reportagens. Tem reportagem da Veja, da Info, da Exame. Enfim, inúmeras reportagens tratando do assunto, mas aí pergunto:

Realmente falta qualificação nos profissionais? Depende do ponto de vista... As empresas de TI estão hoje pedindo cada vez mais, e oferecendo cada vez menos, como este caso aqui. Não é difícil encontrar ofertas como essa (na verdade a maioria das ofertas se assemelha a esta), onde exigem muito conhecimento e experiência, e oferecem muito pouco.

Além do que, várias dessas 'exigências' são inviáveis. Tem como o cara ser especialista em Web, Mobile e Desktop ao mesmo tempo? Eu duvido muito. Saber os princípios, OK. Mas daí a ser experiente são mais quinhentos. Sendo assim, não existe realmente profissional "qualificado".

A questão é, muitas empresas sequer sabem o que querem, então tentam encontrar um super-herói que vá atender todas as necessidades deles, já recusei propostas assim. Ainda mais, muitos consideram que desenvolver um sistema é um trabalho fácil e simples, e dá para se fazer em pouquíssimo tempo, e assim subestimam seus próprios projetos e contratam menor quantidade de pessoas, e muitas vezes de qualidade contestável, dado o que andam ofertando.

Resultado? Projetos atrasados, inacabados e cancelados. O Standish Group está aí para provar isto.  Rola por aí uma comparação de "E se contratássem motoristas como se contratam programadores?". Infelizmente esta é a realidade hoje.

Para piorar a situação, muitos destes veículos de comunicação mentem com relação a expectativa salarial, completamente distante da realidade. Eu adoraria saber quais foram as fontes para reportagens como esta, que dizem que o salário médio de alguém que trabalha com suporte técnico varia de 1300 a  17 mil!!! Se alguém conhecer alguém de suporte ganhando mais de 5 mil me avisem que quero conversar com ele...

Além de outras reportagens com dados obtidos de forma errônea, como a reportagem no Olhar digital, onde falam que pagam, para desenvolvedores mobile, de 180 a 220 reais POR HORA! Fazendo as contas, o salário de um desenvolvedor desses seria de R$28.800 a R$ 35.200, No mesmo parágrafo dizem que os projetos variam de 20 a 30 mil. Ou isso tá muito errado, ou não sei mais matemática...

Pesquisando em sites como a CathoEmpregaTI, e nos perfis do twitter destinados a vagas de TI, a média salarial está bem abaixo dos 3 mil reais, e muitos exigem fluência em outro idioma, graduação e 2 anos+ de experiência...

Mas vamos supor que, por sorte, você consiga encontrar uma empresa que lhe oferece um salário de acordo com suas expectativas, bem acima da média do mercado. Ela é interessante?

Muitas das empresas que vejo atrás de profissionais, não deixa claro ao mundo externo como é sua cultura, ou pior, "criam" uma boa imagem externa, mas quando você entra, a coisa é outra.

Percebo que falta muito cuidado com a qualidade nas empresas(e também em muitos desenvolvedores) hoje... Ouço falar de pouquíssimas empresas que têm algum cuidado com isto.

Boas práticas? Muitas empresas sequer sabem o que é TDD, estímulo a se preocupar com isso então? Nem pensar. mas como alguém disse (Se alguém souber o autor me avise): "Se você não consegue testar seu próprio código, não deveria se chamar desenvolvedor profissional"

Processo de desenvolvimento? Não existe algum, as vezes existem apenas no papel, na prática é o XGH "by the book".

Agile? Nem pensar. Pior! Muitas ainda vendem a imagem de que "usam" o Scrum, ou tem processos "baseados" no mesmo, mas apenas para aproveitar a onda e ganhar um pouco de destaque, mas quando vai ver, o scrum passou longe e deixou apenas um quadro de ToDo/Doing/Done, e acreditam estar usando Scrum...(Isso rende assunto pra outros posts...).

Integração contínua? Eu, não consigo contar 10 pessoas que conheço no Brasil onde sua empresa *realmente* utiliza integração contínua.

Fora isso, existe o grande problema cultural na empresa, muitas vezes avessa as mudanças, preferindo continuar seguindo seu processo (ou, quase sempre, ausência do mesmo  / XGH) à investir em idéias novas (Se bem que processos como o XP já tem quase 15 anos de estrada) . Não estou defendendo que agilidade e as práticas citadas vão resolver todos os problemas, mas, no meu ponto de vista, seus princípios são os mais promissores atualmente.

E a qualidade de vida? Não é difícil encontrar anúncios onde um dos requisitos seja "Gostar de trabalhar sob pressão". Quem gosta disso? Nunca conheci...

Mas de onde vem essa pressão? De acordo com o que vejo, recentemente iniciou-se esta demanda imensa por profissionais, e nessa época também iniciou-se a 'prostituição' da área, como é costume chamar. O que aconteceu? As empresas começaram a iniciar vários projetos novos, começaram a contratar gente ruim pagando pouco e iniciaram seus projetos. Estes projetos estão começando a encostar na data final e não vai ser entregue, por motivos óbvios. Mais cedo ou mais tarde vão contratar pessoas realmente 'profissionais' para resolver os problemas que fizeram nos sistemas, e estes não vao cobrar barato. É a velha história do barato que sai caro.

Então as empresas terão 2 opções:

  1. Não conseguir contratar pessoas boas e/ou arcar com o prejuízo dos projetos e possivelmente falir (já presenciei situações como esta)
  2. Gastar muito dinheiro para remendar os erros gerados. E daí tem-se mais dois caminhos:
  • Investir em melhoria interna para conseguir atrair bons profissionais, e oferecer um salário justo.
  • Continuar errando e voltar para o ponto 1 até quebrar.
Ou seja, a culpa em grande parte, são das próprias empresas, que não se melhoram, e , como disse Einstein "A definição de Insanidade é fazer sempre a mesma coisa e esperar um resultado diferente.". Muitas também não oferecem condições justas de trabalho, e pior: Obrigam as pessoas a fazerem um trabalho lixo, por consequência dos deslizes dela no passado.Quem aqui gosta de fazer um trabalho ruim? Quem gosta de produzir algo do qual você não se orgulha? Eu definitivamente não.
Entrar em empresas para "apagar incêndios", ou participar de "forças-tarefa" não é para qualquer um, e não é nem um pouco fácil. Quero ver quem é o cara que consegue ser feliz trabalhando para otimizar um sistema, onde existem (várias) classes com 50+ campos, 70+ métodos, e 6k+ linhas! Eu já passei por isso, e não foi uma vez. True story!

Enfim, após este desabafo, não se pode mostrar apenas os problemas e não sugerir nada certo?
Aí fica a pergunta: O que podemos fazer?

  1. Trabalhar como freelancer, aproveitando o que você tem de melhor, por tempo indeterminado, ou até encontrar uma empresa interessante.
  2. Iniciar o processo de mudança onde trabalhamos.

Eu prefiro a opção 2, e venho fazendo isto por onde passo. Se você quer ser um bom profissional, aja com tal, e sirva de exemplo para seus colegas. Quando verem que o que você está fazendo dá certo, irão fazer também.

Ensine aos outros o caminho, acho difícil que as empresas lhe impeçam de fazer coisas como ministrar palestras, ou até mesmo lightning talks. Outra forma interessante de disseminar esta cultura é através de eventos como os Coding Dojos.

Não vou dizer que é fácil, pois não é. Mudanças bottom-up são bem complicadas, difíceis e lentas, mas é possível. Se não for, ou não ver resultados, não perca seu tempo e vá para outro lugar!

O que não acho justo fazer é sair sem sequer tentar. A idéia é ser como o beija-flor tentando apagar o incêndio.

 

Faça sua parte

 

30Ago/111

Quando aplicar Injeção de dependência e como testar utilizando Mocks?

Um assunto que sempre vejo em pauta nas discussões é:O que são mocks?

Quando usar?
O que é injeção de dependência?Bem, vou tentar responder algumas destas perguntas com o post de hoje. Como exemplo vou utilizar o ambiente Asp.Net MVC, MsUnit e Moq.

Olhem para este código:

public class HomeController : Controller
{
        public ActionResult Index()
	{
		ViewBag.Message = Cumprimento();
		return View();
	}
	private string Cumprimento()
	{
		int horaAtual = DateTime.Now.Hour;
		if (horaAtual &gt; 0 &amp;&amp; horaAtual &lt; 12)
			return "Bom dia";
		if (horaAtual &lt; 18)
			return "Boa tarde";
		return "Boa noite";
	}
}

Funcionalidade bem simples, aí eu lhe pergunto... Como testar isso?
Uma tentativa inocente seria:

[TestMethod]
public void Se_For_Manha_Eh_Bom_Dia()
{
	// Arrange
	HomeController controller = new HomeController();
 
	// Act
	ViewResult result = controller.Index() as ViewResult;
 
	// Assert
	Assert.AreEqual("Bom dia", result.ViewBag.Message);
	mock.VerifyAll();
}

Opa! Este teste só funciona se estiver de manhã... E se for a tarde, o que fazer? Como testar?

Mudar o horário do computador não é uma opção :P

Como bem falou o Juan Lopes : "Se não está óbvio como testar um certo código, o problema não está nos testes, e sim no código."
Então vamos organizar este código...

Primeiro observamos que nosso código depende da classe DateTime. Esta classe provê várias informações, mas na verdade, só precisamos saber a hora atual da mesma.
Proponho então criarmos uma interface que irá nos responder esta pergunta:

public interface IFornecedorDeHorario
{
	int HoraAtual();
}

Refatorando o controller teremos algo parecido com isto:

public class HomeController : Controller
{
	private IFornecedorDeHorario fornecedorDeHorario;
 
	public HomeController(IFornecedorDeHorario fornecedorDeHorario)
	{
		this.fornecedorDeHorario = fornecedorDeHorario;
	}
 
	public ActionResult Index()
	{
		ViewBag.Message = Cumprimento();
		return View();
	}
 
	private string Cumprimento()
	{
		int horaAtual = fornecedorDeHorario.HoraAtual();
		if (horaAtual &gt; 0 &amp;&amp; horaAtual &lt; 12)
			return "Bom dia";
		if (horaAtual &lt; 18)
			return "Boa tarde";
		return "Boa noite";
	}
}

Perceba agora que, nosso controller explicita sua dependência com IFornecedorDeHorario,
e impõe, através do construtor, que ele depende disto para funcionar corretamente. Este é o princípio básico por trás da injeção de dependência,
bem mais detalhes podem ser encontrados aqui.

Bem, nosso código está mais desacoplado, porém ainda fica a dúvida... Como testar?

Temos duas opções:

  1. Usar um fake
  2. Usar mocks

A primeira opção é a mais simples, porém mais cansativa. Consiste em criar implementações para aquela interface, e cada implementação retorna sempre uma hora diferente.

Então optei por usar mocks. Um teste com mock resume-se basicamente a:

  1. Instanciar um Mock para um determinado tipo
  2. Configurar o comportamente do mock
  3. Utilizar o mock
  4. Verificar se o mock foi utilizado como esperado

Sendo assim nosso teste fica:

[TestClass]
public class HomeControllerTest
{
	[TestMethod]
	public void Se_For_Manha_Eh_Bom_Dia()
	{
		// Arrange
		Mock mock = new Mock();
		mock.Setup(x =&gt; x.HoraAtual()).Returns(7);
		HomeController controller = new HomeController(mock.Object);
 
		// Act
		ViewResult result = controller.Index() as ViewResult;
 
		// Assert
		Assert.AreEqual("Bom dia", result.ViewBag.Message);
		mock.VerifyAll();
	}
 
	[TestMethod]
	public void Se_For_Tarde_Eh_Boa_Tarde()
	{
		// Arrange
		Mock mock = new Mock();
		mock.Setup(x =&gt; x.HoraAtual()).Returns(13);
		HomeController controller = new HomeController(mock.Object);
 
		// Act
		ViewResult result = controller.Index() as ViewResult;
 
		// Assert
		Assert.AreEqual("Boa tarde", result.ViewBag.Message);
		mock.VerifyAll();
	}
 
	[TestMethod]
	public void Se_For_Noite_Eh_Boa_Noite()
	{
		// Arrange
		Mock mock = new Mock();
		mock.Setup(x =&gt; x.HoraAtual()).Returns(20);
		HomeController controller = new HomeController(mock.Object);
 
		// Act
		ViewResult result = controller.Index() as ViewResult;
 
		// Assert
		Assert.AreEqual("Boa noite", result.ViewBag.Message);
		mock.VerifyAll();
	}
 
}

Acho que vocês não devem ter problemas para entender estes testes.
E espero que tenham entendido bem os conceitos apresentados.
Qualquer coisa, só perguntar nos comentários.

6Jul/111

Fazendo requisições via JavaScript para actions Asp.Net MVC

Existem momentos em que precisamos do lado cliente criar uma requisição para um de nossas actions de um sistema Asp.Net MVC,

Por exemplo, ao clicar em uma região da página o browser deve ser redirecionado para alguma outra action.

Como resolver isto?

Uma solução é utilizar JQuery no lado cliente para criarmos as requisições!
Para isto utiliza-se um destes métodos: $.get ou $.post

Como exemplo, vamos fazer com que um clique numa div (pode ser qualquer elemento html) faça uma requisição para uma action, e esta action receba um id como parâmetro.
E então, o resultado desta action seja renderizado numa outra div.

<script type="text/javascript">// <![CDATA[
function getAction(action, actionData, updateTargetId) {
        $.get(
        action,
        actionData,
        function (data) {
                $("#"+updateTargetId).html(data);
        }
    );
}
// ]]></script>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Aqui será atualizado após clicar no texto acima!

Percebam que utilizei um helper para obter a url correta para a action, sem que eu me preocupasse com a construção correta.
Se fosse utilizado o método $.post nada mudaria, pois os parâmetros são iguais.

25Mai/114

Pipes and Filters Pattern com Entity Framework 4.1

Continuando a série de posts sobre o Entity Framework 4.1, hoje irei apresentar uma implementação bacana do padrão Pipes and Filters utilizando o EF4.1 + Linq.

Primeiro uma revisão sobre o padrão Pipes and Filters (também conhecido por Data Flow Architecture).
Como implementar uma sequência de transformações sobre um conjunto de dados, de forma a combiná-los e reusá-los independentemente?

A solução é implementar estas transformações utilizando uma sequência de filtros, onde cada filtro recebe uma entrada, aplica uma simples transformação, e então envia a mensagem transformada para o próximo componente.

Graficamente temos isto:


Para que isto possa funcionar:

  • A saída de Source deve ser compatível com a entrada de Filter 1
  • A saída de Filter 1 deve ser compatível com a entrada de Filter 2
  • A saída de Filter 2 deve ser compatível com a entrada de sink

E com aquele nosso repositório, como ficam as coisas?

Antes vou definir onde vamos trabalhar.

Irei utilizar um repositório genérico (Como no post anterior) para esta classe:

public class Pessoa
{
    public string Nome { get; set; }
    public string Sobrenome { get; set; }
    public string Cidade { get; set; }
    public string Estado { get; set; }
    public string Sexo { get; set; }
}

Irei criar os seguintes filtros:

  • Por Nome
  • Por Cidade
  • Por Estado
  • Por Sexo

Estão lembrados que no repositório, obtemTodos() retornava um IQueryable?
Pois bem, esta interface provê funcionalidade para executar consultas em uma fonte de dados qualquer.

Como estamos utilizando o EntityFramework, o retorno na verdade é uma consulta Linq, que será traduzida pelo EF4.1 em uma consulta SQL apropriada para o banco de dados.

O que existe de especial naqueles que implementam esta interface, é o fato de que a consulta só é executada quando alguém tenta obter dados dela!
Ou seja, se você nunca iterar sobre a consulta, ou convertê-la para nenhum tipo como listas ou arrays, nenhuma comunicação com o banco existiu!

Outro conceito importante para este exemplo é o conhecimento dos ExtensionMethods. Extension Methods lhe permitem adicionar funcionalidade a tipos existentes sem precisar criar um novo tipo derivado, ou recompilar o código ou modificar o tipo original.
Isto nos dá um enorme poder de customização e flexibilidade. Aquele que usa um extension method, o utiliza como se este fosse um método nativo de alguma classe.
Linq, por exemplo, é completamente implementado como extension methods sobre o tipo IEnumerable.

Agora mãos a obra!

Primeiro o código:

public static class PessoasExtensionMethods
{
    public static IQueryable E (this IQueryable query){
        return query;
    }
    public static IQueryable QueTenhamONome (this IQueryable query, string nome){
        return from item in query
                 select item
                 where item.Nome.Equals(nome);
    }
    public static IQueryable QueMoremNaCidade (this IQueryable query, string cidade){
        return from item in query
                 select item
                 where item.Cidade.Equals(cidade);
    }
    public static IQueryable QueMoremNoEstado (this IQueryable query, string estado){
        return from item in query
                 select item
                 where item.Estado.Equals(Estado);
    }
    public static IQueryable QueSejamDoSexo (this IQueryable query, string sexo){
        return from item in query
                 select item
                 where item.Cidade.Equals(sexo);
    }
}

O que foi feito?
Criamos alguns Extension Methods para o tipo IQueryable;, ou seja, qualquer objeto deste tipo, poderemos chamar estes novos métodos.
Lembram que ObtemTodos retorna um IQueryable? Pois bem, poderemos aplicar estes filtros no retorno deste método!
Devem estar se perguntado o por que daquele método "E".
Bem, ele existe apenas para que possamos utilizar uma interface fluente, onde podemos especificar nossos filtros de forma que seja facilmente lido e entendido.

Okay, e como eu utilizo?
Vamos a alguns exemplos.

  1. Quantas pessoas do sexo masculino existem? =>
     Repositorio.ObtemTodos().QueSejamDoSexo("Masculino").Count()
  2. E que morem na paraíba? =>
    Repositorio.ObtemTodos().QueSejamDoSexo("Masculino").E().QueMoremNoEstado("Paraiba").Count()
  3. E que morem em Campina Grande? =>
    Repositorio.ObtemTodos().QueSejamDoSexo("Masculino").E().QueMoremNoEstado("Paraiba").E().QueMoremNaCidade("Campina Grande").Count()
  4. E que se chamem "David"? =>
    Repositorio.ObtemTodos().QueSejamDoSexo("Masculino").E().QueMoremNoEstado("Paraiba").E().QueMoremNaCidade("Campina Grande").E().QueTenhamONome("David").Count()

Legal não é? Com este padrão podemos criar consultas eficientes, fáceis de manter, fáceis de utilizar, e que você consegue ler rapidamente!
Bem melhor que sair espalhando SQL no meio do código hein?

Espero que este post tenha sido útil! Se alguém tiver mais alguma idéia de post utilizando o Entity só avisar que farei o possível!

2Mai/1112

File Upload em Asp.Net MVC 3 e Razor

Então você quer fazer upload de um arquivo para salvar junto do seu model mas não sabe como?

Como tudo em Asp.Net MVC, basta um pouco de HTML.

Hoje irei mostrar como rapidamente fazer uploads de arquivos usando Asp.Net MVC

Suponha que você está com um sistema gerador de crachá, e cada crachá tem um nome e uma foto.
Você provavelmente terá um model como este:

public class Cracha
{
	public string Nome {get; set;}
	public Image Foto {get; set;}
}

Você poderia ter apenas o caminho para a foto, também não tem muita diferença.
Vamos por a mão na massa agora.
Criemos o seguinte ViewModel:

	public class CrachaViewModel
	{
		public string Nome {get; set;}
		public HttpPostedFileBase Foto {get; set;}
	}

O tipo HttpPostedFileBase é uma classe abstrata que provê acessos a arquivos individuais que foram enviados na request.

Na classe CrachaController, na ação Criar é onde iremos receber este arquivo e então tratá-lo adequadamente:

	[HttpPost]
	public ActionResult Criar(CrachaViewModel model)
	{
		string extensao = Path.GetExtension(model.Foto.FileName);
		string path = Path.Combine(Server.MapPath("~/Content/images/"), model.Nome + extensao);
		model.Foto.SaveAs(path);
		//Salva o cracha em algum lugar e retorna para a página inicial
		return RedirectToAction("Index");
	}

Se houver mais de um arquivo, basta usar um array de HttpPostedFileBase e iterar em seus items. E assim fica nossa view:

Cracha
@Html.LabelFor(model => model.Nome)
@Html.EditorFor(model => model.Nome)
@Html.LabelFor(model => model.Foto)

Note que o atributo name tem o valor igual ao nome da propriedade em questão. Se for ter mais de um arquivo enviado, crie múltiplos inputs com o mesmo nome e o model binder os reunirá num array.

É isto! Agora você consegue enviar arquivos para seu controller . Até a próxima

28Abr/1119

Generic Repository Pattern com Entity Framework 4.1

Algum tempo atrás eu apresentei o Entity Framework 4, que estava ainda em fase de Preview, mas já saiu uma release com o Code First, que foi chamado de Entity Framework 4.1

Você pode baixá-lo via Nuget.

Bem, já que foi mostrado como mapear classes usando as convenções ou as annotations, hoje irei mostrar como implementar um repositório genérico utilizando o Entity Framework 4.1:

Após instalarmos o Entity Framework 4.1 (Que já vem incluso automaticamente num projeto Asp.Net MVC3) Esta é a interface do nosso repositório:

	 public interface IRepositorio where T : class
    {
        void Adicionar(T item);
        void Remove(T item);
        void Remove(object id);
        void Edit(T item);
        T ObtemPorId(object id);
        IQueryable ObtemTodos();
    }

 

Duas coisas importantes a perceber:

  • Note que o repositório usa a sintaxe genérica, ou seja, o repositório será "tipado"
  • O método ObtemTodos() retorna um IQueryable, Por quê? No próximo Post quando eu falar de Pipes and Filters vocês perceberão =)

Agora a parte interessante, a implementação utilizando Entity!

	public class Repositorio : IDisposable, IRepositorio where T : class
    {
        protected readonly DbContext contexto;
 
        public Repositorio(DbContext contexto)
        {
            this.contexto = contexto;
        }
 
        public virtual void Adicionar(T item)
        {
            contexto.Set().Add(item);
            contexto.SaveChanges();
        }
 
        public virtual void Remover(T item)
        {
            contexto.Set().Remove(item);
            contexto.SaveChanges();
        }
 
        public virtual void Remover(object id)
        {
            T item = contexto.Set().Find(id);
            contexto.Set().Remove(item);
            contexto.SaveChanges();
        }
 
        public virtual void Editar(T item)
        {
            contexto.Entry(item).State = EntityState.Modified;
            contexto.SaveChanges();
        }
 
        public virtual T ObtemPorId(object id)
        {
            return contexto.Set().Find(id);
        }
 
        public virtual IQueryable ObtemTodos()
        {
            return contexto.Set();
        }
 
        public void Dispose()
        {
            contexto.Dispose();
        }
    }

 

Simples não?
Algumas explicações sobre a mágica:

  • O método Set<T>() retorna a coleção que representa os objetos no banco de dados para o tipo T;
  • O método Entry<T>(item) retorna uma entrada no banco de dados que representa este item;
  • O método Find<T>(id) retorna um objeto do tipo T que tenha o id passado como parâmetro;

Após este pequeno trecho de código você poderá fazer um CRUD de qualquer classe que esteja configurada no seu contexto sem esforços.
Basta instanciar um new Repositorio<T>();

Até a próxima!

No próxiimo post demonstrarei como implementar o padrão Pipes & Filters utilizando Entity Framework 4.1 e est repositório. Confiram!

26Abr/110

JQuery DateTimePicker em Asp.Net MVC 3 / Razor

Post rápido de hoje.

Como eu já havia dito antes, é muito fácil de utilizarmos JQuery com nossos sistemas feitos em Asp.Net MVC.Hoje irei mostrar como utilizar o widget JQuery para escolher datas.

Primeiro de tudo devemos baixar o JQuery e algum tema na página do JQuery. Eu escolhi o tema overcast.
Feito isto vamos criar um Razor Helper para o Widget.

<script type="text/javascript" src="@Url.Content("></script><script type="text/javascript">// <![CDATA[
	    $(document).ready(function () {
	        $(".datePicker").datepicker({
	             showAnim: 'slideDown',           
	        });
	    });
// ]]></script>

Para utilizá-lo é bastante simples, basta fazer algo como:

@Html.LabelFor(model => model.Date)
@Html.TextBox("Date", Model.Date.ToShortDateString(), new { @class = "datePicker" }) @Html.Partial("DateTimeEditor") @Html.ValidationMessageFor(model => model.Date)

 

Simples, você já tem o widget funcionando perfeitamente em sua página.

Até a próxima!

31Mar/110

Como convencer seu cliente/seu chefe a adotar projetos com escopo variável?

Olá pessoal, tudo bem?
Sabemos que a tendência atual dos projetos de software é cada vez mais adotar processos ágeis, e um fator de extrema importância na adoção é o tipo de contrato. Basicamente os contratos fixam prazo, custo, qualidade e escopo. Porém um processo ágil se encaixa melhor em contratos com escopo variável, mas como alcançar isto? E o principal, como convencer as pessoas de que um contrato com escopo variável é vantajoso? Pensando nisso criei duas apresentações (as quais irei utilizar muito em breve) onde tenho o objetivo de convencer a utilizar escopo variável. Uma delas é voltada para o cliente, a outra para seu chefe. O que altera basicamente é a disposição das informações e nível de detalhamento.
Elas estão aqui:

Escopo fixo x escopo negociavel - Para clientes

Ver mais apresentações de davidals.

 

Escopo fixo x escopo negociavel - Para seu chefe

Ver mais apresentações de davidals.

 

A maior parte da informação foi extraída do ImproveIT. Lá você também encontrará um modelo de contrato bem interessante.

Espero que gostem e que lhes seja útil.