Archive for the Atividades profissionais Category

Por que eu escolhi ser programador / Saber programar em uma ou várias linguagens?

Posted in Atividades profissionais, Temas polêmicos on 02/09/2012 by Allan Taborda

O post de hoje possui dois assuntos, ambos voltados ao desenvolvimento de software. O primeiro é sobre por que eu escolhi ser programador (e por que talvez seria bom você escolher essa profissão). O segundo é sobre saber programar em uma ou em mais linguagens de programação.

Antes de eu entrar na FATEC de Praia Grande e cursar o curso de Tecnologia em Informática com Ênfase em Gestão de Negócios, eu pensava em ser professor de matemática e dar aulas em escolas públicas e particulares, da quinta série até o ensino médio, ou ser técnico de computadores, dando manutenção em PCs, consertando-os, montando-os, resolvendo pepinos no sistema operacional, etc, já que eu tinha feito um curso de hardware numa escola profissionalizante. Aí eu acabei passando no único vestibular que eu tinha feito, que era o da FATEC de Praia Grande (passei em décimo segundo lugar entre 254 candidatos, mesmo sem ter estudado para a prova) e cursei aquele curso, no período da tarde.

No curso, aprendi muitas coisas, como o uso e administração de banco de dados, com ênfase no Oracle e sua linguagem PL/SQL; análise de sistemas, que engloba a elaboração dos requisitos do programa, dois casos de uso e criação de diagramas diversos, incluindo o diagrama UML; lógica de programação e estrutura de dados, ambas as matérias usando a linguagem de programação C++ como base; linguagem de programação Java, tanto para desktop quanto para web; gerência de projetos, com ênfase na metodologia PMI; matérias teóricas acerca de sistemas de informação; planejamento de negócios, onde aprendi a elaborar um plano de negócios a fim de montar um negócio próprio; etc, além de matérias menos importantes, como filosofia, recursos humanos, cálculo numérico, computação gráfica, matemática (matrizes e vetores), estatística, marketing, inglês e espanhol, e outras.

Um profissional formado no curso que eu fiz pode atuar em diversas áreas relacionadas ao conteúdo do curso explanado no parágrafo anterior. Pode atuar tanto na área de gestão de negócios (a metade do curso é formado por matérias relacionadas a gestão de negócios) quanto em profissões voltadas à informática, como programador, analista de sistemas, administrador de banco de dados, etc. Para cada profissão, o profissional deve, além de usar o conhecimento obtido no curso, se aprofundar na área buscando conhecimento de outras fontes (cursos específicos, principalmente), uma vez que o curso de Tecnologia em Informática com Ênfase em Gestão de Negócios (que atualmente chama-se Informática para Gestão de Negócios e teve algumas alterações a fim de melhorar o mesmo) não ensina tudo (nem existe curso que ensine tudo), mas dá uma boa base para ir começando e depois se aprofundar na profissão escolhida.

Dentre essas profissões relacionadas, eu escolhi ser programador. Como no curso houve uma ênfase maior na linguagem de programação Java, foi natural eu escolher programar nessa linguagem. Posteriormente, me aprofundei nos meus conhecimentos em Java obtendo a certificação SCJP (fiz um post sobre a obtenção dessa certificação neste blog inclusive) e estudando por conta própria por livros e tutoriais na Internet. Pretendo no futuro tirar mais certificações Java (a próxima será a SCWCD, que agora é OCWCD, uma vez que a Sun foi comprada pela Oracle), além de fazer cursos com conhecimentos mais avançados.

Mas por que eu decidi ser programador, e não analista de sistemas ou administrador de banco de dados, por exemplo?

O principal motivo é que programar é uma coisa que me dá prazer (tá, sexo também me dá prazer, mas acho muito perigoso trabalhar como profissional do sexo, além da concorrência estar brava nesse ramo). Eu sinto prazer em criar aplicações (e também alterar aplicações já existentes, melhorando-as) e vê-las funcionando bem, fazendo o que foram projetadas para fazer. Gosto tanto de programar que programo não apenas profissionalmente, como também por hobby, desenvolvendo meus projetos pessoais de software, como o Robowebert Player e o AOPT, ambos já citados aqui neste blog.

Outro motivo é a grande quantidade de vagas de emprego existentes no mercado de trabalho. Devido à escassez de profissionais qualificados em desenvolver softwares (e para piorar a situação, há os qualificados que não sabem programar direito), aliada à alta demanda por esses profissionais, uma vez que milhares de sistemas precisam ser desenvolvidos do zero ou alterados a fim de ficarem aos gostos dos clientes, os profissionais que se qualificam têm praticamente emprego garantido (apesar do primeiro emprego como programador ser um pouco mais difícil de se conseguir, devido à falta de experiência e ao fato do fato da maioria dos empregadores exigir experiência anterior, mas há quem contrate programadores sem experiência, além de ser possível obter experiência por conta própria, desenvolvendo sistemas como autônomo, ou começar como estagiário), com um salário maior do que muitas profissões por aí (a não ser que comece como estagiário), ainda que o mesmo não seja tão grande nos primeiros empregos.

Um outro motivo, este um pouco polêmico, pois não é um consenso entre os programadores, é o salário, que eu acho que é um bom salário. Eu não vou dizer o quanto eu ganho, mas é o suficiente para pagar minhas contas e juntar um pouco na poupança. Mas há os que acham que não ganham um bom salário, agora vai saber que salário eles ganham… Já vi gente achar um valor que era mais ou menos o que eu ganhava aviltante (vai saber quais são as necessidades de dinheiro do cara, como ele administra o dinheiro dele…), já vi gente exigindo salários muito altos e irreais e já vi gente se contentando com um pouco mais da metade do que eu ganho atualmente para fazer a mesma coisa que eu faço.

Um programador de início de carreira não vai ganhar um salário tão alto, mas a medida que ele vai ganhando experiência, seu salário vai aumentando, seja com aumento salarial dado pela empresa onde trabalha ou quando esse programador muda de emprego, sendo contratado por uma outra empresa que paga um salário maior do que a empresa anterior, visto que agora possui mais experiência profissional do que quando entrou no emprego anterior.

Ainda na questão do salário, a relação esforço/remuneração, em minha opinião, é melhor do que a de outras profissões relacionadas à informática, como a de técnico de computadores, que é uma relação bem ruim, pois um técnico ganha muito menos e se esforça muito mais do que um programador (eu ensaiei ser técnico e vi o esforço que era, além de assuntar quanto um técnico ganhava), ou a de administrador de servidores.

Um programador, por saber programar, caso tenha alguma necessidade não suprida por algum programa de computador existente, pode criar o seu próprio programa que satisfaça essa sua necessidade, sem depender de algum outro programador ou empresa que desenvolva esse programa. Pode também alterar um programa já existente, adaptando-o às suas necessidades.

São basicamente esses cinco motivos de por que eu escolher ser programador. Talvez haja mais algum outro que eu não me lembre, mas o mais importante é isso.

Emendando um assunto no outro, existe a questão de saber programar em uma ou em mais linguagens de programação. O que seria melhor para o profissional de desenvolvimento de software, saber apenas uma ou saber um monte delas?

No mercado de trabalho, há vagas para trabalhar como programador de várias linguagens de programação, algumas tendo mais vagas que outras (Java, C# e VB.net costumam ter muitas vagas). Sabendo mais de uma, teoricamente, o programador possuirá mais chance e mais qualificação no mercado de trabalho.

Já vi alguns afirmarem que o melhor é saber várias linguagens, pois o mercado de trabalho pode mudar e uma outra linguagem passar a ser mais usada que outra, ou porque sabendo várias, o programador tem mais chance de ser contratado, ou outros motivos. Mas há um porém de saber várias linguagens de programação: você acaba dividindo seus estudos entre várias e não aprofunda seus conhecimentos em nenhuma, muitas vezes sabendo apenas o básico de cada uma delas. Aí não vai adiantar nada saber mais de uma e não saber programar direito em nenhuma, cometendo erros de, por exemplo, na linguagem Java, comparar Strings com dois sinais de igual ao invés de usar o método equals (eu já cheguei a, neste blog, dedicar dois posts para enumerar erros irritantes cometidos por programadores Java, e talvez eu dedique outros no futuro) ou não saber usar uma biblioteca na qual o uso da mesma é melhor do que uma outra que é mais simples e mais arcaica, mas que é a única que o programador sabe (por exemplo, o programador não saber JPA e fazer a persistência dos dados no banco de dados com JDBC, que é bem mais trabalhoso).

Muitas vagas para se trabalhar programando em uma linguagem requerem conhecimentos específicos em frameworks e bibliotecas e um profissional que não se aprofunda nessa linguagem terá menos probabilidade de saber esses conhecimentos específicos.

E não apenas os estudos são divididos entre várias linguagens de programação: a experiência profissional pode acabar também sendo dividida. Há vagas que requerem um ou mais anos de experiência com a linguagem em questão. Se você dividiu sua experiência profissional entre várias linguagens, irá demorar mais para obter os anos de experiência em cada uma das linguagens.

Então o programador deve saber apenas uma linguagem e se aprofundar somente nela? A resposta é: Não. Apesar de as linguagens de programação não ficarem obsoletas e deixarem de ser usadas da noite para o dia e de haver muitos sistemas legados, feitos em linguagens antigas, como Cobol e Clipper, que demandam manutenção por serem usados até os dias de hoje, pode ocorrer de, no futuro, uma determinada linguagem outrora popular deixar de ser tão usada (foi o que ocorreu com o Delphi, por exemplo, que era uma linguagem muito popular aqui no Brasil, mas atualmente não é tão usada pelas empresas ao implementar sistemas novos, a não ser uma ou outra empresa). Além disso, há softwares que são melhor implementados usando determinadas linguagens do que outras devido a particularidades dessas linguagens.

O que eu aconselho é se aprofundar em uma em específico e, após estar bem aprofundado nessa linguagem, começar a aprender uma segunda linguagem (ou até uma terceira linguagem, caso deseje aprender duas de uma vez, aí depende de você), mas sem se estagnar na primeira, pois as plataformas de desenvolvimento de software estão em constante evolução, mesmo linguagens antigas, como C e C++. Se você sabe lógica de programação, já é meio caminho andado para se aprender uma linguagem nova e sua sintaxe (a outra metade do caminho são os conhecimentos específicos que estão além da sintaxe da linguagem). Aí, com o tempo, você vai se aprofundando nessa segunda (ou terceira) linguagem, podendo, dependendo de seus conhecimentos, atuar profissionalmente utilizando as mesmas.

O ideal é saber pelo menos umas duas ou três, mas se você é iniciante no desenvolvimento de software, uma já é mais que o suficiente.

Antes que me perguntem, além do Java, que a linguagem na qual eu programo profissionalmente, eu sei um pouco de C e C++ (estou aprendendo ambas ao mesmo tempo por serem semelhantes, apesar de que, por falta de tempo momentânea, parei de estudá-las), JavaScript (inclusive usando a biblioteca JQuery, a uso bastante no ambiente de trabalho na interação do usuário com o navegador, se bem que JavaScript não é bem uma linguagem de programação como Java, C# e outras), PL/SQL (também não é bem uma linguagem de programação como Java, C# e outras, mas dá para programar nela, tal qual JavaScript, é uma linguagem do banco de dados Oracle) e um pouco (muito pouco) de Delphi/Lazarus. Pretendo me aprofundar nessas linguagens e aprender outras no futuro.

Por hoje é só, até o próximo post.

Anúncios

Minha experiência com um MacBook Pro

Posted in Atividades profissionais, Temas polêmicos on 29/07/2012 by Allan Taborda

Quem me conhece, sabe que eu não sou fã da Apple e de seus produtos. Sempre critiquei a postura dessa empresa com relação às suas restrições absurdas de design e usabilidade, além de suas políticas restritivas tanto em seus produtos, como no que entra ou não na app store do iPhone por exemplo, quanto com relação às ameaças desleais aos seus concorrentes, processando a todo custo os mesmos por violação de supostas patentes, não com intenção de ganhar dinheiro em cima, como faz a Microsoft, mas com a intenção de eliminar os concorrentes do mercado. Isso sem contar nos erros de projeto que têm ficado cada vez mais frequentes, como iPad que esquenta muito e iPhone que pega fogo e tem problema de sinal caso segurado pelo usuário da maneira tradicional (e a Apple, na maioria das vezes, não admite as falhas, fazendo de conta que não existem).

Eu sempre critiquei a Apple (na verdade, nem sempre, só passei a criticar após conhecer melhor a empresa e ouvir falar mais de seus produtos e ver como eles realmente eram, antes disso, eu até achava legal a empresa devido a comentários de terceiros e, devido a esses comentários, tinha uma imagem positiva da Apple), mas até então nunca tive que usar um produto da empresa por um tempo prolongado. Minhas experiências anteriores com produtos da Apple se resumiam a duas vezes que usei o iPad, uma vez a primeira versão do tablet, na Saraiva, localizada no Shopping Metrô Santa Cruz, e a outra vez o iPad 2, na Fast Shop, próxima ao Metrô Carandiru. Nas duas vezes, eu abri alguns programas (não vi nada de mais nos mesmos), mas não consegui fechar nenhum deles por não descobrir de jeito nenhum como fazer isso. Na primeira vez, eu tentei até acabar a bateria do bagulho, na segunda o iPad tinha acesso à Internet e pesquisei no Google como fechar os programas e vi que existem tutoriais completos apenas para fechar programas no iPad (algo que deveria ser simples, como clicar num ícone de fechar o programa), mas acabei achando o tutorial demasiadamente complicado e desisti. O iPhone eu nunca usei (me parece que é praticamente o mesmo sistema operacional do iPad), o iPod menos ainda, e o MacBook eu tinha olhado por cima duas vezes em lojas de eletrônicos e não vi nada de mais, mas também não deu para tirar nenhuma conclusão, a não ser que o sistema operacional parece um “Linux com um ambiente gráfico diferente”.

Dos produtos Apple, o que eu tinha uma imagem menos negativa era justamente o MacBook, bem como o iMac (a diferença é que um é desktop e outro é notebook, mas ambos são “computadores tradicionais” da Apple). Eu tinha uma imagem menos negativa principalmente pelo fato de eu não ser fã de smartphones e tablets, independente de ser da Apple ou não, e ser mais fã de computadores tradicionais (desktops e notebooks). Mas, como eu já havia dito, nunca havia usado um computador da Apple por um tempo prolongado.

Nesta última semana, comecei a trabalhar numa nova empresa. Quando eu comecei a trabalhar, não havia um computador para mim, então a empresa teve que comprar um novo (que não é da Apple e provavelmente virá com Windows). Enquanto o novo computador não chegava, eu usei um outro pertencente a um colega que estava de férias no momento. Este outro computador era um MacBook Pro, o único computador da Apple da empresa (acredito eu). Este MacBook Pro possuía processador Core 2 Duo 2,53 GHz e sistema operacional MacOS X (sistema operacional exclusivo dos computadores da Apple), versão 10.6. Eu aceitei usar aquele notebook e passei a semana toda trabalhando no MacBook Pro. Para quem não sabe, eu sou programador Java. Agora, irei contar como foi essa minha experiência com o MacBook Pro. Vou adiantando desde já que não foi uma boa experiência.

Eu até estou conseguindo realizar meu trabalho, mas com um rendimento bem abaixo do que eu costumo ter quando uso um computador normal, com Windows ou Linux. Não devido a “mudar a cor do pasto”, porque eu costumo me adaptar bem a alterações de interface, como quando eu passei a usar o Gnome no lugar do KDE como ambiente gráfico do Linux e quando testei outros ambientes gráficos e sistemas operacionais, mas devido a vários problemas de usabilidade que encontrei.

Um dos problemas era que os programas tinham teclas de atalho diferentes do que costuma ser o padrão dos programas Windows/Linux. Muitas vezes, as teclas de atalho envolviam o uso de uma tecla que só existe no Mac, a tecla Command, a maioria das vezes substituindo a tecla Ctrl, apesar do Macbook ter a tecla Ctrl, que é usada em outras combinações de atalhos.

Além disso, algumas teclas tradicionais não possuem o mesmo comportamento como em outros computadores, como por exemplo a tecla End, que, quando pressionada, deveria fazer o cursor ir para o fim da linha, mas no MacOS X, faz o cursor ir para o final do documento ou não tem efeito algum. Talvez até exista uma maneira de como fazer o cursor ir para o final da linha (uma combinação de teclas talvez), mas não consegui descobrir e nem pesquisei como (isso é uma coisa que deveria ser algo intuitivo de ser feito).

Ainda com relação às teclas, apesar do MacOS X instalado no equipamento ser em português do Brasil, os dois teclados (o do notebook e outro USB, provavelmente o dono do equipamento não gostava do teclado do mesmo e plugou um USB, também da Apple, feito de alumínio) não possuíam teclas de acentuação e a tecla C cedilha, fazendo com que, quando eu precisasse acentuar as palavras, eu tinha que recorrer ao corretor ortográfico (quando tinha no programa em questão) e torcer para que o corretor corrigisse corretamente, quando não corrigia corretamente, ou quando não tinha corretor ortográfico, eu jogava a palavra no Google para ver se aparecia resultado escrito com acentuação correta ou copiava e colava o caractere acentuado de outro lugar, ou escrevia sem acento mesmo. Na verdade, até tinha alguns acentos no teclado, como o acento circunflexo na tecla 6, ativado em conjunto com a tecla Shift (nos teclados tradicionais, padrão ABNT2, a tecla 6 possui o trema), mas quando pressionadas as teclas com acentos, tanto antes quanto depois da letra a acentuar, o acento não ficava sobre a letra, ou seja, não servia para nada.

O teclado de alumínio USB tinha teclas de funções até o F19 (no do MacBook, só havia até o F12, como os teclados tradicionais). Para que serviam essas teclas de funções extra eu não sei, mas o que tinha de teclas de função de mais, tinha de teclas essenciais de menos. Por exemplo, não havia, além dos acentos e C cedilha, teclas como a Insert e a Print Screen. A tecla Backspace estava com o nome de “Delete”, apesar de ter outra tecla Delete, que era a Delete normal.

O principal problema de usabilidade do sistema operacional era a alternância falha entre os programas abertos, usando as teclas Command e Tab (equivalente à combinação entre as teclas Alt e Tab nos PCs normais). Mesmo quando um programa era fechado, ele ainda constava na lista de programas a alternar, atrapalhando a alternância entre programas e obrigando o usuário a clicar mais vezes no Tab ou a clicar no ícone presente no dock (uma barra de ícones que fica na parte de baixo da tela, com um efeito visual quando se passa o mouse sobre o mesmo). Além disso, o MacOS X trabalha com o conceito de alternância entre programas como um todo, com todas as suas janelas abertas (independente de quantas sejam), não das janelas individualmente, o que atrapalha a alternância entre as mesmas.

Parece que, mesmo após um programa ser fechado, ele continuava aberto em partes, constando na lista de programas a alternar e no menu da barra superior (no MacOS X, os menus ficam integrados à barra superior ao invés de ficarem localizadas nos próprios programas, algo aceitável, porque não atrapalha a usabilidade, apenas se muda o lugar do menu). Para fechar o programa completamente, tinha que se clicar na opção correspondente na barra de menus, e isso não funcionava para todos os programas.

Ainda sobre os programas abertos, não há como saber que programas estão abertos ou não, pois o dock exibe tanto os programas abertos quanto os fechados e não há uma barra de tarefas informando quais são os programas abertos, como ocorre nos outros ambientes gráficos. Só se sabe quais estão abertos minimizando todos eles.

O menu do MacOS X não possui uma lista dos programas instalados. Quando eu precisei de uma calculadora (e a mesma não estava presente no dock), recorri à busca presente no menu. Só depois que eu descobri que, para ver quais eram os programas instalados, tinha que abrir o gerenciador de arquivos, chamado de Finder. É como ter que abrir o Windows Explorer para saber quais são os programas instalados no Windows ou ter que abrir o Nautilus para saber quais são os programas instalados no Linux (ou FreeBSD, ou outro sistema que utilize o X Window System) com Gnome.

O programa responsável por editar arquivos TXT é o Editor de Texto (o nome é esse mesmo), apesar disso, caso o Editor de Texto seja aberto sem abrir um arquivo TXT existente, não há a opção de salvar o arquivo no formato TXT. O Safari, o navegador web padrão do MacOS X, possui problemas de usabilidade diversos, como não ter barra de status ou algo equivalente informando o destino de um link e não ter como voltar ou avançar mais de uma página no histórico de navegação (pelo menos, tinha o Firefox instalado).

Com relação ao hardware, o touchpad (área onde o usuário movimenta o mouse deslizando o dedo, presente na grande maioria dos notebooks) não possuía os dois botões relativos ao clique com os botões esquerdo e direito. O teclado presente no notebook possuía teclas com iluminação embaixo (não vi vantagem nenhuma nisso, a não ser se eu fosse usar o MacBook no escuro). O mesmo teclado possuía um botão que sugere que, ao ser pressionado, o drive de CD abriria (como ocorre nos outros notebooks que possuem essa tecla), apesar disso, aquele MacBook não possuía drive de CD e aquele botão não tinha efeito algum.

Havia um mouse sem fio da Apple (com conexão via bluetooth), o Magic Mouse, que era a única cousa que eu gostei naquele equipamento por possuir, além do scroll vertical, um scroll horizontal, devido ao mouse não possuir uma rodinha, mas sim um sensor no qual o usuário passa o dedo no sentido horizontal ou vertical e faz o efeito do scroll. Apesar disso, uma vez ou outra o scroll horizontal atrapalhava, mas algo totalmente aceitável, nada que comprometa o trabalho.

Pontos positivos do MacBook Pro: o mouse (que na verdade nem faz parte do MacBook, é um acessório externo). Pontos negativos do MacBook Pro: todo o resto. De zero a dez, eu dou nota 1,5 para este que está sendo até o presente momento o pior computador no qual eu já usei até hoje.

Eu, sinceramente, esperava mais do MacBook Pro, ainda mais que muito se ouve que os produtos da Apple, incluindo o MacOS X, são mais fáceis e mais intuitivos de se usar (algo que eu não vi naquele equipamento, muito pelo contrário, o sistema não era lá muito intuitivo, talvez seja porque uma mentira dita muitas vezes acaba sendo aceita como verdade). Para piorar, um MacBook Pro é muito mais caro do que um notebook de configuração similar fabricado por outro fabricante. Não sei o que os fãs da Apple e usuários do MacBook veem no mesmo, caso alguém tenha algo a dizer em defesa desse computador, escreva seu comentário na seção de comentários, expondo seu ponto de vista e/ou defendendo o computador da Apple.

Atualização em 05/08/2012: Após conversar com o dono do MacBook que eu havia usado (desde essa última semana, já estou usando o novo computador que já chegou, e veio com Linux, mais precisamente um Debian Testing customizado), ele me explicou umas coisas sobre o mesmo.

Sobre a acentuação nas palavras, realmente não há como teclar acentos como costuma-se teclar em outros sistemas operacionais, e nem dá para alterar o layout do teclado, mas há teclas de atalho que geram acentos, como por exemplo, Option + C que gera um C cedilha e outras combinações envolvendo a tecla Option com outras letras que geram acentos e, em seguida, o usuário tecla a tecla desejada. Apesar de ser pouco prático, como ele já se acostumou a gerar acentos dessa forma, ele nem acha ruim.

Sobre a tecla Home ir para o início do documento ao invés de ir para o início da linha, me foi explicado que, para ir ao início da linha, tecla-se Command + seta para a esquerda. Isto porque a Apple possui um ponto de vista diferente do que as teclas Home e End deveriam fazer. Como as funções de ir para o início e o final da linha são mais usadas do que as de ir para o início e o final do documento, creio que este ponto de vista acaba por fazer o uso do teclado um pouco menos prático, visto que usa-se mais a ida do cursor para o começo ou o final da linha do que do documento, ou seja, o segundo é que deveria ter combinações de teclas para essas funções, não o primeiro.

Sobre o MacBook não possuir drive de CD, ele possui sim um drive de CD, mas é diferente de qualquer drive de CD que eu já vi. Ele não possui uma bandeja, e sim uma fenda (que eu pensei que seria apenas uma fenda por onde o notebook dissipava calor), onde se introduz o CD ou o DVD (e por onde pode entrar poeira, já que a fenda nunca fica fechada). Aí, para ejetar a mídia óptica, aperta-se o botão do teclado, que também existe no teclado plugado na USB. Sobre o MacBook não possuir botões no touchpad, na verdade ele tem sim, mas não estão visíveis.

Sobre fechar completamente os programas, de fato eles ficam abertos mesmo após clicar no X, em estado de repouso, mas podem ser fechados pelo item correspondente do menu, como eu havia dito no post, ou com a tecla de atalho Command + Q.

Achei essa página acerca das teclas de atalho dos computadores da Apple, para caso alguém fique perdido tendo que usar um desses:

http://support.apple.com/kb/HT1343?viewlocale=pt_BR&locale=pt_BR

Erros irritantes cometidos por programadores Java, parte 2

Posted in Atividades profissionais on 15/10/2011 by Allan Taborda

Este é o segundo post sobre erros irritantes cometidos por programadores Java. No primeiro post, citei seis erros relacionados a comparações entre valores e objetos. Neste segundo post, irei falar sobre outros nove erros também muito comuns, mas que devem ser evitados a todo o custo.

A numeração dos erros começa do 7 porque está continuando a numeração anterior, que parou no 6. Se houver um terceiro post sobre erros irritantes cometidos por programadores Java (e tá na cara que irá ter, pois há outros que deixarei para posts futuros, já que este ficou muito grande), a numeração começará do 16, continuando a numeração deste post.

7) Usar um loop com um contador (variável crescente de um em um) para iterar pelos valores de um List, acessando-os pelo método get: Seria o famoso for(int c = 0; c < list.size(); c++) valor = list.get(c); apesar de haver variantes ligeiramente diferentes, como decrescendo o contador ou usando o loop while e uma variável a parte como contador. Essa maneira de iterar pelos valores funciona bem para arrays, mas pode causar perda de performance em Lists, ou até comportamentos inesperados na lógica da iteração, caso objetos sejam removidos do List. Somente itere por um List dessa forma caso o mesmo seja com certeza um List baseado em array, como o ArrayList ou o Vector, e que não haja jeito do List ser baseado em outra implementação, como o LinkedList, que é baseado em lista encadeada, não em array, o que causaria perda de performance pelo fato de todos os objetos, desde o começo (ou o fim, o que estiver mais próximo) do List até a posição acessada, serem acessados, já que não há como acessar um objeto diretamente, a não ser que o objeto seja o primeiro ou o último da lista. E nunca remova valores do List, pois os valores seguintes serão recuados em uma posição, fazendo a iteração “comer” um valor a cada remoção de objeto do List. A não ser que o contador seja decrementado a cada remoção de objeto.

A maneira correta de se iterar por um List, bem como qualquer outra coleção do Java Collections Framework, é usando o loop for incrementado, algo como for(String s : list) valor = s; ou usando um Iterator, que pode ser obtido invocando o método iterator das coleções do Java. Na Internet, há vários exemplos ensinando a usar o Iterator e seus métodos, não é nada complicado. O Iterator possui a vantagem de permitir a exclusão de objetos usando o método remove.

8) Remover objetos de uma coleção sem ser pelo método remove da classe Iterator: Caso remova um objeto da coleção sem ser pelo Iterator, no caso de loops idiotas que citei no erro 7, a iteração pode “comer” um valor (a não ser que o contador seja decrementado) e, caso ocorra na maneira correta de iterar por uma coleção, será lançada uma ConcurrentModificationException, pois o Java não terá como saber qual a sequencia correta da iteração.

9) Suprimir o tratamento de uma Exception verificada: Se uma determinada Exception é verificada (isto é, que não extende a classe RuntimeException e, por isso, necessita que a mesma seja tratada num bloco try-catch), logo ela necessita que ela seja tratada de alguma forma. Ela é verificada por algum motivo, se ela não precisasse ser tratada, ela seria uma Exception não verificada.

Suprimir o tratamento de uma Exception verificada pode fazer com que um erro que ocorra no programa passe despercebido, ferrando com a lógica do bagulho. Se uma Exception é verificada, deve ser tratada, nem que seja para mostrar uma mensagem de erro.

10) Usar objetos sincronizados desnecessariamente: Objetos sincronizados seriam os pertencentes a classes sincronizadas, isto é, que foram implementadas de modo que os objetos delas podem ser acessados por threads simultânas sem ocorrer inconsistência nos valores dos mesmos. Exemplos de classes sincronizadas são a Vector, a Hashtable e a StringBuffer. Acontece que essas classes possuem performance inferior em relação às suas contrapartes não sincronizadas (ArrayList, HashMap e StringBuilder, em relação às três que citei). Somente se houver acesso concorrente que tais classes devem ser usadas.

11) Concatenar Strings com sinal de adição: A cada vez que uma String é concatenada com outra, mesmo se existir mais de uma concatenação em uma mesma linha, uma nova String será criada, poluindo o pool de Strings com Strings desnecessárias. Vale lembrar que, uma vez que uma String é criada no pool, ela só sairá de lá quando o programa for encerrado. Use a classe StringBuilder para concatenar Strings, passando-as como parâmetro do método append e depois pegando o resultado da concatenação pelo método toString. Isto evita lixo no pool de Strings e faz a concatenação ter performance melhor.

Pior que simplesmente concatenar Strings com sinal de adição, é passar duas ou mais Strings sendo concatenadas com sinal de adição como parâmetro no método append da classe StringBuilder. Se já está usando StringBuilder, por que vai concatenar com sinal de adição, se poderia passar cada uma das Strings separadamente pelo o método append?

12) Programar de forma procedural: Java é uma linguagem orientada a objetos, não é uma linguagem procedural, onde o código descreve um procedimento do início ao fim, num bloco enorme de código. Mas ainda assim, há programadores que não separam os códigos responsáveis por cada tarefa em métodos distintos e botam tudo num método só, programando de forma procedural no Java e não aproveitando a orientação a objetos, que tem como principal finalidade (ou uma das principais finalidades) o reaproveitamento do código. Colocar tudo num método só acaba prejudicando a manutenebilidade do código, fazendo-o ser um código de manutenção mais difícil, além de prejudicar seu posterior reaproveitamento.

13) Repetir o mesmo código várias vezes em um programa: Isto prejudica a manutenebilidade e a possibilidade de reaproveitamento do código. Se isto estiver acontecendo, é melhor escrever um método com o código e chamar este método em todos lugares onde o código repetido estava. São para isto que os métodos servem.

14) Não separar o código do software e misturar código de telas gráficas com código de acesso a banco de dados e com código de outras regras de negócio: Isto prejudica bastante a manutenebilidade e a possibilidade de reaproveitamento do código, ao ponto deste, em muitos casos, virar um lixo. Aí, quando precisa dar manutenção no programa, é aquela tristeza. Mexe numa coisa e estraga outra, pois uma coisa tá colada na outra. Vai tentar aproveitar um código em outro lugar e não dá, pois o mesmo tá acoplado com outra parte que não tem nada a ver.

O código de um software deve ser sempre separado em pelo menos três camadas: a de negócios, que contém a regra de negócios do programa; a de persistência, que contém o código relativo a acessos ao banco de dados; e a de apresentação, que contém o código das telas gráficas (ou o código relativo à geração do HTML, caso este seja uma aplicação web). O software pode ser separado em apenas duas camadas, caso este não possua acesso a banco de dados (por exemplo, uma calculadora). E somente se o software for muito pequeno que o código pode ficar tudo junto (por exemplo, um programa que calcula o índice de massa corporal, que faz apenas isso, um único cálculo, seria só uma tela pequena com dois campos para informar peso e altura e outro para exibir o IMC e um cálculo a ser feito).

15) Usar classes e métodos depreciados ou obsoletos: Se estão marcados como depreciados (isto é, com a anotação @Deprecated), significa que seu uso é desencorajado e que há alternativas melhores de se chegar a mesmo resultado, com outros métodos e classes. Os métodos depreciados só continuam existindo por questões de retrocompatibilidade com aplicações antigas, da época que estes métodos não estavam depreciados, e não devem ser usados em novos códigos.

Classes nas quais não foram marcadas como depreciadas mas que sabe-se que são obsoletas (como as classes StringTokenizer e Stack, onde consta no próprio Javadoc das classes que as mesmas são obsoletas) devem ter seu uso evitado, pois há alternativas melhores a elas. A StringTokenizer, por exemplo, ficou obsoleta após passas a existir o método split da classe String, que é mais simples. Já a Stack foi substituída pelas classes que implementam a interface Deque, que possui métodos equivalentes aos da Stack e possuem performance melhor por não serem sincronizadas.

Bom, por hoje é só, mas futuramente, irei escrever pelo menos mais outro post acerca de erros cometidos por programadores Java, que será a continuação deste aqui, assim como este post foi a continuação do outro post, que foi a parte 1.

Erros irritantes cometidos por programadores Java, parte 1

Posted in Atividades profissionais on 03/09/2011 by Allan Taborda

No post de hoje, eu irei falar sobre alguns erros muito comuns cometidos por programadores Java ao codificarem seus programas. São erros estúpidos que costumam me irritar bastante quando vejo um no meio do código. São erros que podem provocar desde o desperdício de recursos (memória, principalmente) até comportamentos inesperados que podem resultar em erros nos aplicativos.

A intenção era de colocar outros erros além desses seis, mas o post acabou ficando muito comprido e os outros erros ficarão para futuros posts. Então, acabei por colocar neste post apenas erros relacionados a comparações de igualdade.

Este post (e os próximos com a mesma temática deste) tem por finalidade alertar programadores (tantos os iniciantes como os experientes, que, como todo ser humano, também cometem erros) para que estes deixem de cometer esses erros. Seguem os erros abaixo:

1) Comparar Strings com dois sinais de igual (==): Esse é um dos erros muito comuns cometidos pelos programadores Java. Comparar Strings com == presumindo que comparações de Strings iguais (com a mesma sequencia de caracteres) feitas dessa maneira sempre retornará true (ou seja, que a condição é verdadeira) pode provocar erros de lógica, pois a comparação pode muito bem retornar false (ou seja, que a condição é falsa). Isto porque comparar Strings com dois sinais de igual (ou melhor, comparar qualquer objeto com dois sinais de igual) significa que você está verificando se as duas referências aos objetos apontam para o mesmo objeto, ou seja, você está verificando se os dois objetos (as duas Strings, neste caso) são, na verdade, o mesmo objeto. Como novas instâncias da classe String podem ser criadas com o comando new (assim como qualquer instâncias de qualquer classe), e o comando new sempre resulta na criação de um novo objeto, e como não dá para garantir que uma String vinda vai saber de onde é uma String declarada com um literal de String (uma String que é declarada com seu valor entre aspas) ou resultante de um comando new, então não é garantido que uma comparação com dois sinais de igual irá retornar true caso as Strings sejam iguais.

Ao invés de comparar Strings com dois sinais de igual, o correto é comparar as Strings com o método equals. Basicamente, pega-se uma das Strings e chama-se o método equals nessa String, passando como parâmetro a outra String, que vai ser comparada com a primeira a fim de verificar se ela é igual à outra. Caso as Strings sejam iguais, ainda que sejam objetos diferentes, o método equals retornará true.

Objetos String até podem ser comparados com dois sinais de igual, desde que tanto a String da esquerda do == quanto a String da direita, ou devem ser literais de String, ou devem ser String resultantes de uma chamada do método intern de outra String, ou então deve ser uma referência cujo valor foi sabidamente atribuído (e sem ter jeito de não ser) ou a um literal de String, ou a uma String resultante de uma chamada do método intern de outra String. O método intern sempre retorna uma String do pool de Strings da máquina virtual igual à String de onde o método foi chamado, ou a mesma String, caso ela seja uma String do pool de Strings.

2) Comparar números encapsulados por objetos numéricos wrappers com dois sinais de igual (==): É o mesmo problema de comparar Strings com dois sinais de igual, já que os objetos podem ser diferentes. Com números inteiros até o 128 não há problema, pois números até o 128 são armazenados num pool de inteiros pela máquina virtual (poucos programadores sabem disso), entretanto, como não é garantido que um objeto de uma classe wrapper de um tipo numérico representa um número menor ou igual a 128, é melhor não arriscar e fazer a comparação com o método equals. Ou então pegar os valores resultantes de chamadas aos métodos da própria classe wrapper que retornam o número propriamente dito (armazenado em um tipo primitivo, não em um objeto), como o método intValue, que retorna um número inteiro de 32 bits (o popular int), e fazer a comparação com dois sinais de igual, pois daí você estará comparando os valores numéricos em si, que não são objetos. Utilizar os métodos que retornam números em tipos primitivos permite que sejam feitas comparações entre objetos wrappers de tipos diferentes, como Integer e Long, por exemplo.

3) Comparar dois objetos de uma classe implementada pelo programador com o método equals, mas sem sobrescrever o mesmo: O método equals pode ser chamado a partir de qualquer objeto e tem por finalidade verificar se o conteúdo do objeto em questão é igual ao conteúdo do objeto passado como parâmetro. Em classes escritas pelo programador que estão sujeitas a terem seus objetos comparados entre si a fim de verificar se são iguais, o programador deve sempre sobrescrever o método equals, implementando um algoritmo que efetue a comparação dos atributos da classe em questão, verificando se o conteúdo dos atributos é igual ao conteúdo dos atributos do objeto a comparar.

Caso o programador não sobrescreva o método equals padrão que é herdado da classe Object (a classe mãe de todas as outras classes Java, que possui métodos comuns a todas elas), a comparação é feita com a implementação padrão provida pela classe Object, que… Adivinhem! Compara os objetos com dois sinais de igual! Ou seja, compara se os dois objetos são, na verdade, o mesmo objeto. Aí, caso os objetos tenham os mesmos valores em seus atributos, a comparação poderá retornar false, caso os objetos sejam diferentes.

4) Sobrescrever o método equals, mas não sobrescrever o método hashCode: caso desses métodos seja sobrescrito, o outro também deve ser, pois o contrato de ambos os métodos (não irei explicar aqui o que é um contrato de um método, caso não saiba, acho que o Google pode lhe ajudar, assim como me ajuda quando eu não sei algumas coisas) diz que, caso a comparação entre dois objetos pelo método equals retorne true, o retorno do método hashCode de ambos deve ser igual. Atenção: isto não significa que objetos com valores diferentes não devem ter o mesmo hashCode. sobrescrever o método equals e não sobrescrever o método hashCode pode resultar em resultados imprevisíveis caso o objeto em questão seja utilizado em alguma classe que chame ambos os métodos internamente, como as classes do Java Collections Framework, que são as populares coleções do Java (classes ArrayList, LinkedList, HashSet, HashMap, etc).

5) Armazenar um objeto de uma classe implementada pelo programador em uma coleção ou um Map sem implementar os métodos equals e hashCode dessa classe: as classes do Java Collections Framework fazem uso massivo desses dois métodos a fim de saber se um objeto possui os mesmos valores de outro, principalmente as classes que implementam a interface Map (HashMap, TreeMap, LinkedHashMap, ConcurrentHashMap, etc), que usam o valor retornado pelo método hashCode para posicionar o objeto dentro do mapa de objetos que foram postos dentro do Map. Caso um dos dois métodos deixe de ser implementado, um objeto da classe em questão pode se perder dentro do Map (entrar e não sair mais), já que, na hora de recuperar o objeto, é verificado o retorno do método hashCode a fim de saber onde o objeto está em relação ao mapa, além de eventualmente (dependendo das implementações dos Maps e de quais métodos forem chamados) haver comparações com o método equals a fim de saber se um determinado objeto é igual a outro. Isso vale para todas as classes do Java Collections Framework, mesmo para Lists (ArrayList, LinkedList, Vector, etc), uma vez que alguns métodos fazem uso do equals e do hashCode em seus objetos armazenados, como o método contains, que verifica se um objeto está contido na lista comparando cada um com o método equals.

6) Comparar String ou números encapsulados por objetos numéricos wrappers ou qualquer objeto usando um ponto de exclamação e um sinal de igual (!=): um ponto de exclamação e um sinal de igual é o contrário de dois sinais de igual, ou seja, verifica se dois objetos (ou dois tipos primitivos) são diferentes. Do mesmo modo que comparações com == presumindo que isto faz comparar se o valor dos objetos é igual podem zicar com o funcionamento de um programa, comparações com != presumindo que isto faz comparar se o valor dos objetos é diferente também não é uma boa ideia, apesar de que objetos cujas comparações entre si com o método equals retornem false são sempre objetos diferentes. Isto porque, do mesmo modo, presume-se que comparações com != entre objetos iguais retornem false, quando podem acabar retornando true na hipótese dos objetos serem diferentes. Neste caso, usa-se o método equals com um ponto de exclamação à esquerda do objeto cujo método equals está sendo chamado. Isto faz com que o retorno do método equals seja “invertido”, ou seja, faz retornar false quando o método retorna true e vice-versa. Aliás, o ponto de exclamação à esquerda de qualquer método que retorne um valor boolean (true ou false) sempre “inverte” o retorno desse método.

Bom, por hoje é só, mas futuramente, escreverei melo menos mais um post acerca de erros cometidos por programadores Java, que será a continuação deste aqui.

AOPT – Ferramenta de persistência do Allan

Posted in Atividades profissionais on 19/10/2010 by Allan Taborda

Desde 2007, eu estava com um projeto em mente, mas que, até então, eu estava relutando em iniciá-lo e deixando-o indefinidamente para depois. É um projeto de uma ferramenta de persistência de dados em Java (que terá versão para C++ e outras linguagens no futuro) chamada AOPT (Allan’s Object Persistence Tool, ou ferramenta de persistência de objetos do Allan). Eu já tinha em mente mais ou menos como ele iria ser, embora alguns detalhes eu não tinha certeza de como seria feito Cheguei a citar a intenção de desenvolver o AOPT no meu TCC que fiz para a faculdade, ainda em 2007.

No último fim de semana, tive um momento de inspiração e tomei coragem para implementar o AOPT e definir o que estava faltando na especificação deste. Em pouco tempo, eu já tinha um código funcional com a primeira parte do AOPT já implementada, que salvava e recuperava dados em XML, de três formas diferentes: o XML bruto gravado no disco, o XML compactado com GZip e também gravado no disco e o XML armazenado num banco de dados relacional (eu usei o HSQLDB, mas pode ser qualquer banco).

O AOPT consiste numa ferramenta de persistência que salva os dados em arquivos XML (um arquivo para cada tabela/objeto) e que permite a recuperação desses dados posteriormente. Diferente da proposta inicial, que previa que apenas objetos pudessem ser persistidos, o AOPT permite também a inserção direta dos dados em mapas do tipo chave-valor (usando a interface java.util.Map, nesta implementação em Java). Na verdade, os objetos são traduzidos pelo AOPT em mapas chave-valor e então estes são salvos em XML. O salvamento dos dados pode ser feito de imediato (ao inserir um objeto), com uma chama explícita ao método de salvar todos os objetos ou de tempos em tempos (como no Prevayler). E a recuperação dos dados pode ser feita utilizando APIs semelhantes às do banco de dados orientado a objetos Db4o e das ferramentas de persistência Prevayler e Perola, permitindo, dependendo de como o AOPT estiver configurado, buscar os dados a partir dos XMLs salvos ou a partir da memória (o chamado modo de prevalência de dados, à la Perola e Prevayler).

Ou melhor, o AOPT consistirá nisso após tudo o que eu desejar implementar estiver implementado, por enquanto, há só um esqueleto básico funcional do AOPT. No futuro, eu implementarei mais algumas partes essenciais e então eu hospedarei o AOPT no Sourceforge.

Mais para o futuro, quando eu souber programar em C++ (estou estudando por conta própria a linguagem C, e depois estudarei C++), implementarei o AOPT nesta linguagem. O AOPT em C++ talvez não terá todos os recursos da versão Java (os que são específicos dessa linguagem, como o mapeamento automático de objetos, visto que isto faz uso de reflections, a não ser que exista reflections no C++), mas implementará, pelo menos, a especificação básica do AOPT e terá compatibilidade de banco de dados com a versão Java, visto que o formato XML é independente de linguagem, bastando um parser disponível para a linguagem desejada).

É possível que o AOPT seja usado na camada de persistência do Robowebert Player, o player de áudio que estou desenvolvendo e que já citei aqui neste blog. Vale lembrar (isto se eu já tiver falado disso aqui no blog, nos posts que fiz sobre o player) que o Robowebert Player permitirá a escolha de como será feita a persistência dos dados, se será com Db4o, banco relacional ou outra forma, como o AOPT.

Assim que tiver mais notícias acerca do desenvolvimento do AOPT, eu postarei aqui neste blog.

Dia 25, estarei mudando de emprego, a fim de obter uma maior experiência profissional, além de começar a trabalhar com carteira assinada. Estou bastante entusiasmado com esse meu novo emprego, que, assim como anterior, também fica situado na capital paulista e também é para ocupar um cargo de desenvolvedor Java.

Neste fim de semana, irei postar dois sonhos que tive no meu outro blog, o blog dos Sonhos do Allan.

Até o próximo post (ou o próximo post do outro blog)!

Mais sobre o Robowebert Player

Posted in Atividades profissionais, Lazer, Música on 12/07/2010 by Allan Taborda

Nesses meses nos quais fiquei sem postar no blog, eu não tive vontade e inspiração para escrever algo interessante aqui, então eu acabei não postando nada nesse tempo. Cheguei a iniciar um post acerca dos meus gostos musicais, mas não acabei concluindo-o, apesar dele já estar bem extenso.

Há um ano atrás, escrevi um post sobre o tocador de áudio em Java que eu estava desenvolvendo em meu tempo livre, o Robowebert Player. Eu ainda desenvolvo o player no meu tempo livre, e ele evoluiu bastante desde aquele post até agora, ainda mais que ele é o meu player principal para ouvir música.

Como eu havia adiantado no último post, ele já possui suporte ao preenchimento automático da playlist. Este é, na minha opinião, o recurso mais importante implementado até aqui, de grande importância nas vezes que eu escuto música, pois gosto de escutar músicas variadas, mas não gosto de ter que ficar populando a playlist com músicas manualmente ou com playlists pré-definidas. Este preenchimento automático consiste em sortear uma música contida em uma das pastas previamente cadastradas em um arquivo de configuração (que é editado manualmente, mas posteriormente eu irei implementar o suporte ao acesso ao banco de dados e então a lista de pastas passará a estar no banco). A cada vez que uma música termina, esta é removida da playlist e, caso a playlist tenha menos do que um determinado número de músicas (definido nas configurações do player), o randomizador (como é chamado o sistema que sorteia as músicas) sorteia uma ou mais músicas, até a playlist atingir o número estipulado de músicas. Na maioria das vezes, ao acabar uma música, esta música sai e outra é adicionada ao final da playlist.

Também adiantei no último post que o player passou a permitir configurações personalizadas. Algumas dessas configurações podem ser alteradas pela própria interface do player, clicando no checkbox correspondente, por exemplo. Outras só podem, pelo menos até o momento, serem alteradas editando manualmente o arquivo de configuração. Para gerenciar essas configurações, de início eu usei a classe Properties, do pacote java.util, mas depois fiz a minha própria implementação da classe que guarda as propriedades, com recursos extras, como o de salvar as propriedades no disco assim que uma propriedade é alterada e métodos próprios para salvar e recuperar valores numéricos e booleanos, além de manter as propriedades em ordem alfabética e usar a codifcação UTF-8 ao salvar o arquivo. Essa classe que gerencia as propriedades poderá ser usada em outros programas que por ventura eu possa desenvolver.

Por falar nas configurações, recentemente eu passei a separar as configurações referentes ao funcionamento do player das configurações referentes à interface gráfica, em arquivos diferentes.

Na interface, os botões, com exceção dos que servem para subir e descer uma música na playlist, foram todos para a parte de baixo da tela, num total de dez botões. O botão de tocar agora também é o de pausar e continuar e o botão de adicionar também adiciona playlists salvas, além das músicas. Há um botão também para ativar e desativar o randomizador de músicas. O analizador de espectro ganhou mais espaço com a saída dos botões da parte superior esquerda da tela. Além disso, o tamanho da tela foi ajustado para ficar do tamanho adequado para monitores maiores (se bem que estou pensando em alterar isso novamente, fazendo o tamanho da tela se adequar melhor ao tamanho do monitor) e a tabela que mostra a playlist na memória foi ligeiramente modificada, tendo sua última coluna diminuído de tamanho e centralizada.

Foram feitas modificações no suporte aos metadados das músicas (informações de artista, nome da música, álbum, ano, etc). Agora foi adicionada a biblioteca JAudioTagger, que é usada na leitura dos metadados dos arquivos de áudio no formato FLAC, que antes não havia suporte à leitura dos metadados. Na verdade, o JAudioTagger é usado para ler os metadados de qualquer arquivo de áudio, com exceção dos áudios em MP3, OGG e Monkey’s Audio (os dois primeiros porque o código antigo, baseado em um pedaço do JLGui, que é outro player de áudioem Java (ver o post publicado há um ano atrás para mais detalhes), possui uma performance melhor na leitura das informações, e o último pelo fato do JAudioTagger não possuir até o momento o suporte a este formato de áudio).

Houve também modificações internas no player, como a inclusão de um pool de threads (usado em todo o player sempre que uma thread é criada, com exceção do motor de execução de áudio, que gerencia a thread princial manualmente), a criação de uma classe com métodos estáticos contendo as rotinas mais usadas e de uma interface contendo valores constantes (e as classes que vão usar esses valores implementam a interface), além de outras alterações internas no código.

Outras coisas que foram implementadas: o suporte ao formato de playlist conhecido como SMIL, usado no Windows Media Player, a geração de logs com os erros ocorridos internamente, a possibilidade do “Look and Feel” do player ser alterado (só há duas opções, por enquanto), dois novos painéis modais para a escolha das músicas manualmente (que podem ser escolhidos pelas configurações do player), suporte ao salvamento do estado do player (ele pode ser fechado e reaberto posteriormente, sem que o conteúdo da playlist e o estado interno do randomizador sejam perdidos), o início da implementação de uma interface em modo texto para o tocador de áudio, uso do KJDSS 1.3 (última versão da biblioteca do analisador de espectro até o momento, com a possibilidade de usar o analizador de espectro antigo aterando uma configuração), modificações nessa biblioteca, dentre outras coisas implementadas.

Ainda faltam muitos recursos dos que eu gostaria de adicionar a este player, como cronômetro, a possibilidade de se voltar ou avançar para um ponto qualquer no meio da música e a alteração dos metadados das músicas. Pretendo também traduzir a interface do player para outros idiomas, usando uma biblioteca de gerenciamento de traduções também escrita por mim e que ainda não está pronta.

Estou pensando em, ainda esse ano, disponibilizar o código do player no Sourceforge.net, ainda não o fiz por falta de tempo, ainda mais que, para isso, terei que elaborar um texto em inglês apresentando o software. Mas, para aqueles que pedirem, eu posso estar enviando o código por e-mail.

Por hoje é só, até a próxima vez.

Meu novo emprego em São Paulo

Posted in Atividades profissionais on 27/07/2009 by Allan Taborda

Depois de meses procurando um emprego, enviando currículos e até participando de entrevistas, finalmente consegui um emprego como programador Java.

Logo no início desse mês, fui chamado para fazer umas provas a fim de averiguar se eu possuía o conhecimento teórico necessário para preencher a vaga. Fiz a prova em questão no dia 6.

Posteriormente, me chamaram para a segunda fase do processo de seleção, onde fiz uma entrevista de emprego e um teste prático. A entrevista e e este teste foram feitos no dia 10 de julho.

No dia 13, recebi um e-mail me convocando para ir no dia seguinte na empresa a fim de fazer a entrevista final de contratação. A essa altura, eu já estava com quase certeza que eu iria ser contratado. Em tal entrevista, me foram feitas algumas perguntas adicionais, me falaram como seria o cargo na empresa, as condições de trabalho e mais algumas outras coisas. Eu aceitei tais condições e fui informado que eu havia sido contratado para a vaga. Comecei a trabalhar no dia seguinte.

Nos três primeiros dias de trabalho, tive que ir e voltar de São Paulo, foi bastante corrido pelo fato de acordar de madrugada e voltar só de noite, pois o ônibus demora muito, principalmente o ônibus da volta.

Mas a partir dessa última semana, passei a ficar hospedado na casa da Tia Carmen, apesar dela morar um pouco longe do serviço (tenho que pegar ônibus e Metrô, inclusive com baldeação na estação Sé) e de não haver acesso à Internet na casa dela. Mas agora está sendo melhor do que subir e descer todo o dia, inclusive mais barato do que se eu tivesse contratado o ônibus fretado (que vai ficar mais caro do que já tá graças ao prefeito burro daquela cidade).

Nos fins de semana (ou melhor, ao término do expediente das sextas-feiras), eu retorno a Praia Grande para passar o fim de semana. Então, retorno a São Paulo na segunda-feira de manhã, já descansado.

Mas infelizmente, esta semana, acabei pegando uma gripe e passei este fim de semana meio mal, mas já estou recuperado para voltar ao trabalho. Por falar nisso, está havendo uma epidemia de gripe na capital paulista, pelo que vi no telejornal (também, né, com um monte de gente tossindo e espirrando nas estações do Metrô sem pôr a mão na boca e com todo aquele aperto principalmente na estação Sé, ainda mais com este clima frio, não tem como não pegar gripe).

Vou encerrando este post por aqui, ainda mais que eu já escrevi o que eu tinha que escrever e eu já deveria estar dormindo para amanhã eu acordar cedo para ir a São Paulo trabalhar. Até o próximo post (sabe-se lá quando será postado).

Observação: a Tia Carmen em questão é a mesma na qual eu sonhei no dia 30 de Março de 2004, sonho este postado no meu outro blog (o que eu escrevo meus sonhos) no dia 10 de Abril do mesmo ano, ainda no antigo endereço no Blig (ainda antes do blog ser transferido para o UOL Blog), na época que meus relatos de sonhos eram pequenos. Quem quiser conferir o sonho em questão, pode acessá-lo em http://sonhosdoallan.blig.ig.com.br/2004/04/ola-internautas-hoje-eu-irei.html