Coisas que odeio em Java

Se é isso que queria então está errado de duas formas:

  1. Date tem todos os get e set deprecated. Não mais devem se alteráveis. Devem ser usados apenas como VO para transporta milisegundos na epoca definida pelo java (em vez de usar long). O objeto mutável para trabalhar com datas é Calendar.
  2. Mesmo que os get/set não fossem deprecated existem muitas regras ocultas no calculo correco de datas e tempos ( que ficam dentro de calendar) e portanto alterar Date directamente seria errado.

O ponto aqui é que é errado definir um date para depois o usar num calendar, defina logo o calendar e pronto. O unico uso de Calendar.setTime() é quando vc obtem Date de legados.

Uma vez retirada essas coisas desnecessárias, não é tão complexo assim.

E o que isso tem a ver com criar coisas complicadas?
[/quote]

Isso levaria dias explicando…
Versão resumida: criar objeto neutro em relação ao local é muito difícil. Ainda para mais quando mexe com datas.

Dê uma olhada na API Joda-Time para ver só como é complicado quando vc decide que Calendar não é suficiente. Agora compare com a biblioteca Time and Money para ver como é fácil cometer erros e tornar os objetos não internacionalizáveis.

Hum, não que essa seja a principal discussão do tópico, e acho que mesmo vc sabe que a API poderia - alias, deveria - ser mais simples. Vamos lá, eu trabalho com código legado, de outras APIs e esses códigos usam Date para lidar com datas, não Calendar, Date. Então, em determinado momento, alguma dessas APIs tão legais me retorna um date e preciso somar sete dias e devolver para API gente boa um objeto Date. A partir disso chegamos em algo parecido com o método que mostrei.

[quote=sergiotaborda]Isso levaria dias explicando…
Versão resumida: criar objeto neutro em relação ao local é muito difícil. Ainda para mais quando mexe com datas.[/quote]
O erro não é ter que lidar com conceitos complicados. O erro é expor uma interface complicada para manipular datas. Joda-Time, por exemplo, apesar de lidar com as mesmas complicações, oferece uma interface bem mais humana.

valeuz…

[quote=jack_-_ganzha]
O erro não é ter que lidar com conceitos complicados. O erro é expor uma interface complicada para manipular datas. Joda-Time, por exemplo, apesar de lidar com as mesmas complicações, oferece uma interface bem mais humana.

valeuz…[/quote]

Calendar não foi feito para ser uma interface humana. Da mesma forma que Joda Time não foi. TimeAndMoneyAPI foi e tem um monte de defeitos . Pq ? simplesmente pq o próprio assunto de datas e calendários é muito complexo.
Concerteza acharia maravilhoso fazer intervalo = date1.minus(date2) mas isto está errado pelo próprio conceito de data. Data é um conceito cultural e não um conceito cientifico. a operação “diferença de data” não é unica ela depende do contexto em que está sendo feita.
Exatamente por isso Calendar não define operações de subtração, apenas de soma. É realmente muito complexo e a Calendar faz o trabalho que se propõe a fazer.
O que ela não faz é o trabalho que seus inventores se propuseram -universalidade- nem o que o programador precisa - simplicidade e encapsulamento total de todas as regras. Só que um programador no brasil não calcula diferença de datas da mesma forma que um na china - e lá se vai o encapsulamento.

Concerteza a Date and Time API irá resolver muitos dos dilemas dos programadores, mas os problemas de calcular diferenças continuarão.
veja porque
http://www.javaworld.com/javaworld/jw-03-2001/jw-0330-time.html

Agora, o que isto tem a ver com o tema ? Date e Calendar não são odiáveis. Em VB e Delphi nem existe nada parecido , em C nem pensar.
Date e Calendar demonstram exatamente como o Java é maior que essas lamexices, pq quem não gosta pode sempre fazer melhor! E depois enviar para o JCP tal como vez o pessoal da JT.

Ok, mas acho que é justamente esse o problema que está sendo citado. Deveria ter sido feito de maneira mais humana.

Ok, mas porque GregorianCalendar não define? Eu poderia ter métodos para trabalhar facilmente num calendário gregoriano. Além do que, embora o conceito possa estar errado, infelizmente, as pessoas fazem SIM contas com datas!

Veja o método get do calendário gregoriano. Ele é simplesmente ridículo! Usaram o mesmo método para retornar vários fields. Por que essa decisão? Por que não simplesmente gregorianCalendar.getDay()?

Outro problema aqui é investir numa API que é complexa em 90% dos casos de uso, para facilitar outros 10%. A maior parte do mundo onde interessa exportar um programa ainda usa o calendário gregoriano. Certamente, muitos programadores japoneses, chineses, indus, estão fazendo aplicações usando esse tipo de calendário. Então, para esse caso, a preocupação de uma classe fácil e agradável deveria ter sido levada muito mais em conta.

Isso é uma grande verdade. Mas creio que as superclasses poderiam manter o encapsulamento, enquanto subclasses exportassem o comportamento específico de cada região.

O ideal até é que houvesse uma forma de converter um calendário de uma região para outra. Afinal, o calendário nada mais é do que a representação localizada de um instante no tempo. E esse instante no tempo, é o Date.

Que ironia do destino… Não demorou muito e olha o tópico que apareceu no GUJ:
http://www.guj.com.br/posts/list/0/53947.java#283472

Aliás, aproveita e dá uma olhada também em:
http://www.guj.com.br/posts/list/3515.java
http://www.guj.com.br/posts/list/22287.java
http://www.guj.com.br/posts/list/3051.java
http://www.guj.com.br/posts/list/22900.java

Agora pelo menos você pode dizer que já viu gente pedindo para limpar a tela…

Mas não fazem da mesma forma. Por exemplo, numa empresa de entregas trabalhas com dias uteis para entrega. Num banco calculas juros com meses de 30 dias e anos de 360 dias. Nada disto corresponde com o calendário , é uma regra de negocio.

Porque nem todos os calendários têm 12 meses. Nem todos os meses tem 30 dias.

O dia do mês , do ano , da semana ?

O assunto é muito mais complexo do se imagina à primeira vista.

Não sei se você leu.

Estou falando do GregorianCalendar. Aquele definido pelo papa Gregório, que foi uma correção do calendário Juliano, definido por Julio César tempos antes.

É um calendário solar. Nesse calendário, todo ano tem efetivamente 12 meses. Se você me mostrar um calendário Gregoriano sem 12 meses, certamente você vai estar me mostrando um calendário Gregoriano errado.

Nem a empresa de entregas e nem o banco, usam o calendário gregoriano. Nesse caso, você deveria implementar seu próprio calendário. Ou, fazer programa que adapte a regra de negócio da empresa ao calendário gregoriano (usado pelos clientes), o que seria muito mais fácil se a classe GregorianCalendar fosse mais fácil.

[quote=sergiotaborda]
O dia do mês , do ano , da semana ?

O assunto é muito mais complexo do se imagina à primeira vista.[/quote]

Ok, isso um javadoc resolve facilmente. É o mais comum, ou seja, o do mês. É o que normalmente queremos quando fazemos getDay() num calendário gregoriano. Nada contra ter outros métodos, getWeekDay(), getYearDay(). Mas, na minha opinião, usar constantes para o field não só deixa o código mais rebuscado à toa, como também é menos intuitivo.

Também não tenho nada contra um get mantendo o field para a superclasse. Afinal, sabe-se lá como são divididos os calendários no mundo a fora… Mas a classe GregorianCalendar, que é muito usada, certamente deveria ter métodos mais digeríveis. E aqui não estou falando só de gets, mas métodos para soma/subtração de dias, meses ou anos numa data, e outros métodos que o pessoal já comentou por aqui…

É muito importante que a interface da classe GregorianCalendar seja fácil e agradável de usar. Como ressaltado no javadoc da própria classe:
“provides the standard calendar used by most of the world

[quote=ViniGodoy][quote=sergiotaborda]
Mas não fazem da mesma forma. Por exemplo, numa empresa de entregas trabalhas com dias uteis para entrega. Num banco calculas juros com meses de 30 dias e anos de 360 dias. Nada disto corresponde com o calendário , é uma regra de negocio.

(…)

Porque nem todos os calendários têm 12 meses. Nem todos os meses tem 30 dias.
[/quote]
Não sei se você leu.

Estou falando do GregorianCalendar. Aquele definido pelo papa Gregório, que foi uma correção do calendário Juliano, definido por Julio César tempos antes.
[/quote]

Mas GregorianCalendar herda de Calendar e Calendar é genérico, então GregorianCalendar não pode não o ser. Pode ter método utilitários como getDay , mas os métodos get(int) não podem ser retirados.

Além disso vc fala como se usasse GregorianCalendar directamente. Isso é um erro comum e perigoso. Vc deveria usar Calendar.getInstance(new Locale(“pt”,“BR”)) , vai que no futuro este método não retorna mais GregorianCalendar e sim uma versão melhorada ou revista como, digamos, GregorianCalendar2. Vc viola o encapsulamento e isso , claro trás os problemas que vc afirmou. Parece que é tudo mais complicado do que deveria ser. Pois, mas tente usar Calendar.getInstance e verá que faz todo o sentido.

É obvio que o GregorianCalendar terá que ter todos os métodos de Calendar. Mas ele não é obrigado a se restringir a eles. Métodos que auxiliassem calendários desse tipo seriam muito bem-vindos na maior parte do mundo, onde o calendário é usado.

A abordagem de Calendar cal = Calendar.getInstance(); tem uma série de problemas:

  1. A maior parte dos negócios é dependente do formato do calendário retornado. Nesse caso, seu programa também terá essa dependência. Por exemplo, você fará um algoritmo para calcular dias comerciais pulando finais de semana e feriados. Entretanto, não haverá sábados e domingos caso um calendário muito exótico seja retornado…
  2. Trabalhar genericamente com um calendário não só é extremamente complicado, como também não é necessário em uns 90% das aplicações;
  3. Se você fixar o local Calendar cal = Calendar.getInstance(“pt”, “BR”), sua aplicação continuará não sendo genérica e, portanto, seria muito mais inteligente utilizar uma classe que te facilitasse a vida.

Se você quer tanto assim separar a implementação da classe final, porque não criar uma interface para o Calendário gregoriano, que seja filha da interface Calendar? Nesse caso, um método Calendar.getGregorianCalendar(Locale loc) faria a mágica.

Ainda sim, mesmo que isso não seja feito, discordo da sua alternativa de dizer que é perigoso trabalhar com GregorianCalendar diretamente por dois motivos:

  1. Calendários não mudam todo o dia. É muito mais provável que implementações mais eficientes de GregorianCalendar serão feitas na própria classe GregorianCalendar, não em uma classe separada.

Mesmo que um calendário se alterasse, o sistema dependeria do novo formato e certamente teria que ser alterado de qualquer jeito.

  1. É muito melhor contar com uma interface simples e que ajude a programar, que torne erros menos propícios e que tenha sido planejada considerando situações comuns (e possíveis enganos) do uso do calendário mais comum do mundo do abrir mão disso para contar com a promessa de uma “futura, possível, porém muito improvável, implementação mais eficiente em uma classe diferente dessa”.

A generalização é interessante, mas existe um trade-off que não creio que tenha sido corretamente avaliado no caso do GregorianCalendar. Imagine se todas as classes da Collections Framework tivessem como sua interface principal Collection, e apenas Collection? Seria um inferno trabalhar com um list, ou com um set, ou com um map. Muitas implementações mais eficientes também seriam simplesmente abandonadas.

Na minha opinião, o calendar deveria ter seguido um modelo semelhante. Uma interface genérica para quem quer suportar calendários do mundo todo (e esse programador sim, vai sofrer, mas porque as regras do negócio exigem, não porque alguém da Sun quis mostrar o quanto o java é “genérico”), e uma interface mais específica para quem quer apenas se preocupar com o calendário do papa Gregório, com métodos úteis, otimizados e eficientes para operações nesse tipo de calendário (como soma/subtração de dias, obtenção de dias úteis entre duas datas, etc).

rpz tava vendo uma coisa que fiquei com raiva em java é uma classes que tem remove() e outras que tem delete()… po isso me confude toda hora… se a class tem o delete ou o remove… perco maior tempo com isso… e as vezes tenho q consultar a api…

[quote=rodrigo_gomes]Olá,

Acho que uma das coisas que mais enche a paciencia é mexer com data (sem user JODA).

[]´s[/quote]

Concordo por isso to ajudando a fazer a JSR-310 com o Mister M, dessa vez vai melhorar… :smiley:

Pessoal, no começo do tópico apareceram várias vezes os termos fall through e workaround. Vcs podem me explicar o que significam?

fall through é quando você tem uma condição do switch sem break. O que o switch faz? Ele “cai para” (fall through) a próxima condição e a executa!!! Exemplo:

[code]
int i = 2;

switch (i) {
case 1:
System.out.print(“1”);
case 2:
System.out.print(“2”);
case 3:
System.out.print(“3”);
case 4:
System.out.print(“4”);
}[/code]

Qual é o resultado do programa acima? Resposta, devido ao Fall through é 234, pois faltam os breaks. Breaks são facilmente esquecidos (principalmente no início). Outro problema é que, como não contamos com uma condição sem o break, é muito difícil encontrar um erro devido ao fall through (acho sinceramente que nossa cabeça tende a completar a condição com o break quando estamos analisando o código, especialmente se isso ocorrer em uma só condição).

O termo workaround é quando você não tem uma solução direta para o problema e precisa contorna-lo usando formas indiretas. É praticamente um xunxo, exceto pelo fato de que no workaround você sabe que está fazendo e o porque…

Um exemplo de workaround comum em java é chamar Runtime.exec com o comando cls para limpar a linha do console. O correto seria ter um comando java puro para isso, mas como não existe, recorremos a essa “gambiarra”.

O problema é que workarounds são imperfeitos, sujeitos a erro e geralmente são um trabalho adicional.

Veja o exemplo de interoperabilidade com C++. No C, existem tipos unsigned, ou seja, um byte pode ir de 0 até 255. Vamos supor que em java, você precise ler um valor 230 que veio de um byte em C. Não existe um tipo “unsigned byte” no Java, então o workaround para isso é ler o byte e converte-lo para um short:
short valor = (short)sockInputStream.readByte();

E se você precisasse ler um unsigned short? Teria que le-lo para um int. E assim sucessivamente. Mas o workaround deixa de ser prático ao tentar ler um unsigned long.

Veja que para enviar bytes, você também terá que fazer ao contrário. Para enviar um unsigned byte você teria que fazer:
byte byteValue = (byte)(0xFF & shortValue);
sockOutputStream.write(byteValue);

E veja, nesse caso, que trabalho adicional!

Esqueci de perguntar um:

O que significa spurious wakeups? Obrigado por responder minhas dúvidas!

E só pra constar, eu concordo com vc, o break deveria ser removido.

[quote=von.juliano]Esqueci de perguntar um:

O que significa spurious wakeups? Obrigado por responder minhas dúvidas!

E só pra constar, eu concordo com vc, o break deveria ser removido.[/quote]

O método wait deveria fazer a thread esperar até uma ocorrência do método notify ou notifyAll, mas ela pode, aleatoriamente, deixar de esperar e acordar. O certo então, é chamar o método wait num loop que verifica se a condição para a thread acordar já foi alcançada. Dê uma olhada em http://java.sun.com/javase/6/docs/api/java/lang/Object.html#wait(long)

Então spurious wakeups é quando uma thread que deveria estar esperando “acorda” sozinha?

SWING!!!
:smiley:

É isso mesmo.

O wait pode “acordar” num notify ou no tempo indicado pelo parâmetro, certo? Em partes…

Com o spurious wakeup o wait pode acordar antes disso, sem razão aparente alguma para que isso ocorra… por isso, waits sempre devem estar precedidos por um while, que certifiquem a condição de parada e mantenham o código no wait caso um wakeup desse ocorra.

[quote=pcalcado]

Deixa eu adivinhar: você nunca implementou uma aplicação com interface de linha de comando ou a la curses, certo?[/quote]
certo.

deixa eu ver… uma aplicação a la curses apaga a tela e redesenha tudo de novo toda vez q vc muda de janela ou menu, certo?

por q ficar se preocupando com limpar tela em java se já fizeram API’s pra aplicações gráficas em console?

http://www.guj.com.br/posts/list/22579.java#284478