Arquivo

Arquivo de março, 2010

[POG] Mascarando dados sigilosos de cartão de crédito

28 de março de 2010

Se você não sabe o que é POG, veja esse post antes.

Imagine que você tenha uma string formatada como um XML, e nesse XML exista um nó com um dado sigiloso, por exemplo, o número de um cartão de crédito. Então você cria um método que recebe essa string e mais um parâmetro com o nome do nó que contém o dado sigiloso. O método irá retornar a mesma string substituindo o valor sigiloso por asteriscos (*).

Por exemplo, para a representação XML abaixo:

<prodis>
  <some_text>Prodis</some_text>
  <sensitive_data>4010098287290192</sensitive_data>
  <some_value>456</some_value>
</prodis>

Queremos o valor “4010098287290192″ presente no nó sensitive_data seja substituído por “****************”. A utilização desse método em C# seria assim:

string xml  = "<prodis>"
       xml += "  <some_text>Prodis</some_text>"
       xml += "  <sensitive_data>4010098287290192</sensitive_data>"
       xml += "  <some_value>456</some_value>"
       xml += "</prodis>"

xml = Util.MaskXmlData(xml, "sensitive_data");

/*
O valor da variável xml agora é:
<prodis>
  <some_text>Prodis</some_text>
  <sensitive_data>****************</sensitive_data>
  <some_value>456</some_value>
</prodis>
*/

Nem vamos entrar no mérito do porquê esse XML está em uma string. Vamos nos concentrar na resolução do problema em questão.

Veja agora como um Pateta implementou esse método utilizando técnicas POG:

{
  public static string MascaraCartaoXml(string xml, string tagAbertura, string tagFechamento)
  {
    string retorno = xml;

    int posicaoInicio = (xml.IndexOf(tagAbertura)) + (tagAbertura.Length);
    int posicaoFim = (xml.IndexOf(tagFechamento));
    string cartao = xml.Substring(posicaoInicio, posicaoFim - posicaoInicio);
    string cartaoMascarado = cartao;

    for (int i = 0; i < cartao.Length; i++)
    {
      cartaoMascarado = cartaoMascarado.Replace(cartao.Substring(i, 1), "*");
    }

    retorno = xml.Replace(tagAbertura + cartao + tagFechamento, tagAbertura + cartaoMascarado + tagFechamento);

    return retorno;
  }
}

Meus comentários a respeito:

  • Que fique bem claro que esse método é única e exclusivamente para mascarar dados de cartão (de crédito?). Qualquer outro texto que não seja cartão não poderá ser mascarado. Será que serve também para cartão telefônico ou cartão de Natal?
  • Você já viu algum XML bem formatado onde o nome da tag de abertura de um nó é diferente do nome da sua tag de fechamento? Talvez no mundo POG isso seja possível.
  • Preciso dizer alguma coisa sobre as linhas 9 a 14 ou posso somente dar risada?

POG , ,

POG: Programação Orientada a Gambiarras

28 de março de 2010

Programação Orientada a Gambiarras, ou somente POG, é uma técnica avançada de desenvolvimento de software que tem como base a utilização de todo tipo de gambiarra, remendo e tudo de pior que um código pode ter. POG se baseia em conceitos como duplicação de código, fluxos redundantes, tarefas desnecessárias e reinvenção de rodas.

A primeira POG que se tem notícia é datado de 1582 d.C. O nome desta POG hoje é chamada de Ano Bissexto e foi criada pelo Papa Gregório XIII. Esta POG foi aplicada quando descoberto que a Terra leva 365,25 dias para dar uma volta no Sol, porém nosso calendário tem apenas 365 dias, o que leva a uma diferença de 6 horas por ano. Ao invés de corrigir o “sistema” para que não houvesse essa diferença, a solução adotada pelo Papa foi: “A cada quatro anos, é só colocar mais um dia ali”.

Acredita-se que a POG está presente desde os primórdios da criação de software. Alguns até dizem que ela já existia desde a época de cartões perfurados. POG mantém sua evolução ao longo do tempo, onde perdurou com a programação estruturada e atingiu seu ápice com o surgimento da orientação a objetos.

Se você não conhece POG e não está entendendo nada, leia esse artigo para entender melhor.

No meu primeiro post havia mencionado que iria mostrar alguns códigos POG que tenho encontrado durante esses 10 anos que trabalho com desenvolvimento de software. Relutei quase um ano para tocar no assunto, tentando até certo ponto preservar os autores dos códigos POG que encontrei pela frente.

Mas outro dia me deparei com um trecho de código que me serviu de motivação para publicar os exemplos de POG que tenho guardado. Era um código em C# de um método que retornava um valor booleano indicando se uma requisição HTTP teve uma resposta com sucesso:

private bool IsResponseOK()
{
    return this.response.StatusCode == 200 ? true : false;
}

Uma versão em Ruby seria assim:

def response_ok?
  @response.code == 200 ? true : false
end

Preciso uma motivação maior do que essa para publicar os códigos POG? É claro que não vou citar o nome de ninguém aqui, mas vou chamá-los carinhosamente de Patetas.

Meu próximo post mostrará uma técnica POG avançada de substituição de caracteres em uma string.

Observação importante

Não estou aqui dizendo que sou um programador perfeito, que não cometo erros ou que escrevo o código mais limpo do mundo. Com certeza eu já fiz alguma POG, seja por falta de conhecimento ou por falta de opção. O ponto aqui é aprender com os erros, os seus e os dos outros.

Por outro lado, eu me esforço para aprimorar a qualidade do meu código a cada dia. Isso se dá com a prática do dia-a-dia, trocando experiências com outros desenvolvedores, lendo o código dos outros, fazendo programação pareada e estudando e lendo muito. Também sei que sou detalhista, sistemático e até certo ponto chato em relação à qualidade de código. Um código ruim me incomoda, mesmo que esse código produza o que se espera dele.

Além disso, todo e qualquer código POG que eu venha a publicar aqui foi escrito por desenvolvedores experientes (ou que se diziam experientes). Achar defeitos em código de um programador iniciante ou um estagiário é fácil, publicá-los seria puramente sacanagem.

Segunda observação

No blog The Daily WTF, na seção CodeSOD (Code Snippet Of the Day), vários trechos de código POG são publicados periodicamente e seus leitores contribuem enviando suas experiências. Se você já teve contato com alguma POG de algum Pateta por aí e quiser compartilhá-lo, pode me mandar que eu o publico.

POG ,

Corrida Batavo Pense Light - 5 km

27 de março de 2010

No domingo de 21 de março de 2010 parcitipei dos 5 km da Corrida Batavo Pense Light.

A corrida foi disputada no interior da Cidade Universitária (USP), em um percurso praticamente plano, e foi organizada pela Corpore.

Infelizmente estava impossibilitado de correr pra valer, pois ainda estou me recuperando de um procedimento cirúrgico no ombro. Mas o que vale mesmo é participar.

Foto de MidiaSport

Foto de MidiaSport

Esportes , , , ,

Utilizando debug em aplicações Rails

20 de março de 2010

Muita gente acha (assim como eu achava há um tempo atrás) que não é possível utilizar debug (ou “depurar”, ou “debugar”) uma aplicação Ruby on Rails. Acredito que isso se deve ao fato de Ruby ser uma linguagem interpretada, diferente de outras linguagens que requerem compilação.

Existe uma forma muito simples de se “debugar” em Rails. Primeiro vamos instalar a gem ruby-debug.
$ sudo gem install ruby-debug

Agora vamos criar uma aplicação Rails de exemplo para utilizar o debug.
$ rails prodis-debug
$ cd prodis-debug
$ rails script/generate scaffold MyModel my_text:string my_value:float
$ rake db:migrate

E ao invés de subir a aplicação com script/server, iniciamos a aplicação em modo debug:
$ rdebug script/server
/Users/Prodis/Blog/code/prodis-debug/script/server:2
require File.expand_path(’../../config/boot’, __FILE__)
(rdb:1)

Esse é o momento de adicionarmos o(s) breakpoint(s) desejados, informando o arquivo e a linha do mesmo. Vamos colocar um breakpoint na ação create de MyModelsController:
(rdb:1) break app/controllers/my_models_controller.rb:43
Breakpoint 1 file /Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb, line 43

E usamos o comando cont para prosseguir com o carregamento da aplicação no servidor.
(rdb:1) cont
=> Booting Mongrel
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server

No browser, através do endereço http://localhost:3000/my_models/new, vamos criar um novo registro de MyModel.

Quando clicarmos no botão “Create”, a aplicação irá parar no breakpoint que colocamos na linha 43 de MyModelsController.
Breakpoint 1 at /Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb:43
/Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb:43
@my_model = MyModel.new(params[:my_model])
(rdb:6)

A partir daqui podemos investigar o código e ter acesso as suas variáveis. Por exemplo, exibindo os valores da variável params:
(rdb:6) p params
{”my_model”=>{”my_text”=>”I am some text”, “my_value”=>”50.00″}, “commit”=>”Create”, “authenticity_token”=>”qN9mUhJelZD0V/P2CB1fhBkQrIxFvvk+NRkY5m6EFWg=”, “action”=>”create”, “controller”=>”my_models”}

Mas a maneira mais fácil de inspecionar variáveis é pelo irb, que irá se manter no contexto atual onde a aplicação está parada.
(rdb:6) irb
irb(#):001:0> params
=> {”my_model”=>{”my_text”=>”I am some text”, “my_value”=>”50.00″}, “commit”=>”Create”, “authenticity_token”=>”qN9mUhJelZD0V/P2CB1fhBkQrIxFvvk+NRkY5m6EFWg=”, “action”=>”create”, “controller”=>”my_models”}
irb(#):002:0>

Saindo do irb (com o comando exit), nós voltamos para o ambiente de debug. Há uma série de comandos úteis para se utilizar. Um deles é o list, que exibe o trecho de código onde a aplicação está parada e indicando sua linha exata através de uma seta:
(rdb:6) list
[38, 47] in /Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb
38 end
39
40 # POST /my_models
41 # POST /my_models.xml
42 def create
=> 43 @my_model = MyModel.new(params[:my_model])
44
45 respond_to do |format|
46 if @my_model.save
47 flash[:notice] = ‘MyModel was successfully created.’
(rdb:6)

Para avançar até a próxima linha, usamos o comando next:
(rdb:6) next
/Users/Prodis/Blog/code/prodis-debug/app/controllers/my_models_controller.rb:45
respond_to do |format|
(rdb:6)

Para listar todos os comandos disponíveis, basta entrarmos no help:
(rdb:6) help
ruby-debug help v0.10.3
Type ‘help ‘ for help on a specific command

Available commands:
backtrace delete enable help next quit show trace
break disable eval info p reload source undisplay
catch display exit irb pp restart step up
condition down finish list ps save thread var
continue edit frame method putl set tmate where

(rdb:6)

Também podemos visualizar a ajuda de um comando específico:
(rdb:6) help next
n[ext][+-]?[ nnn] step over once or nnn times,
‘+’ forces to move to another line.
‘-’ is the opposite of ‘+’ and disables the force_stepping setting.
(rdb:6)

E para continuar a execução da aplicação, usamos o comando continue (ou um dos seus álias c ou cont)
(rdb:6) continue

Processing MyModelsController#create (for 127.0.0.1 at 2010-03-20 12:20:54) [POST]
Parameters: {”my_model”=>{”my_text”=>”I am some text”, “my_value”=>”50.00″}, “commit”=>”Create”, “authenticity_token”=>”qN9mUhJelZD0V/P2CB1fhBkQrIxFvvk+NRkY5m6EFWg=”}
MyModel Create (0.5ms) INSERT INTO “my_models” (”my_text”, “created_at”, “updated_at”, “my_value”) VALUES(’I am some text’, ‘2010-03-20 15:45:19′, ‘2010-03-20 15:45:19′, 50.0)
Redirected to http://localhost:3000/my_models/4
Completed in 1464995ms (DB: 1) | 302 Found [http://localhost/my_models]

Existe também uma outra maneira de se “debugar” com a gem ruby-debug. Nós podemos colocar uma instrução debugger (que na verdade é um método) em qualquer lugar do código para marcar como breakpoint. O Railscast #54 Debugging with ruby-debug mostra os passos de como fazer isso.

Eu particularmente gosto de configurar os breakpoints direto no Terminal, evitando assim ter que colocar qualquer informação de debug no código.

Esse esquema de debug não se restringe somente à aplicações Rails. Você pode muito bem utilizá-lo com código Ruby diretamente. Por exemplo, o código abaixo é do arquivo some_class.rb:

#lib/some_class.rb
class SomeClass
  def some_method
    # do something here
  end

  def other_method
    # do another thing here
  end
end

É só utilizar o comando rdebug passando o nome do arquivo:
$ rdebug lib/some_class.rb
/Users/Prodis/Blog/code/prodis-debug/lib/some_class.rb:2
class SomeClass
(rdb:1)

Para informações mais detalhadas sobre a gem ruby-debug, veja a documentação completa.

Ruby , , ,

Ruby e Rails no Mundo Real 2010

15 de março de 2010

Estão abertas as inscrições para o Ruby e Rails no Mundo Real 2010, o evento da comunidade de Ruby e Rails em São Paulo.

O evento, que é organizado pelo Guru-SP, acontecerá no dia 29 de maio, das 9h às 18h, no Century Flat Paulista, Rua Teixeira da Silva, 647 - Paraíso.

A edição do ano passado reuniu 160 participantes, e eu estava lá. Dá uma olhada no cara de camiseta laranja e boné vermelho na foto.

Esse ano as palestras serão:

O valor da inscrição é R$ 69,00 ou R$ 49,00 para quem participou no ano passado.

Demais informações você tem no site do evento.

Eventos, Ruby , , , ,

Algoritmo para encontrar o range ao qual pertence um número

9 de março de 2010

Para atender uma lógica de negócio tivemos a necessidade descobrir qual range um determinado número pertencia.

Por exemplo, para intervalos de 5000, todos os números de 1 a 5000 (inclusive) pertecerão ao range 5000, os números 5001 a 10000, pertencerão ao range 10000, de 10001 a 15000, ao range de 15000 e assim por diante.

Então tínhamos que criar um algoritmo que recebendo a posição e o intervalo, devolveria o range ao qual a posição se encontrava.

def generate_range(position, interval)
  # Implementation
end

generate_range  4999, 5000 # =>  5000
generate_range  5000, 5000 # =>  5000
generate_range  5001, 5000 # => 10000
generate_range 12350, 5000 # => 10000

Eu dei a idéia de substrair do valor da posíção o valor do intervalo até o valor da posição ficar negativo e então multipiclar a quantidade de vezes que aconteceu a subtração pelo valor do intervalo.

A primeira versão saiu algo do tipo assim:

def generate_range(position, interval)
  rest = position - interval
  substract = 1

  if rest > 0
    substract += 1

    while rest > 0
      rest = rest - interval
      substract += 1 if rest > 0
    end
  end

  substract * interval
end

Zuado esse código, né?

Nisso o Herbert Francarelli perguntou para o Fábio Akita se havia alguma forma em Ruby para diminuir a quantidade de código desse método. De bate pronto ele pensou em usar o método include? da classe Range, mas queria uma solução de uma linha.

Ficamos de cada um da equipe tentar encontrar a solução do problema no fim de semana.

Eu comecei tentando utilizar o método include? da classe Range:

def generate_range(position, interval)
  lrange = 1
  rrange = interval

  while !(lrange..rrange).include?(position) do
    lrange += interval
    rrange += interval
  end

  rrange
end

E também consegui resultado semelhante com a ajuda do método between? da módulo Comparable:

def generate_range(position, interval)
  lrange = 1
  rrange = interval

  while !position.between?(lrange, rrange) do
    lrange += interval
    rrange += interval
  end

  rrange
end

Mas somente quando eu parei de procurar alguma solução com comandos Ruby e pensei em solução matemática, encontrei o que eu queria:

def generate_range(position, interval)
  ((position - 1) / interval + 1) * interval
end

O Fábio Akita já tinha criado o método com uma linha no mesmo dia. Ele combinou a solução matemática com recursos da linguagem:

def generate_range(position, interval)
  (position.to_f / interval.to_f).ceil * interval
end

Essas coisas (entre muitas outras) é que tornam divertido o trabalho de desenvolvedores de software.

Ruby , ,

Instalando ImageMagick no Mac OS X 10.5

4 de março de 2010

PaperClip é um plugin de upload de arquivos para Ruby on Rails que cria atributos dos arquivos nas classes ActiveRecord funcionando da mesma maneira como se estivesse utilizando campos do banco de dados.

Para utilizar esse plugin, é necessário instalar o ImageMagick, que pode ser feito via MacPorts:
$ sudo port install ImageMagick

Eu fiz isso e obtive o seguinte erro:

On Mac OS X 10.5, tiff 3.8.2 requires Xcode 3.1 or later but you have Xcode 3.0.
Error: Target org.macports.extract returned: incompatible Xcode version
Error: The following dependencies failed to build: tiff xorg-libXext xorg-libX11 autoconf help2man p5-locale-gettext m4 automake libtool xorg-bigreqsproto xorg-inputproto xorg-kbproto xorg-libXau xorg-xproto xorg-libXdmcp xorg-util-macros xorg-xcmiscproto xorg-xextproto xorg-xf86bigfontproto xorg-xtrans xorg-libXt xorg-libsm xorg-libice
Error: Status 1 encountered during processing.

.
Para instalar o ImageMagick no Mac OS X 10.5 é preciso ter o Xcode 3.1 ou superior. Eu tinha o Xcode 3.0 instalado, então fui até a página de desenvolvedores da Apple e baixei a últma versão do Xcode para Mac OS X 10.5.

O endereço é https://connect.apple.com. Você precisa se logar para ter acesso aos downloads. Se você não tem cadastro, pode criar uma nova conta.

Depois de logado, clique no link Downloads, depois no menu da direita em Developer Tools, localize a seção Xcode 3.1.4 Developer Tools e faça o download dos 993 MB do arquivo Xcode 3.1.4 Developer DVD (Disk Image).

Após instalado o Xcode 3.1.4, você já pode instalar o ImageMagick via MacPorts e depois utilizar o PaperClip.

Para mais informações sobre o PaperClip, acesse esse link:
http://delicious.com/prodis.net/paperclip

Unix , , , , , ,