Archive for the ‘domain.specific.languages’ Category

JustJava 2007 (Upped)

Monday, October 8th, 2007

Update: Enfim o Paulo publicou.

A palestra com o paulo foi sensacional. Muita gente me perguntou ao final da palestra qual minha relação com a Caelum, se sou instrutor de lá ou coisa do tipo. Bem, não :)

Palestra

Além de ser amigo do pessoal da empresa eu acredito fortemente na proposta de trabalho da Caelum, mas não tenho nenhum vínculo empregatício, comercial ou que quer que seja com eles.

Eu simplesmente acredito que o nível de treinamento que alguém obtém lá é bem superior ao treinamento pasteurizado dado pelos centros de treinamento que eu conheço. A palestra em si foi prova disso, nós falamos sobre tecnologias e técnicas que não são vistas nos ‘cursos de arquitetura’ normais e sobre como as tecnologias que de fato fazem parte do programa destes cursos quase sempre é antiquada e/ou inadequada. É uma empresa que consegue sair do commodity que é treinamento Java hoje em dia e trazer algo de valor, geralmente por um preço muito mais acessível.

Caelum

Os slides devem estar disponíveis no site da Caelum em breve.

Ruby “ou” Rails?

Tuesday, October 2nd, 2007

Esse post no GUJ me fez pensar sobre a melhor maneira de absorver algo como o Rails. Rails é uma plataforma de desenvolvimento altamente produtiva e boa parte da produtividade vem do fato de que não é preciso abstrair um domínio na linguagem.

Desenvolvimento de aplicações web é um domínio que inclui diversos conceitos e abstrações. Vejam por exemplo uma sessão web. Se uma pessoa ler sobre o protocolo HTTP em si vai perceber que não existem sessões, o protocolo não mantém estado entre as requisições. Para burlar este problema nós utilizamos cookies ou URIs especiais para informar ao servidor o ID da sessão do cliente. Este é um conceito.

Em Java (ou outra plataforma parecida) vamos abstrair a sessão em uma classe. É desta forma que trabalhamos em Java: criamos classes para representar os conceitos do domínio.

O problema é que até conhecer o suficiente para utilizar de maneira adequada esta abstração na forma de classe você precisa conhecer o que é uma classe e todos os conceitos derivados desta. Basicamente não se consegue criar algo razoável sem saber um mínimo de programação orientada a objetos.

E como Rails resolve isso? Rails abstrai boa parte destes conceitos na linguagem. Ruby é uma linguagem OO e é possível representar a sessão da mesma maneira que se faz em Java mas este não é o meio utilizado em Rails e esta forma de representar as coisas é seu maior diferencial.

Uma sessão em Rails está embutida implicitamente dentro do controlador. Trabalhar com elas é muito simples, para efeito de comapração é como se seu controlador em Java herdasse uma classe que possuísse o objeto que representa a session (que tem a mesma interface que um Map) como atributo protected. Exceto que o acoplamento gerado para acessar a session da classe-mãe em Ruby é muito fraco enquanto em Java seria enorme (na verdade provavelmente a melhor opção em Java seria um método e não um atributo. Em Ruby estes conceitos são bem mais flexíveis) é mais uma questão de filosofia do framework do que de linguagem utilizada em si.

Apesar da polêmica se é ou não uma Domain-Specific Language, Rails é um exemplo claro de Language-Oriented Programming. Neste paradigma de programação (praticado em Lisp desde…sempre!) a linguagem utilizada é modificada e estendida para acomodar os conceitos do domínio. No caso do Rails a linguagem Ruby ganha características que permitem ser estupidamente simples criar uma aplicação web.

E o que isso representa para quem está aprendendo? Eu diria que existem 2 tipos de pessoas que desenvolvem em Rails: desenvolvedores e desenvolvedores de aplicações web. Qual a diferença?

Desenvolvedores aos quais me refiro são desenvolvedores profissionais de software (analistas, programadores, hackers, o que quer que você queira chamar). São pessoas que se dedicam profissionalmente a entender as milhões de coisas que são importantes no desenvolvimento de projetos de software. Utilizar Rails para eles é apenas se beneficiar de uma boa ferramenta que implementa conceitos de MVC, ActiveRecord, LOP, Domain Model, Meta-Programação, convention over configuration, JavaScript, etc.

Para eles eu recomendo primeiro aprender Ruby. Rails sem Ruby é exotérico demais, você não vai entender como é possível que sua classe ganhe métodos conforme precisa deles e outras coisas estranhas (principalmente se você vem de Java ou C#).

O outro estereótipo, o desenvolvedor de aplicações web, geralmente é umc ara com menos conhecimento técnico, menos interesse em construção de software e habilidades em outras áreas. Pode ser o designer que quer fazer seus projetos com relativa independência de programadores, pode ser o cara que tem um estalo e uma brilhante idéia para uma aplicação Web 2.0 que o fará milionário… O ponto é que desenvolver software para este cara é só uma parte do processo, o meio, e não o fim. Este cara não precisa aprender tantos conceitos, ele pode se basear em receitas prontas e correr para um técnico quando precisar de algo mais heavy-metal. Para este cara eu recomendo aprender diretamente Rails, eventualmente ele pode melhorar Ruby e programação em geral com a evolução do seu projeto.

Interessante notar o conceito que funciona com Rails e com desenvolvimento baseado em Domain-Specific Languages (sendo Rails uma ou não): o usuário não vai desenvolver o software sozinho. Ele se baseia em algo construído para ele por um técnico (seja o framework Rails ou uma DSL) mas não consegue sair muito daquele escopo específico e limitado sem acompanhamento profissional. Este é o objetivo dos pesquisadores de DSLs neste momento.

Construindo Expressividade com Linguagens Elegantes

Friday, July 27th, 2007

Ainda não vi uma definição sobre o que seria uma linguagem elegante, então lá vai a minha:

Uma linguagem elegante é baseada em primitivas simples e extensíveis e, principalmente, sem muitas exceções.

Segundo esta definição Ruby, Smalltalk e LISP são elegantes. Java é um pouco, C# com suas centenas de exceções (sobrecarregar + é diferente de sobrecarregar [], dentre outras várias exceções) não é.

Uma linguagem elegante é simples e compacta. É de se esperar que não tenha sobrecarga de operadores, mas isso não é verdade. O problema das pessoas com sobrecarga de operadores é porque elas vêem isso como uma quebra da rule of least surprise. Essa regra diz (implora, eu diria) para não surpreendermos nossos usuários modificando o mundo que eles já conhecem para que uma ação traga consequências não esperadas. Por exemplo imagine que você vai modificar um programa como o ls para dar mais performance (uau, você é bom!). Faça o que quiser mas não mude os parâmetros de entrada e saída ou você vai quebrar um zilhão de programas e scripts pelo mundo todo. Caso introduza uma feature nova faça o usuário explicitamente solicitar por ela (passando um flag no estilo ls -lira –my-fancy-new-feature) e mantenha o default como o antigo.

E onde entra sobrecarga de operadores nisso? Lá no seu primeiro curso de programação (ou no seu primeiro livro se você opta pelo caminho mais difícil) deve ter aprendido sobre literais, variáveis, condicionais e… operadores. Operadores são caracteres especiais com uma função bem definida na linguagem, por exemplo o operador de divisão, de resto, de adição…

Em Java, quando você chama:

String texto = "abc".toUpperCase();

É fundamentalmente diferente de quando chama:


int numero = 12 + 24;

Porque um método e um operador são coisas diferentes e você aprendeu a pensar desta forma. Se amanhã eu puder sobrescrever o operador + para que escreva algo na tela você vai se surpreender porque não era isso que o manual da linguagem te disse.

Ainda assim, existem muitas ocasiões onde sobrecarga de operador são mais que convenientes, são semânticos. Imagine o exemplo do nosso BigDecimal:


BigDecimal a = new BigDecimal("100");
BigDecimal b = new BigDecimal("300");

Some os dois. Ok, você é um programador Java esperto e sabe que vai ter que fazer algo como:


BigDecimal resultado = a.add(b);

Mas disso até me dizer que é melhor que usar ‘+’ é outra história.

Mas e a simplicidade? Não é legal termos um conjunto pequeno de operadores que faz coisas previsíveis e que servem na maioria das vezes? Sim, é! Mas num mundo onde tudo migra para mais expressividade, com Model-Driven Development e Domain-Specific Languages ter este tipo de limitação não é interessante. As melhores linguagens para construir DSLs são as mais flexíveis e por acaso as mais elegantes, que coincidência, não? E como Ruby, que se enquadra nestes dois aspectos, lida com isso?

Simples. Em Ruby não existem operadores, pelo menos não como você está acostumado em Java, operadores são apenas apelidos para métodos. A vantagem disso é que se muda o modelo mental, a partir do momento que você sabe que um operador e um método são a mesma coisa você tem com operadores o mesmo cuidado que tem com métodos. Ao chamar add() do BigDecimal você tem que saber se o método vai retornar o resultado como um objeto separado, se vai modificar os objetos passados como parâmetros, etc. Como você faz isso? Lendo a documentação até se familiarizar com a classe e seu idioma. Após familiarizado você começa a usar sem pensar.

E quando você espera estar lidando com uma classe que sobrescreve um operador e na verdade recebe como parâmetro uma subclasse dela? Sem problemas! Se o autor seguiu os princípios básicos da Orientação a Objetos, que derivam do Design by Contract e o Princípio de Substituição de Liskov a subclasse tem que obedecer o contrato da classe-pai, e se você obedeceu os mesmos princípios não precisa de nada que não esteja no contrato.

Esse tipo de resistência com funcionalidades é o tipo de coisa que se elimina aprendendo várias linguagens e estudando suas motivações. Existem algumas linguagens como as citadas que merecem ser estudas ainda que você nunca as vá utilizar de fato. Elas abrem a sua cabeça.

Model-Driven Development é Durepoxi

Friday, July 27th, 2007

O Paulo Vasconsellos lá do finito ensaiou sua opinião sobre como código não pode representar a documentação sobre um processo de negócios. O post que originou a conversa é bem fraquinho, mas o ponto é bom.

Basicamente a idéia é que não dá para confiar no código porque ele possui o que Joel Spolsky catalogou como ‘leaks de abstração’ em um dos seus artigos mais citados. ~Tenho que admitir que isso pode ser verdade na maioria dos casos mas apenas porque as pessoas ainda não aprenderam o conceito simples de separação de responsabilidades, e isso é muito pior na cultura .Net que é a do autor do artigo original.

Imagina que temos um processo de negócio automatizado num software OO. A coisa é simples, o clássico e onipresente exemplo de adicionar usuários a um grupo:


void adicionarUsuario(Usuario u, Grupo g){
g.adiciona(u);
}

E como estamos falando de um software OO as regras de negócio estão nos respectivos objetos (grupo e usuario) e não nesse método de serviço. Muito bem, eu consigo gerar uma documentação em fluxograma, UML, o que for desta sequência simples de instruções imperativas. O problema é que software não é simples assim.

Eventualmente nós precisaremos persistir a alteração feita no banco de dados.


void adicionarUsuario(Usuario u, Grupo g){
g.adiciona(u);
repositoriousuarios.atualizar(u);
}

E possivelmente precisamos saber se o usuário logado possui direito a fazer esta alteração, esse é um requisito não-funcional de segurança. Adicionar um log também é útil para auditoria.


void adicionarUsuario(Usuario modificador, Usuario modificado, Grupo g){
if(podeAlteraroutrosUsuarios(modificador){
g.adiciona(modificado);
repositoriousuarios.atualizar(modificado);
logger.info("Alterou");
}
else{
throw new IllegalQualquerCoisaException();
logger.error("Tentou alterar");
}
}

E isso pode piorar ainda mais. Agora utilize o código acima como documentação de negócios por favor. Mostre ao seu cliente e peça para ele tentar te explicar. não dá, né? E por quê? Porque cada uma destas coisas são conceitos ortogonais, que deviam ser implementados por técnicas de AOP e não embolados no meio do código de negócio.

Domain Driven Design possui a modelagem de negócios no código como sua essência. Um dos pontos que mais causam dúvidas, por exemplo, é o da diferença entre Repositórios eDataMappers (DAOs no mundo Java EE). A diferença é que eu coloco um repositório num diagrama de negócios (ainda que chame de outra coisa) mas não coloco um DataMapper . E por quê? Porque a responsabilidade de um Repositório é referente à objetos que mapeiam o negócio enquanto a responsabilidade de umDataMapper é transformar objetos em tabelas (ou coisa do gênero) e objetos ou tabelas não são conceitos de negócio. Assim ainda que um DataMapper implemente um Repositório eles são tratados sob pontos de vista bem diferentes para análise de sistemas.

No passado nós tínhamos uma discrepância enorme entre os modelos de negócio e o modelo físico do software. Há mais de vinte anos que não há motivo para esta diferença existir, exceto uma cultura dominante. O problema, como sempre, está nas pessoas.

Model-Driven Development, conjunto de idéias que Domain-Driven Design faz parte, é exatamente sobre isso. Por enquanto nós ainda precisamos educar os desenvolvedores para que usem as ferramentas de maneira correta, num futuro próximo eu espero que Domain Specific Languages poupem este trabalho na maioria dos casos.

DrDobbs2007 - 25/07 Almoço

Wednesday, July 25th, 2007

Após a palestra xarope sobre pseudo-Domain Models foi a hora do almoço com direito à keynote de Ivar Jacobson. Se você acompanha a Dr. Dobbs sabe que o cara -um dos pais da UML e do RUP- está cansado de processos e foi sobre isso sua palestra. Eu estava esperando para comentar sobre a série de artigos aqui em algum momento, pelo visto vai ser agora.

Imagine uma empresa que constrói sistemas. Agora imagina que ela só domina Struts e Hibernate como ferramentas. Todos os projetos, se exceção, são feitos nestas duas plataformas, e pior: os desenvolvedores só usam o que leram em tutoriais na Internet, ninguém sabe de fato utilizar as próprias ferramentas. Além de usar a dupla para implementar aplicações tão pequenas quanto um “fale conosco” (quem nunca viu uma aplicação que nem SGBD acessava e tinha os JARs do Hibernate no classpath?) a empresa usa mal e porcamente as ferramentas quando precisa de fato, simplesmente porque usar ou implantar não significa usar corretamente.

É assim que Jacobson vê a implantação de projetos nas empresas, e disso que ele está cansado. “Ninguém lê livros sobre processos”, ele exclama e isso embasa toda a minha série de posts sobre “pare de se enganar: você NÃO usa RUP”.

O que Ivar propõe é o foco no uso de práticas que fazem sentido. Vê-lo falar (e sacanear o Scott Ambler, na primeira fila, ocasionalmente) fazia transparecer a sabedoria que décadas tentando enfiar conhecimento na cabeça dos outros traz e as consequências que se chega. Recomendo os artigos, vamos focar no tema em outra ocasião.

Logo depois parti para um talk de Juha-Pekka Tolvanen com título “Creating a Domain-Specific Modeling Language: Hands-On”. propaganda da MetaCase apenas, que eu considero um bom case de DSL mas não gosto da ferramenta. Acho que as pessoas precisam aprender que RAD não deu certo para sistemas de verdade e não dará para definição de DSLs, que são programas em si. Que saudades da sabedoria do Jacobson! Bom, fiquei na sessão para recarregar a bateria do meu notebook de qualquer forma…

DrDobbs2007 - 25/07 Eventos da Manhã

Wednesday, July 25th, 2007

Manhã morna no evento. Primeiro uma palestra bem legal com James Hobart entitulada “Designing Usable Web 2.0 Applications” onde ele delineou alguns dos “Design Patterns” (eu chamaria de “Interaction Patterns”) e alguns divertidos exercícios de usabilidade derivados destes. Bem legal.

A segunda foi “Domain Models and Requirements that Span Projects”, de Petter Graf.. Decepcionante. Os slides prometiam bastante mas a apresentação se mostrou uma sequência de conceitos do século passado sobre Domain Model gordos e sobre como derivar requisitos do domínio, geralmente ignorando que o sistema mapeia apenas uma parte pequena do domínio e um foco enorme em ferramentas, sejam CASE ou Mind Maps. Para piorar no final rola um pequeno comentário de como a arquitetura de Entity Beans 2.x mapeia o conceito apresentado muito bem. Já viram o tamanho do problema, né? Medo das pessoas que assistiram esta palestra, muito medo… Os slides desta apresentação estão online. Cuidado com eles! Tome como anti-exemplo!

@Atlanta

Tuesday, July 24th, 2007

Estou em Atlanta esperando minha conexão para Chicago onde participarei da conferência Dr. Dobbs Archtiecture & Design World. Entrar no país do Tio Sam não é fácil nunca, mas até que foi tranquilo (tirando o eterno alerta laranja do aeroporto). Definitivamente com essa cara de chicano e cavanhaque sou presa fácil pra ir parar na inspeção…

O que mais me interessa na conferência são as apresentações sobre DSLs, um tema que vai demorar um tempinho para de fato chegar no Brasil.

Bom, durante a semana devo comentar os acontecimentos.

Objetando: Objetos e o Mundo Real

Saturday, June 16th, 2007

E-mail do Caike:

Olá Phillip, tudo bom ?

Leio sempre seus posts em seu blog e no fórum do GUJ e vejo como algumas vezes suas constatações vão por caminhos diferentes dos do ’senso-comum’ (Freakonomics?). Gostaria de agradecer as ‘guerras’ (inclusive algumas vezes levadas muito mais a sério do que deveriam, por outras pessoas) sobre diferentes arquiteturas e aplicações de OO. Graças a elas, tenho ganho diversos pontos a serem investigados em meus estudos.
Sou recém graduado em Ciência da Computação por uma faculdade de Belém, PA, e a pergunta que estou prestes a fazê-lo envolve a tâo polêmica orientação a objetos.

Batendo a cabeça sobre tudo o que o pessoal vem falando e a idéia que você vem tentando passar, gostaria que avaliasse a minha possível avaliação de OO.

Vejo a OO como algo que tenta expressar mais como o mundo real funciona, e não como ele realmente é. Acredito que o foco da abordagem orientada a objetos deva estar nas mudanças de processos e, por conseqüência desta, acaba dando uma idéia de como as coisas são. Durante a modelagem de uma idéia devemos prezar pela situação que melhor expressar seu funcionamento, e não sua estrutura. A grosso modo: Se nosso sistema resolve um problema relativo a segurança de uma casa em Brasília, não deveríamos nos preocupar com a ameaça de um marémoto. Não devemos fazer nossos objetos serem capazes de fazer coisas que eles não vão precisar fazer. Um pensamento como este construirá uma boa arquitetura que terá sempre a robustez para se adequar a mudanças, ou, complementos de atividades.
Parabéns pelos posts e espero estar pensando de maneira coerente.
- Caike

Este é um ponto deveras interessante, como diria um grande amigo.

Orientação a Objetos é pura e simplesmente um conceito técnico. É pegar dados e lógica e manter num mesmo componente, seja através de classes ou qualquer outra forma (por isso tanta gente se espanta quando descobre que JavaScript é OO). É por isso, por exemplo, que Ma href=”http://www.objectmentor.com/ “>Uncle Bob introduz sua apresentação sobre design eliminando o mito de que “objetos modelam melhor o mundo real” e focando sua utilidade em gerenciamento de dependências.

Alan Kay, inventor de Smalltalk e um dos pioneiros na área (ele criou o termo object-oriented descreve em seu paper “The Early History of Smalltalk”:

In computer terms, Smalltalk is a recursion on the notion of computer itself. Instead of dividing “computer stuff” into things each less strong than the whole–like data structures, procedures, and functions which are the usual paraphernalia of programming languages–each Smalltalk object is a recursion on the entire possibilities of the computer. Thus its semantics are a bit like having thousands and thousands of computer all hooked together by a very fast network. Questions of concrete representation can thus be postponed almost indefinitely because we are mainly concerned that the computers behave appropriately, and are interested in particular strategies only if the results are off or come back too slowly.

Para Kay, objetos são mini-computadores especializados em um conjunto específico de comportamentos. A idéia do autor era utilizar estes mini-computadores para aproveitar os recursos das máquinas mais eficientes dos anos 70.

Com o passar do tempo surgiu outro tipo de profissional, o que não estava mais tão preocupado assim em resolver problema computacionais mas sim em como a tecnologia pode ajudar seus clientes (este é o elo perdido entre os programadores e os pseudo-analistas de sistemas de hoje). As pessoas desta linha de pensamento começaram a fazer paralelos entre objetos e conceitos do mundo real e perceberam que podiam utilizar as boas características da OOP (herança, encapsulamento, contratos…) para modelar o domínio de um software.

Por isso um objeto serve para modelar o processo de negócios de uma empresa de uma maneira relativamente eficiente (pelo menos mais eficiente que abordagem de programação estruturada) assim como serve para modelar um Servlet, algo completamente tecnológico sem paralelo no domínio de negócios. Ambos, Servlet e objetos de domínio, tiram proveito das características de OO.

Esta falta de relacionamento real entre OO e “modelar o mundo” dá uma pista de que você está no caminho certo. Abstrair é tirar detalhes não-interessantes dentro de um contexto. Quando abstraímos algo nós nos concentramos apenas no que é necessário para fazer o que precisamos, é como quando eu falo para você “meu vôo sai assim que o sol nascer”. O vôo não é meu e ele não depende do Sol nascer para partir, mas você entendeu a mensagem mesmo abstraindo os detalhes. Objetos servem para modelar, seja br.com.empresa.Pedido ou javax.swing.JButton de forma abstraída.

Note que OO nem sempre é o ideal. Cada domínio já desenvolveu na sua história meios para modelar seu domínio. Pense no sempre utilizado exemplo de contabilidade. Por séculos os contadores utilizaram estruturas tabulares para efetuar seus cálculos, estruturas que evoluíram até planilhas eletrônicas como a Google Spreadsheet ou OpenOffice.org Calc. A tecnologia evolui e talvez estes modelos caiam, mas se você se manter próximo destes paradigmas vai conseguir muito mais satisfação ao lidar com usuários. Por isso os domínios expostos com orientação a objetos estão sendo desafiados por domínios expostos por Domain-Specific Languages (DSLs).

Seu exemplo, entretanto, foge mais do conceitual sobre modelagem e entra em princípios de processo de desenvolvimento. Se você mostrar este exemplo para algumas pessoas elas certamente dirão “Ah, mas amanhã pode ser que a empresa venda o produto para alguém no Rio, ou pode ser que o Sertão vire Mar e o Mar vire Sertão. O que fazer neste caso? YAGNI. Implemente o que você precisa agora, deixe o amanhã para amanhã. Claro que é papel fundamental de um bom arquiteto (e não, arquiteto não é aquele cara que faz diagrama o dia inteiro, na maioria dos projetos todos somos arquitetos em maior ou menor nível) é prever possibilidade de extensão e flexibilidade, mas a minha experiência diz que a melhor maneira de criar flexibilidade sem overengineering é utilizar um ótimo design OO.

DDD e DTO

Thursday, June 7th, 2007

Pergunta na lista UML-BR:

Boa tarde a todos,

Estava estudando o DDD (Domain Drive Design)…

Percebi que a camada de negócios deve ser um reflexo da realidade, para que
o sistema possa evoluir de maneira mais fácil (flexibilidade) conforme a
regra de negócios do cliente tb muda…
Por isso temos as entidades.. Por exemplo Funcionario, Departamento, etc…

A duvida que eu tenho é a seguinte:
Vamos supor que eu tenha que exibir todos os funcionários em um JSP… eu
deveria criar um DTO do Funcionario e “mandar” para a camada de visão? ou
posso mandar o proprio objeto de negócio (o que na minha opinião é mais
pratico, já que eu não preciso duplicar código no DTO)?
Pois eu li o Artigo do Phillip Calçado e do Martin Fowler
http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs
http://www.martinfowler.com/bliki/AnemicDomainModel.html
onde eles dizem que não é bom criar DTO´s… e por isso estou confuso….

O que vcs acham… para exibir as entidades em tela a camada de visão pode
ter contato com as entidades… ou vou ter que duplicar o código criando um
DTO para cada entidade?

[...]

Então eu tb penso assim….

Mas pensando no lado negativo disso, imagine se eu tiver 50 JSP´s mostrando
os dados desse Funcionario…. Ai eu vou e faço uma refatoração no codigo
(talvez mudando metodos de uma classe pra outra, etc)…. vou ter que
verificar nos 50 JSP´s pra ver se não deu nenhum problema, ou até mesmo para
ajusta-los a nova mudança!!!!!
Talvez se eu criasse DTO´s para isso eu não teria esse problema pois os
DTO´s não mudariam…..
O que vcs acham disso…. faz sentido????

valeu pessoal…..

Felipe Regalgo

Você poderia ter objetos de transferência apenas para a interface - DDD
não fala explicitamente sobre isso- mas existem algumas questões
práticas neste sentido:

- Hierarquia duplicada desnecessariamente: Ao manter um DTO (VO é um
nome que já foi usado para DTOs mas não é mais) para isso você está
duplicando toda a sua hierarquia de classes, o que indica código
duplicado, tendo em dois ou mais lugares no seu sistema o mesmo
conceito implementado.

- Mudanças: Da mesma maneira que se eu alterar minha classe de
negócios vou ter que alterar a interface sem DTOs, com DTOs a cada
mudança no meu modelo de negócios *eu tenho que alterar o DTO
correspondente em si*, logo você só transfere o problema de lugar mas
continua com ele -e com código duplicado que é *muito* ruim.

- Se você pensar neste isolamento então precisa de DTOs para qualquer
coisa que não seja camada de negócios, logo vai precisar também para
persistência, por exemplo, caindo nos mesmos problemas acima para
outra camada.

- Encapsulamento: OO exige que suas abstrações sejam encapsuladas, e
isso quer dizer que dificilmente a mudança na implementação de uma
classe vai afetar outras em tão grande escala. Quando isso acontece é
porque houve um grande refactoring ou uma grande mudança de conceito de
negócios, e isso -além de raro- vai afetar seu sistema com ou sem
DTOs. A diferença, como citando no primeiro item, é que sem DTOs você
não precisa se preocupar em mudar vários lugares, apenas a classe de
negócios.

- Conceito de Negócios: DDD pressupõe que seu sistema modela ao mais
próximo da realidade possível. Se uma classe muda no modelo de
negócios é porque seu entendimento sobre o negócio mudou e
provavelmente alguma coisa na interface vai refletir isso.

Em DDD temos os ContextMappers que mapeiam domínios diferentes que
precisam se comunicar. Esta é a abordagem normal para os casos onde se
percebe a necessidade de algo como um ‘DTO interno’.

‘DTOs internos’ (”VOs”) são uma péssima prática, completamente não OO
e difundidas tristemente pela Sun para lidar com as falhas da
arquitetura de EJBs pré 3.0.

[]s

A Culpa é da Marvada

Tuesday, May 22nd, 2007

O Vitor respondeu meu post, eu tentei colocar um comentário mas ficou muito grande, então vamos tentar retrucar por aqui mesmo :)

Eu entendi que ele quis dizer algo como “em >coloque -um-valor-muito-alto-aqui<% dos casos usar OO é overhead” e, como disse, concordo em parte, mas acho que mais uma vez houve uma certa ênfase errada.

Para começar, acho que mudou bastante de idéia. Em Fevereiro você disse:

Como um bom amante da Orientação a Objetos pura eu odeio os bancos de dados tradicionais e acho os frameworks de O/R um saco (além de ser uma grande gambiarra)! Por isso eu uso Prevayler. :D

Que foi o que começou este debate todo. Bom, vamos lá.

Por exemplo, com o BabaXP eu forcei a implementação de um DAO, mesmo usando o Prevayler. Achei que era possível criar um DAO OO, algo bonito, que abstraísse as diferenças entre Prevayler e um banco relacional qualquer. Me enganei. É impossível fazer algo nesse nível só por causa de uma única diferença entre as duas tecnologias, o acesso direto a memória dos dados.

Bom, Prevayler em si não é OO, como já discutimos no seu blog e em um post passado aqui neste mesmo, mas ainda que fosse não há problema em ter um Mapper (que é conceito por trás de um DAO) entre dois domínios de objetos diferentes. Na verdade, Eric Evans possui ótimos textos sobre Context Mappers no seu livro que fazem exatamente isso.

Quando trabalhei com Hibernate 2 e EJB 2, não consegui imaginar uma forma melhor de se programar do que seguir um fluxo de ida e volta: Locator -> Facade Session Bean -> Transaction -> DAO -> Hibernate Entity. Com VOs circulando entre eles. Aparentemente uma bela estrutura OO, exceto por um problema: os algoritmos continuavam seqüenciais, apenas em objetos diferentes. Os objetos não resolviam os problemas da regra de negócio, mas sim simplificavam o uso da própria tecnologia (EJB). Não haviam objetos inteligentes, apenas os JavaBeans secos, como o Hibernate 2 queria, e VOs secos, com regra de negócio pertinente ao objeto e só.

Ahm? Por que o Hibernate fazia você usar DTOs? Eu usei Hibernate com objetos de negócio nesta versão e não tive nenhum problema, poderia explicar melhor? Mesmo os tão mal-falados EJBs podem ser utilizados com objetos. Não não é tão fácil quanto em JPA/Hibernate 3, mas também não é difícil.

E não, DTOs/VOs/TOs ou como estejamos chamando esta semana não fazem um bom modelo OO, muito pelo contrário.

Uma estrutura semelhante foi criada com o JavaFreeCMS, uma arquitetura Action Based não poderia gerar outro resultado do que uma implementação Action Based, que é um nome mais bonito para implementação seqüencial. Por mais que eu quisesse implementar algo OO, tinha algo que me prendia ao modelo relacional. Cultura? É, foi sim. O JavaFreeCMS foi baseado no phpNuke, no qual é muito fácil adicionar módulos e componentes. Lá basta você adicionar um .php e criar a tabela, pronto. Tentei fazer algo semelhante, mas orientado a objetos. Acabei descobrindo que o esforço para implementar tal flexibilidade era tamanha que eu precisaria de uma equipe para desenvolver um Simples e Idiota CMS OO. Acabei chutando o balde e implementando o mais simples possível.

Foi então que comecei a suspeitar da utilidade da Orientação a Objetos e dos Design Patterns. Como falei antes, até então eu considerava que o problema era eu. Que eu era incapaz de fazer algo bom utilizando o melhor da OO e dos design patterns. Afinal, tanta gente mais experiente falava bem dos patterns e tals, alguma utilidade eles deveriam ter, não é? No entanto, hoje eu vejo que não é bem assim.

Antes de mais anda não existe nenhum vínculo entre OO e Design Patterns, um existe sem o outro. Depois, existem diversos CMS OO por aí para provar que não é bem o paradigma que tem problemas. Em boa parte deles adicionar ou remover módulos é simples, provavelmente o design que se fez para este caso do JavaFreeCMS em específico não foi adequado (aliás o Prevayler prega um paradigma Action-based em suas transações).

Não adianta você querer implementar a sua estrutura de dados com o melhor da orientação a objetos se você vai acabar migrando esses dados para um sistema relacional. Você tem um esforço considerável para identificar várias heranças, composições, agregações, relacionamentos uni e bi-direcionais e após isso mais um esforço para migrar essa estrutura para o ambiente relacional. Para variar, não existe nenhum framework de O/R que consiga mapear atributos específicos de cada abordagem sem perder em performance, em simplicidade ou produtividade. Até hoje eu nunca vi ninguém conseguir implementar um sistema completo OO e somente depois de tudo criado integrar com alguma forma de persistência de maneira transparente. A OO aplicada, com todos os seus recursos e ideologias, neste tipo de aplicação, só serve para complicar as coisas, trazer mais trabalho e problemas para o desenvolvimento.

Você está ignorando simplesmente décadas de técnicas de mapeamento Objeto-Relacional e, mais uma vez colocando problemas no Hibernate e JPA que eles não possuem. Pode explicar por que eles não fazem este mapeamento?

Segundo este conceito podemos chegar à conclusão que linguagens de Assembly foram uma coisa muito ruim, já que elas apenas adicionam uma abstração em cima do modelo “real”, de linguagem de máquina. Será que elas não trazem benefícios?

A mesma coisa pode-se dizer das aplicações request-response, que mudam de nome a cada ano, mas continuam a mesma coisa. Muitos frameworks não nos deixam fazer muita coisa da OO. Você recebe uma lista de parâmetros e devolve uma lista de resultado. Lista == tabela == relacional. Para provar, pense no seguinte, a cada resposta que um sistema como esse dá, ele carrega todos os relacionamentos de cada objeto, ou carrega apenas a parte que interessa ou que a aplicação cliente usaria? Agora outra pergunta, para isso utiliza-se VOs específicos para cada request ou um único VO com sistema de lazy loading? Implementar um VO para cada requisição é dose. Deixar por conta de um lazy loading também muitas vezes falha (ou a conexão fica aberta e bloqueia outros acessos ao banco ou ela se fecha e se o usuário pedir algum objeto, irá ter um belo “session closed”). Alguém já ouviu falar no conceito de “páginas” com Orientação a Objeto? Não né. Por que esse conceito foi criado pelos bancos de dados e implementado graciosamente com a instrução “limit” no SQL.

Acho que você confundiu um pouquinho listas de estruturas de dados com álgebra relacional. Em um programa eu posso ter listas de qualquer coisa, e elas não precisam obedecer aos princípios de álgebra relacional. Por um acaso bancos hierárquicos ou em rede não implementam listas? Por um acaso uma HashTable é relacional? Prevayler trabalha com listas de objetos, ele é relacional então, certo? Sua prova… bem, não condiz com a realidade.

2007. Faz pelo menos 3 anos que VOs são completamente desnecessários em java, se é que algum dia foram. Lazy loading funciona muito bem, obrigado. O problema de sessão aberta é contornável facilmente com algumas técnicas, apesar de sim, ser um problema real, mas nada impede que eu tenha paginação em uma consulta OO via Hibernate, basta eu fazer eager fetching (que pode, inclusive, contar com consultas polimórficas) antes.

Mas… putz…dizer que páginas foram criadas nos bancos de dados é ignorar solenemente os diversos usos de paginação em memória e outras estruturas uhm… não relacionais.

Pense na seguinte frase: Os dados saem de uma base relacional, são transformados em objetos, executam uma regra de negócio simples (Somas, médias, grupos, contatores, etc), são transformados em relacional novamente e exibidos. Esse é o fluxo de muitas aplicações web e desktop. Se é assim, para que diabos alguém adicionaria aquela transformação e destransformação para OO no meio do processo?
Não parece. É, uma coisa desnecessária. Se a regra é simples, se a arquitetura que você utiliza dificulta o processo ou se os objetivos da aplicação são “relacionais”, para que ficar inventando moda? Os Design Patterns também não escapam. Em várias ocasiões eu vi que era possível implementar padrões um pouco mais complexos diretamente na regra de negócio, como o State por exemplo. No entanto, o State é tão complexo e chato de manter que não vale apena trocar por um campo de “situação” e mantê-lo com o próprio objeto.

Sua aplicação é simples? Ótimo! Pode abrir mão do bom uso de OO e ainda assim manter uma estrutura legível e com manutenção razoável? Excelente! Só não tome isso como regra geral. Se você acredita que a complexidade de criar um programa com estruturas de dados de objetos quase nunca é justificável eu realmente não entendo o que te faz não utilizar uma linguagem que permita este design e ainda traga mais vantagens, como ASP clássico, ColdFusion, PERL+CGI ou PHP. Java pra quê?

Quanto á confusão com Patterns vou considerar respondida acima.

Obviamente, nem toda a aplicação web é tão simples assim, mas minha intuição me diz que 98% do mercado brasileiro segue essa estrutura. Apenas 2% das aplicações merecem ter boas implementações de OO e Design Patterns.

Mais ou menos concordo (mais sobre isso abaixo), mas existe um problema intrínseco aí. Como você frequentou a academia mais tempo acredito que saiba melhor que eu que existe algo chamado programação estruturada e suas variantes, dentre elas programação OO e procedural. Agora, dado que a grande bibliografia de Yourdon, Page-Jones e seus amigos mostra que fazer programas em paradigma procedural exige várias técnicas (fan-in, fan-out, coesão, divisão de módulos, controle de flags, acoplamento… lembra?) para manter um programa… hmm… editável… acho que você está saindo da programação estruturada pura e simplesmente, certo? Segundo este princípio crie classes apenas com atributos públicos sendo manipulados por funções estáticas, aliás, por UMA GRANDE função estática :P

Eu concordo em gênero, número e grau que OO pode ser um overhead tremendo quando se tem um domínio simples, e inclusive defendo arduamente o uso de DSLs simplificadas para construção de sistemas, mas simplesmente largar o paradigma OO em favor de algo que não é OO nem Procedural é retroceder para antes de Dijkstra. Só falta um GOTO.

Entre esses 2% estão, em geral, aplicações com baixa quantidade de informação do usuário: compiladores, ferramentas de BI, diagramadores de interface, toolkits gráficos, aplicações como diagramadores vetoriais, gimp, blender, engines de jogos, browsers, IDEs, etc. Aquelas aplicações de sistemas de informação que seguem a estrutura de frameworks, o estilo de linguagens ou APIs, definitivamente não precisam de mais padrões ou mais OO. Você está preso a ela, portanto faça o que ela mandar e você será produtivo, invente moda e já era! Tente trabalhar de uma forma diferente da MVC com o Swing, e você se verá enrascado. Tente transformar as entities do EJB em Business Objects e estarás f.u.d.i.d.o. :)

Sei não. Ou minha realidade é muito diferente ou a sua é meio..exótica. Nos últimos anos trabalhei em sistemas de gestão de previdência privada, billing de telefonia, análise de risco, gestão de malha ferroviária, gestão de passageiros, conteúdo multimídia, gerenciadores de conteúdo (sim! e alguns deles)… e boa parte das pessoas que eu conheço ficam com sistemas parecidos. Todos eles tinham lógica a modelar como objetos

Fiz também muito destes CRUDs simples na vida mas eles definitivamente não são 98% nem do que eu fiz nem do que as pessoas que conheço fizeram. Se alguém só faz CRUDzinhos simples que nem um Domain Model se justifica a primeira sugestão é deixar Java de lado e trabalhar com algo mais produtivo como PHP4. O problema é que sistemas crescem, se integram e mudam, e acho que é este ponto que você ainda não entendeu que um bom design, seja ele OO ou não, faz diferença.

Caindo nos bons designs você irá ver um bom design procedural e perceber que existem práticas que são melhor implementadas num modelo de objetos, como quando você precisa proteger uma estrutura de dados de acesso indevido, ou sua invariante. Foi assim que o design de aplicações evoluiu até hoje.

Concluindo, nos dias de hoje, em grande parte dos sistemas de informação, a estrutura relacional atuando sozinha é perfeita! Ninguém precisa de Objetos para tais atividades, a não ser, é claro, que você utilize um banco de dados Orientado a Objeto, aí a coisa muda de figura. Mas como muita gente tem medo deste recurso… Hoje, está bem claro para mim: Aplicações com mais regra de negócio do que informação, utiliza-se orientação a objetos. Para sistemas de informação, onde há mais dados do que regras, vai do banco. Bancos relacionais, aplicações relacionais, SQLs e etc. Com bancos OO, aplicações OO.

Isso é complicado. Se você coloca o banco de dados no centro do universo é bom colocar as regras de negócio lá também, cheia de Stored Procedures, e ficar apenas com front-ends em linguagens de programação convencionais. Do contrário o que você faz quando duas aplicações tentam compartilhar o mesmo conceito? Se eu tenho um conceito formado por um join entre duas tabelas o conhecimento sobre este formato deve ser espalhado por todas as aplicações que utilizam o conceito, e quando eu mudar a implementação das tabelas tenho que mudar TODOS os sistemas, ou criar malditas views para segurar o legado.

O modelo de SGBD como centro do universo já foi substituído há quase vinte anos, uma boa lida sobre componentes e serviços vai te dar uma luz neste tema.

No entanto, se você puder escolher que tipo de abordagem usará, saiba que o que vale é a sua intuição. Não force as coisas. Não deixe de implementar a sua estrutura OO só porque alguém te disse que deveria ser implementado o Design Pattern Xyz. Utilizando o mesmo exemplo do State, se você quer fazer uma enumeração e ficar controlando no teu objeto, faça, se achar melhor cair no mundaréu de leis do State, vá em frente. Tudo se resume a sua intuição. Se alguém disser que pode ser feito de um jeito melhor, sem atrair complexidade e dificuldade de manutenção, mande o cara refatorar o teu código e pronto! Mas, não se assuste em ver gente complicando as coisas sem a mínima necessidade :)

Sim, cada caso é um caso mas acredito que o que deve guiar a escolha técnica não é a intuição e sim a razão, derivada da experiência e estudo das diversas técnicas e práticas, arquiteturais e de design, que foram desenvolvidas pela comunidade de desenvolvedores, acadêmicos, pensadores e práticos por todas estas décadas.

Eu tenho certeza absoluta que você pode me mostrar um monte de coisas super-simples sobre sua área de engines gráficas que eu vou achar mega-complexas sem estudar o motivo pelos quais as coisas são desta ou daquela forma. Por isso que não adianta, plataforma não vence cultura.

Update:

O Vitor colocou um follow-up no blog dele. Como não traz nenhum novo argumento aos pontos aqui levantados além de fazer um bashing sem nenhum argumento concreto em cima de AOP e OO (poxa, até o BileBlog usa alguns argumentos), e cisas estranhas como “eu disse que era impossível porque não faz nenhum sentido gastar tempo e simplicidade implementando esse tipo de coisa”, questionamentos vazios como “por que HQL não implementa todas as funcionalidades da OO?” (Como se Java os implementasse…), tratar um ERP, coração de qualquer empresa, como “coisa menor”, não saber o que é eager fetching e detaching e ainda assim achar os criticar, e, principalmente, este trecho:

Shoes, pergunte para alguém das antigas se ele leu Yourdon e Page-Jones para poder programar. Não leram. Se você for olhar o fonte de alguém das antigas perceberá que tem uma organização. Não é uma OO, mas é tão organizado quanto, e certamente não baixa a produtividade da equipe. Hoje só para programar uma boa OO precisamos ler várias bibliografias, conhecer Design Patterns, e várias outras coisas que você conhece bem. Porquê? Para desenvolver um sistema onde o cara vai cadastrar e ler dados? No máximo um relatório com algumas aglutinações, somas, consultas, limites e etc?

Que me preocupa muito vindo de um estudante de mestrado (além de ser bravata, já que a maioria dos engenheiros de sistems de verdade em algum momento tiveram seu contato com análise struturada/essencial e projeto estruturado).

Eu realmente adoraria ter um debate sadio mas a falta de argumentos e o excesso de factóides, evidências anedotas, falácias e achismos não deixa. Eu realmente tentei mas fico por aqui.

Eu já vi este ponto de vista várias vezes e na grande maioria delas um pouco mais de leitura e experiência ao manter sisteminhas “simples” “de cadastro” que viraram bombas-relógio, vivem mais tempo do que deviam e têm que ser integrados, entendidos, estendidos ou meramente consertados mudaram a perspectiva. Provavelmente é só questão de tempo.