Tugwar-cabodeforca

Um tempo atrás eu indiquei quando usar ASP.Net Webforms ou MVC. Agora vamos a outra dupla igualmente polêmica: WF (Windows Forms) ou WPF (Windows Presentation Foundation).

Eu não gosto de recomendações sem contexto. Mas se fosse para dar uma recomendação sem contexto, seria essa:

Use WPF.

Mas a idéia não é essa.

Vamos entender primeiro a história de cada tecnologia.

Windows Forms: nasceu junto com o .Net, em 2002. Era a maneira de fato de criar aplicações desktop para o Windows, e ainda é a mais usada. A idéia, ao que tudo indica, era dar uma interface que fosse familiar ao desenvolvedor de VB 6, mas adaptada para o .Net. Já nasceu com vários controles úteis, mas os controles só bateram os que o VB 6 tinha na versão 2.0, lançada em 2005.

WPF: nasceu em 2007, com o .Net 3.0 (ou seja, sobre o CLR 2.0). O Visual Studio 2008 ainda não havia sido lançado, e um pacote de atualização para o Visual Studio 2005 foi lançado, o que permitia desenvolver WPF nesta IDE. O pacote era, para dizer o mínimo, incompleto. No VS 2008 ela apareceu com a versão 3.5, na prática sua segunda versão. Nesta versão o suporte da IDE já é muito melhor, mas somente com o Expression Blend é possível ter uma IDE gráfica completa para edição. Em 2009 a adoção do WPF começa a se intensificar.

Quando usar WPF então? Vejam aqui os cenários em que entendo que vale a pena usar WPF:

  • Se você quer trabalhar com o framework que vai receber mais evoluções, WPF é o ideal. WPF é agora a maneira recomendada pela Microsoft para desenvolver aplicações desktop, e não Windows Forms. Não espere grandes evoluções no WF daqui por diante, apenas pequenas melhorias.
  • Se você gostaria de uma separação clara entre o trabalho de design e de engenharia, o modelo declarativo de construção da interface gráfica com XAML permite isso.
  • O suporte das ferramentas de design da família Expression é total, habilitando aplicações mais agradáveis e a criação de grandes efeitos, como transparências, animações, etc.
  • O MVVM, padrão filho do presentation model, é a maneira mais apresentada sobre como fazer uma aplicação WPF. O padrão prima pela separação entre visão e controle da aplicação, e oferece uma maneira desacoplada e testável de desenvolver. Espere aplicações mais bem desenvolvidas com WPF do que com Windows Forms. Ainda que isso não signifique que todas vão usar MVVM, ou ser bem desenvolvidas, isso sem dúvida é um ponto a favor, já que em WF não há um padrão recomendado ou sequer demonstrado em 99% das demos por aí.
  • WPF é praticamente um superset do Silverlight. O XAML é muito parecido. Se você avalia eventualmente migrar de uma aplicação desktop para Silverlight, via WPF será infinitamente mais fácil do que via WF.
  • WPF permite fazer aplicações mais bonitas. O exemplo clássico é um degrade de cores. Tente fazer um degrade no WF e verá que não é trivial, já no WPF é só configurar uma propriedade. Ou tente fazer um botão redondo no WF, e verá como é complexo. No WPF isso é simples, feito com poucas linhas de XML. Transparência é outro exemplo. E logo de início você percebe que o grid padrão do WPF é muito mais bonito que o grid padrão do WF.
  • Se é necessário integrar media no projeto, como vídeo, áudio, ou 3d, WPF é a melhor opção, já que isso já vem integrado.
  • Caso a aplicação tenha necessidade de utilizar temas ou skins, WPF oferece um extenso suporte à esse tipo de customizações. As opções são praticamente ilimitadas.
  • O suporte a databind do WPF é muito superior ao oferecido no WF.
  • Quer colocar um botão dentro de um grid, com um vídeo dentro do botão? Trivial, essa composição está na base do WPF.

E quando iniciar um projeto com Windows Forms?

  • O principal motivo é uma reunião de alguns fatores: time não conhece WPF, não há tempo para estudá-la, e não há interesse da empresa nesse investimento. Nesse cenário é melhor seguir com WF. Ainda assim, a grande pergunta é: porque a empresa não quer investir, será que ela já avaliou os benefícios do WPF? Geralmente não é o caso.
  • A performance do WF é um pouco melhor do que a do WPF. O WPF exige mais do hardware. Essa é uma questão complexa, que a Microsoft está tendo que enfrentar, agora que está desenvolvendo o Visual Studio com WPF. Espere grandes melhorias nesse sentido no .Net Framework 4. Mas se o produto for esperado antes do lançamento do WPF 4, e performance for um problema, WF é melhor.
  • O projeto é uma reconstrução de um projeto anterior, ou há uma suite de controles e/ou formulários já pronta que a empresa quer reaproveitar. Nesses cenários, pode ser que o ganho proporcionado pelo reaproveitamento de código já construído supere os ganhos do WPF.
  • A quantidade de controles de terceiros construídos para WF ainda é maior do que os focados em WPF, você tem mais opções. Mas esse jogo está virando, rapidamente.
  • Se você precisa de suporte total do designer do Visual Studio, e não vai comprar ou não tem acesso ao Expression Blend, WF é melhor. Esse suporte só vira no Visual Studio 2010, ou seja, de 3 a 6 meses de hoje.
  • A empresa precisa montar uma equipe rapidamente para um projeto e não tem um orçamento muito generoso. Há mais profissionais no mercado que trabalham com WF do que profissionais que conhecem WPF. E como raridade determina salário, quem conhece WPF tende a ganhar mais. (Mas da perspectiva do profissional, você quer ganhar menos ou mais?)

Há alguns mitos com relação ao uso de WPF que eu gostaria de discutir também:

  • Mito: Se a aplicação é simples e eu não vou ter um designer trabalhando no projeto, tanto faz usar WPF ou WF, e eu já conheço WF.
    Fato: WPF não é só sobre design gráfico. Toda a separação proporcionada entre visão com XAML e código, o suporte rico a databind, a evolução do framework, são motivos válidos para usar WPF até mesmo em aplicações simples, sem grandes apelos visuais.
  • Mito: WPF é difícil de aprender.
    Fato: WPF é difícil de aprender. Não tem o que dizer, a curva de aprendizado é grande para quem nasceu com Windows Forms ou VB6. Mas isso não é verdade se o seu background não é esse, ou seja, é uma questão de paradigma. Em qualquer dos casos, se prepare para bastante estudo.
  • Mito: desenvolvimento em WPF é mais lento que em WF.
    Fato: só é mais lento quando você não está familiarizado com WPF. Coloque um bom desenvolvedor WPF ao lado de um bom desenvolvedor WF, e peça o mesmo resultado, verá que não há diferença.
  • WPF ainda é uma tecnologia muito nova.
    Fato: WPF está na segunda versão, com a terceira sendo lançada em alguns meses. Não é mais uma tecnologia recente, e já há muita gente utilizando. A versão 1 realmente teve pouca adoção, mas isso não é mais motivo para não adotar hoje em dia. Ainda assim, acredito que a versão realmente madura, ou seja, a usada como referência, será a próxima, principalmente pelo suporte do Visual Studio e pelas melhorias de performance.

É sempre bom lembrar que integrar é possível, tanto WPF no WF, quando o contrário. Você pode iniciar a migração de WF para WPF aos poucos.

A idéia de discutir isso surgiu no twitter. Perguntei por lá porque você iniciaria um projeto em Windows Forms e não em WPF. Algumas das respostas, para vocês terem uma visão além da minha:

Ozory Em quanto tempo vou dominar o WPF como domino o Windows Forms? O cliente não vai esperar...
CaioProiete O mais comum: Porque o projeto tem data certa (e irrevogável) para entrar em produção e a equipe não tem experiência com WPF
Dennes Nem toda empresa tem experiência para lidar com essa relação complexa de design
Dennes Até mesmo na web a relação dos profissionais design x código é complicada, em windows então nem se fala.
vquaiato Por que temos preguiça de aprender uma tecnologia "nova"...
Denis_Petri Se não existe necessidade do sistema ter animações é muito mais rapido desenvolver em windows forms do que wpf.
hugoestevam Talvez a questão de desempenho, já testei GRIDs de empresas de comp. diferentes e sempre o WinForms é mais rápido que o WPF.
Denis_Petri Fazer um bind no grid do wpf é um saco, coisa que no winforms é moleza, mas concordo com @vquiato, a preguiça é tb um motivo
fgrehm conheco gente que simplesmente tem medo de mudar :-P
allistonCarlos winforms ao invés de WPF? Só se eu fosse masoquista!
Denis_Petri Cada caso é um caso, analise do que será usado é fundamental para o projeto... pq usar uma bazuca para matar uma formiga?
diogodamiani Porque, por mais que os desenv. queiram, tem empresas que não aceitam largar o passado e aderir às tecnologias do futuro.
rodrigokono 1-Performance (conhecer o ambiente do cliente) 2-Designer- (Terá alguém para fazer a parte cool?!) 3- Conhecimento de WPF.
andrecarlucci Webforms não faz sentido mais. Da mesma forma, se você fosse iniciar uma webapplication, deveria usar silverlight :)
facunte O principal motivo é tempo x capacitação da equipe. WPF não é tão simples qto parece. Mas estão avançando.
antoniodourado talvez para softwares que necessitem rodar em máquinas de menores potencias?! O WPF é relativamente mais pesado ou nd a ver?
edumenoncello somos dois, digo o mesmo p/ web forms, por mim, só MVC e Silverlight
Ozory Se tornar a vida do Dev + fácil, for robusto e rápido tá valendo.
fgrehm ah, e tem gente que tb tem medo do asp.net MVC :-P
fgrehm na verdade nao sei bem se eh medo, ta mais pra acomodação...
eliezerbp A configuração das máquinas onde a aplicação irá rodar (desempenho, acima de tudo). Eu também sou um péssimo designer!
pauloquicoli Sim, WPF na cabeça, mas, pra não usá-lo, só se for por motivo de hardware...
gumalheiros Se a aplicação for clean (Sem firula de Design), funcional como ERPs e sem restrição de máquina, já compensa WPF.

O que você acha? Continue a discussão nos comentários abaixo.


Postado na(s) categoria(s) .Net pelo Giovanni Bassi em 6 de janeiro de 2010 às 08:01 | Tags: ,

Conforme prometido no webcast, seguem os recursos que apresentei no webcast neste post.

Apresentação:

Links:

Meu site de consultoria: http://giovannibassi.com
Site do .Net Architects: http://dotnetarchitects.net
Grupo de discussão online do .Net Architects: http://tinyurl.com/DotNetArch
Evento de arquitetura de software (.Net Architects Day 2009): http://dotnetarchitects.net/dnad2009
Visual Studio 2010 Beta 1: http://tinyurl.com/vs10b1
C# 4 Resources: http://msdn.microsoft.com/en-us/vcsharp/dd819407.aspx
Eric Lippert (Microsoft, time C#): http://blogs.msdn.com/ericlippert/
Eric Lippert falando de variância: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
Traduzido pelo Felipe Fujiy: http://blog.fujiy.net/blog/category/Covariancia-e-Contravariancia.aspx
Sam NG (Microsoft) http://blogs.msdn.com/samng/archive/tags/Runtime+binding/default.aspx
Tags de C#4 neste blog: http://unplugged.giggio.net/unplugged/?tag=/c%234
Renato Guimarães (MVP C#): http://renatoguimaraes.spaces.live.com
Edição 60 com artigo meu sobre C#4: http://www.devmedia.com.br/resumo/default.asp?ed=60&site=1


Postado na(s) categoria(s) .Net pelo giovanni bassi em 20 de junho de 2009 às 01:40 | Tags: ,

Daqui a pouco tem a segunda parte dos webcasts de C# 4.0 (é agora ao meio dia). Vou falar de variância e interoperabilidade com COM.

Vejo vocês lá.


Postado na(s) categoria(s) .Net pelo Giovanni Bassi em 18 de junho de 2009 às 09:26 | Tags: ,

Respondendo então à questão de qual overload é utilizado que fiz aqui na quinta-feira passada. Se você não viu a questão, leia lá antes de ler aqui para não perder a graça.

Revendo as funções:

FazAlgo(object arg) {} //overload 1
FazAlgo(params object[] args) {} //overload 2

Minha chamada é assim:

string[] parametros = {"Giovanni", "Bassi"};
FazAlgo(parametros);

Qual overload é chamado? Revendo as opções:

  1. O primeiro é chamado, passando um array de strings como um objeto.
  2. O segundo é chamado, passando um array de strings como se fosse um array de objetos.
  3. O segundo é chamado, passando um array de strings como um objeto do array args, como se implicitamente fizesse "FazAlgo(new object[] {parametros})"

 

Adianto que a opção 3, apesar de tecnicamente ser possível, não é a correta porque há duas opções mais diretas. Nesta terceira opção o compilador tem que expandir o objeto de object para object[], e, como nas outras duas opção não há mudança alguma, a terceira opção é descartada.

Graças à covariância entre arrays, podemos converter implicitamente de string[] para object[]. Isso coloca o overload 2 como mais específico que o overload 1, e portanto ele é o escolhido. Um array de strings pode até ser um object, mas ele é mais especificamente um array de objetos. O tipo mais específico sempre ganha.

Engraçado que normalmente quando essa questão é levantada a maioria das pessoas dizem que a opção 1 é a correta. Mas não me parece a mais óbvia. Talvez as pessoas não entendam a questão da variância.


Postado na(s) categoria(s) .Net pelo giovanni bassi em 8 de junho de 2009 às 10:50 | Tags:

Conforme prometido no webcast, seguem os recursos que apresentei no webcast neste post.

Apresentação:

Links:

Meu site de consultoria: http://giovannibassi.com
Site do .Net Architects: http://dotnetarchitects.net
Grupo de discussão online do .Net Architects: http://tinyurl.com/DotNetArch
Evento de arquitetura de software (.Net Architects Day 2009): http://dotnetarchitects.net/dnad2009
Visual Studio 2010 Beta 1: http://tinyurl.com/vs10b1
C# 4 Resources: http://msdn.microsoft.com/en-us/vcsharp/dd819407.aspx
Eric Lippert (Microsoft, time C#): http://blogs.msdn.com/ericlippert/
Sam NG (Microsoft) http://blogs.msdn.com/samng/archive/tags/Runtime+binding/default.aspx
Tags de C#4 neste blog: http://unplugged.giggio.net/unplugged/?tag=/c%234
Renato Guimarães (MVP C#): http://renatoguimaraes.spaces.live.com
Edição 60 com artigo meu sobre C#4: http://www.devmedia.com.br/resumo/default.asp?ed=60&site=1


Postado na(s) categoria(s) .Net pelo giovanni bassi em 4 de junho de 2009 às 14:48 | Tags: ,

Essa é uma pegadinha. Tendo os seguintes métodos:

FazAlgo(object arg) {} //overload 1
FazAlgo(params object[] args) {} //overload 2

Se você chamar assim:

FazAlgo("algum param");

Sabemos que o primeiro overload é chamado, certo?

Mas e se chamarmos ele assim:

string[] parametros = {"Giovanni", "Bassi"};
FazAlgo(parametros);

O que acontece? Qual overload é chamado?

Vejam as opções:

  1. O primeiro é chamado, passando um array de strings como um objeto.
  2. O segundo é chamado, passando um array de strings como se fosse um array de objetos.
  3. O segundo é chamado, passando um array de strings como um objeto do array args, como se implicitamente fizesse "FazAlgo(new object[] {parametros})"

Dou a resposta na próxima segunda-feira.

Dêem as respostas nos comentários. Não vale apenas dizer qual das opções é a certa, tem que explicar por que.

(E não vale ir no Visual Studio ver o que acontece.)


Postado na(s) categoria(s) .Net pelo giovanni bassi em 4 de junho de 2009 às 11:29 | Tags:

Tenho visto algumas pessoas dizendo que o C# está com muitas novidades. Com o LINQ ganhou muita novidade (extension methods, lambdas, etc) e agora com dinamismo está complicado demais.

Outros acham que a linguagem tem que evoluir. Os outros que se virem para aprender as novidades.

Eu? Acredito que a linguagem deve sim evoluir, mas deve crescer de maneira inteligente e ordenada. Os que criticam a evolução do C# dizem que ele vai ser o novo C++, que em pouco tempo vai estar tão grande que vai ser impossível de entender. Eu não acredito nisso.

Sim, o LINQ trouxe conceitos de linguagem funcional ao C#.

Sim, podemos fazer código unsafe com C#.

Sim, lambdas e delegates são muito parecidos e resolvem problemas semelhantes.

E sim, o C# agora tem também conceitos de uma linguagem dinâmica.

Mas entendo que isso faz parte da riqueza da linguagem.

Os críticos também dizem que o custo de entrada para um novo programador no C# está ficando muito alto, porque a linguagem está muito grande e há muito a estudar. Eu não vejo isso como um problema. Quem sabe com isso teremos menos falsos sêniors no mercado.

 

O que você acha? O C# está complexo demais?


Postado na(s) categoria(s) .Net pelo giovanni bassi em 3 de junho de 2009 às 10:30 | Tags:

Nas próximas semanas farei 2 webcasts sobre C# 4.0.

O primeiro será dia 4, na próxima quinta-feira:

MSDN Webcast: Apresentação do C# 4.0 - parte 1: dinamismo e argumentos opcionais e nomeados

O segundo será dia 18, quinta-feira, daqui a três semanas:

MSDN Webcast: Apresentação do C# 4.0 - parte 2: variância e interoperabilidade com o COM

Como vocês podem ver, no primeiro vou tratar de dinamismo e argumentos opcionais e nomeados. No segundo vou falar de variãncia e interoperabilidade com COM. Com isso fecho as 4 grandes inovações da quarta versão do C#.

Vejo vocês lá.


Postado na(s) categoria(s) .Net pelo Giovanni Bassi em 29 de maio de 2009 às 18:10 | Tags: ,

O C# 4.0 está praticamente concluído. Nós já temos que ir estudando.

Eu publiquei um monte de informações sobre C# 4.0 aqui no blog, publiquei um artigo sobre C# 4.0 na .Net Magazine quando a linguagem ainda estava em definição e mal tinhamos ferramentas para testar, e agora a Microsoft criou uma página só para falar de C# 4.0 (ou Visual C# 2010 com tem se falado). Acessem esses recursos aqui. Tem artigos, vídeos, opiniões. Vale a pena dar uma olhada.

Além disso, vale a pena ler também o blog do Eric Lippert, do time de C#. O cara é um ignorante, sabe muito de linguagens em geral e C# em específico. Toda vez que vejo ele dando uma opinião sobre linguagem, é uma opinião matadora.

Aqui no Brasil, há os MVPs de C#. Dos que eu sei que tem presença online (blog/site):

  1. Adriano Bertucci
  2. Alfred Myers
  3. Carlos dos Santos
  4. Renato Guimarães

E você, já está vendo o C# 4.0?


Postado na(s) categoria(s) .Net pelo giovanni bassi em 29 de maio de 2009 às 17:51 | Tags:

Se você gerar um diagrama no Entity Framework, ele vai gerar as classes para você. Estas classes são geradas automaticamente pela ferramenta. Se você alterá-las diretamente, não vai poder regerar ou alterar o diagrama, porque isso alteraria o código gerado. Ou seja, não pode mais alterar o diagrama em nada. Esse é o motivo que impede o EF de funcionar com os atributos do Validation Application Block do Enterprise Library: atributos alterariam o código e você perderia tudo se fizesse qualquer alteração no modelo do EF.

Esse padrão é comum em qualquer código gerado por ferramenta: se você alterar o código gerado não pode mais usar a ferrramenta para atualizar o código, ou vai perder tudo. Nos datasets tipados já era assim. Por isso a Microsoft inventou o conceito de partial classes, que é bem legal e ajudou bastante. Elas oferecem hooks, ganchos, para você se plugar nelas de fora. Assim, você tem uma classe para o designer, e outra para você trabalhar e estender.

Só que com classes parciais não dá para aplicar atributos em propriedades ou métodos. Aí eles inventaram as buddy classes, que apareceram pela primeira vez no ADO.Net Dynamic Data, e agora estão aparecendo no RIA Services, conforme fiquei sabendo neste blog.

Buddy classes são o seguinte: já que você não pode alterar o atributo de uma propriedade, nós te arranjamos uma outra classe, que é "amiga" daquela que você queria alterar. Lá você aplica seus atributos, e depois o framework junta tudo, entendendo que o atributo que você aplicou na classe amiga (buddy), era na verdade para aplicar na classe auto-gerada. A classe amiga não serve para nada além de ser a classe a que você vai decorar com seus atributos, já que a classe principal é gerada por uma ferramenta.

Um exemplo, esta seria sua classe auto-gerada:

    public partial class MyClass
    {
      public int MyProperty { get; set; }
    }

Como aplicar um atributo sobre esta propriedade "MyProperty"?

São dois passos: primeiro você aplica um atributo em uma classe parcial, que indica quem é sua classe "amiga", o tal MetadataClass:

    [MetadataClass(typeof(MyMetadataClass))]
    public partial class MyClass { }

E depois basta criar a propriedade igualzinha à da classe original e aplicar o atributo nesta outra classe:

    public class MyMetadataClass
    {
      [RangeValidator(1,100)]
      public int MyProperty{ get; set; }
    }

Simples, não é?

Agora faça isso 10 vezes para cada uma das suas 30 classes de negócio. Dá umas 300 vezes. Depois refatore tudo. Parece divertido, não é?

Na prática, este esforço quase elimina o fato de você ter um designer visual para te ajudar. Se eu estou utilizando um designer visual, eu quero que ele me ajude a fazer o código, não quero que eu precise recodificar tudo de novo. Além disso, se eu mudar o nome de uma propriedade, vou ter que alterar também na classe amiga. O mesmo vale para qualquer outra refatoração, como mover propriedades entre classes.

Isso viola violentamente o pricípio DRY, que diz que você não deve se repetir. E está na cara que com buddy classes vamos nos repetir bastante, não é?

A grande questão é: como ter o melhor dos dois mundos, ou seja, ter a geração de código funcionando bem, mas ainda assim permitir estensibilidade matendo bons princípios, como o DRY. Isso é algo muito difícil de fazer, e acredito que é um dos motivos que frameworks como o NHibernate até hoje não fizeram designers visuais: eles teriam que gerar código, e isso sempre é complicado, porque qualquer código gerado seria muito criticado.

Ainda há a possibilidade de colocar a validação de forma externa, utilizando XMLs de configuração por exemplo. Mas isso é separar responsabilidades que deveriam estar na classe. Está longe do ideal…

Eu tenho um certo pós-conceito com código gerado por ferramentas. Já fui impactado diretamente mais de uma vez, onde o projeto engessava por causa deste tipo de "ajuda". O que vocês acham? Esse problema tem solução?


Postado na(s) categoria(s) .Net , Arquitetura pelo giovanni bassi em 11 de maio de 2009 às 10:12 | Tags: ,

Um conceito que eu acabei entrando em contato mais próximo enquanto estudava interfaces fluentes foi operadores implícitos. Operadores implícitos são operadores chamados quando você quer fazer um cast automático de um tipo para outro tipo.

A classe de builder de itens (CatalogItemBuilder) que usei nas interfaces fluentes tinha um desses. Ele era assim:

    public class CatalogItemBuilder : DomainObjectBuilder<CatalogItem>, ICatalogItemBuilder
    {
        //uma função Build existe
        //resto do código oculto

        public static implicit operator CatalogItem(CatalogItemBuilder builder)
        {
            return builder.Build();
        }
    }

Isso permitia que eu fizesse isso:

CatalogItemBuilder builder = ObterBuilder();
CatalogItem item = buider;

Ou passasse ele para uma função, como a de adicionar um novo item:

Category category = new Category();
category.Items.Add(builder);

Nesse caso, "Items" é uma coleção de CatalogItems, não CatalogItemBuilders. Na chamada, a conversão é feita implicitamente.

Você só pode usar operadores implícitos quando não há perda de informação, a documentação deixa isso bem claro. Nesse caso, estamos convertendo para um objeto totalmente diferente e realmente não havia perda de informação, então o operador implícito caia muito bem. Muito interessante, porque abre o horizonte para seu uso em outras atividades de negócio no código. Muito diferente dos exemplos mais comuns, que geralmente envolvem converter um inteiro para um double.


Postado na(s) categoria(s) .Net pelo giovanni bassi em 4 de maio de 2009 às 10:32 | Tags:

Estou dando uma olhada no F#, e uma das primeiras coisas que você percebe é a inferência de tipos. Que é muito legal. Vejam esse código:

let quadrado x = x * x

let somaDosQuadrados nums =
    let mutable total = 0
    for x in nums do
        total <- total + quadrado x
    total

Esse código apresenta uma função que faz o quadrado de um número, na primeira linha. Na terceira linha em diante há uma função que soma quadrados a partir de uma sequência de números.

Atenção: Em nenhum lugar há o tipo do número a ser somado ou elevado ao quadrado, ou que a lista de números, descrito. São inteiros? São doubles? São floats?

Respondendo então: São inteiros. Aqui a prova:

São inteiros!

Recebe uma sequência de inteiros (seq<int>) e retorna um inteiro (-> int).

Eu executo isso na console interativa do F#, e ele me dá o resultado:

image

Inteiros mais uma vez.

Atenção: O F# não é uma linguagem dinâmica. Ele é fortemente tipado com static dispatch. Tudo isso é inferência de tipo.

Como ele sabe? Ele faz a inferência do tipo lendo a função ao contrário. Ele percebe que minha variável "total" é um inteiro, e portanto o retorno da função (dado na última linha, que só tem escrito "total") só pode ser um inteiro. E para somar na variável total com o resultado da função quadrado, essa função deve retornar também um inteiro. E se ela retorna um inteiro, ela recebe um inteiro também (vejam que a função quadrado recebe x, e retorna x vezes x). E se x, dentro do meu "for", é um inteiro, a variável nums só pode ser uma sequência de inteiros. Portanto, a função recebe uma sequência de inteiros e retorna um inteiro.

Uau!!!

Se eu mudar isso para:

let quadrado x = x * x

let somaDosQuadrados nums =
    let mutable total = 0.0
    for x in nums do
        total <- total + quadrado x
    total

(Só mudei a variável "total" de "0" para "0.0".)

Tudo muda, e "x" passa a ser um double (chamado de float no F#), e nums uma lista de doubles (pulei algumas linhas para mostrar que mudei a variável total):

Agora são doubles

A função quadrado também passa a trabalhar com doubles:

Aqui também são doubles

Uma mudança na função somaDosQuadrados afetou a função quadrado. Uau de novo!

Está clara a influência desse tipo de construção sobre o C#, principalmente na construção de lambdas e do LINQ, não está? Bem legal que algo que tenha iniciado nas universidades, em algum momento foi parar no Microsoft Research, e foi incorporado ao C# mesmo antes do lançamento do F#, previsto só para o Visual Studio 2010 no fim deste ano, começo do ano que vem. Aliás, lambdas são consideradas o "lado funcional" do C#, e são um dos motivos que o C# é chamado de uma linguagem de múltiplos paradigmas.

Antes de terminar, eu só queria dizer que essa não é a maneira correta de fazer uma função com F#. Programar F# assim é como usar C# para fazer programação estruturada, sem OO, algo que devia dar cadeia. Esse programa, altamente imperativo, vai contra tudo o que o F# propõe, que é uma programação funcional, não imperativa. Mas isso fica para outro post.


Postado na(s) categoria(s) .Net pelo giovanni bassi em 24 de abril de 2009 às 10:45 | Tags: ,

Engraçado que algo que você entende como óbvio simples e direto, às vezes teve tanto planejamento por trás que é difícil imaginar.

Fico pensando em mim, como usuário, muitos anos atrás. Um clique no botão de volume, e o volume aumentava. Era óbvio, as coisas eram ligadas. Obviamente ligadas.

A não ser pelo fato de que não eram. Alguém programou que o clique no botão de volume disparava uma mensagem que ia parar na placa de áudio, que controlava meu fone de ouvido. Nada automático.

Pois é. E quando falamos em compilação de uma linguagem, vejam só, nada também é automático. Ou simples.Vejam a excelente discussão do também sempre excelente Eric Lippert, do time do C#, sobre a diferença de Equals e == no C#, para entender o que eu estou querendo dizer.

Você já havia considerado que são coisas tão diferentes, que tomamos por iguais? E quando você vê, parece que sempre foi óbvio. Mas não era.


Postado na(s) categoria(s) .Net pelo Giovanni Bassi em 23 de abril de 2009 às 10:28 | Tags:

Assisti o vídeo sobre a maluquice do ObjectiveC#, do Lang.Net que eu havia mencionado. Ele é curtinho. E pelo visto foi só uma elocubração, e não vai rolar. Mas valeu pelos conceitos.

A idéia era trazer ao C# uma maneira de fazer dynamic dispatch para passagem de mensagens, de forma diferente do dinamismo que está sendo implementado no C# 4.0, e mais parecida com a implementação feita em ObjectiveC e SmallTalk.

Por exemplo, para criar uma classe pessoa chamando o construtor, e depois chamar o método "DarAumento", você faria algo assim:

Person person = [[person alloc] init firstName:"Giovanni" lastName:"Bassi"];
person![DarAumento];

O interessante é que a chamada seria totalmente dinâmica, acrescentando ao dinamismo que já está sendo preparado para o C# 4.0.

Bem legal. Mas não vai acontecer.


Postado na(s) categoria(s) .Net pelo Giovanni Bassi em 21 de abril de 2009 às 10:33 | Tags:

Peguei um bugzinho em uma implementação que eu havia feito na implementação de um operador de igualdade, e fui ver se estava com o mesmo erro em outros lugares. Encontrei uma implementação diferente para o mesmo operador. Vejam abaixo as duas.

Primeira, comparando os atributos no operador diretamente. O "<>" e o equals usam o operador "=".

    Public Shared Operator =(ByVal siteA As WebSite, ByVal siteB As WebSite) As Boolean
        If siteA Is Nothing OrElse siteB Is Nothing Then
            Return False
        End If
        Return siteA.Id = siteB.Id AndAlso siteA.Name = siteB.Name
    End Operator

    Public Shared Operator <>(ByVal siteA As WebSite, ByVal siteB As WebSite) As Boolean
        Return Not siteA = siteB
    End Operator

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        Dim site = TryCast(obj, WebSite)
        If site Is Nothing Then
            Return False
        End If
        Return site = Me
    End Function

Segunda, comparando no Equals, e os operadores usam o Equals para resolução.

    Public Shared Operator =(ByVal a As ServerEnvironment, ByVal b As ServerEnvironment) As Boolean
        If a Is Nothing OrElse b Is Nothing Then
            Return False
        End If
        Return a.Equals(b)
    End Operator

    Public Shared Operator <>(ByVal a As ServerEnvironment, ByVal b As ServerEnvironment) As Boolean
        Return Not a = b
    End Operator

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        Dim dest = TryCast(obj, ServerEnvironment)
        If dest IsNot Nothing AndAlso dest.Name = Me.Name Then
            Return True
        Else
            Return False
        End If
    End Function

Interessante, não é? Talvez você esteja se perguntando porque eu faria isso. Oras, objetos de valor ("OVs" ou "VOs") devem ser comparados pelos seus atributos, já que não possuem identidade. Nada mais justo do que sobrescrever o método Equals e já criar os operadores de igualdade.

Para quem está curioso, o bug era na linha 2 do primeiro exemplo. Eu não fazia a verificação de existência do objeto, o que resultava em uma exceção na comparação com objetos nulos.


Postado na(s) categoria(s) .Net pelo giovanni bassi em 22 de janeiro de 2009 às 11:19 | Tags:

Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  março 2010  »
seteququsedo
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in