.comment-link {margin-left:.6em;}

Friday, January 13, 2006

Escrevendo (código) Demais

Resolvi escrever esta nota, não para criticar os desenvolvedores que gostam de codificar de tudo, mas alertar que quanto mais simples e comentado deixamos o código, melhor será nossa vida no futuro - e tomando emprestado o ditado: "quem fala demais dá bom-dia a cavalo", escrever código desnecessariamente também não é uma boa idéia.

Dias atrás, estava navegando através dos forums e me deparei com uma dúvida relacionada ao código abaixo. Não me lembro da dúvida, porque a primeira coisa que eu faço quando leio uma, é otimizar a semântica, não a sintaxe, portanto tento entender o que a pessoa pretende, para ajudá-la.

Neste caso, nosso herói queria escrever uma função para converter data Gregoriana em data Juliana (número de dias desde as 12:00 de 1 de janeiro de 4713 aC). Ora, de primeira minha resposta foi: por que está codificando algo que já existe? Se o TO_CHAR( date, 'J' ) faz isso! Mas o pior foi constatar que a função estava errada!

Me Mostra?

No código, eu retirei os comentários para evitar identificação. Não estou preocupado em apontar o dedo à ninguém e sim alertar para: primeiro procurar esgotar as possibilidades que o built-in oferece. Além de já estar pronto e testado, preserva o código como legado em migrações futuras.

Eis a função.
CREATE OR REPLACE Function to_juliana (dt_a_converter DATE )
RETURN NUMBER IS
dt_juliana NUMBER;

BEGIN
/* ------ -- ------- -- --------- ---- ---- ------- */

dt_juliana := 0;
dt_juliana := To_Char( TO_DATE( dt_a_converter ) , 'YYYYDDD') - 1900000 ;

/* ---------- - ------- -- ------ */
RETURN( dt_juliana );
END To_Juliana;
/

ops$marcio@LNX10GR2>
ops$marcio@LNX10GR2> CREATE OR REPLACE Function to_juliana (dt_a_converter DATE )
2 RETURN NUMBER IS
3 dt_juliana NUMBER;
4
5 BEGIN
6 /* ------ -- ------- -- --------- ---- ---- ------- */
7
8 dt_juliana := 0;
9 dt_juliana := To_Char( TO_DATE( dt_a_converter ) , 'YYYYDDD') - 1900000 ;
10
11 /* ---------- - ------- -- ------ */
12 RETURN( dt_juliana );
13 END To_Juliana;
14 /

Function created.

ops$marcio@LNX10GR2> select to_juliana(sysdate) x,
2 to_number(to_char(sysdate, 'j')) y
3 from dual
4 /

X Y
------------- -------------
106013 2453749

1 row selected.

Substituindo agora para reverter de juliana para gregoriana. Aqui é a prova dos nove.

ops$marcio@LNX10GR2> select to_date( 106013, 'j') feito,
2 to_date( 2453749, 'j') builtin
3 from dual
4 /

FEITO BUILTIN
------------------- -------------------
01/04/4422 00:00:00 13/01/2006 00:00:00

1 row selected.

Agora sim, podemos ver nitidamente que o valor obtido pela função TO_JULIANA (vermelho) não está nem de perto correto. Neste caso, a função seria:

create or replace
function to_juliana ( p_date in date ) return number
is
begin
return to_number(to_char(p_date, 'j'));
end;
/

ops$marcio@LNX10GR2> select to_juliana( sysdate ) from dual;

TO_JULIANA(SYSDATE)
-------------------
2453749

1 row selected.

ops$marcio@LNX10GR2> select to_date( 2453749, 'j' ) from dual;

TO_DATE(2453749,'J'
-------------------
13/01/2006 00:00:00

1 row selected.

Comments:
a função to_juliana nunca poderia estar coreta, já que o ano tem 365 dias. usando a mascara 'yyyyddd' nunca teriamos por exemplo uma data "juliana" com os 3 ultimos algarismos terminando com um numero entre 366 e 999.
 
O problema é que a função to_juliana existiu e estava em um forum onde participo. Quis mostrar exatamente isso: que além de não haver necessidade da codificação, o código está errado.
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?