Não sei se felizmente ou infelizmente mas a API java não dá suporte a algunas coisas que são bem comuns no desenvolvimento de software. Algumas ele até suporta, mas as pessoas não usam direito. Quando se constroi um sistema do zero, algumas coisas precisam ser desenvolvidas simplesmente porque não ha nenhuma biblioteca que as tenha, e mesmo se houvese, não as teria exactamente como precisamos. Então equipas afoitas que querem logo começar a debitar entreguas esquecem-se deste pequeno promenor e não dispendem o tempo e o estudo necessário relativamente a estes detalhes. Depois o que acontece ? Acontece que como o design não coopera com a realidade, as gambiarras começam a acontecer. E todos sabemos onde isso nos leva… Então ha que ter cuidado com estes impulsos…
Não ha muita documentação sobre isto, porque é bastante trivial e se aprende nas primeiras páginas de qualquer livro sobre orientação a objetos : Classifique os conceitos. Ou seja, crie classes para os conceitos. Classes não são artefactos que permitem reaproveita código, elas são artefactos que nos permitem classificar o codigo, da mesma forma que os biologos classificam os seres vivos usando uma classificação em reinos, filos, etc, até as espécies.
Apenas uma pessoa sem noção lhe dirá que exista tal coisa como “classes demais” .. acaso existem conceitos “demais” ? Podem existir conceitos que não cabem no contexto, mas não conceitos demais. Não se poupe de criar classes , por muito simples que pareça.
Java é fortemente tipado e existe uma muito boa razão porque as linguagens de propósito geral são fortementes tipadas : permitem melhor classificar conceitos e por consequência melhor polimorfismo. Use isso em sua vantagem.
Crie tipos especiais para todos os tipos de dado, objeto, conceito , etc… que não forem suportados pelos tipos básicos do Java. CPF não é um numero, não é um texto, é um código. Não existe uma classe Code no java. Crie um objeto CPF, Telefone, etc…e se quiser até um objeto Number e Text. Afinal o number do java não tem operações aritméticas básicas como somar e subtrair.
A aritmética computacional de ponto flutuante é mais complexa do que explicam na escola. Não confie nela. Use objetos especiais para frações, taxas e sobre tudo para dinheiro. Mesmos que seja apenas para uma moeda e apenas para encapsular um BigDecimal ( mas , na real, implemente o padrão Money sem BigDecimal), mas sempre crie um tipo especifico para representar dinheiro.
Aprenda a usar Date e Calendar, mas não os use diretamente. Crie tipos especializados. Crie objetos de intervalo, muito uteis, mas inexistentes em java. Use uma API como o Joda-Time (no futuro use a API de Date & Time do java) , ou crie a sua, mas criar uma API de tempos e datas não é trivial, você precisa ter muito conhecimento de como funcionam os mecanismo. Nunca , nunca, use Calendar como um atributo de uma entidade. Isso é o equivalente a vc usar um objeto Calculadora em vez de Integer.Use Date ou um objeto que faça o mesmo que Date, ou seja, nada. É um objeto que contém um long que é o numero de milesegundos desde 1 de janeiro de 1970. Apenas isso.
Não assuma que trabalhar com tempos de datas é facil. Não cometa o erro muito básico de fazer as contas você mesmo. Nunca faça isso. Delege a Calendar ou a uma API especilizada como o Joda-Time. Nunca faça calculos do tipo o mês tem 30*24h ou assuma que uma hora sempre têm3600 segundos e um dia tem sempre 24 horas. Crie objetos para representar a duração e o periodo independentemente. Investigue até você saber a diferença entre estes dois.
Date e Calendar não dão suporte a dias uteis que é uma demanda comum em sistema, portanto você terá que implementar essas lógicas. Não é simples. A definição de dia util depende do negócio. Nem sempre o Domingo é uma folga. Feriados normalmente são lidos de um banco. Tenha isso em atenção.
Monte uma estrutura e reuse-a. Não se contente com o simples, faça-a robusta e reutilizável em mais do que um sistema. Use muitos cenários e mantenha muitos testes. Faça-a exacta, não um tapa-buraco.
Tratamento correto de exceções tem regras. Force-as. Tome atenção à camada onde a exceção será lançada, e de onde, na camada, o será. Entenda o conceito de exceção, e sobretudo a diferença prática entre exceções verificadas e não verificadas. Siga boas práticas de tratamento de exceções como se a sua vida dependense disso. Ela realmente depende. Ok, talvez não a sua vida. Mas as a sua saúde mental com certeza.
Não tente criar uma hirarquia “auxiliar” de exceções. Não faça suas exceções muito espertas, mas faça-as informativas. Enriqueça-as com parametros. FileNotFound – qual file ? ClassCastException ? qual classe ? Não use mensagens hardcoded. Use chaves de mensagem e um sistema deresource bundle para a tradução (ver internacionalização). E nunca, nunca, pelo que lhe for mais sagrado, mate um stacktrace. Se vc não sabe o que isto signfica, então vá estudar mais. Você não está preparado para trabalhar com java e muito menos para criar um sistema do zero.
Não confunda Internacionalização (i8n) com Localização (L10n). Internacionalização significa : “Nenhuma informação que seja passivel de ser diferentes entre culturas é hardcoded”. Localização sgnifica : “Faça todas as informações passives de serem diferentes entre culturas sejam especificas e coerentes com a cultura X, por agora”.
Não cometa a o erro de achar que internacionalização é sobre traduzir textos. Nem pense que não faz falta se o sistema apenas será usado em uma cultura.
Repare que eu disse cultura, e não Locale. Cultura não muda apenas entre paises e linguas. Pode mudar entre empresas e négocios e até mesmo entre departamentos da mesma empresa.
Aprenda a usar os recursos do pacote java.text como DateFormat, NumberFormat e MessageFormat. Aventure-se a criar a sua API de globalização (que soma as ferramentas para internacionalização com de localização). Crie uma convenção de nomenclatura para as chaves das mensagens. Faça-a hierarquica separando os niveis com ponto ,por exemplo: label.cliente.nome
Nunca escreva codigo de conversão de String para data ou de String para numero, etc… use formatadores. Crie formatadores para os seus tiny types. Formatações são etérias, dados são eternos.
Mas internacionalização não é apenas uma questão de estilo. O seu sistema trabalha com endereços ? Ele aceita endereços no estrangeiro ? Imagine se Amazon não aceitasse endereços no estrangeiro…
O seu sistema segue padrões internacionais ISO para pesos e medidas ? Ou é como a sonda NASA que faz metade no sistema métrico e metade no sistema de libras ? O seu sistema trabalha com dinheiro? várias moedas ? como vc grava no banco ? com duas casas decimais ? E as moedas que não têm casas decimais ? E as que têm mais de 2 casas ? Você grava datas no seu banco de dados ? Em qual fuso horário ? O seu banco suporta diferentes fusos horários ? Seu sistema é um site ? Ele atende vários paises ? qual é o encoding das suas páginas ? Não é UTF-8 ?
Sempre que vir o requisitos “Este sistema deve ser internacionalizado” trema de medo, porque vêm muita coisa ai. Não assuma que é simples, nem fácil, nem barato.
Validação não é o mesmo que consistência. Consistência : garantir que o objeto não tem um estado impossivel. Por exemplo, 30 de fevereiro é inconsistence. Validação é verificar que um objeto consistente, é usável pelas regras da aplicação/negócio. Use uma API de validação. De preferencia faça a sua mesma. É um bom exercicio de OO. Inspire-se em bibliotecas que já existem como a Apache Validator ou a JGodies Validations. Tem a JSR de Beans Validation, dê uma olhada também… quiça faça parte do futuro do java.
Modificadores ( vulgo, setters) não fazem validação. Eles fazem consistência !
Entenda que a parte que importa de um sistema de dados é pesquisa. Tenha uma API preparada para isso. Não foque apenas no CRUD, lembre-se que existem relatórios e existe importação/exportação de dados. Faça um sistema orientado a dominio. É mais simples, mas tenha cuidado de não abusar ou confiar demais em ORM. JDBC funciona muito bem, obrigado.
Use um sistema de Critérios+Intrepretador. Mesmo se usar o Hibernate. Não crie critérios do Hibernate diretamente. Isso ajudará a manter uma API de critérios que faz oq ue você quer mesmo que o Hibernate ou o JPA não façam. Nesses casos você apela para estratégias alternativas.
Não assuma que suas tabelas têm poucos dados e nunca precisará paginá-los ou carregar mais de 10 mil registros de um só vez. Vcoê precisará. Os dados acumulam-se. Tenha isso em conta desde o inicio. Use padrões como Fastlane Reader para ler muitos dados .
Não menospreze o poder do banco de dados de fazer calculos agregados (somas, médias, etc…) aproveite-se disso para aumentar a performance, mas nunca à custa de violação de camadas.
Se está com pressa use o Hibernate como motor das pesquisas, mas faça uma casca em torno dele. Ele não é perefeito e você terá que limar algumas arestas. Aprenda a mexer com Hibernate. Não é simples. Ele é bastante complexo , mas o abandone à primeira.Se tem tempo, crie sua propria API. É ainda mais complexo do que fazer o hibernate e o risco é brutal, mas o aprendizado é grande … faça você olhar o hibernate com outros olhos .. mesmo com todas as suas falhas.
Desista de usar like para pesquisas textuais do tipo que vemos em sites de e-comerce. Aprenda a usar o Lucene. Melhore a experiencia dos usuários.
Use-os. Não use tags de terceiros. É tentador, mas você cai no vendor lock-in que nem um patinho ( ou será como um “bobinho” ?). Sobretudo tags relacionadas a internacionalização e acesso. Proiba todo e qualquer uso de scripts ( excepto, talvez, em tag files). Use tag files para coisas que dependem de css ou da estruura gráfica do sistema em si e taglibs ( o nome correto é tag handler, mas todo o mundo conhece como taglib) para coias mais gerais, até para coisas que mais do que um sistema poderia usar ( como o controle de acesso).
Não use includes ( se tiver que usar use a tag jsp:include e não a diretiva include). Use frameworks como o sitemesh ou o tiles , ou desenvolva seu mecanismo. Mais uma vez, não é trivial, portanto se você não sabe, use uma API canónica. Não invente muito, use JSP e nada de velocity ou freemarker ou essas outras tecnologias de renderização. Nem sequer xml+xslt (jsp pode escrever xml também, sabia ?).
Se usa JS F ignore a parte de jsp e taglibs, mas não ignore o problema de usar componentes de terceiros.
Sim. É complexo. Muita coisa para começar uma aplicação decente, mas somos programadores java ou ratos ?
Muito bom o post, parabéns! Mostra umas verdades muito importantes que o pessoal deveria saber mas muitas vezes não sabe.
Discordo talvez só da ideia de abandonar o Hibernate na primeira oportunidade. Acho que dá pra ser feliz com ele fazendo tudo bem encapsulado como você disse.
E sou grande fã também de JSPs com meus próprios tagfiles 🙂
Bom artigo Sergio,
sobre a parte de aprender Hibernate (ou algum outro ORM) a fundo, tbm é legal ler o PoEAA, tem tudo muito bem mastigadinho lá.
Outro ponto formidável é a sua diferenciação entre i18n e l10n, pra falar a verdade, é raríssimo alguém que conheça esses conceitos bem, e é importante diferenciá-los.
Parabéns.
Muito bom o artigo. São atitudes simples que todo bom programador precisaria ter, mas como a presa é inimiga da perfeição, deixamos de lado certos princípios que poderiam nos ajudar muito num futuro próximo. Parabéns!
Olá !
Muitos avisos interessantes para os marinheiros de primeira viagem ou mesmo relaxados no desenvolvimento, mas não concordo onde vc instrui à construir novos frameworks de tratamento de datas, ou validadores,etc… Hoje em dia, é muito difícil não encontrar algo pronto e maduro que não sirva para vc.
O maior problema que encontro nos projetos que passo, é exatamente os desenvolvedores fazerem seus próprios frameworks, incluir essas horas durante o desenvolvimento e não entregar nada de valor para o cliente e culpar o Java como sendo uma linguagem de desenvolvimento lenta.
Construir esses frameworks para tecnologias mais comuns, deixe para fazer em casa, em sessões de Dojos, pq no trabalho o que faz um cara bom é entregar software de valor para o cliente.
[]’s
Excelente artigo. Direto ao ponto e realmente recheado de dicas importantes.
A mensagem que deve ser entendida não é “faça seu próprio framework”, porque isso é dificil. Sobretudo no assunto datas e tempos. Sempre que possivel use frameworks já prontos. Eu mencioneio o Joda-Time, Apache Validation e o Hibernate, por exemplo. A mensagem é “não use frameworks de terceiros diretamente” , tente sempre encapsulá-los numa API sua. Isto porque eles sendo bons , não são perfeitos , e alguns são bem trabalhosos (o JFreechart por exemplo) , alguns fazem coisas que não são intuitivas, como o Hibernate. Então, uma API sua, sempre pode ser usada para limar essas arestas.
Fantástico artigo, parabéns mesmo. Poucas coisas não concordei, beeeeeeem poucas coisas.