Discutiremos aqui os próximos passos a serem dados, como a normalização de endereços, aumento(substancial) do pack de métricas e a inclusão de novas features a serem propostas(e discutidas) nesse tópico.
Lembrando que todas as features/sugestões que forem enviadas DEVEM vir acompanhadas de um testcase(JUnit) e comentadas com as explicações necessárias.
bom, então vamos lá …
Eu acessei o codigo da api e tenho algumas duvidas/perguntas/sugestões.
Primeiro que tudo a padronização de nomes. O ideal é programar usando inglês porque facilita a criação de nomes compostos , mas por outro lado existem coisas muito especificas para as quais não existe uma tradução direta. Eu gostava de saber qual é a directriz: se se deve preferir o ingles ou não. Em qualquer dos casos a API pecisa de uma refactoração geral relativamente a isso. sugiro que se use Ingles e que se traduzm ou abreviem os nomes especificos. Exemplo Inscrição Estadual = IE
Mas o javadoc acho que deveria ser primeiramente em portugues uma vez que o publico alvo é o brasileiro e todos sabemos como nem todos os programadores dominam o ingles.
Depois existe a falta de aplicação de design patterns e os aplicados nem sempre estão bem aplicados. Por exemplo , o chain of responsability não se aplica da forma que está sendo aplicada à logica de validação. O padrão que se deveria aplicar era Composite. Depois ha uma violação grave de separação de responsabilidade. Objectos como cnjp não se devem validar a si mesmos. Eles deveriam atuar como VO e ter objectos especiais para a validação. A minha proposta é que se implemente a seguinte estrutura
interface Validator
public boolean isValid(Object obj) throws ClassCastException
Este objeto faz validações. Se o objecto passado não puder ser validado por ete validador uma ClassCastException acontece. (por exemplo, tentar validar CEP com o validador de CPF )
Com isto é simples criar um
class CompositeValidator implements Validator
addValidator(Validator v)
Este objecto permite adicionar vários validadores que se encadeiam na validação do mesmo objeto.
Isto permite também que sejam criados validadores de negocio e acidionados à regra. Por exemplo, o Endereço tem que ser válido E ser de São Paulo
A interface AutoValidatable com o unico método isValid() marca objetos que se podem auto validar. Mas na reaidade o que eles farão é invocar o validadadro certo.
Outra coisa são os numeros de identificação como CNPJ, CEP , etc…
Eles representam códigos alfanumericos, normalmente apenas numericos.
Eles não representam as entidades Cadastro Nacional de Pessoa Juridica, e apenas o numero do cadastro. então sugiro que os nomes sejam alterados para CNPJNumber , CPFNumber e assim por diante. A exceção é o CEP porque ele representa reamente um codigo (Codigo de Endereçamento Postal).
Em relaçao a isto tenho outro ideia. Definir uma interface marcadora chamada CodeNumber que implementa CharSequence e representa codigos alfanumericos com métodos utilitários como asDigits() que retorna um int[] com os digitos nos lugares certos e digitAt(index)
Isto facilita imenso na hora da validação pq a transformação para int é muito usada. CharSequence tem o método length tb muito util na hora de fazer validações. Todos este codenumber são imutáveis e aceita uma string no cosntrutor. Esta strng sempre será desformatada e guardada internamente desse jeito.
Depois , a classe Brazil . esta classe tem metodos estáticos utilitários para as operações mais comuns como por exemplo Brasil.cnpj(“[telefone removido]”).isValid()
isto poupa o utilizador de ter que criar um monte de objeto vara fazer algo simples. Mas, pode se quiser, criá-los. Isto é apenas para ajudar.
Existe a classe UF com várias instancias estáticas.
Esta classe tem dois problemas: 1) cada UF contem uma inscriçãoEstadual.
Isto não é necessário e obriga a construção de objectos que podem não vir a ser usados. A UF deveria ter apenas o nome e sigla. Esta sigla é na realidade um codigo curto para o estado o codigo mesmo é “BR-SP” como definido pela ISO . Acho que isso deveria ser tomado em conta colocando os métdos getCode() e getShortCode().
A lista de estados é obtida com o metodos estático values() ,mas internamente ele cria um colection. Isto poderia ser feito via reflection e usar um cache. O retorno deveria ser um array para evitar alterações ou um unmodifiableCollection.
Esse objects Inscriçãoestadual são na realidade validadores misturados com VO. como sugeri , o ideial é separar isso. Um objeto IENumber heradsndo Codenumber para colocar os numeros e Objectos validator para o validar. Os validadores obdecem a uma naumenclarura exemplo IEValidatorForSP com o UF no fim. Desta forma é possivel obter os validadores por reflection e ter o metodo estático IEValidator.getInstance(UF) que obtem o validador correcto para a UF. Dessa forma é simples criar o método Brazil.ie(“numero”).isValidFor(UF)
Isto, junto com o CompositeValidator permite fazer validações em cadeia de forma simples e permite o codigo dos validadores e dos codenumber ser muito simples. ao contrário do que é agora com métodos estanhos que dizem servir para encadear as validações (?!)…
Eu criei este códigos mas estão noutra máquina, eu deixarei eles aqui assim que possivel. Mas enquanto isso aqui ficam as sugestões para discussão. (tenho mais sugestões, mas fica para depois)
Na minha opinião a padronização e aplicação dos desing paterns só ajuda o desenvolvimento e o uso da API. E ainda estamos a tempo de marcar deprecated ou até mesmo remover métodos e objectos que não cumpra seu papel
outro assunto é relatiamente a casos de uso. Em que cenário, por exemplo, eu iria querer validar uma Inscrição Estadual em vários Estados?
Uma lista deste casos, traduzida numa unidade de teste seria tb util.
RafaelRio
Boa pergunta. Vai saber… Mas se quisesse, poderia validar uma incrição estadual para um ou n estados, de forma orientada a objetos.
Dificilmente um sistema lida com IE de apenas um estado. Quando tiver que lidar com n estados, isso já estará pronto. É só pegar e usar, e vai evitar que muita gente use laços for para validar uma IE.
sergiotaborda:
o chain of responsability não se aplica da forma que está sendo aplicada à logica de validação. O padrão que se deveria aplicar era Composite
Sério? Como assim não se aplica? O que se quer é que cada objeto cuite de sua própria responsabilidade (validar a IE para um estado) e, caso não consiga, delegue a tentativa para o próximo.
Por que deveria usar Composite? Não entendi sua preferência. Os dois padrões têm suas semelhanças. Entre as diferenças fundamentais, Composite é padrão estrutural, tem o foco em processar coleções de objetos primitivos ou compostos. Veja aqui.
Eu usaria Composite, por exemplo, se precisasse calcular o valor do salário de todos os empregados de uma empresa. Chain é muito melhor para delegar responsabilidades, permitindo que cada objeto faça apenas o que foi desenvolvido para fazer.
Ironlynx
Deve-se preferir o inglês.Talvez a dica de abreviação de IE e outras seja válida.Mas cuidado para não termos um JanuaryRiver ou coisas do gênero! :shock:
Eu já falei para o Rafael, e vou falar para você(Sérgio):Cuidado ao usar patterns numa API de validação.Ainda mais usando java 1.4.A BU, é um “cinto de utilidades” do programador.NÂO devemos abrir mão do desempenho para programar de forma mais elegante.Por enquanto isso não ocorre, mas depois que ela estiver inchada, poderá ser difícil o refactoring.
++
sergiotaborda
Chain of Responsabiliy = Cadeia de Responsabilidade , como foi dito quando um objecto não sabe/pode/quer fazer o que tem a fazer ele delega ao próximo. Próximo é um conceito relativo, não significa que ha uma arvore, nem que o proximo existe.
Exemplo do padrão CoR são os Filter da tecnologia de servelt e os proprios servelet em si. Filter é mais obvio pq vc pode encadear os filtros quando o request vai para o servelet e na volta
Isto é CoR.
Os servelet usam o mesmo pattern através de RequestDispatcher. Aqui a delegação é explicita, o servelet escolhe outro servlet para delegar o trabalho. Nos filtros ela é implicita, fica denifia no web.xml.
Pq este padrão é ruim ? Ele não é ruim. ele é otimo, mas para aquilo que se pretende. Existe uma diferença fundamental entre um objecto Request/Response e um objecto como CNPJ. A diferença é que a cada passo cada membro é livre de ler e escrever no objecto que lhe foi passado. É como aquelas brincadeiras que uma pessoa fala algo no ouvido da outra e assim por diante e no fim o que a ultima pessa fala é diferente do que a primeira disso. Isso se deve a que os membros da cadeia mudaram (ou não) a mensagem. É um padrão para processamento de mensagens. Ora, CNPJ não é uma mensagem, ele não pode ser manipulado.
Composite é muito simples de implementar e usar. Um Validador que é composto de outros validadores. A ordem não é pre-estabelecida e com uma interface como validator é muito simples o usuário criar outros validadores para coisa mais especificas ou de negocio.
Exemplo: a API aceita 00000000 como um cpf válido. possivelmente o programador que a usar não vai querer isso. Ele pode introduzir um validador na cadeia para não permitir isso, mas é opcional. claro que a API irá prover um validador mais restrictivo (espero que vá) ,mas o seu uso é opcional.
Poderia ser criado tb um validador complementar ou seja, ele aceita o valor se algum dos seus validadores o aceita (OR). Este conceito é diferente do outro que só aceita se todos aceitam(AND). Desta forma
por exmeplo uma string poderia ser aceite como CNPJ ou CPF desde que fosse válido para um dos dois.
embora as classes de validação sejam para simplificar as classes e os mecanismos ela servem para uso da API, o usuáro não é obridado a usá-las. Como eu falei antes ele irá usar Brasil.ie(“83857475”).isValidFor(UF).
MAS uma API é melhor quando dá mais liberdade ao usuário.
O que eu estou fazendo no primeiro codigo ? Estou adicionando inscrções estatuais umas às outras ?! e pq coloco o numero em rs ? poderia ser rj ?
Fora isso , o codigo tem comentários assim “isto é necessário para a validação em cadeia funcionar” … meio estranho , não é ?
E na segunda forma ? Estou criando um validador, composto de vários validadores e pedindo que seja validado uma inscrição estadual que não sei a que estado pertence.
Vcs que digam qual acham mais simples.
Por que deveria usar Composite? Mas hei, nada disto impde que exista um IENumber.isValidFor(UF uf). so que ele irá usar o validador internamente e não ele mesmo processar a validação.
Sim, mas qual objecto ? Um objecto InscriçãoEstatual pode validar-se a si mesma ? Isso é como eu dizer que sou otimo jogador de futebol. Eu, sobre mim, digo o que quiser. A responsabilidade tem que ser de um validador, certo ? (é o treinador/olheiro que avaliaria se sou bom ou não, não eu mesmo). Até porque existe uma razão muito simples para que o objecto não se possa validar: validação pode ter muitas regras , nem todas préviamente conhecidas pela API. Imagina um email Ele pode ser validado com base na mascara, mas tb com base no dns do servidor e até mesmo enviando um email para o endereço, e ainda fazendo todas ao mesmo tempo. O ponto é que a validação que a API se propoe é apenas uma das muitas possiveis.É a validação padrão.
Não segundo a diretiva chamada de Separação de Responsabilidade (Separation of Concerns , cuja tradução literal é Separação de Preocupações). O objecto CodeNumber deve preocupar-se em tranportar os dados e fornecer operações simples com eles, como asDigits() , o validador preocupa-se em validar o CodeNumber e o formatador em formatar e desformatar o Codenumber de uma string. Compara isso com
Number e NumberFormat , Date e DateFormat. E para validação veja a API de validação usada no JGoodies.
Porque é mais simples de entender , usar e implementar. Reduz código nos objectos de numeros , centraliza a validação e sua regras e é mais flexivel para futuras alterações/extenções. Facilita tb o teste de uniddae pq se limita o dominio de objetos a testar por vez
quanto ao desempenho… as implementações que eu vi não sao failfast. Por exemplo a de CNPJ calcula os dois digitos verificadores e depois testa os dois. Ela tem que testar o primeiro, se der errado já retorna false e pronto. Isso é Failfast e é mais rápido. imagine validar 1000 CNPJ tendo que calcular sempre os dois digitos verificadores… Outras coisas o uso de coleções em vez de arrays e coisas assim , menos preocupantes… mas que limitam o desempenho da mesma forma.
Programar de forma elegante é importante, sobretudo num projeto opensource porque:
simplifica o codigo quase sempre caido no paradoxo do inventor (quando vc tenta fazer mais generico vc resolve mais problemas de formas mais simples)
É mais facil as outros programadores entender sem ter que ler comentários e ao usuario final de usar.
É normalmente mais eficiente e extensivel.
Evita refactoring constante e quando necessário ele é minimizado.
Os programadores aprender mais sobre design e patterns.
RafaelRio
Sérgio, suas idéias são ótimas.
Mas eu sugiro que você estude um pouco mais a API da BrazilUtils, e depois estude como funciona a implementação. Ninguém utilizou Chain para validar CNPJ ou CPF. Você confundiu tudo. Depois, veja como funcionam as classes de validação de Inscrição Estadual.
Não, não está! Como eu disse, estude um pouco mais a biblioteca e suas classes.
Composite seria útil se eu tivesse uma série de objetos Inscrição Estadual e tivesse que realizar processamento em cima de todos eles. Não é isso o que acontece. O que temos é uma Incrição Estadual e várias classes esperando pela chance de lidar (validar) com essa Inscrição Estadual.
A validação para CPF e CNPJ ainda não está pronta. É a única API lançada na versão 0.1 que talvez sofra alteração. Certamente levaremos suas idéias em consideração.
RafaelRio
Sugestão, tenta escrever menos, focando num assunto por vez.
E lucubrar muito em cima de um assunto só também não ajuda. Melhor ir para as próximas questões. Tem muita coisa que merece ser discutida.
Ironlynx
Eu entendi o seu ponto.E é por isso que o Rafael disse que essa parte ainda não está pronta.Não sei se vc sabe, mas o Douglas(outro Owner) trabalha no Serpro, e parece que está perigando mudar a forma de cálculo/ou ter mais números CPF/CNPJ, por isso ainda teremos que ver o que faremos sobre isso.
Programar de forma elegante é importante, sobretudo num projeto opensource porque:
simplifica o codigo quase sempre caido no paradoxo do inventor (quando vc tenta fazer mais generico vc resolve mais problemas de formas mais simples)
É mais facil as outros programadores entender sem ter que ler comentários e ao usuario final de usar.
É normalmente mais eficiente e extensivel.
Evita refactoring constante e quando necessário ele é minimizado.
Os programadores aprender mais sobre design e patterns.
Vc tocou num ponto chave aqui.Programar de forma elegante não implica em necessariamente usar DP para tudo. Implica em aplicar corretamente os conceitos OO, usar Herança com cuidado, programar por interfaces…
O problema que eu vejo as vezes com tanto DP,é IMHO, que eles muitas vezes atendem corretamente a UMA solução de programação, e são aplicados a finalidades distintas aos quais foram projetados. Singleton que o diga…
Mas e sugestões de features, tem alguma(s) em mente?Tempos atrás, o Meyer ficou de me enviar uns detalhes de um pack de Datas, algo que é deficiente pacas na API da JDK.
renatosilva
Serpro? Meu sonho…
dsiviotti
Oi Pessoal,
É bom iniciar um novo tópico pra tocar o projeto. Vamos aproveitar este tópico do BrazilUtils e otimizar as discussões sobre a API. Devo lembrar a todos que o objetivo desse tópico é fazer o código, bem como o trabalho da API como um todo, evoluir. Sempre vamos encontrar críticas e isso é normal. O código sempre poderá melhorar e isso também é normal.
Várias vezes no outro tópico algum membro do fórum postava várias boas idéias apontando vários erros/equivocos no código proposto. Muitas vezes eu já tinha visto esses erros e na maioria delas eu até concordava com a crítica. Não corrigir ou não ter feito da melhor forma da primeira vez pode simplesmente ser falta de tempo e/ou disponibilidade pra se dedicar ao código.
Se vocês procurarem no outro tópico vão ver que eu mesmo critiquei a forma como está a parte de Cpf/Cnpj, mas esta é a forma como já está lá e funcionando. Espero melhorar e fazer o melhor possível. Sempre procuro trabalhar assim, mas vamos ter em mente que este é um projeto open source. Nos últimos meses tenho tido quase nenhum tempo e não pude fazer nem um décimo das alterações que eu gostaria de ter feito antes de soltar a primeira versão. Na verdade, só deu pra passar o código pra 1.4 e olhe lá. O pacote de endereço nem saiu.
Uma das funções de um projeto como este é que quem participa aprende. E aprender errando faz parte do aprendizado. No outro tópico tá cheio de exemplos onde a API foi pra berlinda (pra usar um termo leve) e eu e Ironlyx nunca deixamos isso nos afetar. Quando pudemos fizemos o que pudemos.
Há alguns meses eu assumi a liderança de um projeto enorme e prá lá de complicado pela natureza política. Hoje eu tenho clareza que o BrazilUtils precisou de mais planejamento. Os objetivos não foram bem traçados e a coisa foi andando sempre meio sozinha e com esforços heróicos (louváveis). Eu e Ironlynx sempre dissemos que precisávamos de um gerente pois nenhum de nós tinha experiência nisso. Precisamos dividir algumas tarefas básicas como, por exemplo, alguém pra gerar as distribuiçoes. Fizemos de uma forma a aprendemos com ela o que funciona e o que não funciona.
Ao pessoal que está chegando ou simplesmente fazendo uma crítica eu peço um pouco de paciência e compreenção sobre como funciona esse tipo de trabalho. Muitas vezes vocês vão estar fazendo uma crítica à alguém mais experiente e com mais conhecimento mas que, por algum motivo, não fez o melhor código. Muitas vezes será o inverso, alguém com pouca experiência mas que precisa de incentivo pra melhorar.
Ao pessoal que está fazendo código e participanto eu peço que se preocupem mais com o conteúdo técnico das críticas que com a forma como ela foi feita. Isso é uma coisa produtiva pra vocês mesmos. Eu recomendo que vocês leiam o tópico antigo e vejam como foram feitas as críticas sobre Regex que não estávamos usando onde poderíamos (eu nem sabia o que era). Não foram nada simpáticas. Hoje em dia, aqui no projeto (trabalho), sempre sou eu que faço códigos com Regex e muitas vezes um código horroroso é trocado por uma Regex que simplifica bastante. Isso porque, ná época, eu me preocupei com o conteúdo técnico das críticas feitas, por mais sarcásticas e até pessoais que tenham sido. Comprei um livrinho de Regex e todo mundo saiu ganhando.
Bom trabalho a todos. As críticas são sempre bem vindas.
sergiotaborda
Como havia dito deixo aqui o codigo que baixei do CVS junto com o que adicionei. Eu tentei adicionar tudo em pacotes separados para vcs verem a diferença. Existem alteraçoes que eu ainda nao comentei.
Fora a inclusao de uma sub’API especifica para validaçao e a inclusao de interfaces e classes abstractas para facilitar o trabalho de validacao , existe um outro ponto mais …
Procurem em http://en.wikipedia.org/wiki/ISO_3166-1 procurem pelo brasil e cliquem em SO 3166-2:BR. Aqui sao apresentados os codigo completos dos estados e DF. Isso é um padrão internacional e não apenas do brasil.
A duvida é a seguite : não sei até que ponto a API deve ficar amarrada a consideracoes apenas brasileiras. Parece-me que sendo uma API de localização de aplicações ela tem que ser especifica, mas isso não significa que não se possam deixar ganchos para facilitar o trabalho de extençao e mesmo a compreencao da API. Com vista isto introduzi dois conceitos o t
de Unidade Territorial (TU) e o pais (Country)
TU tem dois atributos : codigo do pais e codigo de TU que seria o codigo da ISO 3166-2 , que no caso do brasil são as siglas dos estados.
FIz a UF herdar de TU por uma questão para que de certa forma se possa ser compativel com a ISO e ao mesmo tempo poder diferenciar explicitamente as UF . A UF tem um nome em protugues que a TU não tem ( e não teria como ter) . A classe Brazil que falei antes é um Country. e as UF são TU. à primeira vista isto é inutil ,mas serve para deixar claro o que Brazil e UF são , assim como compatabilizar isso com a ISO e possivelmente depois com as API de Locale e TimeZone (trabalho futuro)
Isso me leva a outro ponto: parece que estão querendo incluir uma sub-API para tratamento de datas. Isso é muito complicado e parecer ser a reinvenção da rda, já que a PI joda Time está ai … mas eu não li nada sobre quais as intenções de ter mais uma API para isso… Contudo, mesmo que fossemos fazer essa sub API sugiro que seja apenas uma fachada para a api JODA -TIme, que no futuro possamos substiturir pela Date and Time API que será o padrão logo, logo.
Em relação ao que vc escerveram:
Com o modelo de CodeNumber e VAlidator a transição para um outro modelo de numeros e valdiaçoes é simples. Podemos ter o validador CPFValidator e CPFValidator2007 (supondo que o novo padrão entre em 2007) e com compositeValidator poderemos validar os dois simultanemante. Acho que isso não será um problema se usarmos esta estruttura.
Defacto eu não tivemuito tempo para estudar a API, isso devendo-se principalmente ao fato de que ela é dificil de ler e ao facto de que não domino algumas partes, como a barcode API. O meu aport neste momento
vai mais na organização e estrutura do codigo, por isso realmente não me prendi com a implmentação (aliás, pq estou propondo outra) Mas tentei implementar o algoritmo de validação de CNPJ e IE de são paulo para demonstrar as vantagem do novo modelo que proponho. Deem uma olhada por favor. A minha procupação com a API é que ela parte de conceitos muito simples que são tratados -não se ofendam - de forma simplista, mas que não são tão simples assim porque envolvem internacionalização. (como telefone, por exemplo, mas falarei disso outra hora). VC poderão argumentar que o objectivo não é fazer uma API válida para outros paizes que não o brazil, mas ai eu teria de invocar o paradoxo do inventor e o facto de que se api é compativel com outros paizes poderiamos ver, no futuro, algum grupo extendê-la para o seu ppr pais sendo uma mao na roda para quem trabalho com expostações/importações.
Quanto ao texto extenso, vcs vao desculpar mas eu não tenho muito tempo e tenho que deixar bem claro o que proponho para minimiar duvidas e portanto futura escrita. Nas próximas semanas não vou poder usar o meu computador de desenvolvimento por isso apenas estarei conversando com vcs sobre a API, mas assim que me for possivel estou disponivel para codificar mais coisas.
P.S: Deem uma olhada no pacote adress onde tem um esboço do uma api para endereços Uma outra coisa que parece simples, mas não é.
RafaelRio
Para os próximos lançamentos, temos que deixar mais claro o que exatamente foi lançado, o que está por vir, qual o estado das coisas no repositório no Java.net. Enfim, todas aquelas decisões que fazemos via Skype ou e-mail.
Isso vai ajudar quem quiser colaborar e nos ajudar também. Por exemplo, não adiata criticarem código para normalização de endereços ou telefone, simplesmente porque vamos mudar tudo aquilo que está lá. Tanto que essas features não saíram na versão 0.1.
Agora, como é que as pessoas vão saber disso se nós não publicamos nada a respeito? :roll:
RafaelRio
Aliás, Douglas, Ironlynx, aproveitem e deixem claro quais as principais atividades de vocês na BrazilUtils no momento, quais as features esperadas para a versão 0.2, onde precisam de ajuda, pedidos de sugestões, etc.
Eu começo!
[color=darkblue] [/color]
Os meus maiores esforços vão para a normalização de endereços, que segundo o Douglas, será refeita totalmente.
Além disso, terminar o tutorial sobre as features da BrazilUtils 0.1 - faltam CPF/CNPJ e código de barra - e deixar o código do que já lançamos mais “parrudo”, com ajuda de ferramentas.
sergiotaborda
O que significa exactamente “parrudo” e “ajuda de ferramentas” ?
Ironlynx
sergio, vamos ler com carinho as suas sugestões.
Bom, quanto as features, eu vou prosseguir com o pack de métricas(já tem umas centenas para entrar), e eu estava esperando idéias do pessoal principalmente na parte de Datas(que muitos reclamam, reclamam, mas não dizem direito o que querem) e talvez, Criptografia(ago + ou - básico).
Vou deixar aqui um aviso(já mandei por email):
Todos os usuários NÂO ativos com roles diferentes de Observer serão devidamente “EXONERADOS”, por isso quem quiser participar, que entre selecionando a role Observer.Há mais de uma centena de Developers/ContentDeveloper que nunca disseram nem um oi.Isso dá uma falsa grandeza ao projeto que não temos.
sergiotaborda
Isso de datas vai mesmo entrar ? Qual seria a vantagem/diferença para as outras API de data ?
A meu ver a vantagem seria se focasse o calendário usado aqui , possivelmente com hipotese de consultar feriados e funcionalidade de dias úteis/ de trabalho
Algumas ideias seria:
o)Uma classe genérica chamada Interval para trabalhar com intervalos de qualquer classe que seja comparable ou tenha um comparator. Esta seria util em geral tb para a parte de moeda e de quantidades/métricas
o) Um TimeInterval que herde de Interval para intervalos de tempo em especifico. TimePoint para pontos no tempo que seria as estremidades do intervalo.
o)Depois classe para data sem hora, hora sem data e hora com data.
o)Conversão fácil para objetos do pacote sql.
o) class Month e Year que seriam TimeInterval e a classe Day
o) Month e Year seriam iteraveis Year itera os meses e Month os seus dias
o) permitir calculos de datas/ horas
// formato iso ano-mes-diaCalendarDateaniversario=newCalendarDate(2008,1,1);Quantofaltaparaoaniversárioacontardehoje?Periodperiod=CalendarDate.today().until(aniversario).toPeriod();System.out.println(period.toString());// P0000-07-01T12:23:14
P0000-07-01T12:23:14 <- padrão iso para periodos que significa que falta 7 meses , 1 dia , 12 horas , 23 minutos e 14 segundos para o dia 2008-01-01 à meia-noite.
O primeiro devolde o hash propriamente dito, o segundo devolde o hash codificando em base64. Este é muito usado para passwords por exemplo.
claro que teriamos tb CriptoUtils.base64(byte[] bytes);
Dinheiro
Vamos trabalhar com várias moedas ou só reais ?
Money
ammount
java.util.Currency
// operações de soma etc…
// operações de divisão inteira e parcelada.
java.util.Currency é importante se for para várias moeda, porque contém a informação de quantas casas decimais a moeda aceita (nem todas as moedas tem centavos… algumas tem milésmos e algumas não tem parte decimal)
O truque do Money é usar um long internamente e não um BigDecimal que junto com Currency mantém tudo ok. E a importancia dele é na hora da divisão porque não pode desaparecer/ser criado dinheiro durante a operação.
uma classe abstrata para conversão entre moedas seria interessante tlv possamos fazer uma implementação simples com JDBC (tabela de cotações) para exemplificar. Ou lendo de um xml que seria bom para teste.
Teriamos tb Money m = Brasil.reais("124587") e Money m = Brasil.reais(1458,87) para facilitar as construções.
Formatação já existe com CurrencyFormat
pack de metricas: o que é isso a final ?
Pelo codigo parece-me que é conversão de unidades, mas é só isso ?
Espera-se poder converter todas as unidades para todas as outras da mesma especia ? qual é o objetivo e a necessidade aqui ? envolve calculos também ?
Ironlynx
É esse o ponto.Não temos por objetivo concorrer com Time and Money ou Joda.
São apenas coisas específicas que o pessoal pede.
O Philip e o Fernando se não me engano tinham idéias sobre isso também.
Para datas me parece perfeito.
Eu já tinha exposto aqui outrora(ná época pensei até em Bouncy Castle), e eu acho essa abordagem mais simples melhor.
É inegável a preferencia por reais, mas se alguém tiver algo pronto para implementar, não vejo o porquê de não fazê-lo.
No que tange a conversão, sim é só isso, até pq a API mais completa existente nisso é feita em javascript.Não existe nada disso em Java. Isso é uma feature que pode parecer imbecil(até pq é um mero conversor), mas todas o são até a necessidade de usá-las.
A maioria das pessoas não sabe por exemplo, que não existe KMH ou km/hora e sim km/h.
qual é o objetivo e a necessidade aqui ? envolve calculos também?
Poderá envolver, mas não no momento.É apenas um simples conversor de unidades relacionadas.
Nós não julgaremos as features(o q é idiota para um, é útilpara alguém) eu por exemplo, poucas vezes precisei de algo relacionado a datas, no máximo:
SimpleDateFormat formatoData = new SimpleDateFormat("dd/MM/yyyy");
Date data = new Date();
System.out.println(formatoData.format(data));
ou
Date d = new Date();
PreparedStatement pstmt = consulta;
pstmt.setDate(1,new java.sql.Date(d.getTime()));
Mas sei q muitos precisam de coisas mais sofisticadas do que isso.
Sérgio, você gostaria de implementar algumas dessas suas idéias para nosso projeto? Como Criptografia ou datas para os dias úteis?
sergiotaborda
É esse o ponto.Não temos por objetivo concorrer com Time and Money ou Joda.
São apenas coisas específicas que o pessoal pede.
O Philip e o Fernando se não me engano tinham idéias sobre isso também.
Se o objetivo não é “concorrer” , então qual seria ?
Para o básico que vc exemplificou o java base chega e sobra…
Concerteza. Conto em pode enviar alguma coisa no fim de semana, baseado na estrutura que mostrei,mas até lá esperava por sugestões/criticas/ ideias e mais informação sobre o objetivo dessa parte da API.
Ironlynx
Essas API´s são focadas só nisso(datas), por isso serão sempre muito mais especializadas.A função da BU é ser um “cinto de utilidades” do programador.É ajudar no dito “trabalho de corno” do dia-a-dia.
O objetivo é podermos prover soluções simples para problemas cotidianos(e outros nem tanto) para o dia-a-dia de um javaman.No fim de semana eu dou uma olhada na sua estrutura, reinstalei meu eclipse só agoradepois de uns bugs com o 3.3M3…
sergiotaborda
Essas API´s são focadas só nisso(datas), por isso serão sempre muito mais especializadas.A função da BU é ser um “cinto de utilidades” do programador.É ajudar no dito “trabalho de corno” do dia-a-dia.
O qual seria esse “trabalho de corno” do dia-a-dia ? Eu queria exemplos do que está falando, pq não tou entendendo a diferença / utilidade dessa API
RafaelRio
A BrazilUtils visa aumentar a qualidade e produtividade de programadores que precisem de rotinas específicas ligadas ao dia-a-dia brasileiro.
Serve para que eu e outros colegas não tenhamos que escrever cada um por sua conta rotinas para validar Inscrição Estadual, CPF/CNPJ, conversão de valores métricos, colocar valores em Real por extenso, além de outras features que vêm por aí.
Afinal, duas ou mais cabeças fazem algo melhor do que uma.
Agora eu não entendi. Então qual o seu interesse aqui? Mais uma vez, sugiro que você estude um pouco melhor a API - nem estou falando da implementação - e veja os últimos posts na primeira thread sobre a BrazilUtils. Terá respostas para muitas de suas perguntas.
sergiotaborda
A BrazilUtils visa aumentar a qualidade e produtividade de programadores que precisem de rotinas específicas ligadas ao dia-a-dia brasileiro.
Serve para que eu e outros colegas não tenhamos que escrever cada um por sua conta rotinas para validar Inscrição Estadual, CPF/CNPJ, conversão de valores métricos, colocar valores em Real por extenso, além de outras features que vêm por aí.
Afinal, duas ou mais cabeças fazem algo melhor do que uma.
Agora eu não entendi. Então qual o seu interesse aqui?
Um subconjunto de uma API ainda é uma API…Eu estava especificamente falando da API de datas !
Como a BrazilUtils para datas seria usada na prática , exemplos de casos de uso para que eu entenda a diferença entre ela e outras API de data que existem. Uma vez que o objetivo não é inventar a roda então qual é o objetivo dessa parte da API ?
Deu para entender ?
RafaelRio
Sim, agora ficou claro! 8)
Acontece que nós não temos um conjunto fechado e pronto de requisitos. Nós estamos aberto para solicitações de features a partir da comunidade, e entre essas funcionalidades estava algo relacionado a datas.
Mas exatamente o que relacionado a datas, isso nunca ficou claro e é por isso que não temos nada sobre isso ainda na BrazilUtils.
Damos prioridade aos requisitos que já estão bem definidos. Por exemplo, assim que eu terminar de escrever o tutorial da versão 0.1, começarei a implementar a normalização de endereços.
Essa normalização de endereços depende do Douglas. Trata-se de padronizar a forma escrita de um endereço num software. Por exemplo, quando alguém escrever “R. ERNESTO da SilvA, 168”, após a normalização o endereço poderá ficar “Rua Ernesto da Silva, 168”.
Isso é bem trabalhoso por causa da quantidade de logradouros e da imensa variedade com que são escritos, além de ter que que contar com flexibilidade de configuração - talvez alguém possa querer normalizar tudo para maiúsculas.
Se você tiver interesse em colaborar, acho que pode começar por aqui, nos ajudar nessa feature. Mas, como disse, essa funcionalidade de normalização depende do Douglas, o que equivale a dizer que ele tem o know-how sobre isso e tudo passa sobre o crivo dele.
Então a primeira coisa que temos que fazer antes de enviar código é obter maiores informações para que isso não fique dependendo demais dele e fique parado caso ele não tenha tempo de trabalhar na BrazilUtils.
Ironlynx
Exato.Esse é o ponto.
Imagine só o tempo que se perde só procurando requisitos para essas rotinas…
RafaelRio
Douglas, essa é pra você. Estava fazendo testes adicionais como combinado, daí encontrei um erro.
public static boolean isValid(String cpf) {
String s = cpf.replaceAll("[^0-9]*", "");
if (s.length() != CPF_DIGITS) {
return CpfCnpj.isValid(cpf);
}
return false;
}
Esse modo está retornando falso quando o CPF é verdadeiro e vice-versa. Segue o código corrigido (só troquei != por ==).
public static boolean isValid(String cpf) {
String s = cpf.replaceAll("[^0-9]*", "");
if (s.length() == CPF_DIGITS) {
return CpfCnpj.isValid(cpf);
}
return false;
}
Across all Java projects on Ohloh, 35% of all source code lines are comments. For BrazilUtils API, this figure is 45%.
This high number of comments puts BrazilUtils API among the highest one-third of all Java projects on Ohloh.
A high number of comments might indicate that the code is well-documented and organized, and could be a sign of a helpful and disciplined development team.
dsiviotti
Sobre normalização de endereços:
1 - Qual é a lista dos Tipos de Logradouro que será adotada? tem uma que eu estava usando na versão que não fo disponibilizada que era baseada no site do correio). Essa questão parece boba mas não é. O que fazermos com tipos de logradouro de sistema legados? No meu sistema, aqui, tem “Buraco”, “Vala” e “Trincheira” entre outros :shock:. Todos aceitos pelos correios.
2 - Quais são os campos usados no endereço? Estava assim: TipoLogradouro, NomeLogradouro, Numero, Complemento, Bairro, Municipio, UF e CEP. Devemos usar País também? Mais algum?
3 - Tinha pensado em 2 classes pra fazer isso (além do endereco) Normalizador e Normalizacao. Onde um normalizador aplica uma (ou mais) normalização sobre um endereço. O Normalizador contém uma ou várias Normalizações. Assim o cliente da API pode implementar uma NormalizacaoEspecializado oumemso um NormalizadorEspecializado que já é iniciado com algumas Normalizações dentro dele. Normalizador tem add e remove pra colocar e tirar Normalizações. algu assim …
4 - Os Tipos de Logradouro virão em um XML ou similar? A lista de municípios também? Em resumo: O que fazer com as listas?
Esses três pontos já são um bom ponto de início. Gostaria da opinião de vocês.
sergiotaborda
A Lista de logradouros está hardcoded nos fontes, mas seria interessante realmente usar xml. A ideia da normalização é boa , contudo voto a favor de usar Format como base de tudo o que seja mexer con texto. Normalização seria FormatRule ou mesmo NormalizationRule
Se vc der uma olhada no codigo verá divisão do endereço , veja tb o codigo que eu deixei antes e compare. Eu acho que deveria ter pais sim
e cep e como campos especiais, porque isso permitirá implementar um serviço de busca de endereço pro cep.
RafaelRio
Minha opinião:
Os logradouros suportados pela API devem ser os mesmo que os Correios aceitam, sem tirar nem pôr. Se acrescentarmos ou retirarmos algo, um carteiro novato pode se perder.
País também, com certeza! E se algum exportador utilizar a API?
Esse “algu assim” é um começo. Podemos implementar isso, testar e ver onde podemos melhorar. Acho melhor debater em cima de algo concreto. Temos que literalmente experimentar, só filosofar não vai levar a nada.
XML. Vamos ter que compilar os oitocentos milhões de municípios brasileiros? :-o
sergiotaborda
RafaelRio:
4) XML. Vamos ter que compilar os oitocentos milhões de municípios brasileiros? :-o
Não é um XML com os nomes dos lougradouros, é um XML com os tipos de logradouro.
Enquanto não ha nada concreto para discutir sobre, deixem-me so chamar a atenção para 2 pontos:
Normalização de endereços é um assunto complicado. tanto que ha programas proprietários para isso. Tudo bem que façamos uma normalizaão simples, que acaba sendo quase que apenas uma formatação, mas acho que não podemos ir muito mais longe… Ou seja, descobrir a 1001 formas de escrever rua ou avenida não é tão simples quanto parece. (envolve ter um banco de dados ou vários e processá-los)
Nem todos os endereços têm a mesma estrutura. E já que se falou de colocar o pais, então cada pais tem a sua estrutura. Mas mesmo apenas no brasil existem várias estrutura, por exemplo como eu separo este endereço dos campos municipio/bairro/logradouro/numero/complemento ?
Estrada Ponta Leste, Km 07
Estrada Parque ? Km 17 ? Abobral
A resposta é: não separo. Posso dizer que o logradouro é do tipo estrada e o nome e dizer que km X é o numero ou o complemento, mas não terei bairro , por exemplo. Tlv nem municipio. E numero/complemento é em quilometros ? Como eu formato isso depois ?
A API de endereços parte do principio que todos os endereços tem esse campos, mas isso não é verdade para o Brasil e muito menos para os outros paises.
A validação de CNPJ e afins é muito util realmente , mas Datas e Endereços dava uma API por si mesma. E o pior é que excepto as validações , o resto é muito susceptivel de internacilização/localização o que dificulta muito o problema.
Agora , alguém pode dizer para focar apenas no Brasil e esquecer os outros paises. Tudo bem, mas então no brasil ninguém manipula endereços/telefones/unidades de outros países ?
Acho que vcs têm que ficar conscientes do trabalho em que se vão meter se quiserem fazer algo minimamente util. Colocar municipio/bairro/logradouro/numero/complemento num bean e jogar um formatdor em cima não vai resolver o problema… afinal isso é o que todo o mundo faz porque provavelmente tem um banco com esses campos.
Então, eu acho que poderiamos fazer :
API de validação de CNPJ , CPF e afins - é realmente util ter isto pronto
API de manipulação de dinheiro - é simples de fazer e é util.
Criptografia simples - tb util pois deve ser usado para passwords e todo o sistema que se preze te password.
API de Quantidades/Unidades aka Métricas (cuidado que esta palavra não se usa neste como sinônimo de medida física) - Esta tb é dificil deêm uma olhada em JScience para terem uma ideia de onde pode chegar a complexidade.
Aqui é muito importante o objectivo! Pelo que foi dito o objectivo é a conversão. Ora mas isso é exactamente o mais dificil!
5.a) Tal como está agora o negocio seria ter uma classe para cada dimensão e métodos para converter essa dimenção entre N combinações de unidades, por exemplo: Temperature.celciusToFahrenheit() e Temperature.fahrenheitToCelcius() e Temperature.kelvinToCelcius() e Temperature.celciusToKelvin() e assim vai.
5.b)Tudo bem, mas isto implica num código imenso e pouco organizado.
Tlv seja uma boa pensar no conceito de conversor
Converter
convert (numero)
invert():Converter
Ali eu escrevi numero pq não sei em que classe colocar. double é RUIM , mas tb não sei que precisão é necessária. Suspeito, contudo, que se tratando de unidades especiais como de energia, o uso é cientfico, então tvl seja bom usar BigDecimal.
5.c) Ou criar um objeto semelhante a money que agrega um valor e uma unidade. E por falar nisso uma classe de unidade.
Com os conversores não temos que ter uma classe para cada dimensão e poderemos ter um registro central (padrão registry) para obter os conversores exemplo:
Mesure x = new Mesure(40, Unit.CELCIUS)
Converter converter = ConversionUtils.getConverter(Unit.CELCIUS , Unit.FAHRENHEIT);
Mesure y = converter.convert(x);
Mesure x = converter.invert().convert(y); // isto resultaria em x de novo
Ou
Mesure x = new Mesure(40, Unit.CELCIUS);
Mesure y = ConversionUtils.convertTo(x, Unit.FAHRENHEIT);
E poderiamos fazer
Mesure x = new Mesure(40, Unit.CELCIUS);
Mesure y = new Mesure(60, Unit.CELCIUS);
Mesure media = x.plus(y).divide(2); // 50 ºC
e
Mesure x = new Mesure(4, Unit.METER);
Mesure area = x.time(x); // 16 metros quadrados
5.d) permitir operações com unidades diferentes mas que são da mesma especie, por exemplo grama com quilo ou km com milha.
5.e) permitir conversões por translação. Por exemplo, se não tiver o conversor km -> milha , poderia ter km -> pé e pé -> milha , o sistema concatenaria os dois para constuir um conversor km -> milha (esta é bem mais avançada mas diminuir a necessidade de criar muitos conversores)
O trabalho forte é criar os conversores para os pares de unidades e registrar no ConversionUtils
Sistema de endereços. Aqui o negocio é bem mais complexo. ´8E necessário definir um escopo para isto.
Proponho que se lista listagem como TODO pela ordem. Apenas os itens mais avançados de 4,5 e 6 podem ser bem complicados. o resto é simples, simples
P.S. ainda não vi comentários às classes que enviem …
RafaelRio
sergiotaborda:
RafaelRio:
4) XML. Vamos ter que compilar os oitocentos milhões de municípios brasileiros? :-o
Não é um XML com os nomes dos lougradouros, é um XML com os tipos de logradouro.
Não diga! :-o
Era sobre isso a que estava me referindo. Douglas, vamos ter que compilar todos os municípios brasileiros?
Sérgião, só para esclarecer alguns pontos:
Tem API’s proprietárias para geração de código de barras, e qual o problema disso? A API de código de barras da BrazilUtils está muio bem feita e será extendida.
A normalização é só para endereços brasileiros, ao menos por enquanto. O objetivo é cobrir cerca de 90% dos casos; impossível abraçar tudo.
Ironlynx
5.b)Tudo bem, mas isto implica num código imenso e pouco organizado.
Tlv seja uma boa pensar no conceito de conversor
Eu já tinha falado antes(tópico anterior) para não usarem/compararem com o JScience que é algo beemm mais pesado/elaborado no assunto.
Não será tão imenso assim.Eu já tô copiando a estrutura do onlineconversion, serão umas 25 classes e suas respectivas interfaces de constantes.
Suspeito, contudo, que se tratando de unidades especiais como de energia, o uso é cientfico, então tvl seja bom usar BigDecimal.
Nós já usamos BD, e deixamos que o usuário faça a escolha de escala.
vc não leu no meu post anterior: no fim de semana!Se eu for ler agora, vai ser uma olhada rápida e eu posso deixar passar alguma coisa.
sergiotaborda
Depois de ler todas as mensagens do topico anterior dedicado ao BrazilUtils … (os quotes são meros lembretes)
Existe uma dúvida elementar que nasceu no principio e a meu ver não está resolvida. A API é um canivete suiço que pretende ser genérica mas não muito além do brasil. Esta frase contem diverssos problemas de definição de escopo. Se a api é para ser apenas brasileira não faz sentido nomes em ingles nem preocupações com localização nem nada dessas coisas que complicam o design. Se ele é para ter um nucleo universal que se estende em alguns pontos, em particular, para o brasil ai ha que rever o proprio nome da API
Se a API é brasileira o javadoc deve ser em portugues, se a API não é brasileira tem que ser em ingles e com ouro nome pois não é mais BrazilUtils se é para programdores de quaalquer pais usarem.
Esta indefinição é extremamente confusa e irrirante.
Li vários comentários sobre outros programaodres de outros paises usarem a API. Otimo, então deixemos eles entenderem a API e coloquemos um nucleo universal. Se não fizermos isso não ha como ninguem fora daqui ter sequer a ideia de usar esta api.
uma frase que achei interessante foi
como se “metricas brasileiras” existisse. Existem unidades usadas mais em alguns paises e menos nos outros e são TANTAS que foi preciso convencionar quais usar. O Sistema Internacional de Undades que é o padrão oficial do Brasil , tb é de muitos outros paises. A forma como a API de unidades está desenhada nunca irá contemplar todas as possibilidades. Por isso, 1) desiste-se e quem quiser use o JScience 2) Implementa-se o ultra-mega-muit-básico, que de tão básico é inutil 3) ou leva-se a feature a sério!!
Eu acho que se não for a sério, é melhor abolir de vez. Tal como está é muito ingénuo.
Da forma como ele está desenhado eu tenho ideia que o tamanho do pacote de métricas será … imensurável. E isso so significa uma coisa: ninguem vai usar.
Data por extenso - alguem sugeriu - que tal usar DateFormat … ora utilidade é uma coisa desconhecimento da API padrão é outra.
CpfCnpj !? o que diabo é isso ? : Um objeto que é simultamente um e outro ? é como ter um objecto HomemMulher
A API está cheia de nomes ruins como este, confusos pq que não são claros (não respeitam o principio numero de OO : espelhar a realidade)
Que tal CP com duas filhas CPF e CNPJ ? Mas tem outros exemplos…
[quote]
-Vou imprimir esse tópico inteiro pra aprender mais sobre desenvolvimento de software
(…)
(…) so fuja do codigo do (…), a menos que vc queira aprender por exemplo reverso
[quote]
Não sei o que vcs fazem na vida , mas segundo as opiniões não é programar… Eu espero que o esforço para desenvolver a API seja sério.
Será uma biblioteca de validação SIM! e tem que tem que se propor uma arquitectura SIM! Não ha casa sem arquitetura - tb não ha software, especialmente bibliotecas de uso generico.
Arriscado ? Quer dizer que depois de todo o tempo usado para criar a API ela não vai ser usada nunca pq os seus projetistas não tiveram coragem para arriscar ser mais generalistas e menos preocupados com o seu umbigo brasileiro ? Se é isso digam agora, porque em uma semana de texto ainda não vi nenhuma conversa.
Ironlynx
A API é um canivete suiço que pretende ser genérica mas não muito além do brasil. Esta frase contem diverssos problemas de definição de escopo. Se a api é para ser apenas brasileira não faz sentido nomes em ingles nem preocupações com localização nem nada dessas coisas que complicam o design. Se ele é para ter um nucleo universal que se estende em alguns pontos, em particular, para o brasil ai ha que rever o proprio nome da API
Se a API é brasileira o javadoc deve ser em portugues, se a API não é brasileira tem que ser em ingles e com ouro nome pois não é mais BrazilUtils se é para programdores de quaalquer pais usarem.
Aí eu discordo violentamente de vc.Até email de americano perguntando sobre a API eu recebi.O “foco” será o Brasil, mas utilidades gerais como códigos de barras, e outros são universais.BrazilUtils é um nome para focar a API, não diz que a API é inteiramente brasileira.Vc sabe como os EUA se referem ao próprio país?“America”.Peraí, “America” não é a do Sul,Do Norte e a Central???Um pouco de autoestima é legal nessa hora.E qualquer API java que será mexida por alguém que não esteja restrito a uma empresa específica, tem que ter javadoc em inglês.Isso não muda.O seu compilador traduz if para se???
O escopo da API é: canivete-suiço.Principalmente problemas de programadores brasileiros.
2) Implementa-se o ultra-mega-muit-básico, que de tão básico é inutil 3) ou leva-se a feature a sério!!
Aí vc cai naquilo que eu lhe falei antes.É inútil?(??)O americano queria uma coisa mastigada de métricas,simples, mas não o JScience(q tá beem mais maduro agora).
Isso é uma gambiarra e se vc leu realmente o tópico todo vc já sabe o porquê: porque irá mudar.Talvez até a forma de cálculo(nacionalmente).
O meu erro foi não por “beta” no jar… o pessoal cobrava tanto um release, que lançamos e deixamos de acertar uns detalhes.
RafaelRio
Sérgião, é a terceira vez que digo para você estudar a API e o tópico anterior. Ou seria a quarta? Já perdi a conta.
Esse comentário, entre outros, mostra que você não fez o dever de casa. Isso já foi discutido, inclusive fui eu o primeiro a criticar essa classe CpfCnpj.
No primeiro tópico da BrazilUtils tem uma reimplementação dessa API que eu fiz, eliminando a CpfCnpj, entre outras mudanças. O Douglas explicou o porquê da existência da CpfCnpj, e pela enésima vez: essa API está sujeita a mudanças.
Errado! Um exportador brasileiro de softwares para - exemplo - Japão, gostaria muito de ter em suas mãos uma JapanUtils toda comentada em inglês.
Sérgio, isso aqui é um trabalho voluntário e estamos fazendo o melhor que podemos no tempo que dispomos. Não estamos preocupados em fazer algo perfeito, mas sim algo útil e concreto. Não adianta filosofar, filosofar, filosofar e filosofar e não criar nada.
Você não viu meus comentários porque eles seriam um pouquinho rudes. Do tipo: legal que você está contribuindo com código, mas não acha que deveria primeiro entender o que acontece para depois implementar algo?
Sinceramente, minha paciência com seus questionamentos se esgotou. Se tiver uma duvida, traga algo novo, ou então procure direito nos tópicos passados.
Com todo amor, respeito e carinho :lol:
Rafael Fiume.
RafaelRio
O erro foi não deixar claro quais foram as features que saíram na versão 0.1, como havia comentado antes.
E a API de validação CPF/CNPJ deveria ter sido lançada num .jar diferente, já que é a única que foi lançada e está sujeita a mudanças.
Caboblinho está vendo o código no CVS e achando que a BrazilUtils 0.1 é aquilo ali. Tudo coisa que já conversamos, então vamos melhorar o processo de lançamento para a versão 0.2.
sergiotaborda
Em anexo o aport desta semana. Deixarei outros post com um mini tutorial de cda feature mas eis as novas features implementadas
[list]
CryptoUtil
Money
Interval
Datas - primeira fase
[/list]
Ironlynx
Sérgio, eu t^lendo aquele código anterior que vc postou agora.
Ponha as features q vc fez concentradas num único tópico!!!Abrir muitos tópicos deixa o pessoal perdido!
Ah, o pack de métricas que tá naquele exemplo do CVS não tem NADA a ver com o que foi comitado.Aquele é muuuito antigo…“BrazilianMetrics”, eu desisti disso na primeira palavrinha do cv :shock:
Depois eu posto minhas considerações sobre o seu código!
sergiotaborda
Ironlynx:
Sérgio, eu t^lendo aquele código anterior que vc postou agora.
Ponha as features q vc fez concentradas num único tópico!!!Abrir muitos tópicos deixa o pessoal perdido!
Eu já coloquei neste topico faz dias… o que está em topicos separados é o uso das features.
Como assim, o codigo no java.net não é o codigo actual ? Então qual é , e como eu o obtenho ?
Ironlynx
duvida é a seguite : não sei até que ponto a API deve ficar amarrada a consideracoes apenas brasileiras. Parece-me que sendo uma API de localização de aplicações ela tem que ser especifica, mas isso não significa que não se possam deixar ganchos para facilitar o trabalho de extençao e mesmo a compreencao da API. Com vista isto introduzi dois conceitos o t
de Unidade Territorial (TU) e o pais (Country)
TU tem dois atributos : codigo do pais e codigo de TU que seria o codigo da ISO 3166-2 , que no caso do brasil são as siglas dos estados.
FIz a UF herdar de TU por uma questão para que de certa forma se possa ser compativel com a ISO e ao mesmo tempo poder diferenciar explicitamente as UF . A UF tem um nome em protugues que a TU não tem ( e não teria como ter) . A classe Brazil que falei antes é um Country. e as UF são TU.
Lendo seu tópico e seu código, acho que não é bem por aí…
Talvez seja melhor colocarmos um BR no package para identificar que a feature é brasileira.O mundo é muito distinto, e colocar cada agregação de estado como TU(Eu preferiria q nesse caso fosse por extenso para poder dizer que cada UF é uma UnidadeTerritorial).O Brasil nem é uma federação autêntica(apesar do República Federativa do Brasil…)
Mas eu gostei da parte do Address.Country fica beeem organizado para dizer que uma feature é “daquele” país.
O verdadeiro pack de métricas é beem mais simples que aquele(tá no anexo).É só Interface-Implementação.Não foi feito para ser sofisticado.O exemplo é o onlineconversion.
Quando me mandar um código do CVS, diga em quais packages vc mexeu se não o tio Iron fica perdido…Imagina com mais de 1MB de source! :shock:
sergiotaborda
Vc pode mudar os nomes dos pacotes. Que seja TerritorialUnit , tudo bem. Unidades Federativas são consideradas TU pela ISO, então é só isso que interessa. O que as UF não são é estados. Mas ninguem está chamado state … então acho que tá tudo ok.
Na realidade os pacotes não interessam muito. Eu coloquei em BR porque é experimental. O que interessa ai é a estrutura em arvore que permite que o endereço seja formado por campos e estes campos variem de pais para pais ou dentro do propio pais.
Isto é muito esperimental e é uma alternativa ao modelo que estava sendo usado que é muito engessado ao brasil e até duvido que funcione em todo o brasil.
O que é o onlineconversion ??
Desculpe, eu achei que vc usava o CSV e o eclipse (que tem uma ferramenta de comparação de codigo). Da proxima vez eu aviso, se bem que não mexi nos pacotes existentes, excepto no UF.
Ironlynx
O que interessa ai é a estrutura em arvore que permite que o endereço seja formado por campos e estes campos variem de pais para pais ou dentro do propio pais.
Isto é muito esperimental e é uma alternativa ao modelo que estava sendo usado que é muito engessado ao brasil e até duvido que funcione em todo o brasil.
Saquei.
É o maior site de conversões da net(claro q em tempos de google…), é um “mero” conversor.Mas indispensável quando necessário…
Eu uso Eclipse(3.3M5), mas não sei pq cargas d´agua eu não consigo me conectar ao CVS! :evil:
Aquele exemplo do CVS q vc tinha me mandado era antigo pacas…acho que o pessoal tinha esquecido de atualizar aquela parte(eu tava mandando em packs separados)!Vamos atualizar isso!
RafaelRio
Apenas para demonstrar a utilidade de ferramentas específicas para melhorar o código-fonte sob vários aspectos, como FindBugs, PMD, Checkstyle, vejam a thread Cleaning up SwingX? . 8)
Ironlynx
Sérgio, seu código vai para a nossa incubadora, assim vc pode desenvolvê-lo como bem entender, e quando opessoal tiver testado bastante, pode vir a se tornar estável.Rafael, explica aqui a idéia da incubadora.
RafaelRio
[size=9]Ok, Ctrl+C / Ctrl+V do meu blog, sobre a incubadora.[/size]
A biblioteca BrazilUtils visa aumentar a qualidade e produtividade de programadores que precisem de rotinas específicas ligadas ao dia-a-dia brasileiro.
Para tanto, além das features (validações de CPF/CNPJ, conversões de medidas, normalização de endereços, e outras), é preciso contemplar aspectos não-funcionais, como compatibilidade entre diferentes versões do JDK e da própria BrazilUtils.
A confiabilidade da biblioteca está ligada à previsibilidade de seu comportamento. Exatamente por isso, a meta é não alterar a API da BrazilUtils. Mas, ao mesmo tempo, uma certa dose de flexibilidade é necessária para que a biblioteca possa evoluir.
Os usuários devem estar cientes sobre quais API’s estão maduras e estáveis e quais podem ser alteradas no futuro. Para tanto, a BrazilUtils possui o seu núcleo (core) e uma incubadora.
As API’s no núcleo da BrazilUtils não serão alteradas no futuro, garantindo a compatibilidade entre versões. A incubadora permitirá colocar código novo com mais liberdade. Será o local para ousar, aprender, inovar.
Geralmente, novas funcionalidades serão inseridas na incubadora; dependendo de sua evolução, de sua utilidade e do feedback dos usuários, serão promovidas ao núcleo. O core da BrazilUtils será distribuído separadamente da incubadora, que é opcional.
Sempre que houver mudanças importantes em cada lançamento da BrazilUtils, como a promoção de uma feature ou mudanças na API, essas mudanças serão noticiadas à comunidade.
RafaelRio
Finalmente, comecei a melhorar o código fonte da BrazilUtils com o PMD. Por enquanto, só modifiquei as fontes da API de geração de código de barra. Dependendo do resultado, eu começo a alterar as outras API's estáveis da v0.1.1.
Então mandem feedback e vejam se eu não fiz besteira. Eu testei, e parece que está tudo ok. As alterações já estão disponíveis no CVS. Qualquer coisa é só desfazer.
Algumas mudanças foram simples, como:
- definir variáveis e parãmetros como final (final para todo lado)
- colocar {} em if's, for's, etc
- substituir throw RuntimeException e NullPointerException por IllegalArgumentException
- retirar public das interfaces
- eliminar imports (não utilizados)
Como podem notar, algumas mudanças foram referentes ao estilo. Isso é mais interessante de ser feito com o Checkstyle, pois assim cada um pode codificar da forma que quiser, mas, antes de enviar o código ao repositório, utilizá-se o Checkstyle para manter o estilo uniforme.
Mas acho que isso não é necessário por enquanto. A não ser que vocês se oponham a alguma convenção especifica como {} em if's, etc, a retirada de public das interfaces e por aí vai.
Outras mudanças que considero mais importantes:
- eliminei algumas variáveis (não utilizadas)
- retornar cópia de vetores, ao invés do vetor original, evitando expor a estrutura interna da classe. Ex:
O inverso também é verdadeiro agora. Um método recebe um vetor diretamente do cliente, mas armazena e trabalha com uma cópia. Ex:
// Antes...publicvoidsetWeights(finalint[]weights){if(weights==null){thrownewNullPointerException("Weights cannot be null.");}this.weights=weigths;}// DepoispublicvoidsetWeights(finalint[]weights){if(weights==null){thrownewIllegalArgumentException("Weights cannot be null.");}finalintlength=weights.length;finalint[]copyWeigths=newint[length];System.arraycopy(weights,0,copyWeigths,0,length);this.weights=copyWeigths;}
E por aí vai.
RafaelRio
Continuando, agora na API de métricas. Surgiram dúvidas enquanto eu fazia as análises. Vamos primeiro às modificações que já fiz.
- final para todo lado
- conformidade com as convenções do JavaBeans. Na prática isso significa o uso de transient e mudança do nome de uma variável.
- simplifiquei um pouco alguns métodos.
2) Tem uma regra de degin no PMD que diz que não é uma boa ter constantes definidas em interfaces, pois estas devem definir apenas comportamento. Ex:
publicinterfaceLengthUnits{/** * meter is the standard basis */UnitMETER=newUnit("m",newBigDecimal(String.valueOf(1)));UnitBRACES=newUnit("br",newBigDecimal(String.valueOf(0.546806649)));UnitCADEIAS=newUnit("ca",newBigDecimal(String.valueOf(0.[telefoneremovido])));UnitYARD=newUnit("y",newBigDecimal(String.valueOf(1.093613298)));UnitMILES=newUnit("mi",newBigDecimal(String.valueOf(0.000621371)));UnitNAUTIC_MILES=newUnit("nmi",newBigDecimal(String.valueOf(0.000539956803)));UnitFEET=newUnit("f",newBigDecimal(String.valueOf(3.280839895)));UnitINCH=newUnit("in",newBigDecimal(String.valueOf(39.37007874)));UnitKILOMETER=newUnit("km",newBigDecimal(String.valueOf(0.001)));}
O que acha?
3) A descrição de Area diz Area is the class which allow an application to convert area metrics into other area metrics, porém várias outra classes que não tem nada a ver com Area, como Temperature, utilizam Area. Por que? Não estou criticando, é que não entendi mesmo.
4) Isso eu acho até grave: os métodos da interface Temperature começam com caixa alta, tipo CelsiusToKelvin().
5) Cadê os testes unitários para a API de métricas?
6) Não seria melhor utilizar BigDecimal do que double? double talvez não tenha muito utilidade quando alguém precisar dos valores exatos. Que tal double e Bigdecimal?
7) Por que não utilizar métodos estáticos? Ex: na classe Power, ao invés de
public class Power {
public double hpToWatt(final double energy){
return energy*745.7;
}
public double wattToHp(final double energy){
return energy/745.7;
}
}
teriámos
public class Power {
private Power() {
}
public static double hpToWatt(final double energy){
return energy * 745.7;
}
public static double wattToHp(final double energy){
return energy / 745.7;
}
}
Ironlynx
Rafael eu já tinha pedido anteriormente para limparem!!!
Lembra do email que eu disse que tava com problemas no Elipse de comitar código lá no java.net?Sua role lhe permite isso, dá uma limpada lá…
Deve ter misturado tudo…na última vez tinha código de 2004 no meio…damn
2) Tem uma regra de degin no PMD que diz que não é uma boa ter constantes definidas em interfaces, pois estas devem definir apenas
comportamento.
Na verdade eu cheguei a perguntar aqui e alguns concordaram que iria para interface e parte para uma UtilityClass.Eu, para fins práticos, prefiro uma interface(poucas constantes), mas acho que deveria sim estar numa Classe de Utilidades, devido ao número, e para não deixar uma interface sem comportamento.Sinta-se livre para refatorar isso.
Acho que os testes não subiram, e essa classe Temperature pode esqueçer.Com a JSR-275, vamos nos concentrar no que existam métricas internacionais, mas que existam também as nacionais(como as unidades de área).
Double???Caralho, essas classes com double são de 2004!!!Tem que ser TUDO String(se necessário) e BD!!!
Sinta-se livre para refatorar isso, pq no momento eu já tô quase tomando
Haldol aqui lidando com tantos clientes burros.(OBS.:Não estou falando de máquinas isoladas da rede, os chamados terminais burros não, estou falando de antas, antílopes e energúmenos que acham que podem mudar de requisitos como quem troca de roupa)
Depois eu vou lhe pedir dicas de como mexer no PMD.
RafaelRio
Já excluí a BrazilianMetrics. Estou a fim passar a borracha no pacote org.brazilutils.currency, que também só está servindo para confundir.
--------------------------------
Pode me enviar os testes de unidade? Por e-mail mesmo.
Que tal? Acho que não precisa de uma classe de utilidades.
--------------------------------
Há 3 classes envolvidas com temperatura: org.brazilutils.metrics.Temperature, org.brazilutils.metrics.TemperatureUnits e org.brazilutils.metrics.conversion.Temperature Excluo as três?
--------------------------------
Então já andou fuçando na JSR 275?
Provavelmente a API de métricas da BrazilUtils terá que lidar com a JSR 275. Será uma extensão dessa especificação? De alguma forma as duas API's terão que se relacionar. Melhor repensar a missão da nossa API de métricas, não?
Pelo que vi, eles já estão pensando em internacionalização. Mas, como você mesmo me disse e como está subentendido na página da JSR 275, eles não irão cobrir todas as unidades de medidas em uso na Terra.
--------------------------------
Era assim:
public class Power {
public double hpToWatt(final double energy){
return energy * 745.7;
}
. . .
}
CONSTANT é porque não sei qual o nome da constante (magic number, né?). Depois você terá que rever o nome dessa e demais constantes.
--------------------------------
Boa sorte com os seus usuários! Quando for a minha vez de apanhar deles, me dê umas dicas para que eu também dispense o Haldol! :P
Ironlynx
Pode me enviar os testes de unidade? Por e-mail mesmo.
Cara, agora eu não sei onde foi que eu pûs(até pq eu mudei várias vezes), mas foi algo mais ou menos assim pegando um esboço aqui (usando o JUnit antigo, que não usa anotações para compatibilidades com java 1.4):
publicclassMetricsTestCaseextendsTestCase{protectedAreafirstValue;protectedAreasecondValue;protectedAreathirdValue;protectedAreastringValue;publicvoidsetUp(){firstValue=newArea(newBigDecimal(10000),Area.M2);secondValue=newArea(newBigDecimal(234000012),Area.M2);thirdValue=newArea(newBigDecimal(789234012.12),Area.M2);}publicvoidtestConversionSquareMetersToHectaresMustNeverLostPrecisionValue(){assertEquals(newBigDecimal(1.0000000000000000000000000000000000),firstValue.convertTo(Area.HECTARE,34,BigDecimal.ROUND_HALF_EVEN));}//irá falhar publicvoidtestConversionSquareMetersToHectaresWithTenDecimalPlacesMustNeverLostPrecision(){assertEquals(newBigDecimal(1.[telefoneremovido]),firstValue.convertTo(Area.HECTARE,10,BigDecimal.ROUND_HALF_EVEN));}//irá falhar publicvoidtestConversionSquareMetersToAcresMustNeverLostPrecisionValue(){assertEquals(newBigDecimal(2.4710538146716534224824392919880626),firstValue.convertTo(Area.ACRE,34,BigDecimal.ROUND_HALF_EVEN));}//irá falhar publicvoidtestIfObjectIsNull(){assertNotNull("O objeto está com valor null!!!",secondValue);}//jamais falha }
Há 3 classes envolvidas com temperatura:
Kill!!!
Será uma extensão dessa especificação?
Nem sabemos se irá a frente né...algumas coisas estão meio turvas na minha cabeça aqui:
There are many different units, partly because the world has different types of properties, such as length and mass, that are not interchangeable in normal physics. This type of property is sometimes called a ?quantity? or a ?dimension.? The word ?dimension? fits because of the orthogonality of these properties?mass and length cannot be exchanged. Further, when we multiply physical measures the dimensions add up as exponents. For example, length times length becomes length2.
A large body of work exists that specifies the dimensions, meanings, and names of various physical quantities. In particular, the 11th General Conference on Weights and Measures in 1960 recommended a practical system of units of measurement, and gave it the name Systeme International d'Units (SI). SI defines units for the base dimensions of length, mass, time, electric current, thermodynamic temperature, amount of substance, and luminous intensity. SI also recognizes names and meaning of derived dimensions, such as area, volume, and force. For some (but not all) of these derived dimensions SI defines units, such as 'liter' for a unit of volume and ?newton? for a unit of force. SI does not have a special name for area, although other systems of measurement do (as in 'acre').
Despite the rising prominence of the metric system (the SI system), many developers have to work with non-SI units, such as feet, miles, acres, and gallons. A measurement can be expressed as a number of any unit, so long as the unit has the same dimension as the measured quantity. For example, any measure of volume can be expressed as a number of liters or gallons, because liters and gallons are units of volume, and all volumes have the dimension of length3. Therefore, a measure expressed as a number of liters can be 'converted' to a number of gallons. Converting measures from one system of units to another is a common problem, but is subject to mathematics that can help to eliminate errors.
Although errors based on confusion or miscommunication about units are common, the mathematics of units is not especially complex. When quantities are multiplied, the exponents of their dimensions are added. For example, acceleration has a dimension of length?time-2. We can multiply a mass by an acceleration to derive a quantity in the dimension mass?length?time-2. The common name for this dimension is 'force'. Quantities with the same dimension can be added and subtracted. For example, we can subtract a cup from a liter and express the result as a number of milliliters or as a number of cubic inches.
será que dará m.. com as métricas não SI?
Java package that supports modeling units should allow developers to easily and correctly perform mathematical operations on units. The package should allow developers to specify the dimension (such as volume) of a passed parameter, rather than insisting on any particular unit (such as milliliters). Finally, the package should help with representing physical quantities as strings, with support for parsing and formatting. The existence of such a package will help Java developers to create safe, correct software to deal with common problem of modeling measurements of the physical world.
Melhor repensar a missão da nossa API de métricas, não?
Exato. :?
Está de acordo?
Y!, mas nem era para essa classe estar aí...(quanto mais esses doubles) era só para estar as unidades de área,peso e comprimento.(Lembrando que eu uso o onlineconversion como base para pegar as constantes).
sergiotaborda
RafaelRio:
Outras mudanças que considero mais importantes:
- retornar cópia de vetores, ao invés do vetor original, evitando expor a estrutura interna da classe. Ex:
O problema do método getWeights não é o array ser modificado é o próprio método em si. Os pesos são fixos, ninguém em sua perfeita sanidade mental os irá alterar. Se pensa que esse tipo de pessoas existe, então não retorne um array de int , retorne uma coleção inalterável de Integer ou, melhor ainda um objecto que encapsule os pesos.
Mas se o método for protected, como deveria, o fato de retornar copias é irrelevante pois a responsablidade continua na mesma classe, ou numa filha O próprio método deveria ser removido e subtituido por um método de calculo que recebe o outro array. Isso simplifica o problema e inverte a responsabilidade. Outras soluções são possiveis, como a que está contida no codigo que passei antes.
Fazer cópias de arrays para um métodos como esse é um exemplo de sobre engenharia.
sergiotaborda
RafaelRio:
2) Tem uma regra de degin no PMD que diz que não é uma boa ter constantes definidas em interfaces, pois estas devem definir apenas comportamento. Ex:
publicinterfaceLengthUnits{/** * meter is the standard basis */UnitMETER=newUnit("m",newBigDecimal(String.valueOf(1)));UnitBRACES=newUnit("br",newBigDecimal(String.valueOf(0.546806649)));UnitCADEIAS=newUnit("ca",newBigDecimal(String.valueOf(0.[telefoneremovido])));UnitYARD=newUnit("y",newBigDecimal(String.valueOf(1.093613298)));UnitMILES=newUnit("mi",newBigDecimal(String.valueOf(0.000621371)));UnitNAUTIC_MILES=newUnit("nmi",newBigDecimal(String.valueOf(0.000539956803)));UnitFEET=newUnit("f",newBigDecimal(String.valueOf(3.280839895)));UnitINCH=newUnit("in",newBigDecimal(String.valueOf(39.37007874)));UnitKILOMETER=newUnit("km",newBigDecimal(String.valueOf(0.001)));}
O que acha?
Use o design pattern enum. Este design pattern foi criado para eliminar o problema que o PMD indica. O padrão é tão bom que virou um dos tipos do java no java 5.0 , mas pode ser criado facilmente no 1.4 usando um construtor privado e constantes estáticas e publicas .Exemplo
P.S. Se não quiser o contrutor private pode ser public, mas ai não será o padrão enum. Contudo, resolve o problema de não ter constantes em interfaces.
Eu não sei se poderia estar postando esta duvida aqui, mais como eu faço para rodar ele num sisteminha web?
lelodois
Olá pessoal!!
Parabéns a todos que estão participando do BrasilUtilz!!
Estou usando e gostei mt e está se encaixando na aplicação que trabalho hoje.
Tenho uma duvida referente a documentação, vocês tem a documentação que se basearam para validar uma Inscrição Estadual.
Tenho que ter uma base para afirmar que a inscrição é inválida, ou seja é invalida pelo motivo x ou y.
Grato
Léo
B
Bruno_Laturner
Usa o Caellum Stella, BrazilUtils tá morto há muito tempo.
lelodois
Caraca, não vi nada do tipo… que encerraram e tal, mas blz.
Já fiz algumas coisinhas com ele agora, jogo fora ou as regras utilizadas tem algum embasamento?
B
Bruno_Laturner
Quanto às regras de inscrições estaduais, pegamos daqui:
Stringie="13.210.579-9";Validator<String>validator=newIEMatoGrossoValidator();try{// lógica de negócio ... validator.assertValid(ie);// continuação da lógica de negócio ... }catch(InvalidStateExceptione){System.out.println(e.getInvalidMessages());}
renanpto
Bom Dia pessoal, estou usando a api que vcs criaram para validar cpf, incricao estadual, cnpj, etc. E acho que peguei um bug.
O resultado da execucao dos metodos estao diferentes.
Consegui pegar o erro, pq estava usando a classe Cpf e retornava false mesmo com um cpf valido, dai troquei para CpfCnpj dai funfo…
flw
neeryck
o.O"
WRYEL
Desculpa o up ai, mas tentei baixar o jar no java.dev e não consegui encontrar!
quem é (era) o responsável por este projeto, podíamos dar um UP nele, eu mesmo tenho um Utils meu que dá pra aproveitar muitas coisas… ficaria feliz em contribuir…
Abrçs.
Marky.Vasconcelos
Esse projeto é do Ironlynx, mas está meio morto mesmo.
E também tenho um projeto de Utils. Poderiamos conversar Priuli.
Priuli
Marky.Vasconcelos:
Esse projeto é do Ironlynx, mas está meio morto mesmo.
E também tenho um projeto de Utils. Poderiamos conversar Priuli.
Não tá morto, mas está parado.
Nunca é demais lembrar que o BU sempre visou projetos legados, e a API tinha por objetivos não usar códigos acima da JDK1.4.2.
Eu tava fazendo uns códigos aqui(ate usadno umas classes dadas pelo dieval para fazer um parser, mas trabalho ficou )
Para algo mais atual, usem Caelum Stella(ou o MarkyUtils).