A Linha Tênue entre o Hackin’ e a Gambiarra

Dia desses estava programando em par com um amigo quando encontramos um problema. Estávamos utilizando o excelente XStream para transformar um domain model em algo que pudesse ser consumido via webservices de arquitetura REST quando percebemos que nossos XMLs iam ficar enormes e com uns 40% de informações repetidas. Simplesmente haviam dados que eram comuns a várias entidades sendo serializadas em uma lista e se repetíssemos os dados para cada entidade serializada teríamos um grande problema.

Conversando com o Guilherme, ficamos sabendo que o XStream possibilita o uso de referências. Infelizmente também descobrimos que isso só funciona se você tem várias referências para o mesmo objeto (ou seja: tem que ser ==, não basta ser equals()). Seguindo indicações do Guilherme, vimos que para alterar este comportamento deveríamos mexer em uma classe específica que, a princípio, poderia ser estendida por uma subclasse nossa.

Aí a falta que faz seguir o Open-Closed Principle (OCP. E não, não é a ) se faz cruel. O OCP foi difundido por Bertrand Meyer, um dos papas da OOP, e diz:

Um módulo (uma classe, por exemplo) deve ter uma interface rígida e encapsulada para uso por outros módulos e ao mesmo tempo ser aberta e flexível apra ser estendida por estes.

Basicamente isso te dá uma diretiz para que crie métodos bem-definidos, não deixando vazar muita informação sobre o que sua classe faz mas ao mesmo tempo faça com que se alguém tiver que estender esta classe isso seja um processo sem dor. Se você não está interessado em deixar que outras pessoas estendam sua classe marque-a como final e acabe com o mal pela raiz.

Bom, ainda que seja uma biblioteca (não, não é uma API!) fantástica, o XStream peca neste quesito. A classe que faz esta comparação é inserida dentro de outra como atributo private e sem setter public ou protected. A primeira tentativa foi utilizar reflection para injetar os atributos ‘na marra’, a reflection em si funcionou mas… descobrimos que tratava-se de uma classe estática definida dentro de outra. Depois de ler algumas dezenas de linhas de código e escrever outras desistimos.

Percebemos um problema porque a quantidade de código que necessitávamos para adaptar o módulo foi crescendo muito. Eram várias horas de desenvolvimento e ainda não tínhamos uma solução aceitável, mas a base de código só crescia. Todos aquele código tomou tempo para ser criado (utilizando TDD) e demandaria ainda mais tempo para ser mantido no decorrer do projeto.
Simplesmente estávamos horas envoltos em código que não tinha nada a ver com a aplicação que estávamos desenvolvendo, nossa missão não era criar um serializador de XML mais flexível e sim transformar meia dúzia de objetos em XML utilizando uma ferramenta de mercado.

Daí, para a infelicidade de nossos egos de programadores, decidimos partir para uma solução simples (manter uma lista no contexto de marshalling do que já havia sido serializado e modificar nossos adapters) que atendia nossas necessidades. Não era tão cool, não usava recursos obscuros da linguagem… mas nos permitiu voltar a fazer o que somos pagos para fazer: aplicações.

Todo programador gosta de hackear uma biblioteca, um subsistema ou qualquer coisa que tenha sido feita por terceiros. Aliás, eu diria que bons programadores obrigatoriamente gostam disso. O problema é que existe um ponto em que a brincadeira deixa de ser produtiva e passa a ser mera masturbação tecnológica.

7 Responses to “A Linha Tênue entre o Hackin’ e a Gambiarra”

  1. mas voce considerou isso uma gambiarra? porque pelo que entendi voce construiu algo novo e não modificou o projeto de terceiro, então tecnicamente voce não fez uma gambiarra.
    gambiarra seria um remendo temporario (sempre se espera :) ) em sua api ou de terceiro, coisa que voce não fez, pode ficar deselegante mas não achei gambiarra :)
    ah, mas voce não fez hacking tambem :)

  2. pcalcado says:

    Então, acho que o texto ficou ambíguo. O framework não era extensível então resolvemos forçar a barra com um haci para substituir exatamente uma linha de código. Quando a coisa tomou proporções gigantescas abandonamos a idéia e fizemos como deveria ser feito, com um serializador personalizado que utiliza os recursos do framework.

    A idéia inicial parecia envolver a mudança de apenas uma linha de código mas de repente estávamos criando nosso próprio fork do framework. Isso é o que eu chamo de gambiarra ;)

  3. ah tá, não peguei esse contexto do seu texto, reli e agora entendi o drama :)

  4. Leandro Ribeiro says:

    Sobre essa tênue linha…

    Tenho uma dúvida “fora de contexto”, esse “novo” padrão JEE chamado JSF usa dos Managed Beans. Pois bem olha minhas dúvidas:

    Nesse modelo: (e usando um pouco de MVC)

    Sou encorajado a usar meus Beans para fazer uma ligação direta com os componentes, isso não é prejudicial (parece que estou quebrando algo oo)?
    Qual a melhor maneira de realizar esta ligação (Só me vem cambiarra na cabeça) dos componentes de negocios com a view?
    Quem seria o controller ? (desconfio que o próprio jsf, mas se for ele não é só para apresentação?)

    Cambiarras ou não, dão dor de cabeça a mim.

  5. pcalcado says:

    Oi, Leandro,

    A View pode (e deve) ter ligação direta com o Model, ela se altera em função das alterações deste. Por isso os objetos podem ser utilizados na página sem problemas, desde que apenas para leitura.

    Ao utilizar MVC, seja com JSF ou não, o Controller é o cara responsável por receber solicitações do usuário e mandar uma mensagem pro model informando o evento. No caso de JSF você está certo, ele é o Controller e sim, JSF é apenas para apresentação.

    Você está confundindo MVC com Camadas ;)

    []s

  6. Renato says:

    Acredito ser uma falha muito comum que ao escrevermos nossas classes não pensemos em sua extensibilidade. O principal erro é o uso exagerado de private, quando na verdade toda informação não pública da classe deveria ser protected e não private.

  7. Renato says:

    ERRATA: protected por padrão, e não private. Isto é, algum motivo especial para usar private? Não, então usa protected.

Leave a Reply