domingo, agosto 30, 2009

Os Álbuns dos Beatles - Introdução

Talvez já exista coisa demais escrita sobre os Beatles e suas músicas. Entretanto, não consegui resistir à tentação de escrever uma série de posts sobre os seus álbuns. No mínimo, é uma boa desculpa para escutá-los mais algumas vezes. Com o lançamento em breve do "Rock Band - The Beatles" é provável que surja uma nova geração procurando saber um pouco sobre eles.

Devo advertir que não me considero um beatlemaníaco. Talvez eu seja um apreciador um pouco mais exagerado que a média, mas estou longe dos fãs mais sérios (já convivi com alguns deles para saber do que estou falando). Não esperem nenhuma revelação exclusiva nesta série, as informações vieram de fontes bem conhecidas, como a Wikipedia e o livro "The Complete Beatles Recording Sessions".

Neste primeiro post, vou falar sucintamente sobre o começo dos Beatles e os seus membros. Nos post seguintes vou falar sobre os álbuns "oficiais":
  • Please, Please Me
  • With The Beatles
  • A Hard Day's Night
  • Beatles For Sale
  • Help!
  • Rubber Soul
  • Revolver
  • Sargent Pepper's Lonely Hearts Club Band
  • Magical Mystery Tour
  • The Beatles
  • Yellow Submarine
  • Let It Be
  • Abbey Road
  • Past Masters 1 & 2
O Começo dos Beatles

Em 1956, John Lennon (então com 15 anos) começou a tocar violão e fundou um grupo chamado Quarry Men. Em 57 Paul McCartney se juntou ao grupo e em 58 George Harrison. No começo de 1960 os Quarry Mem eram um quarteto composto por John, Paul, George e Stuart Sutcliffe (um grande amigo deles mas que não tinha nenhuma vocação musical) e logo depois mudaram de nome para The Silver Beatles.

Em agosto de 1960 o nome foi mudado uma última vez, para The Beatles, o grupo conseguiu o seu primeiro baterista estável, Pete Best e partiram para sua primeira temporada em Hamburgo, onde tocavam de forma incessante em verdadeiras espeluncas. A prática deu resultados e The Beatles começou a chamar atenção.

Em 1961 The Beatles começou a se apresentar em um pequeno clube de Liverpool, The Cavern. Stu deixou a banda, com Paul assumindo o baixo. E, mais imporante, Brian Epstein passou a ser o empresário do grupo.

No começo de janeiro de 62, fizeram um teste pra a gravadora Decca - e foram rejeitados. No começo de junho fizeram um novo teste, agora para a EMI/Parlophone. No final de julho, o produtor George Martin (que coordenou o teste na EMI), informou para Brian que desejava contratar os Beatles. Em agosto The Beatles passou por sua última mudança de formação. Pete Best foi substituído por Ringo Starr. Em setembro os Beatles foram para o estúdio gravar o seu primeiro compacto. Gerorge Martin queria que eles gravassem uma música chamada "How Do You Do It", mas eles insistiram em uma composição própria - "Love Me Do". Com esta rebeldia se iniciava a recordista carreira de gravação dos Beatles.

Os Membros

É difícil analisar friamente os Beatles. A fama e acontecimentos marcantes fizeram com que fatos e mitos se misturassem. Foram considerados deuses para uns e demônios para outros.

Os Beatles tinham um comportamento um pouco diferente de outros astros de rock-and-roll, não incorporando solos longos ou poses forçadas em suas apresentações. Isto faz com que sejam às vezes menosprezados como instrumentalistas.

De qualquer forma, segue a minha tentativa (em ordem alfabética):
  • George Harrison: chamado às vezes de "the quiet Beatle", George era inicialmente responsável pelos solos de guitarra. Teve sempre presença marcante nos vocais, tanto como líder vocal como nas harmonias e acompanhamentos. Poucas composições suas aparecem nos albums dos Beatles, mas quase todas elas são consideradas clássicos. Nos meados dos anos 60 passou a se interessar pela música e religião indiana, o que influenciou profundamente as suas composições. Seu estilo como guitarrista foi "variado, flexível e às vezes inovador" (nas palavras da Wikipedia). Nunca se preocupou em ter a velocidade ou a postura de um "guitar hero" mas utilizou vários tipos de instrumentos e ganhou reconhecimento de seus colegas pela técnica de slide.
  • John Lennon: se destacou sempre pela sua voz, seu senso de humor e suas composições. A partir do seu namoro com Yoko Ono passou a procurar músicas mais "sérias". Do ponto de vista instrumental, cuidava mais do violão ou guitarra base. Nos primeiros álbuns aparecia com certo destaque tocando gaita. Com alguma frequência tocava piano e órgão.
  • Paul McCartney: também se destacava pela voz e composições. É um notado multi-instrumentalista, sendo responsável por trechos marcantes de baixo, violão, guitarra e piano.
  • Ringo Starr: considerado maldosamente por alguns de "o homem mais sortudo do mundo", Ringo sempre teve o respeito dos colegas bateristas. Avesso a solos e malabarismos, Ringo se destaca pela sua constância e precisão. Mesmo sem uma voz notável, comparece nos vocais de pelo menos uma música em cada álbum. Somente duas músicas dos álbuns são atribuídas a ele. Uma contribuição adicional foram expressões incomuns que acabaram se tornando título de músicas (como "Tomorrow Never Knows").
O Quinto Beatle

A expressão "Quinto Beatle" é usada com frequência, vejamos os suspeitos habituais:
  • Stuart Sutcliffe: estava na banda apenas pela amizade, sua contribuição musical é considerada por alguns negativa.
  • Pete Best: embora tenha sido uma figura importante durante a formação dos Beatles, foi descartado antes da assinatura do primeiro contrato de gravação.
  • Billy Preston: grande amigo dos Beatles, participou da gravação do que viria a ser o álbum Let It Be (longa história, não percam!) e foi o único artista a ganhar reconhecimento na capa de um álbum dos Beatles ("The Beatles With Billy Preston").
  • George Martin: produtor de quase todos os álbums, contribuiu significativamente para o aprendizado dos Beatles e ainda tocou teclado em algumas músicas.
Meu voto? Sir George Martin.

Lennon & McCartney

No começo da carreira dos Beatles, Paul e John fizeram um pacto de atribuir as composições à dupla, independente de ser ou não uma composição conjunta.

A maioria das músicas, principalmente com o passar dos anos, foi composta exclusiva ou primordialmente por apenas um deles. Mesmo assim, a influência do outro sempre foi importante. Paul menciona com frequência as composições e revisões feitas com os dois tocando violão um de frente para o outro, que acabaram confirmando ou alterando trechos.

Existe um engano frequente de considerar que Paul é responsável pelas músicas mais melosas e John pelas mais sérias. Como veremos nos próximos posts, os dois mostraram enorme competência em um largo espectro de músicas.

sábado, agosto 29, 2009

Utilitário do Mês: aTunes

Durante muito tempo o "finado" Sonique era o meu tocador de música no PC. Quando mudei de micro no trabalho acabei não o instalando e passei a usar o Windows Media Player, mas não estava muito satisfeito. Procurando alternativas, acabei achando o aTunes.

O aTunes é um tocador e organizador de música. É um software livre multiplataforma, cheio de recursos. A tela principal (com as várias subtelas ligadas) tem a seguinte aparência (clique para ampliar):

Reparar que a interface e as informações estão em português (ocasionalmente macarrônico). Vários idiomas podem ser selecionados nas preferências.

As músicas são organizadas em uma biblioteca (figura da esquerda), a partir da qual se montam as listas de execução (à direita):

A parte mais interessante são as informações de contexto, obtidas automaticamente da internet: Artista, Album, Canção, Semelhante e YouTube:

A aba YouTube permite inclusive baixar o vídeo (sem precisar abrir um navegador ou executar um outro programa).

Outro recurso embutido no aTunes é um "rippador":


O aTunes possui ainda alguns recursos para sincronizar com um dispositivo (como um tocador MP3), desde que ele sejá acessível como um diretório no SO. Não utilizei este recurso até agora.

O aTunes tem funcionado muito bem até o momento. Meu único porém é a falta de documentação, o que obriga a ficar explorando o software para achar os recursos e descobrir como funciona.

O download pode ser feito através do site oficial: http://www.atunes.org/

Recomendado.

sexta-feira, agosto 28, 2009

TechEd 2009 - Dia Três

Terceiro e último dia, mais cinco palestras assistidas:

Melhores Práticas no Desenvolvimento WPF e Novidades do WPF 4.0

Mais uma palestra sobre Windows Presentation Foundation, focada principalmente em desempenho. A Microsoft está apostando bastante na WPF, a utilizando inclusive na interface com operador do Visual Studio 2010.

Uma preocupação para o desenvolvedor WCF é não deixar a aplicação "pesada" demais e este foi o principal tema desta palestra de Bruno Sonnino.

Segurança no Desenvolvimento Web: Novas Defesas

Fiquei um pouco decepcionado com esta palestra do Mauro Sant'Anna. Apesar do conhecimento e habilidade do palestrantes, ficou com um jeitão de material antigo. Os pontos discutidos foram os de sempre: SQL injection e Cross-site Scripting; as novas defesas são versões mais recentes de ferramentas automáticas de análise de código, agora mais integradas com o Visual Studio.

Dicas e Truques: Torne suas Queries Mais Rápidas e Eficientes

Foi a palestra que mais gostei no dia. Embora o assunto também não fosse novidade, Luciano Caixeta Moreira apresentou com bom ritmo uma sequência de demonstrações muito claras e precisas. Conseguiu prender a minha atenção do início ao fim, não desperdiçou nem estourou o tempo e saí com vários pontos importantes fixados na memória.

Paralelismo com .Net FX 4.0 e VS 2010

Como de costume, o Fabio Faluppo conseguiu encaixar uma palestra de nível mais elevado e até mostrar um pouco de código C++. Nestes dias em que processadores multi-core estão virando o default, processamento paralelo deixa definitivamente de ser assunto de laboratório e caminha para aplicações mais corriqueiras. O .Net FX 4.0 e o Visual Studio 2010 apresentam novas APIs e bibliotecas para simplificar o desenvolvimento de aplicações paralelas. Continua sendo necessário um conhecimento específico de paralelismo, mas pelo menos dá para abstrair alguns detalhes mais trabalhosos da programação paralela.

Visão Geral do WCF e do WF no .NET Framework 4.0

WCF (Windows Communication Foundation) e WF (Windows Workflow Foundation) são outras duas tecnologias introduzidas no .Net Framework 3.0 (junto com o WPF), que também ainda tem aceitação reduzida.

A WCF unifica os diversos modelos de comunicação disponíveis originalmente no .Net Framework (como Web Services, Remoting e Message Queue). Na primeira parte da palestra Rafael Godinho falou nas melhorias que virão com o .NET Framework 4.0. São melhorias incrementais, que simplificam a configuração, oferecem novas opções de localização e roteamento de serviços e melhoram o suporte a RESP.

Na segunda parte da palestra, foram apresentadas as novidades no WF que é uma tecnologia para definição, execução e gerenciamento de workflows. A versão 4.0 traz uma revisão completa do modelo de programação, do runtime e das ferramentas. Como consequência, a compatibilidade com as versões anteriores é obtida mantendo as duas versões em paralelo, com as componentes da nova versão ficando em em namespace e assemblies diferentes.

Conclusão

Foram três dias bastante corridos, e eu assisti a um conjunto bastante sortido de palestras. Algumas muito boas, algumas médias, mas nenhuma que eu considerasse ruim. Como de costume, estas palestras não são treinamentos dos quais se sai com conhecimentos completos. As boas palestras mostram alguns highlights e motivam o público a procurar mais detalhes e considerar um uso experimental ou prático do que foi mostrado.

A infraestrutura e organização foi média, nenhuma grande reclamação e nada que maravilhasse. A localização era boa, mas algumas salas eram um pouco pequenas ou apertadas ou desconfortáveis. O sistema de controle e registro de entrada nas salas (usando coletores de dados on-line) apresentou alguns problemas no primeiro dia. Os coffee breaks foram um pouco mais confusos que de costume e a qualidade e variedade um pouco abaixo da média. O acesso a internet via WiFi foi um pouco inconstante e baseado em uma rede aberta. Os brindes de distribuição generalizada foram simples (eu bem que gostaria de um vale Windows 7); a qualidade e quantidade de brindes sorteados nas palestras variou bastante e em muitos casos não entusiasmou a plateia (em várias eram uma mochila e uma caneta).

De qualquer forma, acho que conforto, comida e brindes não devem ser os critérios principais para decidir a participação em um evento. E, no geral, o evento certamente valeu a pena.

quinta-feira, agosto 27, 2009

Projetos com Sucesso - II

Nesta segunda parte, vou examinar as questões do ponto de vista da empresa contratada (empresa).

Analise Friamente Os Motivos de Querer Fechar um Negócio

Na aula de economia da faculdade ganhei do professor a qualificação de "ortodoxo" ao responder "na lata" que o principal objetivo de uma empresa é o lucro. Ortodoxias à parte, acredito que é fundamental para a viabilidade de uma empresa (mesmo uma que se diz sem fins lucrativos) o equilíbrio entre receitas e despesas. É, portanto, no mínimo curioso observar que praticamente todas as empresas, mesmo as que buscam agressivamente o lucro, agem ativamente para fechar negócios que claramente trarão prejuízo.

Existem vários motivos/justificativos para isto. Alguns motivos não razoáveis:
  • Otimismo injustificado na avaliação de custos.
  • Vendedor motivado pelo volume e não pela qualidade das vendas.
Algumas justificativas mais razoáveis:
  • Ninguém (pessoa física ou jurídica) gosta de perder um negócio.
  • Alguns negócios ou clientes são vistos (como ou sem razão) como "estratégicos". Isto ocorre principalmente quando o cliente é uma empresa muito conhecida. Outras considerações nesta linha são "entrar num novo segmento", "obter uma referência" e "colocar um pé no cliente".
  • Expectativa de recuperar o prejuízo em expansões futuras do projeto ou no reaproveitamento do resultado em outros projetos.
Nada contra estes motivos mais razoáveis, desde que eles não sejam esquecidos depois que o negócio ser fechado. Uma receita para o fracasso de um projeto é fechar um negócio sabendo que ele não vai dar lucro e depois pressionar os envolvidos para tentar evitar o prejuízo. O resultado final acaba sendo o prejuízo e o comprometimento do objetivo inicial.

Não Venda Menos que o Necessário

Fala-se muito no vendedor que vende o desnecessário e pouco do que vende menos que o necessário. Reduzir escopo e baixar o preço é mais fácil que justificar itens que o cliente não tinha previsto, mesmo que a experiência prove que eles são essenciais.

O resultado final é mais um exemplo de perde-perde: ou o projeto afunda pela falta destes itens essenciais ou eles são implementados sem custo (e consequentemente o projeto estoura tempo e custo, gerando prejuízo e desgaste).

O Risco das Novidades

Existe uma grande atração, principalmente na área de tecnologia, pelas novidades. Isto vem tanto da atração técnica como pela pressão de marketing de estar alinhado com os buzzwords que estão na moda.

Não se deve esquecer que o novo é em grande parte desconhecido e portanto os erros de avaliação serão melhores. É preciso lembrar dos investimentos a serem feitos em ferramentas e aprendizado. É muito provável que a primeira tentativa de algo novo tenha uma qualidade inferior ao que será conseguido com o acúmulo de experiência.

Gerencie as Expectativas Durante a Negociação

Na primeira parte eu falei na importância de estabelecer um escopo e não recorrer a meias-verdades e mentiras inteiras. Mais que isto, é preciso tomar cuidado com as expectativas criadas. Expectativas exageradas irão se traduzir em dificuldade na aceitação do projeto e stress desnecessário. Isto não significa que os pontos positivos não devam ser destacados durante a negociação, são estes pontos que irão destacá-lo da concorrência e criar o tão falado "valor".

Aloque a Equipe Correta

Cada projeto requer uma equipe com certas competências, experiências e perfis. Infelizmente as pessoas mais adequadas podem não estar disponíveis no momento do fechamento do projeto. É preciso tomar cuidado ao alocar pessoas a um projeto simplesmente porque elas estão disponíveis no momento. Uma supervisão ou um acompanhamento mais próximo pode corrigir desvios antes que virem críticos. Em casos limites, pode ser melhor deixar uma pessoa inadequada "fazendo nada" do que alocá-la.

É importante definir as funções e responsabilidade de cada membro da equipe e repassar isto para o cliente (no que diz respeito ao pessoal que terá contato direto com o cliente).

Garanta Os Recursos Necessários

Como parte da avaliação de um projeto, ainda na pré-venda, deve-se listar os recursos que serão necessários. Fechado o negócio, é preciso providenciá-los. É frequente a tentação de rever agressivamente esta lista, principalmente quando foram concedidos descontos ao cliente.

Conheça o Cliente

Já no processo de pré-vendas é possível aprender um pouco sobre a cultura do cliente e as características das pessoas envolvidas. É importante que isto seja repassado ao pessoal de projeto. Um sintoma típico de que este trabalho não foi bem feito é quando se inicia o projeto sem saber direito quem são as pessoas envolvidas no lado do cliente e quais as suas atribuições.

Sem estas informações, corre-se o risco de não envolver as pessoas corretas nos levantamento ou decisões e de propor soluções que entrem desnecessariamente em choque com a cultura do cliente.

TechEd 2009 - Dia Dois

Neste segundo dia, cinco palestra de assuntos diversos.

Dicas e Truques no SQL Server 2008

Uma palestra média, focada em alguns poucos recursos do SQL Server 2008:
  • Particionamento de base de dados em vários arquivos em função do conteúdo dos registros. Isto facilita o tratamento de bases extensas e permite colocar partes mais recentes ou vitais da base em unidades de disco com melhor performance ou mais redundância.
  • Compactação das partições por registro ou página, para reduzir o consumo de disco.
  • Gerenciamento de recursos (Resource Governor), permite definir limites de alocação de memória e processador em função de critérios como a base sendo acessada ou o usuário.
Desenvolvendo Aplicações com as Novidades do Windows 7

O Windows 7 trás alguns novos recursos que podem ser utilizados por aplicações, principalmente relacionados com o taskbar. A palestra de Bruno Sonnino focou no uso de alguns destes recursos em aplicações .Net, através do Windows API Code Pack, com demonstrações muito didáticas.

Por um lado esta palestra me faz prever aplicações com recursos muito bonitos e úteis. Por outro lado, estes recursos estarão disponíveis somente no Windows 7, o que certamente segurará alguns desenvolvedores.

Estenda seu Web Server: O Que há De Novo no IIS 7.5

Esta é uma das palestras que eu optei mais por falta de opção melhor que por identificação com o tema. O IIS 7.5 é a versão que virá com o Windows Server 2008 R2 e com o Windows 7 e a palestra foi mais voltada para os chamados "profissionais de TI" que para desenvolvedores. Ou seja, se focou mais em aspectos de administração do IIS.

O resumo da palestra, também pontuada por demonstrações bem didáticas de Paulo Teixeira e Guilherme Carnevalle, é que com o IIS 7.5 ficará bem mais fácil instalar e gerenciar um servidor Web.

Compatibilidade de Aplicações com Windows 7

Um dos fatos marcantes do Windows Vista foi abrir mão da compatibilidade com o XP principalmente em nome de maior segurança. O Windows 7 não trás grandes incompatibilidades com o Vista e até melhora a "experiência do usuário" no tratamento das incompatibilidades com o XP. Por este motivo, a palestra de Caio Chaves Gracez dedicou grande parte do tempo a problemas de compatibilidade já existentes no Vista. Outro ponto abordado que não é específico ao Windows 7 é o IE 8, que apresenta incompatibilidades com as versões anteriores principalmente por aderir melhor aos padrões.

A baixa aceitação do Vista permitiu a muitos desenvolvedores ignorarem problemas de compatibilidade. Se o Windows 7 confirmar o sucesso esperado, vamos ter um pico de projetos de correção de problemas de compatibilidade.

Dicas Práticas de WPF para Desenvolvedores Windows Forms

Esta palestra se propunha a mostrar vinte detalhes práticos do desenvolvimento de aplicações WPF através de pequenos exemplos. Infelizmente Carlos Mattos não conseguiu gerenciar bem o tempo da palestra que acabou sendo muito corrida na segunda metade.

A WPF é um certa incógnita para mim. Para quem não sabe do que se trata, a WPF é uma plataforma para desenvolvimento de interfaces com o usuário mais vistosas, introduzida no .Net Framework 3.0. Existem dois grandes problemas: o modelo de programação é muito diferente do Windows Forms e exige bastante do hardware. É parte integrante do Windows Vista, Windows Server 2008 e sucessores e pode ser adicionado ao Windows XP SP2 e Windows Server 2003.

A WPF impõe uma decisão ao desenvolvedor: Windows Forms ou WPF. Escolhido um caminho, passar para o outro é uma tarefa complicada.

A necessidade de compatibilidade com máquinas mais antigas e a curva de aprendizado da WPF fizeram com que a grande maioria dos desenvolvedores ficassem no Windows Forms. É mais uma coisa que poderá mudar com a aceitação do Windows 7.

quarta-feira, agosto 26, 2009

TechEd 2009 - Dia Um

Depois de dois anos de ausência, estou novamente assistindo um TechEd da Microsoft. Este post tem um certo ar nostálgico, visto que o TechEd 2005 foi objeto de um dos primeiros posts deste blog (os posts do TechEd 2005 e 2006 estão aqui).

O evento mudou de lugar mais uma vez. Desta vez está na UNIP Vergueiro, que tem a vantagem de estar bem próxima do metrô, porém as instalações não são as mais apropriadas para um evento deste porte. Por exemplo, não tem um auditório onde cabe todo mundo. As salas da sessões (tracks) são salas de aula com carteiras não muito confortáveis e capacidade às vezes limitadas.

Outra diferença em relação aos eventos anteriores é que para almoço tem um "MS Lanche Feliz" - uma caixinha com um sanduiche, uma fruta e um doce. O meu lado pão duro falou mais alto e dispensei esta refeição na hora da inscrição, pois custava R$25 por dia.

Na manhã do primeiro dia teve a General Session, um conjunto de apresentações para todos os participantes. Quem se credenciou cedo ganhou um passe para o auditorio (na verdade um teatro) e pode ver as apresentações ao vivo, os demais assistiram a transmissão em telões e outras três salas. A apresentação começou com um blá-blá-blá mais tradicional e morno, mas depois os especialistas da Microsoft se apresentaram vestidos de Tropa de Choque para apresentações técnicas sobre os lançamentos para este ano e o começo do ano que vem. Alguns instantes os berros incomodaram um pouco, mas no geral foi bastante divertido e muito melhor que aquelas monótonas leituras de PowerPoint.

Uma brincadeira feita durante as apresentações foi uma competição para formatar um texto, gerar um gráfico a partir de uma planilha e fazer uma apresentação curta, utilizando Google Docs, BrOffice, MS Office 2007 e MS Office 2010. Não precisa dizer quem ganhou nem quem foi vítima de piadinhas, certo?

Depois teve algumas apresentações de futurologia. Começou com coisas mais próximas de acontecerem (como o projeto Natal) e terminou com um vídeo estiloso cheio de interações prá lá dos terminais de Minority Report.

Por último teve a premiação do concurso Win The 7.

No período da tarde assisti a três palestras:

Uma Comparação Estratégica Sobre as Tecnologias de Acesso a Dados

No começo da palestra, Luciano Condé mencionou algumas tecnologias da infância do VB: RDO e DAO. É realmente incrível a quantidade de tecnologias de acesso a dados criadas (e abandonadas) pela Microsoft. Depois destes tivemos ODBC e ADO (que nem foram mencionadas); a palestra se fixou nas quatro tecnologias atualmente suportadas na plataforma .Net: ADO.Net, LINQ, Entity Framework e ADO.Net Data Services. Uma palestra boa e sólida.

C# - Dicas, Truques e o Futura da Linguagem

Esta palestra me decepcionou um pouco, pareceu que o Alfred Myers não estava bem sintonizado com o assunto. A enfase foi nas novidades previstas para o C# 4.0. De dicas e truques acabou tendo pouco.

ASP.Net MVC com jQuery

Esta foi a boa surpresa. Escolhi esta palestra por eliminação (não me interessei pelas demais no mesmo horário), apesar de trabalhar muito pouco com programação Asp.Net. O tema da palestra não foi o que o título acima sugere. Giovanni Bassi dicutiu mais a questão de arquitetura, de um ponto de vista mais purista. Não poupou nem um pouco os Web Forms, que são a forma mais divulgada de desenvolvimento com ASP.Net. Alguns exemplos de colocação mais radical foram "desconfie de métodos com mais de cinco linhas" e "chamar diretamente um construtor é sinal de alerta". Radicalismos à parte, o que Giovanni apregoa são os princípios SOLID:
  • Responsabilidade única de cada classe e método
  • A capacidade de expandir uma classe sem alterar o seu código fonte
  • A preservação de pré-condições, pós-condições e invariantes na herança
  • A segregação de interfaces
  • Dependência baseada em abstrações ao invés de classes concretas
Esta pureza conceitual tem um custo na implementação (que é recuperado pela simplicidade de teste e manutenção). No exemplo apresentado, o número de módulos para implementar um programa subiu de 3 para sete.

Um outro ponto é que na implementação pura de MVC no ASP.Net deixa-se de utilizar os web controls, o HTML enviado ao browser é gerado de forma menos automática.

Em suma, uma palestra que questionou bastante a visão do desenvolvimento "instantâneo" de aplicações web na base do arrasta e cola.

terça-feira, agosto 25, 2009

Projetos com Sucesso - I

Gostaria muito de poder bater no peito e dizer que todos os projetos em que me envolvi na minha vida profissional tiveram pleno sucesso. Mas é claro que não foi assim. Como todo mundo, tive a minha cota de projetos problemáticos.

Nesta curta série de posts vou tentar listar algumas atitudes que acredito contribuirem para um projeto bem sucedido. Não são de forma alguma suficientes ou mesmo necessárias, mas são coisas que a minha vivência e o bom-senso me dizem aumentarem a probabilidade de um final feliz. Não falarei aqui de aspectos técnicos; eu ousaria dizer que eles são secundários frente às atitudes que vou mencionar.

Devo alertar que a minha experiência é predominantemente com projetos de software de um porte que chamo de "médio" (duração inferior a um ano com uma equipe de até três pessoas). É provável que estas ideias se apliquem a outros tipos de projeto, mas não posso afirmar por experiência própria.

Vou considerar três pontos de vista:
  • Da empresa sendo contratada para executar o projeto (empresa)
  • Da empresa que está contratando o projeto (cliente)
  • Do profissional alocado pela empresa para executar o projeto (desenvolvedor)
Nesta primeira parte vou falar um pouco de atitudes gerais aos três (que acabarei repetindo nas outras vezes).

Escopo Bem Definido

A primeira coisa importante é existir um escopo bem definido desde o momento da contratação. Uma fonte comum de aborrecimentos para todos os envolvidos são renegociações durante o andamento do projeto provocadas por divergências entre o que faz parte ou não da negociação inicial.

Pode parecer absurdo, mas negócios envolvendo valores significativos são fechados com frequência sem uma proposta formal. O combinado fica espalhado entre documentos desatualizados, e-mails escritos às pressas e a memória dos envolvidos.

Mesmo um documento formal pode ser pouco útil se não tiver uma descrição razoável do meu escopo. Um dos meus primeiros sustos como profissional, quando trabalhava em um fabricante de hardware, foi ser alocado para o projeto de um produto novo e descobrir que o contrato estipulava apenas o preço e a quantidade de peças. Não existia nem mesmo uma lista sucinta de características técnicas ou funcionais. Felizmente, este caso teve um final feliz graças a pessoas entusiasmadas e bem razoáveis dos dois lados. No entanto o risco foi imenso, bastaria ter uma pessoa menos flexível de um dos lados para surgirem questionamentos que o contrato não resolveria.

Comprometimento com o Término

Pode parecer óbvio que quando as duas partes fecham um negócio, e um desenvolvedor é alocado a um projeto, que todos estão interessados em conduzir o projeto até o final. Nem sempre isto acontece. Seja por "outras prioridades", brigas políticas internas ou simples "picuinhas", uma ou várias das partes pode se desinteressar do projeto. O projeto acaba se tornando um exercício de desatolar a vaca do brejo.

Se não existe um desejo forte de levar até o fim, é melhor nem começar. Vai poupar dinheiro e paciência de todos.

Pensar Em Todas As Etapas

Existe uma tendência a se concentrar em determinadas etapas do projeto e ignorar todas. Etapas tipicamente menosprezadas são testes, treinamento e implantação.

Ritmo e Acompanhamento

Um projeto médio é como uma prova de atletismo de meia distância: um ritmo bom e constante é muito melhor que alterar corridas desenfreadas e paradas. A forma de se verificar o ritmo é através do acompanhamento periódico do projeto.

Honestidade e Franqueza

Seja por insegurança, seja por má-fé, muitos projetos se afundam em meias-verdades e mentiras completas. Honestidade e franqueza requerem tanto coragem de quem fala como a compreensão de quem escuta.

Talvez seja ingenuidade minha esperar uma total honestidade; fico satisfeito se pelo menos mentiras irrelevantes forem evitadas.

Um Bom Projeto É...

Distinguir um bom de um mau projeto é mais ou menos como distinguir o lado bom e o lado negro da Força. Como diria Yoda, quando você está entusiasmado, calmo, receptivo a críticas e sugestões e percebendo as coisas andando, você está num projeto bom. Descaso, raiva, intolerância e a sensação de estar atolado sinais de um projeto ruim são.

segunda-feira, agosto 24, 2009

Construindo Uma Ponta de Prova Lógica

Uma ponta de prova lógica é um instrumento para medir o nível lógico (zero ou um) de um ponto de um circuito digital. Eu achava que não era muito útil, até sentir falta de uma quando fui depurar o meu Lunar Lander.

Encontrei na internet vários circuitos para montar uma ponta lógica; eu acabei selecionando este circuito de William Swanson, pela promessa de distinguir pontos desconectados. Os outros circuitos que examinei eram baseados em portas lógicas; este utiliza um amplificador operacional TL082.

O circuito é bastante simples e os componentes podem ser encontrados facilmente por alguns poucos reais. A parte desafiadora está em fazer um montagem compacta. No meu caso, decidi montar o circuito dentro de uma canetas que ganhei de brinde em algum evento. A foto abaixo mostra as peças utilizadas:

O primeiro passo foi desmontar a caneta:

Resolvi montar o circuito em tiras de plástico, cortadas de um cartão. Estas tiras encaixam nas partes de cima da caneta. O CI (com as pernas cortadas) foi preso com uma fita dupla face. Os resistores e os LEDs foram presos com uma pistolinha de cola quente. A ponta é uma das pernas cortadas do LED e também foi presa com cola.

As ligações foram feitas com fio de wire-wrap. Uma dificuldade é que ao demorar muito para fazer uma solda a cola amolece.

Soldados os circuitos, é hora de encaixar na parte de cima da caneta e interligar as duas partes. Os dois fios à esquerda estão ligados às garras "jacaré" que alimentarão o circuito.

Em seguida é hora de soldar o fio que vem da ponta e delicadamente fechar a caneta.

O resultado final ficou até simpático:

Que tal foi o resultado? Satisfatório. Alguns detalhes para quem for reproduzir o projeto:
  • Como os LEDs verde e vermelho tem características diferentes, as luminosidades não ficaram iguais. Talvez tivesse sido melhor conectar um resistor a cada LED ao invés de colocar os dois LEDs em paralelo e ligados ao resto do circuito por um único LED.
  • O posicionamento dos LEDs ficou ruim, dificultando a visibilidade.
  • O circuito é bem sensível, por exemplo acende se você encostar o dedo ou conectar um fio comprido (que vai funcionar como antena). Portanto nem sempre um LED aceso indica que o ponto está conectado corretamente ou apresenta um sinal lógico válido.

sábado, agosto 22, 2009

Links: Jogos Livres, Livro Grátis e Notícias Diversas

Alguns links interessantes que encontrei revendo o histórico da semana passada:

Jogos Livres

http://www.osnews.com/story/22021/Some_of_the_Best_Free_Linux_Games

Embora tenha Linux no título do artigo (em inglês), os jogos que eu examinei também estavam disponíveis para Windows. Alguém já reparou que todos os "melhores jogos livres" tem descrição do tipo "clone de xxxx", "jogo semelhante a yyyy"? É muito difícil achar algo inovador. Se bem que isto vale também para os jogos comerciais.

Livro Grátis: O Homem que Calculava

http://www.cdb.br/prof/arquivos/17272_20080312114624.pdf

Encontrei este link no blog Bendita Matemática, não encontrei nenhuma referência sobre a legalidade ou ilegalidade do arquivo. O que não se duvida é a qualidade do livro, que me encantou na infância. Tanto no blog como no final do arquivo tem um pouco da incrível história do autor.

Grátis - Mas Nem Tanto

http://www.theregister.co.uk/2009/08/20/hp_windows_7_upgrade/

Com a iminência do lançamentos do Windows 7, os fabricantes de PC estão oferecendo atualização "grátis" para quem comprar agora micro com o Vista. Grátis, mas nem tanto. O artigo acima (em inglês) conta quanto a HP está cobrando de frete de alguns clientes na Inglaterra: mais de 20 libras por cópia!

The Beatles - O Jogo

http://www.estadao.com.br/noticias/tecnologia+link,beatlemania-digital,2938,0.shtm

Sempre achei um pouco tolo estes jogos de "tocar música" com alguns botões em uma guitarra de plástico, mas a introdução do jogo tem uma qualidade gráfica à altura da trilha sonora.

O longo artigo acima, tradução de texto do The New York Times Magazine, fala um pouco do trabalho para preparar as músicas e o jogo.

Falha de Segurança Antiga Encontrada no Linux

http://www.theregister.co.uk/2009/08/14/critical_linux_bug/

Uma falha séria de segurança foi encontrada no Linux - e está presente há oito anos (artigo em inglês).

Apple Vendendo Menos Para Estudantes

http://www.theregister.co.uk/2009/08/19/apple_losing_out_to_netbooks/

A fonte da pesquisa não é das mais confiáveis, mas o resultado faz sentido: com a crise econômica os estudantes estão procurando micros mais baratos - o que significa netbooks e/ou Windows. Com o MacBook mais barato custando mais de $900, a Apple estaria perdendo clientes. Ou talvez a campanha "Laptop Hunters" esteja fazendo efeito. Também em inglês.

E a Novela do Windows "Europeu" Continua

http://www.osnews.com/story/22020/Mozilla_Not_Satisfied_with_Microsoft_s_Browser_Ballot_Proposal

Agora é a vez da Fundação Mozilla reclamar da proposta da tela de votação de browser. Como o autor do artigo (em inglês) eu fico chateado de ver justo a Mozilla, que conseguiu emplacar o browser na base da qualidade, ficar choramingando sobre a ordem de apresentação dos ícones.

O Escritório Virtual

http://marketplace.publicradio.org//display/web/2007/09/11/virtual_office/

Empresas estão oferecendo escritórios "de mentirinha" para empresários que controlam suas operações de casa (ou do boteco da esquina). Se o cliente ligar ou aparecer lá, vai ouvir sempre que "o dono não está no momento, quer deixar recado?". Pensando bem, pode ser que já exista este serviço por aqui... (artigo em inglês).

sexta-feira, agosto 21, 2009

Compactação - Parte 7

Fechando esta série de posts, vamos ver como usar a zlib no .Net. A empresa Component Ace adaptou a zlib para C#, gerando assim uma versão 100% gerenciada (managed). O resultado está disponível gratuitamente aqui, com uma licença BSD-like (semelhante à da própria zlib).

Para usar a zlib.net, basta copiar o arquivo zlib.net.dll e referenciá-lo no seu projeto.

O coração da zlib.net são as funções de compactação e descompactação com o encapsulamento zlib (o encapsulamento gzip não é suportado), que estão nas classes Deflate e Inflate. A classe ZStream por sua vez encapsula estas duas. Os métodos destas classes são equivalentes às funções que vimos na parte anterior e portanto o código fica muito semelhante:
// Compacta Arquivo
// Usa diretamente a classe Deflate
private void btnCompacta_Click(object sender, EventArgs e)
{
const int bufsize = 30000;
int flush = zlib.zlibConst.Z_NO_FLUSH;
byte[] bufIn = new byte[bufsize];
byte[] bufOut = new byte[bufsize];
FileStream inFS = new FileStream(txtOrigem.Text, System.IO.FileMode.Open);
FileStream outFS = new FileStream(txtDestino.Text, System.IO.FileMode.Create);
zlib.ZStream z = new zlib.ZStream();

z.deflateInit(zlib.zlibConst.Z_DEFAULT_COMPRESSION);
do
{
z.avail_in = inFS.Read(bufIn, 0, bufsize);
z.next_in_index = 0;
z.next_in = bufIn;
if (z.avail_in == 0)
flush = zlib.zlibConst.Z_FINISH;
do
{
z.avail_out = bufsize;
z.next_out_index = 0;
z.next_out = bufOut;
z.deflate(flush);
outFS.Write(bufOut, 0, bufsize - z.avail_out);
} while (z.avail_out == 0);
} while (flush != zlib.zlibConst.Z_FINISH);
z.deflateEnd();
outFS.Close();
inFS.Close();
}
A zlib.net implementa ainda uma classe ZOutputStream que deixa o processo de compactação ou expansão transparente, como mostra a rotina abaixo:
// Expande arquivo
// Utiliza ZOutputStream
private void btnExpande_Click(object sender, EventArgs e)
{
int len;
const int bufsize = 30000;
byte[] buffer = new byte[bufsize];
FileStream outFS = new FileStream(txtDestino.Text, System.IO.FileMode.Create);
zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFS);
FileStream inFS = new FileStream(txtOrigem.Text, System.IO.FileMode.Open);
while ((len = inFS.Read(buffer, 0, bufsize)) > 0)
{
outZStream.Write(buffer, 0, len);
}
outZStream.Flush();
outZStream.Close();
outFS.Close();
inFS.Close();
}
Obs.: para usar ZOutputStream para compactar, especifique o nível de compressão no construtor (o que não é muito intuitivo).

O projeto completo do teste, para o Visual Studio 2005, está aqui.

quinta-feira, agosto 20, 2009

Sete coisas que o Windows 7 pode aprender com o Linux?

Via OSNews, cheguei a um artigo que lista sete coisas que o Windows 7 poderia aprender com o Linux (na opinião do autor, é claro). Não tenho muita vivência com o Linux, mas me arrisco abaixo a examinar a lista do ponto de vista de alguém que é usuário e desenvolvedor de aplicações para o Windows.

Lançamento Mais Frequente de Versões

Resposta curta: Não!

De certa forma podemos dizer que a Microsoft tem feito isto de forma discreta (e gratuita), através dos Services Packs. E pagar por um service pack deixa um gosto amargo na boca (alguém se lembrar do Win98 SE?).

Para as médias e grandes empresas, atualizar o sistema operacional é uma operação de guerra. Requer planejamento, preparação, execução e estabilização. Se tiver que fazer isto ano sim ano não, metade do pessoal de TI enfarta.

Do ponto de vista dos desenvolvedores, é preciso lembrar que a substituição de versões "no campo" é uma coisa bastante lenta. Ainda encontramos clientes apegados a coisas antigas como Windows 2000 e IE 6. Isto complica os testes e o suporte.

O fracasso do Vista deu um bom respiro para os profissionais de TI e para os desenvolvedores, quem sabe algum dia alguém consegue medir tudo o que se conseguiu fazer graças a ele.

Acho que uma nova versão a cada quatro ou cinco anos está de bom tamanho. Não pressiona demais TI e desenvolvedores e dá oportunidade de fazer e testar um conjunto significativo de novas funcionalidades e aperfeiçoamentos.

Identificação Mais Sensata para as Versões

Resposta curta: nada para ver aqui, siga em frente.

Do ponto de vista do desenvolvedor, a versão do Windows se resume (para a maioria das aplicações) a dois números: MajorVersion e MinorVersion.

Acontece que a identificação das versões saiu do Desenvolvimento faz muito tempo e foi parar no Marketing. Talvez até antes de 1980, quando George Tate criou um sócio fictício, chamou a empresa de Aston-Tate e lançou o DBase II sem nunca ter existido um DBase I. Parece ridículo, mas deu certo.

É claro que eu gostaria que a Microsoft (e outros) seguisse sempre a mesma lógica para identificar as versões para o mercado, mas é claro que isto não vai acontecer.

Atualizações On-Line

Resposta curta: ok para Windows, nem tanto para aplicações.

Isto já ocorre com os Service Packs. Somente duas coisas seguram a disponibilidade das novas versões como download: o medo (bobo) da pirataria e a não universalidade de banda larga de verdade.

No que diz respeito a aplicações de terceiros, fico muito em dúvida. Como usuário, é bom encontrar todos as atualizações em um único local. Como desenvolvedor, fico receoso. Alguém será responsável pelo repositório de aplicações e isto representa um grande poder e uma grande responsabilidade. Não gostaria de algo como a App Store da Apple para os aplicativos de PC.

Melhor Integração de Aplicações com a Web

Resposta curta: Hã?

Não entendi bem este ponto. O Windows Vista já tem um esquema de Gadgets para o desktop. E ele se "integra com a Web" da mesma forma que a maioria das soluções "Web 2.0": usando JavaScript, sem precisar de "KDE hackers". E será que já tem alguns gadgets para download por aí?

Suportar Ambientes Abertos de Desenvolvimento

Resposta curta: Hã?

Ou o meu inglês está ruim ou estão faltando algumas palavras no texto do artigo...

De qualquer forma, o que se espera da Microsoft é que ela crie e documente interfaces do programação no Windows que possam ser usadas pelos mais diversos ambientes de desenvolvimentos. Apesar de alguns escândalos no início da história do Windows (os bons tempos do Undocumented Windows) a maioria das interfaces estão aí para quem quiser usar. E são usadas por uma grande quantidade de ambientes de desenvolvimento, tanto abertos como fechados.

Emagrecer Para o Mundo Móvel

Resposta curta: Em termos.

O que o texto sugere (emagrecer, deixar modular, etc) já foi feito no final do século passado, resultando no Windows CE. Que foi projetado sim para notebooks pequenos (os H/PC). O que se viu na prática é que os usuários relutam em abrir mão dos recursos do Windows completo (o que continua a segurar o mercado dos netbooks). Não custa lembrar que o próprio Linux cresceu bastante também e que este é um dos motivos de muitos netbooks optarem por distribuições específicas.

O Windows 7 requer bem menos do computador que o Vista; por outro lado a capacidade dos netbooks continua crescendo. Eu prefiro aguardar até o final do ano antes de dar uma palavra final.

Melhor Suporte a Dispositivos

Resposta curta: Em termos.

É no mínimo curioso ver isto, quando uma das reclamações mais frequentes que vejo é que os fabricantes de dispositivos não suportam o Linux.

Enfim, a questão é: de quem é a responsabilidade de desenvolver drivers - o desenvolvedor do sistema operacional ou o fabricante do dispositivo?

Minha expectativa é que um sistema operacional venha com os drivers para os dispositivos padronizados ou mais populares. Me parece exagerado esperar que ele venha com drivers para dispositivos muito antigos ou extremamente específicos. Por outro lado, devem existir recursos (bibliotecas, documentações, ferramentas, exemplos) que simplifiquem a tarefa de quem quiser desenvolver drivers. Não tenho experiência com isto, mas o pessoal que mexe com isto não parece muito insatisfeito com a Microsoft.

O que complica no caso do Windows (e não sei como é nos outros SOs) é que o formato dos drivers mudou várias vezes. Se por um lado isto significa aperfeiçoamento do modelo, por outro significa que drivers para uma versão antiga não servem para uma versão mais nova. Neste ponto o Windows 7 se beneficia da compatibilidade de drivers com o Vista (até onde eu sei).

A maioria dos relatos que eu tenho visto mencionam que o Windows 7 está muito melhor que o Vista neste aspecto, com os drivers sendo encontrados na maioria dos casos no disco de instalação do Windows.

quarta-feira, agosto 19, 2009

Compressão - Parte 6

Agora é hora de deixar para traz o meu código amador e dar uma olhada em uma biblioteca profissional de compactação, a zlib.

A zlib foi escrita por Jean-loup Gailly (compressão) e Mark Adler (expansão), autores do utilitário gzip do GNU. A zlib implementa o algoritmo Deflate que surgiu com a versão 2 do PKZIP e é usado no gzip.

O algoritmo Deflate se baseia no LZ77, que vimos mencionei na parte 1 desta série. Recordando, o LZ77 procura codificar os dados procurando-os em uma "janela" que desliza sobre eles. Ao encontrar uma repetição, o LZ77 os codifica como um deslocamento dentro da janela e no tamanho. Na zlib, esta janela tem 32KBytes.

O resultado da codificação LZ77 passa então por uma codificação de Huffman (que também mencionei na parte 1), na qual se utilizam códigos de tamanho variável associando os códigos menores ao mais usados. A codificação de Huffman se baseia em árvores binárias; a mesma árvore precisa ser usada para compactar e expandir.

Durante a compactação a zlib vai dividindo os dados em blocos. Em cada bloco pode ser usado um dentre três variações do algoritmo:
  • Não compactar (ideal para o caso dos dados já estarem compactados)
  • LZ77 seguido de Huffman com uma árvore fixa pré-definida (que não precisa ser passada para o expansor)
  • LZ77 seguido de Huffman com uma árvore específica (que precisa ser gravada/transmitida junto com os dados)
Os detalhes do Deflate podem ser encontrados aqui, no site oficial da zlib. Este algoritmo é hoje um padrão de facto e também um padrão da internet (RFC 1951)

A zlib é basicamente um conjunto de fontes em C, com uma licença bem liberal. De forma resumida, você pode usar e modificar à vontade (inclusive em softwares comerciais), desde que você deixe claro que não é o autor do software original e que versões alteradas não são as versões originais.

Além dos fontes, o site oficial possui para download uma DLL para Windows 32 bits. Existem várias versões binárias não oficiais para diversos sistemas operacionais e uso com as mais variadas linguagens. Os programadores Java talvez saibam que a zlib está disponível no JDK desde a versão 1.1 (ver java.util.zip) e que é usada no formato JAR. Para os programadores .Net está disponível uma versão totalmente reescrita em código gerenciado, que veremos na próxima (e provavelmente última) parte.

Vamos ver agora como usar a zlib em um programa C. A documentação oficial está no fonte zlib.h ("por enquanto").

O formato dos dados comprimidos através da zlib tem duas partes: os dados compactados em si (o deflate stream, especificado na RFC 1951) e o seu encapsulamento (que pode ser o formato zlib, definido na RFC 1950, ou o formato gzip, definido na RFC 1952). O encapsulamento zlib é voltado para manipulação dos dados em memória, o formato gzip é voltado à compactação de arquivos e usa um cabeçalho maior que guarda informações sobre o arquivo. Vou apresentar aqui exemplos apenas do encapsulamento zlib, junto com os fontes da zlib tem o minigzip.c que mostra o uso do encapsulamento gzip.

A compressão com encapsulamento zlib é feito pela rotina deflate. Esta rotina trabalha com dois buffers, um de entrada e outro de saída. No começo você carrega o início dos dados a compactar no buffer de entrada; o buffer de saída está vazio. Quando você chama deflate, ela processa os dados no buffer de entrada e vai colocando os dados compactados no buffer de saída, até que o buffer de entrada fique vazio ou o buffer de saída fique cheio. No primeiro caso você precisa recarregar o buffer de entrada e no segundo você precisa gravar os dados no buffer de saída. Uma forma de gerenciar isto é colocar um laço que processa o buffer de entrada e grava o buffer de saída até acabar os dados no buffer de entrada dentro de um segundo laço que carrega o buffer de entrada até chegar ao fim dos dados. O final dos dados deve ser sinalizado para deflate, para que ela "cuspa" os dados que ainda estavam em compactação.

Além de deflate é preciso chamar no início uma rotina de iniciação (deflateInit) e no final uma rotina de encerramento (deflateEnd). Em deflateInit especifica-se o nível de compactação desejado, 0 é sem compactação, 1 é a compactação mais rápida (e menos eficiente) e 9 a mais lenta (e mais eficiente). O estado de todo o processo é guardado em uma estrutura z_stream, que é passada para todas as rotinas. Alguns campos desta estrutura devem ser iniciados antes mesmo de deflateInit.

A rotina abaixo, adaptada do exemplo zpipe.c, efetua a compactação de um arquivo; por simplificação retirei todo o tratamento de erro:
void CompactaZlib (char *origem, char *destino)
{
FILE *fpIn, *fpOut;
z_stream strm;
unsigned flush;

// abre arquivos
fpIn = fopen (origem, "rb");
fpOut = fopen (destino, "wb");

// inicia compactação
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit (&strm, Z_DEFAULT_COMPRESSION);

// compacta até acabar o arquivo origem
do
{
strm.avail_in = fread (bufIn, 1, T_BUF, fpIn);
strm.next_in = bufIn;
flush = feof(fpIn) ? Z_FINISH : Z_NO_FLUSH;

/* compacta e grava até sobrar espaço no buffer de saída */
do
{
strm.avail_out = T_BUF;
strm.next_out = bufOut;
deflate (&strm, flush);
fwrite (bufOut, 1, T_BUF - strm.avail_out, fpOut);
} while (strm.avail_out == 0);
} while (flush != Z_FINISH);


// finaliza a compactação
deflateEnd (&strm);

// fecha arquivos
fclose (fpOut);
fclose (fpIn);
}
Rodando este código sobre o meu arquivo de teste, obtemos um arquivo com 38K usando a compactação default (nível 6), o que é o mesmo que obtemos com o PKZip.

A expansão do arquivo compactado é bem semelhante. É preciso indicar que o buffer de entrada está vazio antes de chamar a rotina de iniciação; o final do arquivo é indicado pela rotina de expansão (deflate).
void ExpandeZlib (char *origem, char *destino)
{
FILE *fpIn, *fpOut;
z_stream strm;
unsigned ret;

// abre arquivos
fpIn = fopen (origem, "rb");
fpOut = fopen (destino, "wb");

// inicia expansão
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
inflateInit (&strm);

// expande até acabar o arquivo origem
do
{
strm.avail_in = fread (bufIn, 1, T_BUF, fpIn);
strm.next_in = bufIn;

/* compacta e grava até sobrar espaço no buffer de saída */
do
{
strm.avail_out = T_BUF;
strm.next_out = bufOut;
ret = inflate(&strm, Z_NO_FLUSH);
fwrite (bufOut, 1, T_BUF - strm.avail_out, fpOut);
} while (strm.avail_out == 0);
} while (ret != Z_STREAM_END);


// finaliza a compactação
inflateEnd (&strm);

// fecha arquivos
fclose (fpOut);
fclose (fpIn);
}
O projeto Visual C com as rotinas acima está aqui.

sábado, agosto 15, 2009

DVD do Mês: The Beach Boys - Good Timin' - Live at Knebworth

Várias coisas me fizeram pensar nos Beach Boys recentemente, como o fato do Captain de Captain&Tennille ter sido tecladista deles e o meu filho estar ouvindo "Barbara Ann" outro dia.

Embora eu conheça o básico da história dos The Beach Boys, até então eu nunca tinha me interessado por ter um CD ou DVD deles. Resumindo a história (que você encontra na Wikipedia): The Beach Boys foi fundado no começo dos anos 60 por três irmãos (Brian, Carl e Dennis Wilson), mais um primo (Mike Love) e um amigo (Al Jardine) e fizeram sucesso cantando rock-and-roll com belas harmonias vocais e temas como surf, carros e garotas. Embora fossem se aprimorando, suas músicas eram do tipo mais superficial.


Até que Brian escutou Rubber Soul e decidiu fazer "o melhor album de rock de todos os tempos". E com isto surgiu Pet Sounds, que se não é "o melhor" é "um dos melhores". A partir daí as coisas se complicaram. Brian teve problemas mentais e dependência de drogas e acabou se afastando da banda de 69 a 75. A direção dada por Brian pra Pet Sounds não era consenso no grupo, Mike Love em particular preferia manter a fórmula vencedora. Dennis Wilson se afundou em problemas pessoais e drogas e acabou morrrendo de forma estúpida em 83. Carl Wilson se foi em 98, vítima de cancer. O restante do grupo acabou se dividindo em três e nunca mais chegou perto do auge do seu sucesso.

Meu primeiro impeto foi procurar para comprar o CD de Pet Sounds. Para minha surpresa, não encontrei nas lojas nacionais. Por outro lado encontrei o DVD Good Timin' - Live at Knebworth England, 1980. É o registro da última vez que o grupo orginal se apresentaria completo na Inglaterra (ainda fez alguns shows nos EUA após isto). Brian estava de volta, pelo menos fisicamente. Uma curiosidade é que encontrei na Americanas duas opções: o DVD sozinho e, por R$2 adicionais, o DVD mais o CD.

O DVD contem um quantidade grande de músicas, cobrindo os princiapis sucessos do grupo. Além das composições próprias, destaque para as de Chuck Berry: School Days, Rock&Roll Music e Surfin' USA (que é Sweet Little Sixteen com outra letra).

Gostei mais das músicas mais elaboradas, como God Only Knows e Good Vibrations (ambas da época de Pet Sounds). Tem algumas músicas bem animadas (como School Days, Surfin' USA, Barbara Ann e Fun, Fun Fun) mas algumas me pareceram bastante bobinhas (Be True To Your School, Little Deuce Coupe, por exemplo). Brian parece estar somente fisicamente ali, como se a cabeça estivesse em outro lugar.

Para quem quiser ter uma ideia do som deles, algum vídeos do You Tube (não são do show do DVD):

http://www.youtube.com/watch?v=BC_UILNwWrc
http://www.youtube.com/watch?v=nC2gZMNkyJo
http://www.youtube.com/watch?v=654H4xfDYKM

Veredito

Recomendando, mas não imperdível.

quinta-feira, agosto 13, 2009

Guia de Sobrevivência na Migração para o Firefox 3.5

Há um bom tempo o Firefox é o meu navegador principal. Esta semana finalmente resolvi adotar a versão mais recente (3.5) nos meus micros de casa e do trabalho. Eu já tinha atualizado o meu notebook e reparado na necessidade de alguns ajustes, mas não tinha tido ainda o tempo de ir atrás.

Instalando o Firefox 3.5

O primeiro passo é simples: baixar o instalador do Firefox 3.5 (por exemplo de http://www.mozilla.com/firefox/) e executá-lo. Eu prefiro a instalação custom, para poder selecionar onde serão colocados os atalhos. Apesar de usar quase que exclusivamente o Firefox, não costumo colocá-lo como browser padrão.

A instalação é tranquila. Se você já tinha uma versão anterior instalada, não é preciso removê-la e as configurações são mantidas. No micro de casa foi preciso reiniciar o Windows para concluir a instalação.

Verificando a Compatibilidade dos Add-Ons

Um dos atrativos do Firefox são os inúmeros add-ons. Na primeira vez que o Firefox 3.5 roda após uma atualização, ele verifica a compatibilidade dos add-ons que já estavam instalados. No caso de alguma incompatibilidade, ele se oferece para verificar se existe uma atualização compatível. Os add-ons incompatíveis são desligados.

A atualização dos add-ons exigiu alguns cuidados adicionais.

Vero

O verificador ortográfico Vero, do BrOffice, é quem tenta me impedir de cometer erros crassos de ortografia. Infelizmente, ele não fica no repositório de Add-ons da Mozilla e portanto o Firefox não encontra automaticamente suas atualizações.

É preciso pegá-lo na mão de http://www.broffice.org/verortografico/baixar.

Aliás, para quem nunca percebeu, um add-on é baixado na forma de um arquivo com extensão xpi. Este arquivo pode ser salvo e depois instalado através do menu File | Open File do Firefox. Isto foi útil no trabalho onde estou com algum problema no acesso ao site de Add-ons da Mozilla.

G-Buster Browser Defence do Unibanco (Guardião 30 Horas)

Não sei bem se é uma vantagem o fato de precisar instalar um Add-on para poder ver o extrato do meu cartão de crédito, mas o Unibanco exige isto. Para atualizar é preciso acessar a página do Unibanco. E (pelo menos neste momento) ela tem um problema de formatação com o Firefox 3.5.

Fast Dial

Apesar de alguns problemas, continuo viciado nesta extensão. Eu estava propositalmente utilizando uma versão antiga, mas ela é incompatível com o Firefox 3.5. O jeito foi atualizar para a mais recente.

A página de informações sobre o Fast Dial informa que alguns usuários relataram problemas com a versão mais recente e que o desenvolvedor está doente e portanto ainda não teve a oportunidade de examinar a questão. Por enquanto não tive problemas.

A instalação da versão mais recente do Fist Dial exigiu alguns ajustes de configuração no PC do trabalho (onde estava com uma versão bem antiga). Nos dois micros, parte das imagens (thumbnails) foram atualizadas; no caso do site do Estadão as regiões da tela onde tinha uma animação flash foram pintadas de preto.

Botão de Fechar em Todas as Abas

Com o meu vício pelo Fast Dial, é comum fechar a última aba para forçar a apresentação de uma nova aba com o Fast Dial. Isto não é possível no Firefox 3.5 padrão, pois o botão de fechar não é apresentado na última aba.

Felizmente, existem instruções de como acertar isto nos forum de suporte do Firefox (aqui).

O aviso acima foi capturado diretamente da tela do Firefox: você pode fazer grandes estragos mexendo nas configurações. Siga em frente por sua conta e risco e se algo der errado não ponha a culpa em mim.

O primeiro passo é acertar duas configurações. Para acessar elas, digite "about:config" (sem as aspas) na barra de endereço. Mude browser.tabs.closeWindowWithLastTab para false, paraa que a janela não seja fechada quando fechar a última aba. Verifique que browser.tabs.closeButtons é 1, para que todas as abas tenham o botão de fechar.

Passamos agora para a parte mais complicada, que é criar ou alterar o arquivo userChrome.css. Este arquivo deve ficar na sua pasta de perfil, que no Windows XP será algo como

C:\Documents and Settings\Daniel\Application Data\Mozilla\Firefox\Profiles\f0siucv8.default\chrome

(é claro que no lugar de Daniel vai estar o seu nome).

Se o arquivo não existir, crie com o seguinte conteúdo:
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */

/* Show Close Button On Last Tab */
.tabbrowser-tabs[closebuttons="alltabs"] > .tabbrowser-tab > .tab-close-button {
display: -moz-box !important;
}
.tabbrowser-tabs:not([closebuttons="noclose"]):not([closebuttons="closeatend"]) > .tabbrowser-tab[selected="true"] > .tab-close-button {
display: -moz-box !important;
}
Se o arquivo já existir, basta procurar a linha @namespace e colocar o texto acima (menos a linha @namespace) após a linha já existente.

Re-inicie o Firefox e o botão de fechar voltará a aparecer na última aba.

quarta-feira, agosto 12, 2009

Compactação - Parte 5

Concluindo as mexidas com o meu código, implementei as seguintes alterações:

Código de tamanho variável

Ao invés de usar um tamanho fixo de 12 bits, o programa compactador começa gravando códigos de 9 bits e vai aumentando conforme necessário. Para facilitar as coisas no lado da expansão, o compactador grava dois códigos especiais, um para indicar que o tamanho do código foi aumentado e outro para indicar o fim do arquivo.

Códigos de 16 bits

Uma vez que memória não é problema nos dias de hoje (e quase ninguém sabe o quanto era complicado acessar uma tabela com mais de 64Kbytes no PC), é trivial aumentar o tamanho do código de 12 para 16 bits.

Qual o resultado de tudo isto?
  • O meu texto de teste tem 172K.
  • Compactando com códigos fixos de 12 bits, o arquivo compactado tem 74K.
  • Compactando com códigos variáveis de até 12 bits, o arquivo compactado tem 73K. O ganho é pequeno, pois a tabela enche rapidamente e os códigos pequenos são usados por pouco tempo.
  • Compactando com códigos fixos de 16 bits, o arquivo compactado tem 62K. Apesar de cada código ser 1/3 maior, a tabela maior permite guardar mais sequências, propiciando uma compactação melhor.
  • Compactando com códigos variáveis de até 16 bits, o arquivo compactado fica com 54K. Ainda não chegou ao nível do PKKip (38K), mas avançamos bastante do ponto inicial.
O código completo está aqui.

A Seguir

No próximo post desta série vamos examinar uma excelente biblioteca livre para compactação, a zlib.

terça-feira, agosto 11, 2009

CodeJam 2009: Inscrições Abertas

Estão abertas desde ontem (10/08/2009) as inscrições para o CodeJam 2009. O último dia para se inscrever é 3 de setembro (com a rodada de qualificação já em andamento).

O esquema é semelhante ao do ano passado. Cada rodada terá de 3 a 6 problemas. Para cada problema existirão dois conjuntos de dados, um pequeno e um grande. Tradicionalmente os conjuntos grandes são feitos de forma a inviabilizar soluções "força bruta".

Serão feitas cinco rodadas:

Rodada de Qualificação

Das 20:00* de 02/09/09 às 20:00 de 03;09/09, com 3 problemas. Você precisa resolver um conjunto pequeno e um grande de qualquer problema dentro destas 24 horas para passar para a fase seguinte.

Primeira Rodada Online

Será dividida em três sub-rodadas, cada uma com 2:30 de duração, das quais você poderá participar até de duas: 11/09/09 às 22:00, 12/09/09 às 13:00 e 13/09/09 às 06:00. Os primeiros 1000 de cada subrodada passam para a rodada seguinte (se você passar na primeira tentativa, não poderá participar da segunda).

Segunda Rodada Online

Será em 26/09/09 às 13:00, com duração de 2:30. Os 500 melhores avançam.

Terceira Rodada Online

Será em 10/10/09 às 13:00, com duração de 2:30. Os 25 melhores vão para a fase final.

Final Onsite

Na sexta-feira 13 de novembro, os 25 melhores enfrentam o teste final na sede da Google. O primeiro colocado ganha um prêmio de US$5000,00.

Detalhes no site oficial (http://code.google.com/codejam/).


* todas as horas no horário de Brasília, se não errei as contas.

sexta-feira, agosto 07, 2009

Solução do Problema de Ontem

Apresento aqui uma solução resumida do problema de ontem. Não pensem que eu achei a solução completa e clara (como espero estar abaixo) de imediato; foi preciso pensar bastante e alguns detalhes só ficaram claros após ler os comentários no The Daily WTF.

O primeiro passo é fazer uma simulação na mão, por exemplo para dez armários:

Na figura acima, os * indicam os toques nos armários e os X indicam os armários que ficaram abertos no final. Deste exercício dá para intuir algumas coisas:
  • Se olharmos as colunas (armários) dá apra perceber que neste processo estamos tocando neles conforme os seus divisores.
  • Os armários que ficaram abertos correspondem aos "quadrados perfeitos" (quadrados exatos de um número inteiro).
  • A distância entre os ármários abertos vai crescendo conforme os números impares ou, se preferir, entre os armários abertos temos um número de armários fechados que correspondem aos números pares. (Isto talvez não seja tão evidente com apenas 10 armários).
Os dois últimos pontos são, por enquanto, hipóteses. Vamos aprofundar um pouco mais no primeiro ponto. Os armários que ficam abertos são os que tem um número impar de divisores, já que os pares de toque se cancelam.

Vamos pensar um pouco em como os divisores se distribuem e como podemos pareá-los. Se um número é divisível por a, ele será também divisível por n/a. Se um número n é divisível por a <= sqrst(n), é fácil perceber que n/a >= sqrt(n), onde sqrt é a raiz quadrada. Em outras palavras, os fatores se distribuem equilibradamente em torno da raiz quadrada. Por exemplo, considerando os fatores do número 6, podemos agrupá-los em (1,6) e (2,3). Já para o número 4, teremos o par (1, 4) e a raiz (2) isolada. Este raciocínio confirma a nossa hipótese de que os armários que ficam abertos são os quadrados perfeitos, e sugere a seguinte solução:
void Solucao1 (int n)
{
int i, max;

max = (int) floor(sqrt (n));
for (i = 1; i <= max; i++)
printf ("%d ", i*i);
}
E quanto à nossa intuição sobre a distãncia entre as portas abertas? Uma técnica muito útil quando queremos otimizar um algoritmo é fazer os cálculos de forma incremental, calculando o resultado seguinte a partir do anterior. No nosso caso, a fórmula para calcular (n+1)2 a partir de n2:

(n+1)2 = n2 + 2*n + 1

O que sugere uma segunda solução:
void Solucao2 (int n)
{
int i, num;

for (i = 1, num = 1; num <= n; num = num + (i << 1) + 1, i++)
printf ("%d ", num);
}
Esta segunda solução tem as vantagens de eliminar a raiz quadrada e a multiplicação (que ficou reduziada a um shift). Este tipo de técnica (cálculo incremental) é muito útil em processadores mais "fracos" como os que eram usados nos primeiros computadores pessoais ou presentes na maioria dos microcontroladores.

quinta-feira, agosto 06, 2009

Preparação para o CodeJam - de uma fonte inesperada

Estou encontrando alguns exercícios de programação em um local inesperado - no The Daily WTF. Há poucas semanas iniciou uma nova série, a Programming Praxis. Toda quarta é apresentado um problema e as soluções vão sendo postadas nos comentários.

Até agora os problemas foram relativamente simples (e com solução facilmente encontrável no Google); a enfase tem sido nas soluções em linguagens exotéricas. Mesmo assim, é um bom exercício.

Apresento abaixo uma adaptação livre (e preguiçosa) do problema de ontem, "Nerds, Jocks, and Lockers". Recomendo tentar resolver antes de olhar os comentários no The Daily WTF. Amanhã publico uma pequena explicação da solução.

Cabeções, Marombeiros e Armários

Sr Zargas era o professor de matemática que todos gostavam. Fosse você um cabeção ou um marombeiro, ele deixava a matemática interessante, desafiadora e divertida de aprender. E na "Guerra dos Armários" os marombeiros podiam usar os músculos - e ganhavam sempre dos cabeções.

As regras da "Guerra dos Armários" são simples. Em um corredor abandonado da escola, existiam cem armários vazios, um ao lado do outro. O problema é determinar quais armarios ficariam abertos se todos os armários forem fechados e depois tocados da seguinte forma (cada toque abre um armário fechado e fecha um armário aberto):
  • cada armário é tocado a partir do primeiro
  • cada segundo armário é tocado a partir do segundo
  • cada terceiro armário é tocado a partir do terceiro
  • ...
  • o centésimo armário é tocado
Os marombeiros resolviam o problema seguindo à risca as instruções acima e correndo de um lado para o outro contando armários.

Sua missão, jovem cabeção, é achar uma forma de determinar quais armários permanecem abertos sem fazer múltiplas passagens (ou seja, achar uma solução que não seja de "força bruta"), para o caso genérico de "n" armários.

terça-feira, agosto 04, 2009

Compactação - Parte 4

Neste post vamos examinar um pouco o que o programa do post anterior faz. Para isto vamos acrescentar à rotina de descompactação uma tabela para contar quantas vezes cada código é usado:
typedef struct
{
int cod; /**< código de compactação */
int contUso; /**< número de vezes que foi usado */
} ESTAT;

static ESTAT TabEstat [ULT_CODE+1]; /**< Estatística do uso dos códigos */
No começo da rotina Expande vamos iniciar esta tabela:
 for (prox = 0; prox <= ULT_CODE; prox++)
{
TabEstat [prox].cod = prox;
TabEstat [prox].contUso = 0;
}
E no final da Expande vamos chamar a rotina SalvaEstat(), que salva uma listagem das estatísticas em um arquivo:
static void SalvaEstat (void)
{
int topo;
FILE *fp;
int i, w;
uchar c;

fp = fopen ("Estatistica.txt", "wt");
for (i = 0; i < ULT_CODE+1; i++)
{
fprintf (fp, "Código 0x%03X, Usos: %d\n", TabEstat[i].cod, TabEstat[i].contUso);
topo = 0;
w = TabEstat[i].cod;
while (w >= 256)
{
if (topo >= sizeof(pilha))
{
printf ("Pilha insuficiente!\n");
exit (1);
}
pilha[topo++] = TabExp[w].car;
w = TabExp[w].prefixo;
}
pilha[topo++] = (uchar) w;
while (topo > 0)
{
c = pilha[--topo];
if ((c < 0x20) || (c > 0x7E))
fprintf (fp, "\\x%02X", c);
else if (c == 0x20)
fprintf (fp, ".");
else
fprintf (fp, "%c", c);
}
fprintf (fp, "\n\n");
}
}
Se olharmos os códigos 0x100 a 0x107 podemos ver o algorítimo em funcionamento com o início do meu texto de teste:
Programação Assembler no PC-IBM e compatíveis

Código 0x100, Usos: 5
Pr

Código 0x101, Usos: 52
ro

Código 0x102, Usos: 1
og

Código 0x103, Usos: 5
gr

Código 0x104, Usos: 60
ra

Código 0x105, Usos: 17
am

Código 0x106, Usos: 30
ma
É interessante notar como uma lógica simples (ir guardando o que for vendo na entrada) fez com fossem registrados alguns pares de letras bastante comuns, como 'ro', 'ra' e 'ma'.

Podemos alterar um pouco mais o programa para ver quais os códigos mais usados. Basta incluir no início de SalvaEstat uma chamada à rotina qsort e definir uma rotina de comparação:
qsort (TabEstat, ULT_CODE+1, sizeof(ESTAT), Compara);

static int Compara (const ESTAT* elem1, const ESTAT* elem2)
{
return elem2->contUso - elem1->contUso;
}
Os dez códigos mais usados são:
Código 0x158, Usos: 1365
====

Código 0xB9F, Usos: 574
\x0D\x0A..........

Código 0x046, Usos: 538
F

Código 0x041, Usos: 489
A

Código 0x020, Usos: 463
.

Código 0x228, Usos: 389
....

Código 0xFDF, Usos: 388
\x0D\x0A...............

Código 0xFCD, Usos: 346
\x0D\x0A\x0D\x0A........

Código 0xB30, Usos: 332
11

Código 0x02C, Usos: 325
,

No próximo post vamos fazer algumas mexidas para melhorar a taxa de compactação. Até lá!

domingo, agosto 02, 2009

Captain & Tennille - Alguém Se Lembra?

Estou, lentamente, digitalizando os meus CDs. Um dos que digitalizei recentemente foi Captain & Tennille - Greatest Hits.


Este CD me traz várias lembranças. É um CD importado, que eu comprei por impulso nos anos 90, quando estava "matando tempo" em uma loja por ter chegado extremamente cedo para um compromisso.

Eu conhecia Captain & Tennille da minha adolescência, de quando assistia TV2 Pop Show (um dos primeiros programas de videoclip que passava no fim de semana na TV Cultura aqui em São Paulo). Tinha até um compacto na casa dos meus pais, provavelmente comprado pelo meu irmão:


(é um compacto para vitrola, não um compact disc).

Uma busca rápida no Buscapé encontrou poucas opções da dupla em lojas nacionais. Na Videolar tem um CD com capa parecida mas com uma seleção diferente de músicas.

O tocador que eu ando usando, aTunes, sugere vários vídeos da dupla no YouTube. Alguns que eu gostei e dão uma boa ideia do som deles:

http://www.youtube.com/watch?v=BURIAZwJkPc

Esta é uma das músicas mais conhecidas deles. Esta versão (ao vivo) demonstra o carisma da Tennille. Tente contar quantos teclados eles estão usando!

http://www.youtube.com/watch?v=wEWU25aN67U

A mesma música, na cerimônia do Grammy. A participação dos fãs no telão é impagável!

http://www.youtube.com/watch?v=AF2SbVZoGyI

Mais uma música, do mesmo show que o primeiro vídeo.

http://www.youtube.com/watch?v=xBYV_7a0FQs

No auge do sucesso eles chegaram a ter um show na TV. Neste vídeo eles tocam Muskrat Love que, apesar de ter sido um grande sucesso, tem a triste fama de ter sido eleita uma da piores músicas pops de todos os tempos.

Entre várias curiosidades (que você encontra em detalhes na Wikiopedia) Daryl Gragon ganhou o apelido de Captain quando fazia parte da banda de apoio dos beach Boys e Tennille participou dos backing vocals do album "The Wall" do Pink Floyd e da faixa "Don't Let the Sun Go Down on Me" de Sir Elton Jonh.

Os dois continuam vivos e até lançaram um disco em 2007. O site oficial está aqui.