DevInCachu 2012

February 10, 2012

Este ano ocorrerá no dia 05 de maio a segunda edição do DevInCachu.

Temos muita honra de reunir no nosso modesto palco no interior do Espírito Santo grandes nomes como Klaus Wuestefeld e Paulo Silveira, apenas para citar alguns.

Dente os temas já confirmados, teremos Entrega Contínua, Boas práticas em OO, Computação Soberana, Cloud Computing, etc, tudo em um dia inteiro de aprendizado e networking.

A localização será a mesma do ano passado, no Centro Universitário São Camilo, campus do Bairro Paraíso, em Cachoeiro de Itapemirim.

As inscrições foram abertas ontem no valor de R$ 30,00, pagamento sendo feito via Pageguro, que opera com cartão, boleto, transferência online, etc.

Lista de palestrantes, grade, localização detalhada, inscrição e outras informações disponíveis no site do evento: devincachu.com.br

Para este ano, teremos duas novidades:
A primeira será a entrega de camisas do evento para todos os participantes. A segunda é que pretendemos realizar uma entrevista com os palestrantes, utilizando perguntas sugeridas e votadas por você! Para isso, basta acessar http://www.google.com/moderator/#16/e=1e4b60

0

TMS Aurelius – Novo ORM para Delphi

January 18, 2012

Antigamente, quando o Delphi estava a anos-luz de outras plataformas (hoje felizmente a distancia já diminuiu para alguns meses-luz) eu sempre dizia que primeiro a Embarcadero tinha que implementar coisas como RTTI e generics para que só então o Delphi começasse a ganhar alguns brinquedos legais que existem por exemplo em Java e .Net, “brinquedos” como bons frameworks ORM que não interfiram demasiadamente no design das classes de domínio. Dito e feito, hoje temos o DORM que já foi objeto de um post aqui e, mais recentemente, o TMS Aurelius.

Licenciamento e instalação

Infelizmente o Aurelius é uma ferramenta comercial, diferentemente do DORM, mas achei o seu custo bem acessível. Uma licença para um desenvolvedor sai por 156 euros até o dia 29/02, que na cotação de hoje (18/01/2011) dá aproximadamente R$ 356,00

Além disso, também é possível baixar um trial para experimentar. No trial a maioria das units não vem com os fontes, mas todas as funcionalidades do framework estão disponíveis. Sobre quanto por quanto tempo o trial permanece funcional, não encontrei nada a respeito.

A instalação é muito simples, é só baixar e executar um instalador NNF e assunto encerrado.

Documentação

Em relação à documentação, o Aurelius parece ser muito bem documentado. O pacote acompanha um PDF de 90 páginas que parece cobrir com um bom nível de detalhamento cada aspecto do framework.

Conectividade

Nesta versão, o Aurelius pode se conectar com DB2, Firebird, Interbase, SQL Server, MySQL, NexusDB, Oracle, PostgreSQL e SQLite, através de diferentes suites de componentes, como por exemplo AnyDac, dbExpress, SQLDirect, etc. Além disso, a documentação alega que o framework pode ser facilmente extendido para implementar suporte a outros SGBD e/ou componentes de acesso.

Um detalhe que achei bem interessante é que a documentação do Aurelius lista exatamente quais versões de SGBD e dos componentes de acesso foram utilizadas nos testes, bem como quais combinações entre eles. É apenas um detalhe, mas me passou uma boa sensação de profissionalismo por tras do framework.

Classes de domínio e mapeamento

Como eu já disse na introdução, o Aurelius interfere bem pouco no design das suas classes.
Quando falo sobre interferir no design das classes, me refiro a quando um framework exige que as suas classes herdem de alguma classe ou implementem alguma interface do framework, que as propriedades persistentes sejam todas published, ou que ao invés de usar os tipos pre-definidos do Delphi você tenha que utilizar o próprio sistema de tipos do framework.

Por exemplo, esta classe está pronta para o Aurelius:

type
  [Entity]
  [Automapping]
  TPerson = class
  private
    FId: integer;
    FLastName: string;
    FFirstName: string;
    FEmail: string;
  public
    property Id: integer read FId;
    property LastName: string read FLastName write FLastName;
    property FirstName: string read FFirstName write FFirstName;
    property Email: string read FEmail write FEmail;
  end;

O atributo Automapping é o que diz ao framework para utilizar convenções de mapeamento naquela classe, mas na minha opinião o comportamento deveria ser o contrário: O mapeamento por convenções ficaria sempre habilitado e, caso o programador por algum motivo não queira isso, então adiciona um atributo como por exemplo [NoAutomapping]. Mas isso é um detalhe menor.

De qualquer forma, como a documentação deixa bem claro, o mapeamento por convenções não é “tudo ou nada”, você pode usar o [Automapping] e ainda assim mapear algumas coisas explicitamente, sobreescrevendo as convenções.

O mapeamento manual, isto é, sem utilizar as convenções, pelo que entendi só pode ser feito via atributos. Ou seja, até onde pude ver não há mapeamento por arquivo externo como acontece no DORM ou no Hibernate. Eu provavelmente não usaria este recurso, mas ainda assim acho que é algo importante de se ter. Algumas pessoas preferem não utilizar atributos para não poluir o código, para que as classes de domínio fiquem menos acopladas ao ORM, ou por terem algum outro impedimento.

Especialmente em se tratando do Delphi, há ainda um outro problema: É que devido á forma como as DCU são geradas e tratadas internamente, se por um acaso você alterar qualquer coisa na interface de uma unit e recompila-la, então você precisará recompilar qualquer unit que dependa desta (Este é o motivo por que componentes compilados para uma versão do Delphi não servem em outra versão). Então modificar uma unit para adicionar os atributos de mapeamento pode gerar um pouco de transtorno em alguns casos mais específicos.

Herança

O Aurelius suporta o mapeamento de herança e queries polimórficas. A herança pode ser mapeada de duas formas:

  • Em uma única tabela. Neste caso, todos os campos de todas as subclasses ficam mapeados numa mesma tabela, e há ainda uma coluna extra que permite especificar qual a classe correspondente a cada registro desta tabela.
  • Com tabelas específicas para as subclasses, realizando joins quando necessário

ID

Ao que me parece, o Aurelius não tem muitas restrições sobre o identificador dos objetos (a chave primária para o mundo relacional), os campos podem ser de diversos tipos e você pode ter mais de um campo como id na classe, para o caso de chaves compostas.

Ele pode ainda tratar chaves sequenciais automaticamente, utilizando sequences/generators ou campos auto-incremento dependendo do SGBD, mas pelo que observei esta é a única opção para geração automática de identificadores. E também não vi nenhum meio para que eu possa implementar meu próprio gerador de identificadores. No projeto que estou trabalhando atualmente, tenho tabelas cuja chave é um GUID, então neste caso eu mesmo terei que gerar e atribuir o id manualmente sempre que for persistir um objeto para estas tabelas.

Blob

Campos blob são suportados utilizando o tipo TBlob ou TArray nas classes. Acho que TStream seria uma boa opção aqui, possui várias vantagens sobre um TArray e evita que as classes de domínio tenham mais um ponto de acoplamento (TBlob) com o ORM.

Acredito que deve ter havido algum motivo (indisponibilidade de recursos [tempo, dinheiro] ou algum impedimento técnico) para isso, pois acho improvavel que o uso de streams como blobs não tenha passado pela cabeça de ninguém da equipe.

Lazy

No meu post sobre o DORM eu disse que existem alguns impedimentos técnicos para implementar lazy loading de forma completamente transparente em Delphi (O Hibernate consegue, mas envolve manipulação de bytecode), e acho que o pessoal da TMS conseguiu chegar o mais próximo possível. Veja o exemplo:

type
  TMediaFile = class
  private
    [Association([TAssociationProp.Lazy], [])]
    [JoinColumn('ID_ALBUM', [])]
    FAlbum: Proxy<TAlbum>;
    function GetAlbum: TAlbum;
    procedure SetAlbum(const Value: TAlbum);
  public
    property Album: TAlbum read GetAlbum write SetAlbum;
  end;

implementation

function TMediaFile.GetAlbum: TAlbum;
begin
  Result := FAlbum.Value;
end;

procedure TMediaFile.SetAlbum(const Value: TAlbum);
begin
  FAlbum.Value := Value;
end;

Quando um objeto TMediaFile é carregado, o atributo Album não é carregado automaticamente. Ele só será carregado quando a propriedade Album for acessada (Mais especificamente, quando a propriedade Value do Proxy for acessada).

Entretanto, acho que este Proxy poderia ter algum outro nome que deixe explicito para quem estiver lendo a classe que ele está lá para permitir que determinado atributo seja lazy.. Talvez LazyProxy<>

Bugs

Ao executar o demo MusicLibraryVCL, tudo funcionou perfeitamente num primeiro momento. Então decidi compilar o projeto com o FastMM e descobri que há um bug relacionado a gerenciamento de memória, ao que parece envolvendo um objeto sendo liberado da memória duas vezes. Se o problema é no Aurelius ou neste demo em específico, não sei dizer.

Também encontrei um vazamento de memória ao tentar implementar um pouco de código utilizando Aurelius.

Se alguem quiser reproduzir, este foi o código que utilizei:

type
  [Entity]
  [Automapping]
  TAddress = class
  private
    FId: Integer;
    FStreet: String;
    FCity: String;
  public
    property City: String read FCity write FCity;
    property Street: String read FStreet write FStreet;
  end;

  [Entity]
  [Automapping]
  TPerson = class
  private
    FId: Integer;
    FName: String;
    FAddress: TAddress;
  public
    property Name: String read FName write FName;
    property Address: TAddress read FAddress;
  end;

...

var
  Con: IDBConnection;
  DM: TDatabaseManager;
  OM: TObjectManager;
  P: TPerson;
begin
  ReportMemoryLeaksOnShutdown := True;
  if FileExists('Data.bin') then
    DeleteFile('Data.bin');

  Con := TSQLiteNativeConnectionAdapter.Create('Data.bin');
  DM := TDatabaseManager.Create(Con);
  try
    DM.BuildDatabase;
  finally
    DM.Free;
  end;

  OM := TObjectManager.Create(Con);
  try
    P := TPerson.Create;
    P.Free;
  finally
    OM.Free;
  end;
end;

Já reportei ambos os casos para o Wagner Landgraf, responsável pelo Aurelius.

Update: Segundo o Wagner, o primeiro caso é uma falha especifica do demo em questão, e não do Aurelius propriamente dito, mas que obviamente será corrigida de qualquer forma.
E o segundo caso de fato é um memory leak que surge quando se utiliza automapping com relacionamentos, a causa do problema já foi identificada e o leak foi corrigido. Devo dizer que gostei da velocidade com que a situação foi tratada!

Queries

Para executar queries, a única opção é o uso da API de Criteria. Uma outra opção (não suportada pelo Aurelius) seria o uso de OQL (Object Query Language, algo como um SQL para objetos), como a HQL do Hibernate.

Um exemplo de uso da API de criteria do Aurelius é o seguinte:

var
  Results: TObjectList<TCustomer>;
begin
  Results := Manager1.CreateCriteria<TCustomer>
    .Add(TExpression.Eq('Name', 'Mia Rosenbaum'))
    .List;

Uma situação onde acho Criteria excelente é quando você tem filtros dinamicos definidos pelo usuário. Você teria algo assim:

var
  Criteria: TCriteria<TCustomer>;
  Results: TObjectList<TCustomer>;
begin
  Criteria := Manager1.CreateCriteria<TCustomer>;
  if chFiltrarPorNome.Checked then
    Criteria.Add(TExpressions.Eq('Name', EdNome.Text));
  if chFiltrarPorCidade.Checked then
    Criteria.Add(TExpressions.Eq('City', 'EdCidade.Text));

  Results := Criteria.List;

Já para a maioria dos casos, eu iria preferir fazer algo como:

var
  Results: TObjectList<TCustomer>;
begin
  Criteria := Manager1.ExecuteQuery<TCustomer>('SELECT c FROM Customer c WHERE c.Name = "Mia Rosenbaum"');

Eu penso que criteria e OQL ambos tem o seu espaço no mundo, cada um podendo ser utilizado em determinada situação, e espero que em uma futura versão isso possa ser implementado.

Entretanto, sei que é um trabalho complexo: Envolve todo um trabalho de definir uma linguagem de consulta (provavelmente um sql adaptado), parser para esta linguagem, análise sintatica, tradução para sql nativo, etc.

Também seria interessante a possibilidade de executar queries diretamente em SQL. Você perde um pouco de abstração, mas em alguns casos onde você tenha um gargalo de performance, isto poderia ser a salvação.

Considerações finais

Ainda há alguns pontos para serem melhorados e, embora eu não tenha realizado testes mais profundos envolvendo grafos de objetos mais complexos ou análises de performance, o Aurelius me parece ser uma ferramenta promissora e madura para uso comercial.

Update 19/01/2011:

  • Fui informado que alguns dos pontos que levantei aqui já estavam sendo cogitadas, incluindo mapeamento por arquivos, TStream para blobs e mais opções de geração de identificadores (guid e outros).
  • Reescrevi a seção sobre queries para explicar melhor a api de criteria
37

Hack ‘n Rio 2011: #eufui

December 5, 2011

Nos últimos dias 02 e 03 estive no Hack ‘n Rio 2011, evento apoiado pela SL-RJ e pela ALTA.

O foco do evento não era desenvolvimento de software, mas apesar disso houveram algumas palestras nas quais eu como programador me interessei bastante. Já outras, estavam longe da minha área de interesse, e outras nem sequer se encaixaram na temática do evento (*cof cof* BI *cof cof*).

Houveram palestras claramente com fins comerciais, para promover algum produto ou serviço com o qual o palestrante tem algum vínculo, e eu sou radicalmente contra isso e acredito que a organização deveria tomar muito cuidado este tipo de coisa.

Alguns palestrantes não souberam se manter focados nos seus temas, cito como exemplo a pelestra “Integrando Python com Arduíno” do Álvaro Justen e “(In)Segurança em Smartphones com Android” do Ricardo Kléber Martins Galvão, onde os expositores gastaram boa parte do tempo para apresentar, respectivamente, a linguagem Python e a plataforma Android, algo desnecessário por dois motivos:
1. “O que é Python/Android” não era o tema de nenhuma palestra
2. É bem provavel que quem se interessou em assisti-las já tenha uma mínima noção sobre o assunto

De qualquer forma, após finalmente entrar realmente no assunto que interessava, as apresentações se tornaram interessantes, principalmente a de Python/Arduíno.

Um outro ponto que vale ser mencionado: Pagar R$ 70,00 e não ter coffee-break, dispensa comentários.

Felizmente nem tudo são espinhos, e o evento teve seus pontos positivos: Gostei da palestra sobre integração com Python com Arduino (após o autor entrar no assunto, claro), da palestra de LuaRocks (o gerenciador de pacotes da linguagem Lua), proferida pelo próprio responsavel pelo projeto, da “Engenharia Reversa do Trojan Banker”, dada pelo Ronaldo Pinheiro de Lima e “Controlando sua casa pela internet com Arduíno”, dada por Maurício Feo, sendo esta última a que mais me atraiu para o evento.

Em dado momento tentamos ir nas Lightning Talks mas acredito que caímos numa sala errada, pois o que estava rolando lá não era tão lightning assim, valeu muito à pena e era uma demonstração ao vivo sobre as otimizações feitas por compiladores (no caso era utilizado o GCC) ao gerar o código de máquina, foi muito interessante por demonstrar alguns pontos como a inteligencia dos otimizadores, o o que pode ser feito a nível de código fonte e como isso influencia no código de máquina gerado, e demonstrou o fato de que performance não tem relação com quantidade de código. Infelizmente pegamos o final da apresentação e não tenho ideia do nome do cidadão, mas sabia muito bem o que estava falando.

Em qualquer evento deste tipo, há algo além das palestras/mini cursos muito importante a ser explorado que é o networking, e no caso do Hack n’ Rio 2011 eu e meu camarada @martinusso, que viajou comigo, tivemos a oportunidade de passar algumas horas bem produtivas comendo sanduíche frio e bebendo cerveja (Coca no meu caso!) com @esasse, @cesarliws e @dmalta.

Da esquerda para a direita: Cesar Romero, Daniel Maltarollo, Erick Sasse, eu, Breno Martinusso

Por fim, pretendo voltar no ano que vem? Sendo curto e grosso: Não. A não ser que surja na grade algo realmente muito interessante para mim, o que acho pouco provavel. Não é que o evento seja tão ruim assim, mas é que como ele é voltado para um público do qual não faço parte, o aproveitamento para mim foi muito pequeno.

0

DORM – Delphi ORM

November 22, 2011
Tags: , ,

Há pouco tempo tomei conhecimento que o projeto DORM [1] (Delphi ORM), de autoria do Daniele Teti [2] se tornou público, rapidamente baixei o projeto para poder experimentar, e aqui vão minhas opiniões.

Não pretendo entrar em questões como o que é um ORM, sua utilidade, etc.

De cara o que me chamou atenção no DORM é que a proposta do framework é que ele não interfere na modelagem dos seus objetos. Ou seja, seus objetos de negócio não precisam herdar/implementar nenhuma classe/interface em especial, os atributos não precisam ser published, os atributos são de tipos primitivos da linguagem, etc. Em resumo, uma classe como a abaixo pode ser persistida sem problemas:

type
  TCliente = class
  private
    FId: Integer;
    FNome: String;
  public
    property Id: Integer read FId write FId;
    property Nome: String read FNome write FNome;
  end;

Um outro ponto positivo que encontrei é que ele faz uma clara distinção entre bases de dados para desenvolvimento, testes e produção, sendo que você especifica isso no momento de criar a sessão. Normalmente é simples selecionar bancos diferentes para cada situação (desenvolvimento/testes/produção), então o DORM não trouxe nada de outro mundo, mas o fato de isto já vir embutido no framework é algo muito positivo. Digo isso não por poupar o desenvolvedor de algum trabalho extra, mas por incentiva-lo a trabalhar desta forma.

Uma coisa que senti falta é mapeamento por CoC. Ou seja, para o exemplo que eu dei acima, seria interessante que, sem eu ter fazer nenhum mapeamento, o framework já assumisse que a tabela se chama CLIENTE, e os campos ID e NOME. E para casos em que se deseja sair do padrão, aí sim eu poderia recorrer ao mapeamento manual.

O mapeamento, bem como a configuração de conexão com os bancos, é feita em um arquivo externo em formato JSON. Não investiguei mais a fundo, mas me parece ser possível montar a configuração em memória (montando uma string em JSON) e utilizar isso ao criar a sessão, assim não seria necessario manter um arquivo externo com estes dados.

O mapeamento não é documentado, mas olhando os exemplos que acompanham o projeto foi facil ver como eu devia proceder com as minhas classes.

Alias, documentação é um ponto fraco do projeto, mas não me preocupo muito com isso. Não é que documentação não seja importante, mas uma boa suíte de testes automatizados já quebram um galho quando eu preciso aprender alguma coisa sobre o uso do framework, e de qualquer forma eu prefiro que o autor gaste seu tempo escrevendo código do que documentos :)

Outra coisa que seria legal de ter é mapeamento por atributos. Seria muito interessante se fosse possível mapear as classes com algo mais ou menos assim:

type
  [Table('CLIENTE')]
  TCliente = class
  private
    [PrimaryKey]
    [Column('ID')]
    FId: Integer;
    [Column('NOME')]
    FNome: String;
  public
    property Id: Integer read FId write FId;
    property Nome: String read FNome write FNome;
  end;

Isso, aliado ao CoC, reduziria bastante o esforço para mapear as classes.

O projeto conta com uma aparentemente razoavel cobertura de testes automatizados, o que sem dúvida é um ponto importante, pois mostra a maturidade do autor, e nos dá segurança para confiar no código.

Apesar de eu mesmo ainda não ter usado, sei que o projeto suporta associações, inclusive de coleções. A respeito de coleções, a versão no trunk exige o uso da classe TdormCollection para coleções, mas já existe um branch em desenvolvimento para permitir o uso de qualquer coleção através de duck-typing [3], ou seja, qualquer objeto que possua métodos como Add() e afins, poderá ser utilizado.

Lazy loading também é suportado, mas não de forma transparente como em frameworks mais modernos como por exemplo o Hibernate. Existem uma série de limitações que dificultam/impossibilitam a implementação de lazy loading de forma transparente no Delphi, mas isso não vem ao caso.

Criei algumas entradas no issue tracker do projeto a respeito de alguns dos pontos levantados aqui neste post. Para quem tiver interesse, sugiro ir lá e sinalizar o issue ou mesmo contribuir com algum patch.

  1. http://code.google.com/p/delphi-orm/issues/detail?id=5 Convention over Configuration (CoC)
  2. http://code.google.com/p/delphi-orm/issues/detail?id=6 Mapeamento por atributos
  3. http://code.google.com/p/delphi-orm/issues/detail?id=8 Travamento otimista através de versionamento de registros

Estou tentando contato com o autor há alguns dias, mas ele não me responde nem por e-mail nem nos issues que lancei no projeto. Eu gostaria de contribuir implementando algumas das solicitações que eu lancei, mas antes preciso saber se o autor concorda com as mesmas e aceitaria contribuições de terceiros. Havendo qualquer retorno, eu atualizo o post aqui.

Update – 23/11/2011
Recebi alguns retornos do Daniele Teti, ele aceitou minhas sugestões e me colocou como commiter para que eu possa ir trabalhando nelas, enquanto ele se foca no core do framework.

Infelizmente meu tempo é limitado, já que o Emballo [4] toma boa parte dele, mas dentro das possibilidades pretendo dar minha contribuição ao projeto. Se alguem mais quiser contribuir, é só se manifestar lá no site do projeto.

[1] http://code.google.com/p/delphi-orm/
[2] http://www.danieleteti.it/
[3] http://en.wikipedia.org/wiki/Duck_typing
[4] http://code.google.com/p/emballo

8

Primeiras impressões do LiveBindings

November 16, 2011
Tags:

O XE2 sem dúvida será lembrado como um dos releases mais significativos do Delphi. Esta versão trouxe o há muito pedido (e supostamente muito necessario) compilador de 64 bits, e o não tão pedido e não tão necessário suporte a MacOS, entre outras coisas.

De cara algo que me chamou muito a atenção foram os LiveBindings, que é o novo mecanismo de databinding que possibilita em teoria ligar qualquer coisa em qualquer coisa. É possível, por exemplo, definir um objeto de negócio como um PODO [1], e ligar suas propriedades diretamente a componentes visuais (componentes ordinarios, como TEdit e TLabel, não sendo necessario os famigerados componentes DBxxx da vida).

Após implementar meu primeiro ‘hello world’ com este recurso, meu primeiro pensamento foi: Precisa mesmo de tanto código??

  BindingExpression1 := TBindings.CreateManagedBinding(
    { inputs }
    [TBindings.CreateAssociationScope([
      Associate(FTeste, 'FTeste')
      ])],
    'FTeste.X',
    { outputs }
    [TBindings.CreateAssociationScope([
      Associate(Edit1, 'Edit1')
      ])],
    'Edit1.Text',
    nil);

Isso foi o código para amarrar a propriedade ‘X’ do meu objeto FTeste (que é do tipo TTeste) à propriedade Text do Edit1 que está no formulário.

E ainda há mais um passo: A princípio, o mecanismo de binding não tem como saber quando houve uma alteração nos valores das propriedades, por isso você mesmo tem que notifica-lo quando isso ocorre.

No meu exemplo, adicionei esta chamada ao setter da propriedade X de TTeste:

TBindings.Notify(Self, 'X');

Algumas considerações:

  1. Seria interessante se, baseado na presença de atributos tanto na classe quanto nas propriedades, o próprio compilador gerasse automagicamente o código necessário para notificar o framework quando as propriedades foram alteradas.
  2. No Emballo [2] existem recursos (ainda em desenvolvimento) para criar um hook em métodos virtuais e não-virtuais, que poderia ser utilizado para adicionar dinamicamente a notificação, desde que a instanciação dos objetos fique por conta do framework. Infelizmente, por hora já tenho outras coisas na fila no próprio projeto, mas fica anotada a idéia.
  3. A princípio, creio que alguem poderia, sem enfrentar muitas dificuldades, implementar um mecanismo que leia via rtti as propriedades/atributos de dois objetos e, através de CoC [3], gere todos os bindings entre estes dois objetos. Mais uma idéia para ficar registrada :)

Não explorei o uso de LiveBindings de forma visual, mas usar via código, de forma crua (ou seja, sem implementar um mecanismo mais facil em cima dos LiveBindings), me parece inviável em larga escala. Obviamente, como deixei claro no inicio do post, este foi o meu primeiro contato com o framework, então é bastante possível que eu tenha feito tudo errado.

[1] Plain Old Delphi Object, ou seja, um objeto qualquer, que não precisa herdar nem implementar nada especial.
[2] http://code.google.com/p/emballo
[3] http://pt.wikipedia.org/wiki/Conven%C3%A7%C3%A3o_sobre_configura%C3%A7%C3%A3o

3

Automação de build

July 18, 2011

Sou a favor de eliminar o trabalho manual e repetitivo sempre que possível.

Estas tarefas tendem a ser tediosas, propensas a erro, demoradas, desestimulantes, etc.

Em especial, neste post quero falar sobre a automação do processo de build de software.

Quando me refiro a build, estou falando do processo de pegar um conjunto de arquivos fonte e transforma-los no produto final, pronto para ser instalado e executado. Isso inclui compilar os fontes, arquivos de ajuda, executar testes automatizados, gerar instalador, etc. Idealmente, este processo deve ser facil de ser iniciado, deve ser automatico, e deve ser reproduzível.

Por exemplo, este processo pode consistir em:
Compilar arquivos fonte
Compilar testes de unidade
Executar testes de unidade
Compilar arquivos de ajuda
Empacotar a aplicação
Subir o servidor de aplicações
Efetuar o deploy da aplicação
Executar testes de aceitação
Submeter para Q.A.

Sendo que a qualquer erro em um destes passos, o restante do processo é abortado.

O build deve ser facil para encorajar as pessoas a utiliza-lo, caso contrario o processo será abandonado e as pessoas voltarão a querer fazer tudo manualmente (o que é demorado, sujeito a erros, etc).

Deve ser automatico para que seja menos propenso a erros e para liberar os desenvolvedores para realizar outras tarefas.

E ser reproduzível significa que para cada build, deve ser possível reproduzi-lo (isto é, produzir um outro produto final equivalente) a qualquer momento. Isto é útil por exemplo caso você precise reproduzir o ambiente de produção de algum cliente para analisar algum bug.

Existem ferramentas dedicadas a isso, desde o clássico Make até ferramentas mais modernas como Maven, Gradle, Ant, etc.

Além de invocar compiladores, a tendencia agora é que tais ferramentas tenham recursos de gerenciamento de dependencias. Isto é, em algum arquivo do projeto você informa que o projeto precisa do Hibernate 3.6.5, e com isso a própria ferramenta de build vai se encarregar de baixar os arquivos necessarios caso eles não estejam presentes na máquina, isso vai garantir que todos os desenvolvedores estejam utilizando as mesmas versões de bibliotecas, ao mesmo tempo que evita ter que armazenar bibliotecas de terceiros no seu repositório de código fonte.

Em resumo, esta é uma das práticas que eu particularmente acho essenciais para qualquer projeto sério de software.

6

DevInCachu 2011 – Ducar*lh*

May 2, 2011

Há dois dias foi realizado o primeiro DevInCachu, eu já bloguei a respeito dele, e agora venho aqui apenas para dizer como foi, para mim, estar lá tanto quanto membro da organização quanto como ouvinte das palestras: Do caralho!! Me desculpem a expressão, mas não encontrei nada melhor para expressar o quão impressionante foi esta experiência, o evento foi mesmo do caralho!

Conforme fomos definindo a grade, eu fui vendo que conteúdo definitivamente não seria o nosso problema, pois tínhamos palestras de excelentes profissionais conhecidos e respeitados tanto no cenário local quanto nacional.

A minha maior preocupação era se o público compareceria, se a gente faria uma boa organização, etc. Logo cedo, quando vi a fila que se formou para efetuar o credenciamento eu já tive o primeiro sinal de que o evento iria bombar, e para confirmar isso bastou acompanhar a hashtag #devincachu no Twitter durante (e até mesmo após) o evento.

Tivemos um excelente feedback dos participantes, e isso sem dúvida nos dá um desejo cada vez maior de nos empenharmos cada vez mais em próximos eventos!

Enfim, é isso. Como participante tirei muito proveito do conteúdo do evento, e como membro da organização fiquei feliz de ver lotado um auditório com capacidade para mais de 230 pessoas em uma cidadezinha do interior do Espírito Santo e tambem por receber um retorno tão positivo de palestrantes, participantes e outros colaboradores!

Deixo meu agradecimento a todos aqueles que tornaram este projeto em realidade: Os que se envolveram de alguma forma na organização, os palestrantes, os patrocinadores que financiaram isso tudo, e, claro, aos participantes que, em boa parte, encararam horas de viagem para comparecer ao evento!

0

DevInCachu 2011

February 27, 2011

Eu e alguns parceiros estamos envolvidos na organização de um evento voltado para desenvolvedores de softwares, a ser sediado em Cachoeiro de Itapemirim/ES.

A idéia do evento é reunir a comunidade de desenvolvedores, tanto os estudantes quanto aqueles que estão inseridos no mercado de trabalho, a fim de ampliar nossos conhecimentos e networking.

O DevInCachu 2011 será realizado no dia 30/04/2011 no Centro Universitário São Camilo, campus 1 (Bairro Paraíso).

Para citar algumas palestras já confirmadas:

  • Paulo Jeveaux e Léo Hackin (Giran Soluções e Ensino): Case Giran: Dois anos de uso de metodologias ágeis (
  • Francisco Souza e Andrews Medina (Globo.com): Tema a definir
  • Denis Ferrari (Mindworks): Como errar em desenvolvimento de software

E eu devo apresentar uma palestra sobre o Google Web Toolkit, isso se não encontrarmos nada melhor para colocar no lugar :)

A inscrição deverá ser feita previamente, ao custo de R$ 15,00. Maiores detalhes no site www.devincachu.com.br

0

Review: Kindle DX

January 15, 2011
Tags:

O meu objetivo neste blog sempre foi falar sobre assuntos relacionados a desenvolvimento de software, então não há espaço aqui para reviews de gadgets.

Porém, no caso do Kindle a situação é um pouco diferente. Recentemente adiquiri um Kindle DX, eu o comprei primeiramente para ler livros de desenvolvimento e acredito que ele, ou melhor dizendo, os leitores de eBook em geral, são ferramentas valiosas para estudo. Assim sendo, após pensar um pouco, vi posso falar dele aqui sem fugir da temática do blog, na esperança as minhas opiniões possam ser de alguma serventia para alguem que esteja interessado em adiquirir um leitor deste tipo.

Então vamos lá.

O Kindle é o leitor de eBooks da Amazon, na minha opinião um dos melhores no mercado. Eu já tive um Sony Reader PRS-600, mas o vendi por que achei a tela muito pequena, eram apenas 6″ contra 9.7″ do Kindle DX. Outra vantagem do Kindle é o acesso ao acervo da Amazon. A Sony tambem tem uma loja de eBooks, mas nem se compara com a Amazon.

Eu fiz o pedido no dia 26/11/2010 no eBay, pagando 289 dolares pelo produto mais 60 de frete.

Para quem se interessar, este foi o link do produto que comprei. Comprovadamente seguro :)

Após eu esperar um mês com ele parado na alfândega, e correr o risco do Kindle ser despachado de volta para os EUA devido ao serviço de péssima qualidade prestado pelos correios com seu serviço ImportaFacil, finalmente no dia 10/01/2011 coloquei as mãos no meu eBook Reader.

Quando abri a caixa, já pude ver que a diferença do tamanho da tela em comparação com a tela do meu antigo Sony Reader é gritante. Como eu disse, são 3.7 polegadas a mais!

Sendo justo, devo dizer que o meu antigo eReader tinha lá suas vantagens: Pra começar, tinha tela de toque. É bem mais prático para marcar textos, acessar menus e passar páginas. Além disso, ele já veio com uma capa de neoprene para proteger o aparelho quando estiver fora de uso.

Na falta de touch screen, o Kindle vem com um teclado qwerty físico (que não é lá muito prático) e alguns outros botões (físicos, logicamente) para navegação.

E na falta da capa de proteção, o jeito vai ser eu enfiar a mão no bolso mais uma vez e descolar uma :(

De cara eu quis testar um PDF que eu já tinha aqui no computador e que eu achava insuportavel de ler no PC, devido a ser um artigo científico em duas colunas. E ele coube perfeitamente na tela e com a fonte em tamanho legível (mas menor do que eu gostaria), sem zoom. Um dos motivos de eu ter vendido o meu Sony Reader foi que o tamanho de tela dele não me permitia ler determinados livros sem ter que dar zoom na página ou aumentar o tamanho da fonte (o que dependendo do tipo de conteúdo pode não ser muito bom).

Uma coisa interessante, é que caso eu queira ler com o aparelho na posição paisagem (isto é, com ele de lado), basta eu virar ele na posição que quero e a tela automaticamente é reconfigurada, no Sony Reader eu tinha que fazer isso manualmente acessando os menus do aparelho.

Cabe ainda uma observação a respeito da tecnologia e-ink, utilizada na tela de ambos os aparelhos: O conforto visual é absurdo. Olhando a tela, podemos ver que o texto fica muito parecido com o papel. Não que ler no PC seja insuportavel, mas para mim um LCD ou CRT nem se compara com o papel.

Uma coisa muito legal é o acesso à internet de graça. Eu acreditei que isto estaria disponível apenas nos EUA e em alguns poucos locais aqui no Brasil. Mas para minha surpresa, aqui mesmo na minha casa consegui acessar a Amazon e tambem a Wikipedia através do Kindle. De cara eu nem me espantei pois achei que estava utilizando a minha própria rede wireless, mas depois a ficha caiu e eu pensei: “Epa! Eu não digitei a minha chave wireless em lugar algum aqui!!”, muito legal :)

O navegador dele não fica restrito a estes sites, mas devemos levar em consideração que o navegador em sí é limitado em suas capacidades, portanto nem pensar em acessar um Google Wave da vida através dele hehehe (o que não me preocupa, uma vez que o propósito do aparelho é especificamente a leitura, não é um tablet de uso geral).

Ainda sobre o acesso à internet. Através do Kindle, pude acessar a loja da Amazon, escolher um livro (Implementation Patterns, do Kent Beck), comprar e pagar pelo meu cartão de crédito. Em poucos instantes, o livro estava disponível no meu aparelho. Não precisei nem olhar para o meu PC durante o processo, é realmente muito prático!

Algum tempo após ter comprado um livro e navegado na web, li em algum manual que o acesso à internet em locais fora dos EUA pode estar sujeito a algumas taxas, e neste momento minha animação caiu pela metade. Contudo, vasculhei a minha conta na Amazon e não encontrei nenhuma cobrança referente a isto. Inclusive, encontrei o registro da compra do livro que fiz pelo Kindle, e lá estava escrito explicitamente que não houveram cobranças de taxas extras.

Para concluir, posso dizer que o que mais sinto falta no Kindle é a tela sensível ao toque, mas posso viver sem isso sem problemas. No mais, é um excelente aparelho. Os três pontos mais fortes, para mim, são:

  1. Tamanho da tela
  2. Tem a Amazon por trás dele
  3. Acesso à internet, com a possibilidade de comprar livros pelo Kindle e receber o livro em instantes diretamente no aparelho

Enfim: Uma ótima aquisição. Se eu recomendo? Depende. Sugiro a qualquer interessado que primeiramente leve em consideração o tipo de livro que pretende ler, e também o idioma que pode ler. Por exemplo, para quem quer ler livros sobre desenvolvimento e em português, sofrerá um pouco com a indisponbilidade de material.

6

Qualidade externa x Qualidade interna

December 10, 2010

O que importa é o produto funcionando nas mãos do cliente, não é? É claro que sim.

Mas às vezes isso é usado como justificativa para ser desleixado com a qualidade interna do projeto. Não podemos nos esquecer que se o projeto (os fontes) não for bem feito, dificilmente você conseguirá manter uma boa qualidade externa para o software por muito tempo.

Por qualidade externa me refiro ao que o usuário final consegue perceber, e qualidade interna o que é percebido apenas pelos desenvolvedores.

O fato é que você é pago para entregar um software que funciona, um software de qualidade (externa), e que agrega valor para o cliente. Mas essa qualidade toda não vem de graça, e para consegui-la é necessario algum esforço. O grande problema vem da forma em como este esforço é aplicado.

As pessoas que priorizam apenas a qualidade externa implementam o sistema sem se preocupar com testabilidade e mantenabilidade, e aí empregam o seu esforço em corrigir bugs e implementar novas funcionalidades, coisa que se torna cada vez mais difícil devido ao código do sistema não ser muito flexível. Chega um ponto em que a dificuldade em manter o sistema é tanta que bugs começam a surgir a todo momento, você precisa virar noites e fins de semana corrigindo falhas. Dizem que o bom profissional deve se virar e corrigir isso. Eu concordo. Mas acreditar que o problema trata-se apenas de corrigir bugs, aí já não é mais um profissional, e sim um amador.

Mas tambem não adianta se preocupar apenas com a qualidade interna. Lembre-se que o usuário não enxerga isso, e é ele quem paga o seu salário!

A qualidade interna deve ser apenas um meio que te permita manter uma boa qualidade externa ao longo do tempo, ou seja, no final das contas o seu objetivo principal deve ser sim a qualidade externa, você apenas tem que evitar pensar em curto prazo e pensar mais em médio/longo prazo e em como mante-la ao longo desse tempo.

Em futuros posts pretendo falar sobre fatores que contribuem para a qualidade interna do código… Estejam ligados :)

0