tag:blogger.com,1999:blog-21229076547845865892024-03-13T15:23:51.366-03:00O Peczenyjvarias coisasTiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.comBlogger153125tag:blogger.com,1999:blog-2122907654784586589.post-59851656887264845082009-01-03T15:22:00.002-03:002009-01-03T15:24:33.574-03:00Mudando de endereçoForam centenas de posts desde que comecei a usar o blogspot como valvula de escape.<br /><br />Agora adquiri um domínio próprio e estou usando o wordpress como engine de blog, com MediaWiki para salvar os posts mais importantes daqui.<br /><br />Atualizem os seus feeds: <a href="http://pacman.blog.br">pacman.blog.br</a>, estou desativando este site. Obrigado a todos pela audiência :)Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-30460854585471851692008-12-22T13:44:00.003-03:002008-12-22T13:50:32.918-03:00Novas Distribuições LinuxDiariamente eu leio noticias sobre novas distribuições, brasileiras ou internacionais.<br /><br />Até que ponto isso é <span style="font-style:italic;">realmente</span> necessário? Não seria melhor tentar focar em uma das excelentes distribuições que existem hoje em dia ou então tentar ajudar a manutenção de pacotes ou mesmo traduzir documentação?<br /><br />Acho que produzir uma distribuição é um bom aprendizado, porém produzir algo que sera dificil de manter e atualizar pode ser bem penoso.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com9tag:blogger.com,1999:blog-2122907654784586589.post-53526606770010694852008-11-24T18:26:00.004-03:002008-11-24T19:11:48.444-03:00Tirando o MofoFiquei uns dias sem postar, hehe.<br /><br />Tive pouco tempo livre, afinal além de pegar alguns projetos novos (e ter que aprender muito no processo) ainda tem a faculdade, que agora chega ao fim do semestre com algumas provas.<br /><br />Nesse tempo também participei de alguns eventos legais, a começar pelo <a href="http://www.temporealeventos.com.br/?area=116">workshop de design patterns</a> ministrado pelo <a href="http://www.bruceeckel.com/">Bruce Eckel</a> (Thinking in Java, Thinking in C++). Foram 3 dias imerso em um mundo de orientação a objetos com exemplos em Java e Python. O Bruce é um cara muito bacana, tive a oportunidade de conversar bastante com ele e descobri que tinhamos algo em comum: uma graduação em física incompleta (chegamos a conclusão que não foi um tempo perdido pois aprendemos a resolver problemas, ou pelo menos demorar bastante tempo até desistir). Também tive a oportunidade de participar de um <a href="http://www.dojosp.org/">Coding Dojo</a> onde resolvemos o problema da notação de trits (ao contrário, diga-se de passagem) usando Haskell. A ideia do Dojo é sensacional!<br /><br />Também participei da <a href="http://pyconbrasil.com.br/">PyConBrasil 2008</a>. Foi um evento muito bom, excelente organização, sem falar que a sessão aberta com o Bruce sobre os rumos do Python foi o ponto forte, que surgiu totalmente do acaso. Python é uma linguagem muito interessante, com uma comunidade consideravel. Quem não usa python devido a indentação obrigatória do código usa um dos argumentos mais ridículos possiveis :)<br /><br />Outro evento sensacional foi o workshop de <a href="http://blog.fragmental.com.br/2008/10/08/domain-driven-design-agile-fechando-malas/">Domain-Driven Design</a> ministrado pelo Philip Calçado na <a href="http://www.caelum.com.br/">Caelum/RJ</a>. DDD é sobre comunicação, um ponto essencial no desenvolvimento de software nos dias de hoje. O Phillip foi responsavel, ainda que indiretamente, pela minha vinda a globo.com, porém só agora pudemos tomar aquele chopp e conversar sem ter 12 horas de diferença.<br /><br />Sabado passado começou o curso on-line e intensivo de <a href="http://blog.egenial.com.br/?p=192">BDD on Rails com RSpec</a> ministrado pelo <a href="http://www.dtsato.com/">Danilo Sato</a> pela eGenial. Esta valendo a pena, pois parte daquela premissa que sempre defendi que temos que testar o nosso código e, para isso, existem varias abordagens e frameworks.<br /><br />Estou preparando outros posts, devo atualizar este blog em breve.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com1tag:blogger.com,1999:blog-2122907654784586589.post-34677213196347399772008-10-24T10:02:00.003-03:002008-10-24T10:10:59.844-03:00Fear, uncertainty and doubtFear, uncertainty and doubt (ou simplesmente <a href="http://en.wikipedia.org/wiki/FUD_factor">FUD</a>) não é algo novo. Volta e meia alguma instituição ou candidato a utiliza de forma a enfraquecer o(s) seu(s) adversário(s), geralmente os projetos open-source são vitimas frequentes.<br /><br />Hoje, no Rio de Janeiro haverá o ultimo debate entre os candidatos a prefeito. Não sou de usar blog técnico como meio de propaganda politica porém não posso ficar de braços cruzados enquanto um candidato utiliza FUD, Boatos e Mentiras. <a href="http://porumbrasildecente.blogspot.com/2008/10/boataria-contra-gabeira.html">Aqui</a> e <a href="http://porumbrasildecente.blogspot.com/2008/10/mais-um-boato-da-campanha-de-paes.html">aqui</a> vemos alguns exemplos extremamente baixos, que qualquer pessoa com um minimo de instrução deveria perceber. Até quando isso será permitido? E o TRE? E os panfletos apócrifos apreendidos? <br /><br />Felizmente o outro candidato, cujo partido possui uma cor verde interessante, não responde na mesma moeda pois seria facil usar coisas <a href="http://congressoemfoco.ig.com.br/Noticia.aspx?id=25124">desse tipo</a>, mas que não acrescentam nada. <br /><br />Realmente a melhor forma de se proteger do FUD é informando a população, cobrando das autoridades cabíveis e destacando o quão antiético é esse tipo de abordagem. Felizmente cada cidade tem o prefeito que merece.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com2tag:blogger.com,1999:blog-2122907654784586589.post-24673758667022982312008-10-07T14:06:00.003-03:002008-10-07T14:08:03.485-03:00Policia do RS usa MSNPelo que eu vejo nesse <a href="http://g1.globo.com/Noticias/Brasil/0,,MUL787936-5598,00.html">link</a>, a Policia do RS está utilizando o MSN, que é um messenger bem comum hoje em dia, para receber chamados de socorro.<br /><br />Com protocolos livres como o Jabber e clientes livres como o Pidgin, sera que uma alternativa mais barata e eficiente não poderia ser desenhada?<br /><br />Da forma como é hoje, um serviço de segurança esta nas mãos de software/serviço e protocolo proprietário e <strong>fechado</strong>, e isso me preocupa como cidadão!Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com12tag:blogger.com,1999:blog-2122907654784586589.post-57016065627786958092008-09-02T16:48:00.007-03:002008-09-03T11:33:07.875-03:00Chrome: o browser da googleAs noticias apareceram em todas os sites especializados: o google estaria lançando hoje uma novidade chamada chrome, um browser baseado em Webkit disponivel por enquanto para Windows XP e Vista.<br /><br />Até um <a href="http://www.google.com/googlebooks/chrome/">gibi</a> foi disponibilizado, então esperando até as 4 PM consegui fazer o download em uma maquina virtual e pude testa-lo um pouco.<br /><br />A performance parece ser muito boa, apesar da virtualização. Não observei travamentos ou comportamentos estranhos (como os que ocorrem no Safari para Windows). O visual e as tabs são realmente práticas, com muita área para ver o site e icones intuitivos.<br /><br /><a href="http://www.flickr.com/photos/25513475@N05/2822697182/" title="primeira_impressao by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3226/2822697182_2d26579398.jpg" width="500" height="374" alt="primeira_impressao" /></a><br /><br />Bem interessante é o gerenciador de tarefas, (Controlar Pagina Atual > Desenvolvedor) onde podemos ver o consumo de cpu, memória e rede de cada aba (que rodam como processos independentes).<br /><br /><a href="http://www.flickr.com/photos/25513475@N05/2822697178/" title="gerenciador_tarefas by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3040/2822697178_a150abe1fc.jpg" width="500" height="377" alt="gerenciador_tarefas" /></a><br /><br />E também temos acesso a informações de memória bem detalhadas (infelizmente estáticas, gostaria que houvesse algo como o top do unix, quem sabe no futuro...).<br /><a href="http://www.flickr.com/photos/25513475@N05/2822697176/" title="chrome_memory by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3048/2822697176_fbbb8e2688.jpg" width="500" height="374" alt="chrome_memory" /></a>]<br /><br />O histórico é limpo e muito bonito<br /><br /><a href="http://www.flickr.com/photos/25513475@N05/2822697170/" title="chrome_historico by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3099/2822697170_3f5a9469a0.jpg" width="500" height="376" alt="chrome_historico" /></a><br /><br />E um recurso que eu gostei bastante do novo Opera, mas com uma nova roupagem: ao abrir uma nova aba temos uma pagina com os favoritos e snapshots das paginas.<br /><br /><a href="http://www.flickr.com/photos/25513475@N05/2822697164/" title="chrome_abas by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3114/2822697164_05a9ce10db.jpg" width="500" height="377" alt="chrome_abas" /></a><br /><br />Por fim, basta instalar com um clique o plugin flash para navegar no Youtube ou Globo Videos<br /><br /><a href="http://www.flickr.com/photos/25513475@N05/2822697168/" title="chrome_globo_videos by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3036/2822697168_242b7a4e5d.jpg" width="500" height="374" alt="chrome_globo_videos" /></a><br /><br />Outras coisas que percebi: a pergunta para salvar as senhas dos sites é muito mais discreta, aparecendo acima do site após o login (não é aquele alert que surge do nada). O Gmail parece ter uma boa performance e o gtalk funcionou sem maiores problemas. Com 6 abas o consumo de memória foi de 144408k - e ainda podemos comparar com outros browsers abertos!<br /><br />Sinto falta de usar '/' para fazer pesquisas na pagina (quem usa Vim entende disso) mas o Ctrl + F funciona bem. Para configurar o tamanho da fonte basta usar Ctrl + (mais) e Ctrl - (menos) para alterar o tamanho do texto, Ctrl 0 para voltar ao normal. E, a mais interessante, não há necessidade de um campo de texto para pesquisas rapidas ao google ou outro buscador: basta digitar os termos no lugar da url (bem intuitivo, aliás). O download de algum arquivo é simples e bonito também.<br /><br />Bom, até então eu gostei, só aguardo a versão para Linux e quero por as mãos no tão falado codigo fonte logo-logo :)<br /><br />Link para download: <a href="http://gears.google.com/chrome"> http://gears.google.com/chrome </a><br /><br />Edit: o Chrome tem o mesmo problema que o Firefox tinha para gerenciar senhas: ele mostra a senha sem pudor algum:<br /><br /><a href="http://www.flickr.com/photos/25513475@N05/2822070365/" title="Senhas by grande_uosh, on Flickr"><img src="http://farm4.static.flickr.com/3268/2822070365_c3594ac41b.jpg" width="500" height="390" alt="Senhas" /></a><br /><br />Poderia ter um recurso mais seguro como o da <a href="http://br.mozdev.org/firefox/senha-mestra">senha mestra</a> do Firefox, parece que não pensaram (tanto) na nossa privacidade. Quem sabe no futuro isso não será corrigido?Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com6tag:blogger.com,1999:blog-2122907654784586589.post-67686394134654310182008-08-29T21:13:00.003-03:002008-08-29T21:18:29.487-03:00Despedida do AntonioEsta foi a ultima semana do <a href="http://www.acarlos.com.br/blog">Antonio</a> na <a href="http://videos.globo.com">globo.com</a>. A despedida foi em grande estilo, com direito a galeria gourmet. Fica o exemplo e a saudade desse grande colega.<br /><br />Em clima de festa com direito a montinho e tudo:<br /><object width="425" height="319"><param name="movie" value="http://qik.com/swfs/qik_player.swf?streamname=1711b365461b4d31873bd2a7d043fff7&vid=245068&playback=false&polling=false&user=gchapiewski&displayname=gchapiewski&safelink=gchapiewski&userlock=true&islive=&username=anonymous" ></param><param name="wmode" value="transparent" ></param><param name="allowScriptAccess" value="always" ><embed src="http://qik.com/swfs/qik_player.swf?streamname=1711b365461b4d31873bd2a7d043fff7&vid=245068&playback=false&polling=false&user=gchapiewski&displayname=gchapiewski&safelink=gchapiewski&userlock=true&islive=&username=anonymous" type="application/x-shockwave-flash" wmode="transparent" width="425" height="319" allowScriptAccess="always"></embed></object><br /><br />Fico feliz por ter surpreendido do Antonio nesses poucos meses que trabalhei com ele, agora os desafios são outros (aka Expurgo...)!<br /><br />Toninho, boa sorte no Yahoo!Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com1tag:blogger.com,1999:blog-2122907654784586589.post-49934992543558690532008-08-25T13:11:00.005-03:002008-08-25T15:57:28.898-03:00SQL Injection - A fina arte de criar paginas realmente insegurasEste post diz tudo:<br /><img src="http://imgs.xkcd.com/comics/exploits_of_a_mom.png"/><br /><br />Por mais que existam alertas sobre os perigos de <a href="http://en.wikipedia.org/wiki/SQL_injection">SQL Injection</a>, muita gente resolve ignorar e criar sistemas cujas consultas ao banco de dados são feitas através de concatenações de strings com os dados oriundos do usuário.<br /><br />Uma das primeiras coisas que aprendi quando trabalhava como testador foi tentar este código em telas de login:<br /><br /><pre><code>' or '1' ='1<code></pre><br /><br />Imagine que o impacto dessa belezinha em uma query como esta:<br /><br /><pre><code>"SELECT USUARIO FROM TABELA WHERE USUARIO = '" + usuario + "' AND SENHA = '" + senha + "'"</code></pre><br />temos, então:<br /><br /><pre><code>SELECT USUARIO FROM TABELA WHERE USUARIO = 'qqCoisa' AND SENHA = '' or '1' ='1'</code></pre><br /><br />Consegui efetuar o login devido a extrema <b>preguiça</b> do desenvolvedor que nunca se interessou em estudar um pouco de segurança, muito menos sabe o que é um <b>prepared statement</b>. Isso no melhor dos casos, posso querer inserir um DROP TABLE da vida facilmente, pois o sistema está, literalmente, de pernas abertas.<br /><br />Recentemente um colega testou esse tipo de ataque contra um site de uma <span style="font-style:italic;">instituição</span> por curiosidade. Ele conseguiu obter um arquivo contento a senha e o IP do banco de dados e conseguiu acessa-lo, perceberam o perigo?<br /><br />Sinceramente? Se eu vejo um site que cai nesse truque eu não sinto pena. Não vou zoar ou fazer algo maléfico, as vezes até tento avisar, mas não sei se vale a pena: ou o sistema custou muito barato ou custou muito caro, foi produzido por uma consultoria que lucou 1980% em cima do salario do estágiario e que, por mais documentos que tenham produzido não conseguiram fazer algo básico: um site seguro contra hackers que estudam pela Wikipedia.<br /><br />Se o seu site não pode receber aspas simples, duplas ou %, tenha MUITO medo, pois alguem VAI fazer algo em breve...Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com4tag:blogger.com,1999:blog-2122907654784586589.post-69237561687740007292008-08-11T10:48:00.003-03:002008-08-11T11:46:17.309-03:00Closures em Java - Parte 2Ainda sobre a Closures do java 7, agora será possivel fazer isso:<br /><br /><pre><code>public class A {<br /> public static void main(String args[]) {<br /> @Shared int acumulador = 0;<br /><br /> {int => int } xxx = { int i => acumulador += i; i};<br /><br /> System.out.println(xxx.invoke(1));<br /> System.out.println(xxx.invoke(2));<br /> System.out.println(xxx.invoke(3));<br /> System.out.println("o valor do acumulador eh " + acumulador );<br /><br /> }<br />}</code></pre><br /><br />Só eu estou achando divertido?<br /><br /><a href="http://gafter.blogspot.com/2008/08/java-closures-prototype-feature.html">http://gafter.blogspot.com/2008/08/java-closures-prototype-feature.html</a>Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com5tag:blogger.com,1999:blog-2122907654784586589.post-68962701262942541882008-08-08T19:23:00.003-03:002008-08-08T19:26:03.455-03:00Closures em JavaOlha o que vai ter no java 1.7<br /><br /><pre><code>public class A {<br /> public static void main(String args[]) {<br /> exec( { int a, int b => a + b });<br /> exec( { int a, int b => a * b });<br /> exec( { int a, int b => <br /> System.out.println("closure " + a + ":" + b); <br /> (a * a) + (b * b) <br /> });<br /> }<br /> public static void exec({ int, int => int } closure){<br /> System.out.println(closure.invoke(3,2));<br /> }<br />}</code></pre><br /><br /><pre>$ java -Xbootclasspath/p:./closures-2008-08-04/lib/closures.jar A<br />5<br />6<br />closure 3:2<br />13</pre><br /><br />Divertido :)<br /><br />Fonte:<br /><a href="http://guj.com.br/posts/list/99477.java">http://guj.com.br/posts/list/99477.java</a>Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com2tag:blogger.com,1999:blog-2122907654784586589.post-3979229641243935652008-08-08T15:01:00.002-03:002008-08-08T15:05:21.689-03:00Parsing de XML na linguagem ABCA maior parte das linguagens de progração em uso pelo mundo tem pelo menos 1024 bibliotecas para trabalhar com arquivos XML. Me espanta saber que muitos querem "gravar e ler" arquivos nesse formato mas não fazem ideia do que é um XML!<br /><br />Eis um bom começo:<br /><a href=="http://www.w3schools.com/xml/default.asp">http://www.w3schools.com/xml/default.asp</a><br /><br />Acho que nenhuma linguagem tem mais variações sobre o mesmo tema que Java: http://guj.com.br/artigos.jsp#87031Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-59450458537231009312008-08-08T14:29:00.001-03:002008-08-08T14:30:50.456-03:00Testable & Untestable CodeLeitura recomendada:<br /><br /><a href="http://misko.hevery.com/2008/07/24/how-to-write-3v1l-untestable-code/">http://misko.hevery.com/2008/07/24/how-to-write-3v1l-untestable-code/</a><br /><a href="http://www.testingreflections.com/node/view/7221">http://www.testingreflections.com/node/view/7221</a>Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com1tag:blogger.com,1999:blog-2122907654784586589.post-64637922186286097492008-08-07T18:40:00.005-03:002008-08-07T18:55:55.309-03:00The Good, the Bad and the UglyDepois de ter visto algumas vezes "Era uma vez no Oeste" (com Charles Bronson tocando harmônica), finalmente pude conferir o clássico "Três Homens em Conflito" (The Good, the Bad and the Ugly) do mestre Sergio Leone. <br /><br />Clint Eastwood, Eli Wallach e Lee Van Cleef estão perfeitos nessa história cheia de sangue, traições e a obcessão pela riqueza. As panorâmicas de Leone sobre o desertico velho oeste e a caracterização dos homens embrutecidos daquela época, onde a vida não valia mais do alguns dólares, são majestosas, com direito à mostrar parte da guerra civil americana.<br /><br /><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/hVnoaPPpWog&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/hVnoaPPpWog&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object><br /><br />Esqueçam aqueles filmes de indios e tiros falsos: são personagens densos, únicos, em um momento diferente da história, com momentos fantásticos (como a cena em que o "Feio" monta um revolver com as peças de outros). Sem falar no olhar mortal do "Olhos de Anjo" Lee Van Cleef, que passa uma frieza na espinha...<br /><br />- "When you have to shoot, shoot. Don’t talk!"<br /><br />Sem falar no maravilhoso tema de Ennio Morriconi, clássico absoluto. O estilo Western não é vazio como muitos pensam, basta saber apreciar.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com1tag:blogger.com,1999:blog-2122907654784586589.post-65303573605453445522008-08-07T17:43:00.003-03:002008-08-07T18:05:00.558-03:00Voltas às Aulas e o Java - parte 2Existe o clássico problema de determinar se um aluno passou ou não de ano quando são informados as notas e o número de faltas.<br /><br />Vejamos: <br />1) O número de faltas é acima do permitido?. Aqui entra um <span style="font-weight:bold;">if</span> dos bons com uma comparação numérica, quando um número é maior ou igual a outro.<br />2) A média é basicamente somar as X notas e dividir por X (se for média aritmética). Somar e dividir são operações matemáticas básicas.<br /><br />Uma forma de fazer é:<br /><code> if( numero_de_faltas > maximo_de_faltas_toleradas) {<br /> // reprovado por faltas<br />} else if ( media_do_aluno < media_para_passar ){<br /> // reprovado por nota<br />} <br />// se nem um nem outro, esta aprovado<br /></code><br /><br />O ruim dessa abordagem é que o aluno estar aprovado é uma condição "que sobra". Se passarmos a focar a aprovação do mesmo ficaria assim:<br /><br /><code> if( media_do_aluno >= media_para_passar && numero_de_faltas <= maximo_de_faltas_toleradas) {<br /> // aprovado!<br />} else {<br /> // reprovado!<br />}</code><br /><br />É claro que eu posso que eu posso querer saber o motivo pelo qual o aluno foi reprovado:<br /><br /><code> if( media_do_aluno >= media_para_passar && numero_de_faltas <= maximo_de_faltas_toleradas) {<br /> // aprovado!<br />} else if(numero_de_faltas > maximo_de_faltas_toleradas){<br /> // reprovado pelo número de faltas: ignoro a média.<br />} else {<br /> // aqui só sobra a reprovação por nota, <br /> // basta fazer a tabela-verdade dessas expressões<br />}</code><br /><br />Se o foco do professor for o algoritmo, isso é o que deveria ser analisado. Quem implementa corretamente um método que recebe X notas e um número de faltas e consegue responder a essas perguntas consegue descrever facilmente os casos de teste para verificar se a implementação corresponde ao que se espera.<br /><br />Um programa que tenha algum tipo de interação (seja Swing ou console) ajuda a fazer um macarrão de código, mesclando o algoritmo com o controle de estado dos "menuzinhos". No fim vemos laços de repetição aonde não são necessários, calculo de média errado, etc.<br /><br />Ok, não acho que um marinheiro de primeira viagem devesse começar por JUnit, mas uma com boa noção dos fundamentos da linguagem e evitando a interação desnecessária com o usuario (poderia ser usado até os parâmetros do main), acredito num melhor desempenho. O risco é o aluno acreditar que java é dificil ou que tudo se resume a getters/setters e gigantescos try/catch's onde as exceptions são varridas pra debaixo do tapete. <br /><br />Eu colocaria TDD num segundo momento, mas ai sem perdão, ensinando o caboclo a fazer do jeito certo o quanto antes. O que é dificil se eles conseguem passar sem saber fazer aritmética básica.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-9409237995511818642008-08-06T15:05:00.006-03:002008-08-06T15:51:49.598-03:00Algumas pessoas PRECISAM fazer programas interativosEste código:<br /><pre><code>#include <stdio.h><br />#include <stdlib.h><br /><br />int main(int argc, char **argv){<br /> int i;<br /> double total =0;<br /><br /> for(i=1;i < argc;i++){<br /> total = total + atof(argv[i]);<br /> }<br /><br /> printf("A soma dos %d parametros eh %f\n",(argc - 1),total);<br /><br /> return 0;<br />}</code></pre><br /><br />É limpo, prático e scriptável. Não preciso fazer pergunta nenhuma nem tratar nada que o usuario informe: no maximo posso ver o número de parâmetros e reclamar. Basta saber como funciona o laço for e saber que argc é o número de parâmetros que eu passei para o programa e argv é um vetor de strings (que, em C puro, são vetores de chars) onde cada elemento é um parâmetro. O primeiro é sempre o nome do programa (a posição 0, que eu pulei).<br /><br /><pre>$ gcc -Wall soma.c<br />$ ./a.out 1 2 3 4 5<br />A soma dos 5 parametros eh 15.000000</pre><br /><br />Eu compilo e pelo para que todos os warnings possiveis sejam mostrados. Novamente não tive nenhum problema e o código funciona bem. Nem um flush de stdin foi preciso. Se eu colocar uma palavra no meio, como abóbora, será ignorado.<br /><br />Não é mais facil assim do que fazer milhões de menus? Nem precisa de system("pause") system("cls")!Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com2tag:blogger.com,1999:blog-2122907654784586589.post-33356191237107044022008-08-06T14:31:00.008-03:002008-08-06T15:22:30.070-03:00Test Driven Development - parte 1.Veja este código:<br /><br /><pre><code> public void testEhPar() throws Exception{<br /> assertTrue("2 deve ser par",algoritmo.ehPar(2));<br /> assertTrue("4 deve ser par",algoritmo.ehPar(4));<br /> assertTrue("6 deve ser par",algoritmo.ehPar(6));<br /> <br /> assertTrue("1 NAO deve ser par",!algoritmo.ehPar(1));<br /> assertTrue("3 NAO deve ser par",!algoritmo.ehPar(3));<br /> assertTrue("5 NAO deve ser par",!algoritmo.ehPar(5)); <br /> }</code></pre><br /><br />Dentro de uma classe de teste, usando o framework <a href="http://junit.sourceforge.net/#Getting">JUnit</a>, a leitura dessas linhas é a seguinte:<br /><br />Eu tenho um objeto chamado <span style="font-style:italic;">algortimo</span>.<br />A chamada algoritmo.ehPar(2) deve retornar <span style="font-weight:bold;">true</span>, pois 2 é par, e este método informa se o parâmetro informado é, ou não, par.<br />O método <span style="font-weight:bold;">assertTrue</span> recebe dois parâmetros: uma mensagem informando o significado deste teste, e o resultado do mesmo.<br /><br />Se o método estivesse com algum problema e retornasse false, isso:<br /><br />assertTrue("2 deve ser par",algoritmo.ehPar(2));<br /><br />seria o mesmo que<br /><br />assertTrue("2 deve ser par",false);<br /><br />Logo, o teste falha, pois <span style="font-weight:bold;">2 deve ser par</span>.<br /><br />Esta é uma forma <span style="font-style:italic;">programática</span> de garantir o comportamento do código que eu desenvolvo: testando. Se o meu método só depende dos parâmetros informados, é muito simples verificar o seu funcionamento.<br /><br />Desenvolvendo os testes antes de implementar o código, tendo apenas as assinaturas dos métodos (por isso recorri a uma interface <a href="/2008/08/voltas-s-aulas-e-o-java.html">aqui</a>, lembra?), eu posso pensar nos comportamentos esperados e, então, vou desenvolvendo até que todos os testes estejam passando.<br /><br />Não é nada fácil, funciona melhor quando o projeto que estás desenvolvendo está começando, porém os resultados são excelentes: veja o quanto de tempo estás economizando! Se tu pretendes determinar se um código teu está funcionando por programas que perguntam os valores, escrever <br /><br /><pre>$ ant clean test</pre><br /><br />é muito mais rápido! <br /><br />O problema surge quando queremos fazer algo complexo, pois a dificuldade de testar mostra problemas na arquitetura adotada, por exemplo. Quanto temos objetos que tem objetos, herança, polimorfismo, tecnicas mais avançadas podem ser usadas como usar Mocks de objetos (e prover os mecanismos para injetar estes Mocks).<br /><br />No caso desse exemplo, esta é uma solução:<br /><pre><code>public boolean ehPar(int numero){<br /> return numero % 2 == 0;<br />}</code></pre><br /><br />Muitos alunos desconhecem as operações de divisão e módulo entre inteiros. O 1, inteiro, dividido por 2, inteiro, não é 0.5, (em java), e sim 0, pois este é o resultado da divisão inteira. O resto da divisão, simbolizado por %, retorna 1. Dessa forma, o resto da divisão de um numero par por 2 é 0, caso contrario é um número inteiro. São operações básicas que precisam ser dominadas. Repare que eu fiz um código que funcione, não tentei nada mais maquiavélico que dê 0.0001 milissegundos mais rápido. <a href="http://gc.blog.br/2008/01/08/a-falacia-da-otimizacao-prematura/">Evite a otimização precoce</a>.<br /><br />Programar profissionalmente é uma tarefa de <span style="font-weight:bold;">muita</span> responsabilidade. Desenvolver testes para garantir a qualidade provê excelentes resultados a longo prazo.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com2tag:blogger.com,1999:blog-2122907654784586589.post-33597189160523968562008-08-06T14:19:00.004-03:002008-08-06T15:21:04.491-03:00Trocar de EmpregoCompletando 6 meses de globo.com, refleti sobre a opção que fiz quando resolvi trocar de emprego. Vi essa semana muitas pessoas com duvidas de como ou quando fazer uma opção parecida, por isso resolvi colaborar.<br /><br />A primeira coisa que devemos pensar é na nossa carreira. As vezes chegamos ao limite na empresa onde estamos, ou não há perspectivas, ou a situação está ruim, etc. São muitas as coisas que podem acontecer. Com um mercado com falta de mão-de-obra <span style="font-weight:bold;">qualificada</span>, muito profissional é assediado por empresas, prometendo as vezes salário maior, ou então surge uma oportunidade fora do estado. O que fazer?<br /><br />Todas as oportunidades devem ser vistas de forma crítica. Analise o futuro, a distância, o ambiente de trabalho e, também, a remuneração. Eu sempre escolhi o trabalho à remuneração, mas trabalho que paguem abaixo do esperado eu simplesmente não considero. Escolher um emprego vendo apenas o salário engana: imagine ganhar 20% a mais em um emprego mais longe, onde vais perder mais tempo no trajeto, será que compensa? Ou então sair de um ambiente legal para uma confusão absoluta, onde domingo é dia útil de trabalho? Pois é.<br /><br />Feito isso, temos que pensar em coisas práticas: todas as exigências são atendidas? Tem empresa que só se preocupa com diploma e certificações, mesmo que a sua bagagem supere todas expectativas. Se a empresa é em outra cidade ou estado, temos que analisar o custo de vida, mudança, lugar aonde morar (em grandes centros urbanos é <span style="font-weight:bold;">sempre</span> caótico, veja isso com muito cuidado).<br /><br />O currículo precisa estar atualizado. Ja leu isto <a href="http://info.abril.com.br/aberto/infonews/082008/06082008-25.shl">aqui</a>? E <a href="http://pythonologia.org/2007/06/07/desempregado-ou-despreparado/">isso</a>?<br /><br />Nas entrevistas seja sincero e tenha confiança: tu és um produto, tens que te vender. E, se mentir, babau, vão descobrir mais cedo ou mais tarde... Pra isso, podes estudar bastante algum assunto (eu vim lendo as apostilas da Caelum na viagem de carro que fiz de PoA ao RJ).<br /><br />Por fim, planeje bem a transição: vale a pena sair com as portas abertas, caso ocorra algum problema. Seguindo estes passos é relativamente fácil optar por trocar, ou não, de emprego.<br /><br />O importante é se sentir bem aonde estás trabalhando e colaborar para que o ambiente evolua, caso contrario podes ficar fazendo o mesmo trabalho, da mesma forma, por muito tempo: até que um estágiario possa ficar no seu lugar ;-)<br /><br />Ps: <a href="http://usabilidoido.com.br/como_vai_seu_ingles.html">como vai o seu inglês</a>?Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-23819469136308366002008-08-04T12:20:00.005-03:002008-08-08T20:50:52.278-03:00Voltas às Aulas e o JavaNa época de volta às aulas nas faculdades percebe-se uma grande invasão de alunos desesperados em foruns de informática para resolverem os seus execícios. É facil reconhecer um aluno em pânico com o seu primeiro <span style="font-style:italic;">while</span> ou algum exercício sobre Fibonacci: eles não tentam, simplesmente colam o enunciado do problema esperando a resposta pronta.<br /><br />Entretanto tão bizarro quanto são os exercícios propostos: um programa que leia pergunte 2 numeros e retorne a soma, ou um programa para calcular alguma coisa que pergunte ao usuário... perai, pergunte? Um programa perguntando? Como?<br /><br />Este é o típico programa 'interativo' com o usuário. Quando não usa a entrada padrão (algo completamente misterioso para boa parte dos alunos), usam algum recurso SWING. Mas sera que ninguem pensa o quão PREJUDICIAL são estes exercícios?<br /><br />Normalmente o aluno se preocupa com a apresentação do mesmo, fazendo frescuras de menuzinhos, asteriscos pra lá e pra cá... e o algoritmo que é bom nada. Sinceramente: dane-se os menuzinhos. Sabem quantos programas com menuzinhos e que vão perguntar alguma coisa pro usuario vcs vão fazer na vida profissional de vcs? 0! Zero! Nenhum!<br /><br />Existem muitas formas de interação com o usuario, hoje em dia vc pode ter interfaces web, por exemplo. Eu acho que, num primeiro momento, a única interação com o usuario deveria ser escrever na tela. Nada mais que isso se o camarada não sabe o que significa um NullPointerException.<br /><br /><br />Exemplo pratico:<br /><br />- Prepare um diretório para trabalhar (suponho que vc vai usar linux, senão deve ser facil portar este exemplo para outros sistemas operacionais).<br />- Crie um diretorio lib e copie o junit-4.4.jar pra lá (use o google pra baixar esse arquivo, se vc não conseguir saia do curso de informática).<br />- Crie a estrutura abaixo, ainda no diretório de trabalho:<br />src/java<br />src/test<br />- Instale o aplicativo ant (de novo o google te ajuda, alias vc tem algum JDK instalado, certo??).<br />- Crie um arquivo chamado build.xml no diretorio de trabalho.<br />- Baixe o arquivo ant-junit.jar daqui [ http://www.java2s.com/Code/Jar/ANT/Downloadantjunitjar.htm ] e copie o .JAR para ~/.ant/lib (se não existe, crie).<br /><br />Agora vem a proposta: baseado nessa interface:<br /><br /><pre><code>public interface Algoritmo{<br />/* dado um numero, retorna true se for par */ <br />boolean ehPar(int numero);<br />/* calcula o valor absoluto ou modulo de um numero, ex: -1 vira 1, 1 vira 1 */<br />int calculaModulo(int numero);<br />/* calcula algum termo da série de fibonacci: se 0, mostra o primeiro, se 1 mostra o segundo...*/<br />int calculaFibonacci(int elemento);<br />/* calcula o fatorial do numero indicado */<br />long calculaFatorial(int numero);<br />}</code></pre><br /><br />Vais criar uma classe chamada, digamos, SuaClasse que implementa esta interface (percebeu que tudo deve ficar em src/java não é?). Não pense na implementação dessa classe ainda.<br /><br />No diretorio src/test vc vai salvar esta classe:<br /><br /><pre><code>import junit.framework.TestCase;<br /><br />public class AlgoritmoTeste extends TestCase{<br /> Algoritmo algoritmo;<br /> public void setUp(){<br /> algoritmo = new SuaClasse();<br /> }<br /> <br /> public void tearDown(){<br /> algoritmo = null; <br /> }<br /> <br /> public void testEhPar() throws Exception{<br /> assertTrue("2 deve ser par",algoritmo.ehPar(2));<br /> assertTrue("4 deve ser par",algoritmo.ehPar(4));<br /> assertTrue("6 deve ser par",algoritmo.ehPar(6));<br /> <br /> assertTrue("1 NAO deve ser par",!algoritmo.ehPar(1));<br /> assertTrue("3 NAO deve ser par",!algoritmo.ehPar(3));<br /> assertTrue("5 NAO deve ser par",!algoritmo.ehPar(5)); <br /> }<br /> <br /> public void testCalculaModulo() throws Exception{<br /> assertTrue("modulo de 3 deve ser 3",algoritmo.calculaModulo(3) == 3);<br /> assertTrue("modulo de -3 deve ser 3",algoritmo.calculaModulo(-3) == 3);<br /> assertTrue("modulo de 5 deve ser 5",algoritmo.calculaModulo(5) == 5);<br /> assertTrue("modulo de -5 deve ser 5",algoritmo.calculaModulo(-5) == 5); <br /> }<br /> <br /> public void testCalculaFibonacci() throws Exception{<br /> assertTrue("elemento 0 da serie fibonacci deve ser 0",algoritmo.calculaFibonacci(0) == 0);<br /> assertTrue("elemento 1 da serie fibonacci deve ser 1",algoritmo.calculaFibonacci(1) == 1);<br /> assertTrue("elemento 2 da serie fibonacci deve ser 1",algoritmo.calculaFibonacci(2) == 1);<br /> assertTrue("elemento 3 da serie fibonacci deve ser 2",algoritmo.calculaFibonacci(3) == 2); <br /> assertTrue("elemento 4 da serie fibonacci deve ser 3",algoritmo.calculaFibonacci(4) == 3);<br /> assertTrue("elemento 5 da serie fibonacci deve ser 5",algoritmo.calculaFibonacci(5) == 5);<br /> assertTrue("elemento 6 da serie fibonacci deve ser 8",algoritmo.calculaFibonacci(6) == 8);<br /> assertTrue("elemento 7 da serie fibonacci deve ser 13",algoritmo.calculaFibonacci(7) == 13); <br /> assertTrue("elemento 11 da serie fibonacci deve ser 89",algoritmo.calculaFibonacci(11) == 89);<br /> assertTrue("elemento 13 da serie fibonacci deve ser 223",algoritmo.calculaFibonacci(13) == 233); <br /> }<br /> <br /> public void testCalculaFatorial() throws Exception{<br /> assertTrue("Fatorial de 1 deve ser 1",algoritmo.calculaFatorial(1) == 1);<br /> assertTrue("Fatorial de 2 deve ser 2",algoritmo.calculaFatorial(2) == 2);<br /> assertTrue("Fatorial de 3 deve ser 6",algoritmo.calculaFatorial(3) == 6);<br /> assertTrue("Fatorial de 4 deve ser 24",algoritmo.calculaFatorial(4) == 24);<br /> assertTrue("Fatorial de 5 deve ser 120",algoritmo.calculaFatorial(5) == 120);<br /> assertTrue("Fatorial de 6 deve ser 720",algoritmo.calculaFatorial(6) == 720);<br /> assertTrue("Fatorial de 10 deve ser 3628800L",algoritmo.calculaFatorial(10) == 3628800L); <br /> }<br />}</code></pre><br /><br />Uma ideia sobre o JUnit pode ser encontrada aqui: [ http://guj.com.br/java.tutorial.artigo.40.1.guj ], alias o guj, na sessão de tutoriais, explica varias coisas, é ótimo material de referência!<br /><br />Ok, vc tem a interface que vc deve respeitar e um arquivo de teste. Vamos falar do arquivo de build do ant.<br /><br /><pre><code><project name="Meu Projeto" basedir="." default="dist"><br /> <description><br /> Aprendendo a fazer um build.xml para o ant<br /> </description><br /><br /> <property name="lib" location="lib"/><br /> <property name="src" location="src/java"/><br /> <property name="test" location="src/test"/><br /><br /> <property name="build" location="build"/><br /> <property name="dist" location="dist"/><br /><br /> <path id="classpath.test"> <br /> <pathelement location="${test}" /><br /> <pathelement location="${build}" /><br /> <pathelement location="${lib}/junit-4.4.jar" /><br /> </path><br /><br /> <target name="init"><br /> <!-- Create the time stamp --><br /> <tstamp/><br /> <!-- Create the build directory structure used by compile --><br /> <mkdir dir="${build}"/><br /> </target><br /><br /> <target name="compile" depends="init" description="compile the source " ><br /> <!-- Compile the java code from ${src} into ${build} --><br /> <javac srcdir="${src}" destdir="${build}"/><br /> </target><br /><br /> <target name="dist" depends="compile" description="generate the distribution" ><br /> <!-- Create the distribution directory --><br /> <mkdir dir="${dist}/lib"/><br /><br /> <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --><br /> <jar jarfile="${dist}/lib/Algortimo-${DSTAMP}.jar" basedir="${build}"/><br /> </target><br /><br /> <target name="clean" description="clean up" ><br /> <!-- Delete the ${build} and ${dist} directory trees --><br /> <delete dir="${build}"/><br /> <delete dir="${dist}"/><br /> </target><br /><br /> <target name="test" depends="compile"><br /> <javac srcdir="${test}"><br /> <classpath refid="classpath.test"/><br /> </javac><br /> <junit><br /> <classpath refid="classpath.test" /><br /> <formatter type="brief" usefile="false" /><br /> <test name="AlgoritmoTeste"/><br /> </junit><br /> </target><br /></project><br /></code></pre><br /><br />A utilização desse arquivo é muito simples, não se amedronte pelo tamanho do arquivo, o formato xml do ant é bizarro e verboso, sou muito mais um Makefile, porém uma vez com ele feito basta ir adicionando coisas "com cuidado". Sem falar que tudo tem documentação oficial cheia de exemplos, só não aprende quem <span style="font-weight:bold;">não</span> quer.<br /><br />$ ant <br />isso deve compilar a sua classe e gerar um jar (pode ser util no futuro).<br /><br />$ ant clean<br />limpa os diretorios que vc acabou de criar com as suas paradas compiladas.<br /><br />$ ant test<br />compila e executa os testes unítarios.<br /><br />É claro que vc vai dizer, e agora??? Bom, veja isso:<br /><br /><pre><code>public class SuaClasse implements Algoritmo{<br /> public boolean ehPar(int numero){return false;}<br /> public int calculaModulo(int numero){ return -1;}<br /> public int calculaFibonacci(int elemento){return -1;}<br /> public long calculaFatorial(int numero){return -1;}<br />}</code></pre><br /><br />Olha que legal! Uma classe que tem o minimo pra compilar! Agora vamos testar...<br /><br /><pre>$ ant test<br />Buildfile: build.xml<br /><br />init:<br /> [mkdir] Created dir: /home/GLOBO.COM/peczenyj/test/junit/build<br /><br />compile:<br /> [javac] Compiling 2 source files to /home/GLOBO.COM/peczenyj/test/junit/build<br /><br />test:<br /> [javac] Compiling 1 source file<br /> [junit] Testsuite: AlgoritmoTeste<br /> [junit] Tests run: 4, Failures: 4, Errors: 0, Time elapsed: 0.005 sec<br /> [junit] <br /> [junit] Testcase: testEhPar(AlgoritmoTeste): FAILED<br /> [junit] 2 deve ser par<br /> [junit] junit.framework.AssertionFailedError: 2 deve ser par<br /> [junit] at AlgoritmoTeste.testEhPar(Unknown Source)<br /> [junit] <br /> [junit] <br /> [junit] Testcase: testCalculaModulo(AlgoritmoTeste): FAILED<br /> [junit] modulo de 3 deve ser 3<br /> [junit] junit.framework.AssertionFailedError: modulo de 3 deve ser 3<br /> [junit] at AlgoritmoTeste.testCalculaModulo(Unknown Source)<br /> [junit] <br /> [junit] <br /> [junit] Testcase: testCalculaFibonacci(AlgoritmoTeste): FAILED<br /> [junit] elemento 0 da serie fibonacci deve ser 0<br /> [junit] junit.framework.AssertionFailedError: elemento 0 da serie fibonacci deve ser 0<br /> [junit] at AlgoritmoTeste.testCalculaFibonacci(Unknown Source)<br /> [junit] <br /> [junit] <br /> [junit] Testcase: testCalculaFatorial(AlgoritmoTeste): FAILED<br /> [junit] Fatorial de 1 deve ser 1<br /> [junit] junit.framework.AssertionFailedError: Fatorial de 1 deve ser 1<br /> [junit] at AlgoritmoTeste.testCalculaFatorial(Unknown Source)<br /> [junit] <br /> [junit] <br /> [junit] Test AlgoritmoTeste FAILED<br /><br />BUILD SUCCESSFUL<br />Total time: 1 second</pre><br /><br />Agora basta escrever codigo de verdade na SuaClasse e testar, estara pronto quando TUDO estiver passando. São 4 métodos básicos, sabendo lidar com variaveis locais, if e for, vc consegue muita coisa.<br /><br />Se eu fosse professor eu daria exercícios assim: o projeto deveria compilar e todos os testes deveriam passar senão o aluno leva 0. A nota viria de acordo com o que eu espero, posso usar um EMMA e ver a cobertura de código, posso avaliar a presença de um Javadoc que preste, etc.<br /><br />Enfim, eu seria um professor muito malvado }-)<br /><br />Não perca a parte 2 <a href="/2008/08/voltas-s-aulas-e-o-java-parte-2.html">aqui</a>, e uma introdução ao TDD <a href="/2008/08/test-driven-development-parte-1.html">aqui</a>.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com11tag:blogger.com,1999:blog-2122907654784586589.post-77081486595087604642008-07-08T16:14:00.001-03:002008-07-08T16:16:05.074-03:00Tor: Um sistema anónimo de comunicação na InternetPelo veto ao projeto de cibercrimes - Em defesa da liberdade e do progresso do conhecimento na Internet Brasileira<br /><br />http://www.petitiononline.com/veto2008/<br /><br />Se esta lei for aprovada, podemos fazer uso do Tor para navegar tranquilamente.<br /><br />Tor é um conjunto de ferramentas para um amplo grupo de organizações e particulares que desejam aumentar a sua segurança na Internet. Usar Tor pode ajudar a tornar anónima a navegação e publicação na Web, instant messaging, IRC, SSH, e outras aplicações que usem o protocolo TCP. Tor também disponibiliza uma plataforma para os programadores de software, criarem novas aplicações com funções de anonimato, segurança e privacidade já incorporadas.<br /><br />Tor pretende defender contra a análise de tráfego, uma forma de vigilância que ameaça o anonimato pessoal e a privacidade, a confidencialidade dos negócios e relacionamentos, e a segurança de estados. As comunicações são enviadas através de uma rede distribuída de servidores chamados onion routers, protegendo-nos de sites Web que constroem perfis com os nossos interesses, pequenos espiões que lêem os nossos dados ou registam que sites visitámos.<br /><br />A segurança do Tor aumenta à medida que a sua base de utilizadores aumenta e mais pessoas se oferecem para alojar servidores. Por favor considere oferecer o seu tempo ou oferecer a sua largura de banda. Convém lembrar que estamos a lidar com código em desenvolvimento — Não deve usar o Tor se precisa realmente de fortes garantias de anonimato. <br /><br />Fonte: http://www.torproject.org/index.html.ptTiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-65829540840427831632008-07-03T17:35:00.000-03:002008-07-03T17:36:44.987-03:00Sudo<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://imgs.xkcd.com/comics/sandwich.png"><img style="cursor:pointer; cursor:hand;width: 320px;" src="http://imgs.xkcd.com/comics/sandwich.png" border="0" alt="" /></a>Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-35779366486258661042008-06-19T15:15:00.002-03:002008-06-19T15:19:09.362-03:00Erlang é dificil (parte 2)Agora vamos usar as funções específicas para manipular listas.<br /><br /><pre><code>-module(tut).<br />-export([generate/1]).<br /><br />%%<br />%% Funcao generate(X)<br />%% Quando X for 0, retorna [0]<br />%% Quando X > 0, retorna [X,X-1,...,0]<br />%% Caso contrario retorna [0,1,2,...,abs(X)]<br />%%<br />generate(0) -> [0];<br />generate(L) when integer(L), L > 0 -> <br /> lists:seq(0,L); % cria uma lista de 0 até L<br />generate(L) when integer(L) -> <br /> % vamos reverter a lista?<br /> lists:reverse(generate(-L)).</pre></code><br /><br />Muito mais simples, certo? Veja o teste:<br /><br /><pre>$ erl<br />Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [kernel-poll:false]<br /><br />Eshell V5.5.5 (abort with ^G)<br />1> c(tut). <br />{ok,tut}<br />2> tut:generate(5) ++ tut:generate(-5).<br />[0,1,2,3,4,5,5,4,3,2,1,0]<br />3> </pre><br /><br />O operador ++ une 2 listas :)Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-28786064248860491872008-06-18T19:10:00.002-03:002008-06-18T19:26:15.525-03:00Erlang é dificil?Erlang é realmente dificil?<br /><br /><pre><code>-module(tut).<br />-export([generate/1]).<br /><br />%%<br />%% Funcao generate(X)<br />%% Quando X for 0, retorna [0]<br />%% Quando X > 0, retorna [X,X-1,...,0]<br />%% Caso contrario retorna [0,1,2,...,abs(X)]<br />%%<br />generate(0) -> [0];<br />generate(L) when integer(L) -> gera_lista(L).<br /><br />gera_lista(L) when L > 0 -> gera_lista_direita(L);<br />gera_lista(L) -> gera_lista_inversa(-L).<br /><br />gera_lista_direita(L) -> gera_lista_direita(L,[]).<br /><br />gera_lista_direita(-1,Z) -> Z;<br />gera_lista_direita( L,Z) -> <br /> %io:format("chamando: gera_lista_direita(~p,Z)~n",[L]),<br /> gera_lista_direita(L - 1,[L | Z]).<br /><br />gera_lista_inversa(L) -> gera_lista_inversa(L,[]).<br /><br />gera_lista_inversa(-1,Z) -> Z;<br />gera_lista_inversa( L,Z) -> gera_lista_inversa(L,0,Z).<br /><br />gera_lista_inversa(-1,_,Z) -> gera_lista_inversa(-1,Z);<br />gera_lista_inversa( L,A,Z) -> <br /> %io:format("chamando: h(~p,~p,Z)~n",[L,A]), <br /> h(L - 1, A + 1,[A | Z]).</pre></code><br /><br />Ok, dessa forma é dificil. Erlang é uma linguagem funcional, ou seja, suas funções seguem um raciocínio matemático e não imperativo. Vc sente o problema quando quer resolver algo iterativo ou utilizar variaveis de qualquer forma.<br /><br />Fiz uma pequena função chamada generate, do modulo tut (de <span style="font-style:italic;">tutorial</span>, uma vez que estou seguindo um). Ela é muito simples, se vc informar 0, ela gera uma lista simples contendo 0. Se vc passar um numero positivo ela gera uma lista de 0 até o número, inclusive. Se o numero for negativo, ele assume que vc quer fazer fazer a lista de forma inversa.<br /><br />Veja só:<br /><pre>$ erlc tut.erl # compilando o modulo<br />$ erl<br />Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [kernel-poll:false]<br /><br />Eshell V5.5.5 (abort with ^G)<br />1> c(tut). # carregando o modulo<br />{ok,tut}<br />2> tut:generate(0). # invocando modulo:funcao(parametros).<br />[0]<br />3> tut:generate(10).<br />[0,1,2,3,4,5,6,7,8,9,10]<br />4> tut:generate(-10).<br />[10,9,8,7,6,5,4,3,2,1,0]<br />5> </pre><br /><br />A função <span style="font-weight:bold;">generate</span> chama a função gera_lista se o parametro passado for um número inteiro.<br />A função <span style="font-weight:bold;">gera_lista</span> chama a função para gerar a lista direita ou inversa, de acordo com o valor do parâmetro.<br /><br />Veja só a simplicidade:<br /><br /><pre><code>gera_lista_direita(L) -> gera_lista_direita(L,[]).<br /><br />gera_lista_direita(-1,Z) -> Z;<br />gera_lista_direita( L,Z) -> <br /> %io:format("chamando: gera_lista_direita(~p,Z)~n",[L]),<br /> gera_lista_direita(L - 1,[L | Z]).</pre></code><br /><br />quando eu chamo gera_lista_direita(10) eu estou, na verdade, chamado a função gera_lista_direita(10,[]), onde eu fico usando uma lista como acumulador.<br /><br />A operação [L | X] pode ser lida como [ elemento | lista ] , ou seja, eu adiciono um elemento em uma lista. gera_lista_direita(10,[]) vai chamar, então, gera_lista_direita(9,[10]), e depois gera_lista_direita(8,[9, 10]), e assim recursivamente até gera_lista_direita(-1,Z), quando eu retorno a lista. Fica claro se removerem os comentários (%) da frente dos io:format, que é a forma de fazer PPADD (Passei Por Aqui Driven Development) em Erlang.<br /><br />Erlang precisa de MUITA pratica, principalmente de quem nunca programou em uma linguagem funcional e fica tentado a fazer coisas 'não ortodoxas' ;-)<br /><br />Ah sim, o google é seu amigo:<br /><br />http://www.dei.isep.ipp.pt/~paf/orgcdocs/Intro_Erlang.pdfTiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com5tag:blogger.com,1999:blog-2122907654784586589.post-64448186682841046172008-06-18T15:15:00.002-03:002008-06-18T15:21:02.070-03:00Tabela do Brasileirão 2008 com links + sedO sed é um processador de texto muito versátil.<br /><br />O links é um browser modo texto com features tão interessantes quanto do antigo lynx.<br /><br />Ano passado eu <a href="http://peczenyj.blogspot.com/2007/06/classificao-do-brasileiro-via-shell.html">postei</a> como imprimir a tabela do brasileirão com um one liner interessante. Agora eu resolvi beber de outra fonte:<br /><br /><pre><code>#!/bin/bash<br />TIME=Internacional<br />COLOR=$(echo -ne '\e[31;1m&\e[m')<br />URL=http://globoesporte.globo.com/Esportes/Futebol/Classificacao/0,,ESP0-9827,00.html<br />links --dump ${URL} | sed -r 's/\[[0-9]*\]//;/(^[0-9]|J jogos)/!d' | sed "s/${TIME}/${COLOR}/<br /> 1a-----Libertadores----------<br /> 4a-----Pre-Libertadores------<br /> 5a-----Sul-Americana---------<br /> 13a---------------------------<br /> 17a-----Rebaixado-------------"</pre></code><br /><br />O resultado não é tão bom quanto o do ano passado, é verdade, mas não deixa de ser uma alternativaTiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com3tag:blogger.com,1999:blog-2122907654784586589.post-33913157709646597462008-06-13T23:24:00.001-03:002008-06-13T23:51:37.332-03:00Gerenciando InovaçõesNo ramo da tecnologia da informação, vulgo <em>informática</em>, saber gerenciar inovações é uma <em>arte</em>. Não tenho outras palavras para descrever o fato de vc olhar para uma ideia como o gmail, youtube, icq, orkut ou geocities e dizer "isso tem futuro". Mas não é bem assim.<br /><br />A história de cada inovação bem sucedida é extremamente complexa: são opiniões diversas, conflitos internos, apostas, brigas e muito trabalho para transformar uma ideia em algo que marque de verdade. Com certeza nada naquilo que temos hoje é o que foi imaginado de primeira, afinal os conceitos evoluem. Com certeza aquele chefe chato que barrava todas as ideias contribuiu, mesmo que indiretamente, para o sucesso da ideia.<br /><br />Ai tem um ponto interessante: quem não conhece aquele chefe que barra todas as ideias inovadoras? Estes são o outro extremo da coisa! A informática muda muito, as pessoas que tem computador hoje são diferentes das que tinham no passado e assim por diante, é dificil vc inovar sem se arriscar muito: é ai que entra o <em>medo</em>.<br /><br />Em todos os ramos existe inovação, o que diferencia é a velocidade com a qual as coisas andam. Alguns ramos seguem as mesmas ideias por décadas ou séculos, enquanto outros ramos a escala é de semanas. É dificil não ter medo, afinal ou vc inova ou vc faz coisas loucas, inconsequentes, que podem destruir todo um trabalho de uma vida.<br /><br />O segredo é saber o que vc quer. Empresas de tamanho médio inovam com algum pé atrás, apostando em formulas consagradas e alguma novidade para quebrar o clima. Empresas grandes não podem se dar ao luxo de inovar sob pena de perder o fio da meada portanto podem comprar as empresas pequenas que, inovando, podem gerar lucro para gigantescas corporações multinacionais. E este é apenas um cenário de muitos que acontecem por ai. Temos empresas que sabem vender o convencional como se fosse inovação, e vice-versa. <br /><br />A questão é: como lidar com inovações quando as mesmas podem ser o próximo <a href="http://pt.wikipedia.org/wiki/Microsoft_Bob">microsoft bob</a> ou o Iphone? Acho que cada um tem a sua formula: seja inovando ou comprando inovações por chegar a um tamanho que não é possivel não ser burocrata, cada um enfrenta essas novas tendências como acha melhor, trabalhando num ramo muito recente, onde as regras estão sendo escritas por bilhões de pessoas.<br /><br />A resposta não é algo vago como: dilheiro dá em árvores ou todos tem potencial para ser algo mágico, etc, etc. É necessário entender as inovações que surgiram nos ultimos 10 anos (flash, ajax, orkut, celular, busca por palavras chave, etc) e reconhecer que existem milhões/bilhões de pessoas que contribuem para isso e elas são extremamente intelectualmente ativas. Uma face disso são os projetos open source como Linux, Hibernate e Ruby on Rails que competem de igual para igual com gigantescas corporações.<br /><br />Resumindo: eu não sei lidar com inovações, mas elas chegam até mim via centenas de privilegiados que bebem da fonte. De alguma forma eu participo delas, mas não sei gerar nenhuma, tampouco saberia gerenciar, mas sei respeitar que o assunto é complexo e, principalmente, causa medo.<br /><br />Medo de prejuizos. Principalmente se alguem lembrar <strong>muito</strong>, ou <strong>pouco</strong>.Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com0tag:blogger.com,1999:blog-2122907654784586589.post-32720867852080550902008-05-28T18:17:00.008-03:002008-05-28T18:44:37.264-03:00Pesquisando nos Grupos do YahooMeu amigo MrBits me deu essa grande ideia:<br /><br /><pre><code>#!/bin/bash<br />QTDE=20<br />CHARSET=UTF-8<br />GROUP=shell-script<br /><br />while getopts g:c:q: OPTION ; do<br /> case $OPTION in<br /> g) GROUP=$OPTARG ;;<br /> c) CHARSET=$OPTARG ;;<br /> q) QTDE=$OPTARG ;;<br /> esac<br />done<br /><br />shift $(($OPTIND -1))<br /><br />SEARCH="$@"<br /><br />if [ -z "$SEARCH" ]; then <br /> echo "Usage: $(basename $0) [-q qtde] [-g grupo] [-c charset] search" <br /> exit 1<br />fi<br /><br />BASEURL="http://br.groups.yahoo.com/group"<br />URL="${BASEURL}/${GROUP}/msearch?submit=OK&charset=${CHARSET}&cnt=${QTDE}&query=${SEARCH// /+}" <br />SEDCMD="/message/!d;/${GROUP}/!d;/.*[0-9]/!d;s#/group#${BASEURL}#g;s/<[^>]*span>//g;s/$/<br \/>/"<br /><br />LYNXOPT="-dump -force_html -assume_charset=${CHARSET}"<br />lynx $LYNXOPT <( curl -b /tmp/cookie$$ -sL "${URL}" | sed "${SEDCMD}" )</code></pre><br /><br />Vejamos em uso:<br /><pre>$ ./find.sh <br />Usage: find.sh [-q qtde] [-g grupo] [-c charset] search<br /><br />$ ./find.sh -q 10 getopts # procurando por getopts limitando a 10 registros<br /> [1]Re: [shell-script] Script de busca de mensagens<br /> [2]Re: [shell-script] Re: script iterativo / passo a passo<br /> [3]Re: [shell-script] Script de Backup<br /> [4]Re: [shell-script] Script de Backup<br /> [5]Re: [shell-script] Script de Backup<br /> [6]Re: [shell-script] Script de Backup<br /> [7]Re: [shell-script] Echo e executa: superecho<br /> [8]Re: [shell-script] testar se parametro $1 foi passado<br /> [9]Re: [shell-script] Echo e executa: superecho<br /> [10]Re: [shell-script] testar se parametro $1 foi passado<br /><br />References<br /><br /> 1. http://br.groups.yahoo.com/group/shell-script/message/26373<br /> 2. http://br.groups.yahoo.com/group/shell-script/message/26204<br /> 3. http://br.groups.yahoo.com/group/shell-script/message/26078<br /> 4. http://br.groups.yahoo.com/group/shell-script/message/26076<br /> 5. http://br.groups.yahoo.com/group/shell-script/message/26075<br /> 6. http://br.groups.yahoo.com/group/shell-script/message/26072<br /> 7. http://br.groups.yahoo.com/group/shell-script/message/25742<br /> 8. http://br.groups.yahoo.com/group/shell-script/message/25720<br /> 9. http://br.groups.yahoo.com/group/shell-script/message/25719<br /> 10. http://br.groups.yahoo.com/group/shell-script/message/25718</pre><br /><br />Divertido, não? o default é procurar no grupo shell-script do yahoo, mas ele pode investigar em qualquer um.<br /><br />Valeu Mr.Bits!!Tiago "PacMan" Peczenyjhttp://www.blogger.com/profile/14804218844671345695noreply@blogger.com6