quarta-feira, 31 de outubro de 2007

Dicas de como fazer um bom curriculo

Originalmente iria postar só no outro blog, mas achei que valia apena postar aqui tb.

E aproveitando o embalo das tirinhas trabalhadores (assunto do outro blog), mais um post sobre o duro mercado de trabalho, aquele que a gente faz pra ganhar o leitinho (esperamos que não adulterado) para as crianças XD.

Desta vez, umas dicas para quem está precisando fazer ou atualizar o currículo. O texto abaixo foi retirado da revista Você S/A do mês passado, setembro de 2007. Se você não lê, eu aconselho, é uma das poucas revistas (tirando os meus quadrinhos/mangás, claro) que eu compro na banca.

Bem, esse post foi inspirado mesmo na folha online, que coincidentemente deu essas dicas, que também ajudarão a você formar um currículo nota dez (e se graças a isso ganhar um empregão, eu aceito um presentinho =P):


Então, sem mais delongas, aqui vai:

O currículo certo e o errado

Saiba como evitar os problemas que podem tirar o seu nome da disputa por uma vaga antes mesmo da entrevista
Por Françoise Terzian

Passar para a segunda fase de um recrutamento que começou com a seleção de currículos requer atenção a detalhes. Fotos inadequadas, português errado e letras coloridas chegam a derrubar um em cada quatro currículos enviados por candidatos a uma vaga. "Recebemos 180 000 currículos ao ano e 25% deles são descartados por ser muito longos ou conter erros gramaticais", diz Augusto Costa, diretor- geral da Manpower no Brasil. A consultoria de recursos humanos, de São Paulo, atende empresas como Motorola e Michelin. Aqui, Augusto e outros especialistas em recrutamento apontam quais são os sete erros fatais de um currículo. Sem eles, suas chances de conseguir a vaga aumentam. Veja, abaixo, exemplos resumidos de um currículo bom e de outro ruim.

(Um currículo bem feito)

(E outro nem tanto - veja as dicas abaixo)

EVITE

FOTOS E RG
  • Só mande foto (3x4 comportada, claro) se isso for pedido por quem está fazendo a seleção. "E nunca inclua o número do RG e CPF no currículo", diz Mara Turolla,consultora da Career Center,empresa de recolocação.

POLUIÇÃO VISUAL
  • Nada de firulas: a melhor apresentação são folhas brancas simples e fontes Arial ou Times New Roman — mais clássicas.

ERROS DE PORTUGUÊS
  • São os mais comuns — como os que estão marcados em amarelo ao lado — e podem reprovar um bom candidato. "Demonstram que ele foi desleixado.Ou que não sabe escrever", diz Augusto, da Manpower.

FALAR DIFÍCIL
  • Informações demais fazem o selecionador gastar tempo — e a média que eles dedicam a um currículo é 40 segundos. Não vá escrever que fez curso de datilografia, tampouco. "Prolixidade mascara as informações relevantes", diz Alexandre Ullmann, gerente de recrutamento da CPM Braxis, empresa de tecnologia da informação.

MENTIRAS
  • Há quem diga que concluiu um curso sem ter realmente chegado ao fim. Vale o mesmo para dizer que é fluente em inglês. Por fim, errar nas datas de permanência nas empresas acaba levantando suspeitas do entrevistador.

FALTA DE FOCO
  • Realce seus resultados numéricos mais do que as tarefas que você desempenhava. Em vez de "analisava as estratégias de marketing", use "elevei as vendas da empresa em 15% após analisar a concorrência".

DESTACAR O INÍCIO DA CARREIRA
  • Deixar os últimos empregos para o fim pode fazer seu currículo ser descartado prematuramente.As informações devem vir em ordem decrescente."Se sua carreira for muito longa, saliente os cargos mais recentes", diz Augusto Puliti, gerente da consultoria Michael Page.

...Fim da matéria

Não deixem de ler a Você S/A. E não, não estou ganhando nada pra fazer essa propaganda. XD

P.S. No título a palavra 'currículo' está sem acento, pro blogger não comer o 'i' da palavra no link que ele gera.

segunda-feira, 29 de outubro de 2007

A falta que um ROWNUM faz...

Hoje precisava calcular a média de um campo dentro de uma tabela no Caché, da Intersystems. A lógica era até bem simples: eu precisava ver a média dos preços das últimas N compras, depois de uma certa data.

O Oracle tem a pseudo-coluna ROWNUM, o que facilita bastante. Num SQL do Oracle, eu teria algo parecido:

SELECT AVG(PRECO)
FROM COMPRAS
WHERE DATA > '01/01/01' AND ROWNUM <= 20
ORDER BY DATA DESC


Neste exemplo simples, estamos pegando a média dos preços das 20 últimas compras, efetuadas depois do dia 01/01/01. Bem simples, não?

Fui procurar algo parecido no Caché, mas não encontrei nada. Bem, tem algumas coisas, como o nro de linhas retornadas numa consulta, ou mesmo o TOP, usado no SELECT. Infelizmente, nenhuma solução apareceu, então resolvi fazer um cursor (ou poderia tb ter feito um ResultSet, se quisesse), e iterar pela consulta e calcular a média 'na mão'.

Bem, a consulta ficou mais ou menos assim:

SELECT TOP 20 PRECO
FROM COMPRAS
WHERE DATA > '01/01/01'
ORDER BY DATA DESC


Notem o 'TOP 20', que diz que a consulta só precisa me retornar os 20 primeiros resultados. Infelizmente, não dá pra usar no WHERE, que é onde eu precisaria, para executar a função agregada de média, AVG.

Não vou descrever como eu fiz para iterar na consulta com cursor, e calcular a média, até porque isso é relativamente fácil, e eu já estou muito cansado hoje.

Fui.

sexta-feira, 26 de outubro de 2007

Executando código dinamicamente no Caché

...Ou Como avaliar e executar uma expressão entrada pelo usuário.

O cenário: na aplicação, o usuário pode cadastrar algumas fórmulas, fórmulas que podem conter algumas variáveis previamente cadastradas. Essas variáveis podem conter valores simples, ou ainda, podem ser dependentes de um parâmetro. Um exemplo de fórmula encontrada é a seguinte:

(0.50 * ([VAR1(I)] / [VAR1(0)])) + (0.50 * [VAR2])

onde:

  • VAR1(I) é uma variável, cujo valor depende do parâmetro "I".

  • VAR1(0) é uma variável, cujo valor depende do parâmetro "0".

  • VAR2 é a variável simples.


Notem que por convenção, na fórmula, as variáveis estão entre colchetes []. Muitas variáveis são na verdade, séries históricas com valores. Os parâmetros para elas refletem apenas qual a época/data que o valor deve ser considerado.

O problema: dado um intervalo de tempo, preciso saber do valor da fórmula. Ou seja, preciso executar a fórmula, como se fosse parte do programa, ou então fazer o parsing, etc. Em algumas outras linguagens de script, existe a função eval(), que converte um texto (ou seja, uma string) em código, executando-o. Em Caché Object Script, temos o comando XECUTE, que executa o conteúdo de uma String como se fosse código, ou seja, efetua macro substituição.

Mesmo com essa facilidade, ainda assim precisava identificar dentro da %String cada variável. Para isso, escrevi uma pequena função, que coloquei num arquivo .MAC, para ser usada.

(A função, o código-fonte está aqui.)

Para essa função, passamos a fórmula, bem como caracteres que delimitarão o que será considerado variável, tb passamos uma String que será colocada no lugar da variável na fórmula original, bem como um caracter delimitador (coisa muito usada em sistemas MUMPS-like).

O resultado da função é a fórmula, com as variáveis substituídas pela String, além de todas as variáveis encontradas, separadas na String pelo caracter delimitador. Usando como String de substituição "?", e como caracter delimitador "~", a função para fórmula do exemplo acima retorna:

(0.50 * (? / ?)) + (0.50 * ?)~VAR1(I)~VAR1(0)~VAR2

Em seguida, resolvemos o valor de cada variável, e substituimos na fórmula, e retiramos da String as variáveis. Não vou ilustrar esses passos aqui, pois são bem específicos para o modelo de dados. Neste momento, nossa String da fórmula tem algo como:

(0.50 * (12.3 / 10.88)) + (0.50 * 10)

Note que a sentença é matematicamente bem formada, e inclusive a precedência de operadores é bem explícita com o uso de parênteses, o que deve ser sempre feito, visto que o Caché não segue o padrão matemático quanto a precedência de operadores.

Bem, finalmente vamos executar a expressão. Primeiro, atribuimos o comando SET dentro de uma String, como por exemplo:

SET umaVariavel = "SET resultado = " _ stringComFormula

Depois fazemos o XECUTE:

XECUTE umaVariavel

E pronto! O valor da expressão está na variável "resultado"! Apenas tenham precaução ao usar o comando XECUTE, pois dependendo da situação (e do abuso), ele pode deixar o seu código muito ruim para manutenção.

quinta-feira, 11 de outubro de 2007

Fazendo upload de arquivos com Caché & CSP

Fazendo upload de arquivos com Caché & CSP - ou... Meu primeiro CSP

Como já mencionei por aqui (ou não), trabalho primariamente com o Ensemble da Intersystems (e consequentemente com o Caché, já que o Ensemble é construído sobre este). Portanto, praticamente não mexo com coisas que envolvam interface de usuário, mas essa semana precisei fazer uma página que desse um upload num arquivo para o servidor. Então, toca a aprender CSP, as famigeradas Caché Server Pages. Na verdade, aprender eu não aprendi não, só vi o necessário para os meus propósitos.

Como diz na página de introdução ao CSP, você pode ir por dois caminhos: escrever páginas html e imbutir tags dentro, da mesma maneira que JSP (Java Server Pages) ou PHP, gerando um arquivo .csp; ou escrever uma classe, e nesta classe você jogar outputs montado o html, a mesma abordagem dos Servlets.

Na parte de exemplos (namespace SAMPLES do Caché) já tinha um arquivo .csp com um exemplo de upload (adivinhe qual arquivo: csp/samples/upload.csp). Com base nesse arquivo, preparei o meu.



(Exemplo da página de upload em SAMPLES, e o resultado de um upload)

Bem, como não consegui colocar o código fonte de maneira legal no blogger, vou colocar uma figura, e deixar um link para o codigo fonte.


(Figura com o codigo fonte)

A idéia principal desta página pode ser resumida assim: ao chamar a página, verifica se o parâmetro 'campo' foi enviado, se não foi, nem precisa mostrar nada. Verifica se foi enviado para o csp um arquivo, se não foi, coloca um form html para dar o upload (sendo que o submit deste form vai para o próprio csp), e se já foi efetuado um upload, atribui o nome do arquivo a um campo do html que chamou este csp (este csp deve ter sido aberto de outra página), e exibe um link para fechar a janela.

A seguir, vamos detalhar alguns aspectos.

Como diria o retalhador, vamos por partes:

<CSP:CLASS INCLUDES="SOMEINCFILETOINCLUDE">

Aqui indicamos um arquivo .INC (omitindo a extensão) que vamos referenciar no código, ou seja, estamos importando o INC. Arquivos .INC no Caché geralmente são usados para definição de macros (estilo macros C/C++), tanto para código quanto para definição de constantes.

/***********************************

<csp:if condition='($data(%request.Data("campo",1)))'>

Aqui temos uma tag específica do csp, que determina uma condição, o famoso 'if'. A condição como é vista como o valor do atributo 'condition', da tag csp:if, e pode conter código COS (Caché Object Script), retornando verdadeiro ou falso. Neste caso, apenas estamos checando se a requisição http (objeto %request) contém um parâmetro de nome 'campo'. Mais informações sobre o objeto %request pode ser visto na página da classe %CSP.Request.

/***********************************

<csp:if condition='($data(%request.MimeData("FileStream",1)))'>

Outra vez um if, mas desta vez, se repararmos, não verificamos o parâmetro da requisição http com %request.Data, mas com %request.MimeData. Isso porque desta vez estamos checando se foi enviado um arquivo, usando o padrão MIME.

/***********************************


Arquivo enviado: <b>#(%request.MimeData("FileStream",1).FileName)#</b><br>
Tamanho: <b>#(%request.MimeData("FileStream",1).Size)#</b><br>
Tipo: <b>#(%request.MimeData("FileStream",1).ContentType)#</b><br>


Quando enviamos um arquivo, o %request.MimeData("NOMEPARAMETRO",1) retorna um objeto %CSP.BinaryStream. No código acima, mostramos na tela, algumas informações que podem ser obtidas desta stream. Notem que os valores que serão impressos na tela, estão entre '#(' e ')#'.

/***********************************

<script language="Cache" runat="server">

Aqui iniciamos um bloco de Caché Object Script que será executado no servidor, ou seja, neste bloco, se quisermos que algo apareça na tela, teremos que escrever na saída padrão, usando o comando Write.

/***********************************

set dname = $$$SomeDirectory

Ainda dentro do bloco aberto acima, aqui criamos e atribuimos um valor a variável 'dname'. Este valor é uma macro, indicada pelos três cifrados ($$$). Esta macro deverá estar definida em algum dos arquivos .INC, que como vimos anteriormente, podem ser importados para este CSP.

/***********************************


Set stream=##class(%FileBinaryStream).%New()
Set stream.Filename= dname _ fname

do stream.CopyFrom(%request.MimeData("FileStream",1))
do stream.Flush()
do stream.SaveStream()


Aqui criamos um stream para um arquivo (classe %FileBinaryStream), na variável 'stream', setamos o nome e caminho completo deste, e depois usamos o método CopyFrom, para copiar o conteúdo da stream que foi enviada via http, para o arquivo.

/***********************************

<csp:else>

Aqui fechamos a parte 'então' do if, e colocamos a parte 'senão'.

/***********************************

<form enctype="multipart/form-data" method="post" action="este_arquivo_csp.csp">
Arquivo: <input type=file size=30 name=FileStream>
<p>

<script language="Cache" runat="server">
New bytes
Set bytes="<input type=""hidden"" name=""campo"" value=""" _ %request.Data("campo",1) _ """ > "
Write bytes,!
</script>

<p> <ul><input type="submit" value="Upload file"></ul> <p>
</form>


A parte do 'else' contém a definição de um formulário html, destinado a receber o arquivo que será carregado no servidor. Notem que dentro da definição do form, misturamos uma parte com código Caché, destinado a colocar um campo escondido no form, a fim de preservar o valor que fora anteriormente passado, na requisição. Essa é uma solução, outra solução seria usar sessão, mas como este caso é bem simples, não fui verificar como o gerenciamento de sessão é realizado com os CSPs.

/***********************************

Bem, esse post já ficou maior do que o esperado, então terminamos por aqui. No arquivo csp existem outras funcionalidades, mas não vou comentá-las agora, tais como a parte de javascript, e as funções de diretórios do COS. E tb tirei toda a formatação, sendo um html bem simples. Além disso, como suprimi várias partes, pode ser que o csp não compile de primeira, já que eu não testei ele nessa versão 'mais light'.

Como já dizia o Pernalonga, por hoje é só, pessoal.

sexta-feira, 5 de outubro de 2007

Curiosidades do Caché

Tipagem fraca (bem, seria melhor dizer inexistente) do Caché da Intersystems as vezes produz alguns resultados curiosos, especialmente se o leitor estiver mais acostumado com matemática do que com "as coisas" que existem em TI.

Por exemplo, num terminal Caché, declaramos duas variáveis*:

USER>set x = "5.10"

USER>set y = "5.1"

USER>write x
5.10
USER>write y
5.1

Lembrando que no Caché (assim como no bom e velho C) o 1 (um) representa verdadeiro, e 0 (zero) representa falso, e o separador padrão de casas decimais é o ponto ".", vemos o resultado de algumas comparações*:

USER>write x = y
0
USER>write x > y
0
USER>write x >= y
1

Ou seja, (x = y) é falso, (x > y) tb é falso, mas (x >= y) é verdadeiro. Em bom português, "x" não é igual a "y", "x" também não é maior que "y", mas "x" é maior ou igual a "y", huhuhuhu. 8-)



Bem, vamos as explicações:

  • A primeira sentença (x = y) é falsa, pois neste caso, o Caché testa a igualdade das Strings, e a String "5.10" é diferente da String "5.1".

  • A segunda sentença (x > y) é falsa, mas não porque o Caché compara tamanhos de Strings (x < y também retorna falso), mas porque ao se usar o operador ">", o Caché dinamicamente converte os valores para numéricos, e como "x" NÃO É MAIOR que "y" (numericamente, "x" É IGUAL a "y", já que 5,1 = 5,10), temos o resultado falso.

  • Agora já dá pra entender porque (x >= y) retorna verdadeiro, não? Ao usar operadores "<", "<=", ">", ">=", o Caché tenta converter as variáveis para tipos numéricos, e como numericamente (lembrando que no Caché o separador decimal é o ponto ".") "5.1" É IGUAL a "5.10", a expressão (x >= y) é verdadeira.

Hehehe, não mostrem isso para não iniciados, isso deve confundir pra caramba, assim como a precedência de operadores no Caché, que eu já comentei.

* A saber: o comando "set" é usado para inicializar/atribuir um valor a uma variável, e o comando "write" escreve na saída padrão (no caso, o próprio terminal) um valor.