BrazilUtils API

marcoscorso, me desculpe pela demora!

Logo, o Ironlynx e o dsiviotti vão me bancar ($$$) para trabalhar no BrazilUtils em tempo integral, daí as respostas vão passar a ser instantâneas! * :lol:

Certifique-se que a classe CpfCnpj está no namespace da classe. Importa org.brazilutils.br.cpfcnpj.CpfCnpj ou org.brazilutils.br.cpfcnpj.*.

Instancia um objeto da classe CpfCnpJ e use os métodos setCpfCnpj, isValid, isCnpj, isCpf.

private CpfCnpj validator = new CpfCnpj(); validator.setCpfCnpj("71850816940"); validator.isValid(); validator.isCnpj(); validator.isCpf();
Iron, você conseguiu resolver esse problema ? http://www.guj.com.br/posts/list/48129.java

  • Brincadeirinha! Mas vou tentar responder mais rápido…

Aliás, uma coisa que estava pensando.

Quando lançarmos a primeira versão do BrazilUtils, vai ter uma aviso dizendo que as próximas versões provavelmente não serão compatíveis?

Ironlynx, dsiviotti, se vocês disserem que não, eu começo a chorar agora!

Tem uma biblioteca muito boa - a TimeAndMoney (http://timeandmoney.domainlanguage.com/) - que deixa bem claro que pode haver problemas de compatibilidade entre as várias versões da API, simplesmente porque pacotes e classes deixam de existir, ou mudam de lugar, conforme a TimeAndMoney evolui.

Para manter a compatibilidade entre as versões do BrazilUtils, não poderíamos mexer na estrutura do projeto, o que seria um sacrifício enorme para nós e para a qualidade do TiUzão.

Um exemplo: acho que deveríamos mudar o modo como validamos Cpf e Cnpj. Para mim, não deveria existir uma classe CpfCnpj, já que Cpf e Cnpj tratam de coisas (domínios) diferentes. E muito menos ter outras classes Cpf e Cnpj mais abaixo na hierarquia, o que confunde bastante. E isso fica ainda mais embananado se considermos que, para fazer validação tanto de Cpf, quanto de Cnpj, usa-se a classe CpfCnpj!

Supondo que fique tudo inalterado, não teríamos a liberdade de fazer mudanças estruturais importantes que eventualmente possam ser necessárias.

No caso citado acima, extrair todo o código comum para validação de Cpf e Cnpj para uma superclasse, digamos NumerosFiscais, e concentrar funcionalidades específicas para a validaçao de Cpf e Cnpj respectivamente nas classes de mesmo nome, Cpf e Cnpj, que extenderiam NumerosFiscais.

Não, vou te responder lá…

Mas bem que eu gostaria de dar um incentivo($$$) pro pessoal, mas lamentavelmente tá difícil até para mim…

Vc descobriu o principal motivo pq ainda não houve um oficial release até o momento, e o porquê de estar buscando um PM(ProjectManager) beem experiente. Há pontos(leia-se features) incompletas, “que não fecham”, e cuja estrutura tem que ser repensada.Gerar incompatibilidade a cada release é pedir para não usarem a API.Não há como.
Como API de validação, há sempre uma tendência imediatista, de pensar no resultado, ou seja, tá funcionando, passa.Mas sabemos que isso não é bem assim, e não basta fazer um apanhado de códigos e lançar uma versão.
Rafael, cuidado com uma coisa:prefira composição a herança, e veja se é tão necessário assim existir essa classe de números fiscais, se o comportamento é comum…

[quote=Ironlynx]Gerar incompatibilidade a cada release é pedir para não usarem a API.Não há como.
[/quote]
Não concordo, e por isso citei a TimeAndMoney como exemplo. Mesmo porque não dá pra imaginar todas as features possíveis que uma API pode ter, muito menos como elas funcionarão. E tem esse ponto também, da velocidade do lançamento.

Ironlynx, na boa… :wink: Você não viu as classes CpfCnpj, Cpf e Cnpj do pacote org.brazilutils.cpfcnpj, não é mesmo?

Eu tô falando isso justamente pq eu vi… :shock: :lol:
(Eu ia responder ao marcoscorso, mas vc postou antes, quando eu li eu vi o problema do NumberComposed…)

Por isso a organização dos packs faz toda a diferença nessa hora…
Features novas(não relacionadas) entram em packs novos, logo não há problemas de retrocompatibilidade…
Nosso problema é estruturar as antigas…

Sobre a questão da Chain.

O usuário da classe pode saber exatamente qual o estado da inscrição estadual (IE) que quer validar. Então, UF AC = UF.valueOf("AC"); // Cria a UF a partir da Sigla AC.getInscricaoEstadual().setNumber("01.004.823/001-12"); AC.getInscricaoEstadual().isValid(); Ou seja, fica do jeito que está.

Para os casos em que a IE pode ser de mais de um estado, usa-se a cadeia (pelos motivos já citados anteriormente).

Precisamos de mais uma interface. Que tal ChainValidator? Sei lá, o nome das minhas classes, interfaces e packages sempre me lembram as Organizações Tabajara!

A classe InscricaoEstadual implementa a interface Validable. Validable poderia extender ChainValidator, o que teria um efeito cascata nas classes do TiUzão. Aqui, InscricaoEstadual implementa ChainValidator. public inteface ChainValidator { public void addValidator(ChainValidator validator) ; public boolean validate(String inscricaoEstadual); }
Utilizei as classes InscricaoEstadualAC, InscricaoEstadualTO e InscricaoEstadualRJ para testar.

A implementação da interface ChainValidator em InscricaoEstadualAC, assim como nas classes para as outras uf’s, ficou assim: [code]
private ChainValidator nextValidator;

public void addValidator(ChainValidator nextValidator) {
	this.nextValidator = nextValidator;		
}

public boolean validate(String inscricaoEstadual) {		
	setNumber(inscricaoEstadual);		
		
	if (isValid()) {
		return true;		
	} else if (nextValidator == null) {
		return false;
	}
		
	return nextValidator.validate(inscricaoEstadual);
}[/code]

Continuando…

Tive que alterar os métodos isValid() para que a cadeia funcionasse. É fundamental chamar o método defineCoeficients() antes de qualquer coisa nos métodos isValid().

Também eliminei o método genericValidation() e, conseqüentemente isUseGenericValidation() deixou de existir. Ao invés disso, InscricaoEstadual implementa isValid(), que deixou de ser abstrato, e, quando outras classes precisarem usar uma validação específica, elas sobrepõem (override) isValid().

Sessão de perfumaria: também alterei o escopo de vários métodos para protected e private. Claro que tudo isso são sugestões. Vejam o que serve e o que não serve.

O importante é que funcionou direitinho. 8)

Agora sobre as classes de validação de cnpj (pacote org.brazilutils.br.cpfcnpj).

É melhor fazer logo e mostrar o que estou pensando do que ficar divagando.

Para deixar bem claro, a única coisa que fiz nesse pacote foi um refactoring nas classes, movendo algumas coisas para baixo na hierarquia (o que é mais específico de cada subclasse), implementando o padrão Template (GoF) e renomeei a classe CpfCnpj, que passou a se chamar NumeroFiscal. Não mexi no algoritmo de validação, que está ok.

Tudo isso, de novo, são sugestões. Avaliem se é útil.

Benefícios:

  • métodos isCnpj() e isCpf() não são mais necessários;
  • eliminação de flags isCpf, isCnpj;
  • mais fácil de entender: cnpj é cnpj, cpf é cpf.

Desvantagens:

  • alguma duplicação de código, pelo fato dos algoritimos de validação de Cpf e Cnpj serem parecidos. (Douglas, foi por isso que você criou uma classe CpfCnpj, não foi?)

Seguem as classes NumeroFiscal, Cpf e Cnpj.

Na forma atual usarmos [code]
CpfCnpj c = new CpfCnpj();
c.setCpfCnpj(“29520590000165”);
c.isValid(); // CNPJ valid
c.isCnpj(); // is CNPJ
c.isCpf(); // is not CPF

c.setCpfCnpj(“12345678911”);
c.isValid();// CPF invalid
c.isCnpj(); // is not CNPJ
c.isCpf(); // is CPF
[/code]
Na forma, proposta fica [code]
Cnpj cnpj = new Cnpj();
cnpj.setCnpj(“29520590000165”);
cnpj.isValid();

Cpf cpf = new Cpf();
cpf.setCpf(“123.456.178-15”);
cpf.isValid();
[/code]
Surgiu uma indireção a mais para executar a validação, mas em compensação flags dentro do algoritimo foram retiradas e os métodos de validação estão mais bem definidos. Antes, isValid() validava tanto Cpf e Cnpj (acho que para reaproveitar código).

Outro exemplo de simplificação. Antes, getModule11Dv(String number, boolean isCpf) Agora, getModule11Dv(String number)
Se é Cpf ou Cnpj, descobre-se em runtime, via polimorfismo.

Tanto no caso das classes de validação de inscrições estaduais, quanto nas classes de Cpf/Cnpj, há outras mudanças que não citei. Algumas são perfume, outras são mais importantes.

Abraço a todos! Feliz Natal, galera! :smiley:

RafaelRio(tava inspirado hein?), eu e o Douglas já estamos lendo as suas classes, depois lhe damos um feedback!

Foi o espírito natalino. :smiley:

Qual a nova data de lançamento?

Discuta isso comigo no email, pq o Douglas tá enrolado no CadFuncNadQualquerCoisa lah do Serpro.

Existe um problema prático que depois de desenvolver muitos sistemas acabei antecipanto na classe CpfCnpj. Ela não existe apenas pra ter código em comum e depois ter uma Cpf e uma Cnpj. Na verdade, na maioria dos casos, você não sabe exatamente se vai ter um Cpf ou um Cnpj! Isso complica bastante a equação. Por acaso o algorítimo é semelhante e pode ser usado um só.

Em muitos casos, um objeto CpfCnpj que inicialmente era um Cpf vira um Cnpj! Assim você até pode ter classes de Cpf e Cnpj para os casos onde essa “mutaçao” não é possível, mas ela acontece. Logo, o quanto mais código na superclasse, que não pode ser abstrata, melhor. O mesmo vale pro método estático que faz a validação do número. Ele deve estar preparado pra receber um (11) ou outro (14). Na verdade, há algum tempo tenho me questionado sobre a existência dessas classes da forma como estão. Acho que o método estático que valida os números é o que 99% das pessoas precisa. E da forma que está não serve pro 1% restantante. Acho que essas exceptions de Validation devem sair.

Quanto às alterações na Inscrição Estadual ficaram ótimas. Principalmente porque não altera o que já estava feito. Se for garantido a opcionalidade de usar essa validação em cascata fica ótimo.

Discuta isso comigo no email, pq o Douglas tá enrolado no CadFuncNadQualquerCoisa lah do Serpro. [/quote]

Pô Ironlinx, é CadSincNac - Cadastro Sincronizado Nacional. Aliás, por ironia do destino, em breve o termo CNPJ, provavelmente, será substituído por algo assim. Já que o Cadastro Nacional de Pessoas Jurídicas vai ser incorporado pelo Cadastro Sincronizado Nacional. Os nomes das classes já podem estar caducos! rs

Por falar nisso, os números de CNPJ que tem 0001 no final não são mais, necessariamente, a matriz. Muitas rotinas verificam o número do CNPJ procurando esse "0001" no fim pra saber se a empresa é matriz. Já não é mais assim. (boa sorte)

Minha equipe (de 4 pessoas!!) está com 2 de férias e os prazos você já conhece! Se alguém quiser fazer como o Renato, e dar uma olhada e criticar o pacote "br", é uma boa! Sempre que puder eu respondo aqui alguma dúvida. Código novo, como o do "chain" é bem vindo também.

Uma coisa que deveria ser escrita é uma clase de teste para cada Inscrição estadual validando um número considerável de IEs de cada estado. Algumas certas e outras erradas. Eu segui os algorítimos do Sintegra mas alguma coisa pode ter mudade desde então.

http://www.sintegra.gov.br/ clique em "Informações Gerais -&gt Inscrições Estaduais"

[quote=Ironlinx]
Discuta isso comigo no email, pq o Douglas tá enrolado no CadFuncNadQualquerCoisa lah do Serpro.[/quote]
Estou esperando o seu e-mail.

[quote=dsiviotti]
Em muitos casos, um objeto CpfCnpj que inicialmente era um Cpf vira um Cnpj![/quote]
Pensou depurar ou fazer a manutenção de um software que conta com esse tipo de comportamento? Como diz a Ritinha, obrigado não!

[quote=dsiviotti]
Assim você até pode ter classes de Cpf e Cnpj para os casos onde essa “mutaçao” não é possível, mas ela acontece. [/quote]
E como fica o paradigma de responsabilidade bem definida das classes, um dos pilares da OO? Não se trata de purismo. Levei muito tempo para descobrir o que no algoritimo era referente à CPF, o que era à CNPJ. Dei sorte de não ter quebrado seu algoritimo de validação CNPJ/CPF.

Para os casos em que poderá ser manipulado tanto CPF quanto CNPJ, pode-se ter uma espécie de controlador decidindo para quem despachar as mensagens - a classe CPF ou CNPJ. E Chain of Responsability também é aplicável nesse caso, da mesma forma que na IE.

É possível resover esse problema de várias formas. Temos que ficar justo com a solução de misturar tudo numa classe só?

[quote=dsiviotti]
Cadastro Sincronizado Nacional. Aliás, por ironia do destino, em breve o termo CNPJ, provavelmente, será substituído por algo assim.[/quote]
Pois é! Imagina se resolverem mudar a forma de validar CNPJ. Poderia quebrar o algoritimo de validação de CPF, que não tem nada a ver com a história.

[quote=Ironlynx]
Gerar incompatibilidade a cada release é pedir para não usarem a API.Não há como. [/quote]

[quote=dsiviotti]
Os nomes das classes já podem estar caducos! [/quote]
Fiquei curioso. Como vamos lidar com casos assim no futuro?

Quem?

2006 já era!

Feliz ano novo galera!

*** clicado “citar” no lugar de “editar”. perdão!

???

Apenas um up, é isso mesmo?

[quote=juzepeleteiro]
???

Apenas um up, é isso mesmo?[/quote]
Relaxa, cara! 8) Essa thread nem precisa disso.

[quote=dsiviotti]
***[/quote]
Mas o que seria isso?