True

junho 28, 2012 1 comentário

Voltei aqui para falar (mal) de parâmetros booleanos.
Deu pra perceber pelo título do post? Não? Pois é.

O que um parâmetro booleano diz?
A mim parece uma resposta para uma pergunta que eu não conheço.

Response.Redirect(“http://www.google.com”, true);

O que esse true faz? Como a execução do Redirect é afetada?
Olha só nesse link.

Além disso, não preciso dizer que se tenho um parâmetro booleano, tenho pelo menos um if no corpo do Redirect.
Como sugestão, poderíamos ter dois métodos:

Response.AbortAndRedirect(“http://www.google.com”);
Response.Redirect(“http://www.google.com”); 

Bom, eu achei mais claro. Achou também?

Abraço.

Anúncios

Por que não contratar programadores .Net?

Li esse post durante a semana e não consegui concordar nem discordar. Twittei e recebi uma trollada de volta. Normal.  Então vou tentar, aqui, explicar o que pensei/penso.

Em primeiro lugar, o autor do post, com certeza, nunca programou em C# e não faz idéia do quanto a plataforma evoluiu. Passamos de uma arquitetura component-based, com WebForms, para um framework MVC muito bom e extensível, que é o ASP. Net MVC, enquanto o Java, por exemplo, seguiu o caminho inverso. E taí uma plataforma e comunidade que vem se degradando a cada dia. Component-based a essa altura do campeonato é demais pra mim. Se considera um bom programador? Quer evoluir? Então saia dessa!

No início, a “guerra” era Java x .Net e muitos bons frameworks existentes em Java foram portados para .Net, o que fez a plataforma evoluir MUITO. Nada melhor que aprender através da experiência dos outros e não ficar reinventando a roda. Por exemplo, trabalho hoje em um projeto com alguns frameworks que vieram do Java e posso afirmar que você também. Listando alguns: NHibernate, NUnit e log4net.

A “guerra” hoje não é mais .Net x Java, e sim Todos x Ruby on Rails (cuidado com o javascript!).
Quais são os bons frameworks para desenvolvimento de apps web em Java e .Net? Em Java, só escuto falar de VRaptor e em .Net, como já mencionei, ASP. Net MVC. Sabe da onde vieram ambos? Foram inspirados pelo Rails. Em Ruby, é possível instalar gems via linha de comando enquanto em .Net posso usar o NuGet para fazer o mesmo. Ok. Sou noob em RoR. Falei besteira? Pode xingar.

Agora que falei um pouco da tal guerra entre as tecnologias, agora vamos ao post.

Veja que o autor do post fala tudo dentro de um contexto: startups. (Nunca trabalhei em uma startup. Coincidência?)

Quais são as dificuldades de uma startup? Eu imagino que grana seja uma delas. Visual Studio é massa? É, mas só roda no Windows. Licença do Windows é barata? Não. E do Visual Studio? Também não. E não venha me falar de SharpDevelop. Tem que comer muito feijão com arroz ainda.

Acho que o único ponto com o qual realmente discordo do post:

“Programming with .NET is like cooking in a McDonalds kitchen.  It is full of amazing tools that automate absolutely everything.  Just press the right button and follow the beeping lights, and you can churn out flawless 1.6 oz burgers faster than anybody else on the planet.

However, if you need to make a 1.7 oz burger, you simply can’t.  There’s no button for it. The patties are pre-formed in the wrong size.  They start out frozen so they can’t be smushed up and reformed, and the thawing machine is so tightly integrated with the cooking machine that there’s no way to intercept it between the two.  A McDonalds kitchen makes exactly what’s on the McDonalds menu — and does so in an absolutely foolproof fashion.  But it can’t go off the menu, and any attempt to bend the machine to your will just breaks it such that it needs to be sent back to the factory for repairs.

See, Microsoft very intentionally (and very successfully) created .NET to be as different as possible from everything else out there, keeping the programmer far away from the details such that they’re wholly and utterly dependent on Microsoft’s truly amazing suite of programming tools to do all the thinking for them.

Esses trechos destacados em negrito mostram o quanto ele NÃO conhece a plataforma. Concordo que por muito tempo (enquanto WebForms era a única opção), boa parte da comunidade (qual comunidade? onde?) só sabia usar o mouse, arrastar controles numa página, clicar no controle e escrever o código do evento. Um caminho que não sei por que cargas d’água o Java tentou seguir – pior, sem nenhuma ferramenta comparável ao VS  – , com o JSFail (parafraseando o @cmilfont), e que o RoR nem cogitou trilhar.

Mas como ele pode afirmar que .Net é algo completamente diferente de tudo que se faz em outras plataformas? Citei no começo do post alguns frameworks que vieram do Java e conheço muitos outros. Então a pergunta é: hein!?

Por que não é possível criar “1.7 oz burger”? Simples. Por que o autor não conhece a plataforma. Realmente, assim não dá pra fazer nem um pão com ovo.

Sobre a maioria dos programadores .Net, concordo com uma frase de outro post que li semana passada:

“.Net programmers are largely Enterprise programmers who are not constitutionally constructed to create large scalable websites at a startup pace.”

Não tenho como discordar. E, por favor, leia direito a frase e não me xingue.

Pelo custo de um ambiente .Net, fica difícil que startups o adotem, como mencionei antes (Windows Server 2008, VS2010, TFS, etc etc etc).

Bom, era isso. Vou twittar o post. Se quiser xingar ou trocar idéias lá, faça. Mas prefiro aqui. Não tem limite de caracteres.

Abraço.

Categorias:.Net

Futebol, eleições e teatro bunraku

Ainda há quem acredite que não há manipulação nessas pesquisas pré-eleições e que a diferença entre as pesquisas e a realidade é só um “errinho” aceitável.

Depois de ver Tasso liderar as pesquisas antes das eleições e vê-lo fora, inclusive da vida política, espero que essa visão de alguns mude “um pouco”. Sem falar dos 6 pontos de diferença entre as pesquisas e a realidade de urna da Marina.

Quem não enxerga isso é como um espectador de bunraku (vou explicar :)).

Semana passada li um livro do Luis Fernando Veríssimo que reúne diversas crônicas por ele escritas durante as copas do mundo de futebol que cobriu.

Alguém pergunta: “E o que futebol tem a ver com eleições?”

Bom, segue um trecho do texto:

(…) O bunraku é uma das tradicionais formas de teatro do Japão, junto com o noh e o kabuki. No bunraku, bonecos são manipulados por pessoas encapuzadas vestidas de preto, e uma das suas convenções é que a platéia precisa fingir que os bonequeiros não estão no palco para poder aproveitar o espetáculo. Quem se concentrar nos movimentos dos manipuladores, em vez de nos bonecos, não acompanhará a trama e perderá o melhor. No futebol brasileiro e nos campeonatos mundiais organizados pela Fifa acontece a mesma coisa: para aproveitá-los você precisa fingir que os manipuladores não existem, ou são apenas recursos cênicos neutros. Fica cada vez mais difícil ignorar a presença dos vultos negros movendo os atores e os cenários do futebol. Mas é preciso concentrar-se no espetáculo e fazer de conta que não tem mais ninguém no palco. Pois a única maneira de aproveitar o que uma Copa do Mundo e um campeonato nacional tem de único e de sensacional é encará-los como teatro bunraku. É ver os manipuladores em cena – pois alguns nem se dão mais o trabalho de usar capuz -, saber que eles estão lá, mas ignorá-los e dar toda a atenção à arte e à grandeza do futebol bem jogado. (…)

Para a analogia ficar um pouco mais convincente, ficou faltando só a arte e a grandeza da política. Onde está?

Sem mais.

Categorias:futebol

DDD: Implementando Repository com Specifications

setembro 3, 2009 1 comentário

Já tinha lido alguns posts e artigos sobre Domain-Driven Design, mas ainda não tinha dado atenção suficiente ao assunto. Recentemente comecei a ler o livro Domain-Driven Design: Tackling Complexity int ther Heart of Software e, depois de alguns capítulos, percebi que um dos conceitos mais importantes que se pode extrair da leitura é como se comunicar com os elementos do domínio de forma clara, declarativa e flexível. A solução apresentada é o pattern Repository, que delega ao cliente a responsabilidade de construir queries e submetê-las ao repositório para satisfação, além de prover separação de dependência de única direção entre o domínio e as camadas de acesso a dados.

No post passado, falei um pouco sobre como algumas implementações de Repository se assemelham a implementações de DAO, por expor um método para cada critério de busca, e como isso diverge do que me parece ser o objetivo do pattern. Então, ao invés disso, a implementação a seguir utiliza o pattern Spefication, para criação de uma linguagem declarativa de query.

Durante a leitura do livro, tenho buscado implementar alguns conceitos em uma aplicação simples e pretendo compartilhar essa experiência. Então, sempre que achar um tema interessante, vou trazer uma implementação.

O domínio da a aplicação é um player de música, capaz de criar listas de reprodução dinâmicas a partir de uma especificação.

A figura abaixo traz os elementos do domínio mapeados, até agora, para essa aplicação:

Diagrama

A interface primária do repositório tem um método Match, que recebe uma especificação como parâmetro de entrada e retorna uma coleção de objetos do domínio que satisfazem à especificacão.

public interface IRepository
{
    IEnumerable Match(Specification specification);
}

public interface ISongRepository : IRepository
{
    IEnumerable getSongsFromAlbum(string album);
    IEnumerable getSongsFromGenre(string genre);
    ...
}

public class SongRepository : ISongRepository
{
    internal List songs;

    public SongRepository()
    {
        songs = createRepositoryData();
    }

    private List createRepositoryData()
    {
        ...
    }

    #region IRepository Members

    public IEnumerable getSongsFromAlbum(string album)
    {
        Specification fromAlbumSpec = new SongFromAlbumSpecification(album);

        return this.Match(fromAlbumSpec);
    }

    public IEnumerable getSongsFromGenre(string genre)
    {
        Specification fromGenreSpec = new SongFromGenreSpecification(genre);

        return this.Match(fromGenreSpec);
    }

    public IEnumerable Match(Specification specification)
    {
        List resultSet = new List();

        foreach (Song song in songs)
        {
            if (specification.IsSatisfiedBy(song))
                resultSet.Add(song);
        }

        return resultSet;
    }

    #endregion
}

Uma das grandes vantagens de se usar Specification é a possiblidade de compor critérios de busca sem a necessidade de alteração da interface do repositório. Essa composição se dá pela combinação de especificacões através de operações lógicas.

public interface Specification
{
    bool IsSatisfiedBy(T candidate);

    Specification And(Specification other);
    Specification Or(Specification other);
    Specification Not();
}

public abstract class CompositeSpecification : Specification
{
    #region ISpecification Members

    public abstract bool IsSatisfiedBy(T candidate);

    public Specification And(Specification other)
    {
        return new AndSpecification(this, other);
    }

    public Specification Or(Specification other)
    {
        return new OrSpecification(this, other);
    }

    public Specification Not()
    {
        return new NotSpecification(this);
    }

    #endregion
}

A partir dessas interfaces, devemos buscar identificar quais os principais critérios de busca utilizados pela aplicação e implementá-los como pequenas regras, para possibilitar a criação de novas regras via composição. Para ilustrar essa idéia, criei as especificações SongFromAlbumSpecification, SongFromArtistSpecification e SongTopRatedSpecification.

public class SongFromArtistSpecification : CompositeSpecification
{
    private string artist;

    public SongFromArtistSpecification(string artist)
    {
        this.artist = artist;
    }

    public override bool IsSatisfiedBy(Song candidate)
    {
        return candidate.Artist == artist;
    }
}

public class SongFromAlbumSpecification : CompositeSpecification
{
    private string album;

    public SongFromAlbumSpecification(string album)
    {
        this.album = album;
    }

    public override bool IsSatisfiedBy(Song candidate)
    {
        return candidate.Album == album;
    }
}

public class SongTopRatedSpecification : CompositeSpecification
{
    public SongTopRatedSpecification()
    {}

    public override bool IsSatisfiedBy(Song candidate)
    {
        return (candidate.Rate == 5 );
    }
}

Podemos combinar essas especificações de várias maneiras diferentes de forma a construir conceitos mais complexos. Digamos que queiramos construir uma playlist que contenha todas as músicas de um determinado artista, e que sejam as que possuem melhor classificação.

ISongRepository repository = new SongRepository();

Specification topRated = new SongTopRatedSpecification();
Specification fromMaiden = new SongFromArtistSpecification("Iron Maiden");

Specification topRatedFromMaiden = topRated.And(fromMaiden);

IEnumerable selectedSongs = repository.Match(topRatedFromMaiden));

Ou uma playlist contendo músicas com melhor classificação de mais de um artista.

Specification fromCake = new SongFromArtistSpecification("Cake");
Specification topRatedFromCake = topRated.And(fromCake);

Specification topRatedFromCakeOrMaiden = topRatedFromCake.Or(topRatedFromMaiden);

IEnumerable selectedSongs = repository.Match(topRatedFromCakeOrMaiden));

Identificar os principais critérios de busca utilizados pela aplicação e mapeá-los de maneira extensível são as principais tarefas na construção de uma boa linguagem de comunicação com o domínio, pois, a partir desses critérios, vários outros conceitos podem e devem emergir.

O principal intuito aqui é apresentar implementações dos conceitos expostos no livro, portanto, sugestões e críticas são bem vindas.

Brevemente disponibilizarei o fonte da aplicação.

Repository Pattern

agosto 12, 2009 3 comentários

O modelo de desenvolvimento DDD (Domain Driven Design) é hoje um dos mais prestigiados pela comunidade de desenvolvimento de software, sendo considerado, inclusive, uma maneira “mais OO” de se criar software, adicionando comportamento a objetos de domínio, provendo melhor testabilidade, manutenibilidade, etc. Além disso, um dos princípios do DDD é prover interfaces mais expressivas, com operações bem descritas pelos métodos que a executam.

No livro Domain Driven Design(a bíblia para muitos arquitetos e desenvolvedores), do Eric Evans, o pattern Repository integra a camada de domínio e é usado como uma ferramenta para selecionar objetos de domínio de acordo com um determinado critério.

Pela definição do Fowler, no livro PoEAA(Patterns of Enterprise Application Architecture), o Repository tem o seguinte papel:

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

Traduzindo, o Repository tem o papel de mediador entre o domínio e as camadas de mapeamento de dados para permitir o acesso a objetos de domínio.

Ele complementa dizendo:

A system with a complex domain model often benefits from a layer, such as the one provided by Data Mapper, that isolates domain objects from details of the database access code. In such systems it can be worthwhile to build another layer of abstraction over the mapping layer where query construction code is concentrated. This becomes more important when there are a large number of domain classes or heavy querying. In these cases particularly, adding this layer helps minimize duplicate query logic.

Ou seja, a idéia é, no domínio, abstrair o Data Mapper – responsável pela persistência dos dados, através do Repository, provendo uma linguagem declarativa para construção de queries.

Na prática, os frameworks ORM como NHibernate, Linq To Sql e Entity Framework, fazem o papel do Data Mapper e são eles que devem/podem ser abstraídos.

Na minha opinião, a grande sacada do Repository é fornecer uma linguagem declarativa para construção de queries, pois é ela quem dá ao domínio a liberdade de fazer a consulta que necessitar, sem alterar uma única linha de código do seu repositório. E é isso o que a maioria tem “esquecido” de incluir nas suas implementações.

Já vi implementações que, sob minha ótica, não tiram proveito do pattern, fazendo dele apenas um proxy para o seu respectivo DAO(ou outro pattern para acesso a dados), sob o argumento de que o Repository é uma forma mais expressiva por ter métodos do tipo repository.listarClientesVIP() encapsulando uma chamada a um método do DAO, como dao.consultar(StatusCliente.VIP). Esse tipo de expressividade até um DAO pode ter e não acho que essa seja a idéia.

Se você observou bem, viu que deixei em aberto a possibilidade de abstração do framework ORM. Isso por que, como em todas as escolhas que fazemos, a escolha de um pattern tem seus tradeoffs. E, apesar de trazer muitos ganhos na abstração da infraestrutura de persistência de dados, a implementação da linguagem declarativa de query é muito custosa, pois requer a implementação de várias operações para composição do critério. Particularmente, faria essa implementação se percebesse a possibilidade de, no meio do projeto, precisar trocar o framework de persistência usado na aplicação. Caso contrário, usaria os mecanismos de construção de queries fornecidos pelo ORM, para assim tirar o máximo de proveito do framework.