quarta-feira, 20 de março de 2013

Simulando o Operador Ternário em Python


A partir do python 2.5 esta receita está obsoleta, uma vez que o operador ternário "if" foi incluído oficialmente na linguagem. O texto aqui permance válido por ajudar a entender como a linguagem funciona

Às vezes pode ser desejável fazer testes simples, seguidos de uma atribuição. Existem várias maneiras de se fazer isso, como por exemplo:



if variavel == 5:
  valor = 1
else:
  valor = 0



Uma maneira mais curta seria:

valor = (0,1)[variavel == 5]


Como esse tipo de teste vai ser sempre false ou true (0 ou 1), valor irá assumir o valor do primeiro elemento da tupla se a condição for falsa, e o segundo valor, se a condição for verdadeira. Ou seja: o primeiro elemento dessa tupla deve ser o resultado para a condição falsa.


Em Python 2.5, foi adicionada a "conditional expression", ou "expressão condicional", que tem a mesma função. Ela deve ser usada no lugar dos outros exemplos nesta página exceto onde a compatibilidade com outras versões e já estritamente necessária.
Exemplo:

valor = 1 if variavel == 5 else 0


Truque "and or"

Outra maneira de simular um operador ternário em Python é usando and or. Vejamos como funciona o exemplo abaixo.
Uma string(ou inteiro ou lista ou tupla ou etc...) é sempre True se o valor dela for diferente de vazio. O operador and funciona da seguinte forma:
TRUE and QUALQUER_COISA, retorna QUALQUER_COISA FALSE and QUALQUER_COISA, retorna FALSE
Enquanto o operador or funciona assim:
TRUE or QUALQUER_COISA, retorna TRUE FALSE or QUALQUER_COISA, retorna QUALQUER_COISA

 valor = (variavel == 5) and 1 or 0



quarta-feira, 7 de dezembro de 2011

Detector de Browser em Javascript

Segue abaixo, o código javascript para detectar qual o browser o usuário está utilizando.

var BrowserDetect = {
init: function () {
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
this.version = this.searchVersion(navigator.userAgent)
|| this.searchVersion(navigator.appVersion)
|| "an unknown version";
this.OS = this.searchString(this.dataOS) || "an unknown OS";
return this.browser;
},
searchString: function (data) {
for (var i=0;i<data.length;i++) {
var dataString = data[i].string;
var dataProp = data[i].prop;
this.versionSearchString = data[i].versionSearch || data[i].identity;
if (dataString) {
if (dataString.indexOf(data[i].subString) != -1)
return data[i].identity;
}
else if (dataProp)
return data[i].identity;
}
},
searchVersion: function (dataString) {
var index = dataString.indexOf(this.versionSearchString);
if (index == -1) return;
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
},
dataBrowser: [
{
string: navigator.userAgent,
subString: "chrome",
identity: "chrome"
},
{ string: navigator.userAgent,
subString: "OmniWeb",
versionSearch: "OmniWeb/",
identity: "OmniWeb"
},
{
string: navigator.vendor,
subString: "Apple",
identity: "safari",
versionSearch: "Version"
},
{
prop: window.opera,
identity: "opera",
versionSearch: "Version"
},
{
string: navigator.vendor,
subString: "iCab",
identity: "iCab"
},
{
string: navigator.vendor,
subString: "KDE",
identity: "Konqueror"
},
{
string: navigator.userAgent,
subString: "firefox",
identity: "firefox"
},
{
string: navigator.vendor,
subString: "Camino",
identity: "Camino"
},
{ // for newer Netscapes (6+)
string: navigator.userAgent,
subString: "Netscape",
identity: "Netscape"
},
{
string: navigator.userAgent,
subString: "MSIE",
identity: "IE",
versionSearch: "MSIE"
},
{
string: navigator.userAgent,
subString: "Gecko",
identity: "Mozilla",
versionSearch: "rv"
},
{ // for older Netscapes (4-)
string: navigator.userAgent,
subString: "Mozilla",
identity: "Netscape",
versionSearch: "Mozilla"
}
],
dataOS : [
{
string: navigator.platform,
subString: "Win",
identity: "Windows"
},
{
string: navigator.platform,
subString: "Mac",
identity: "Mac"
},
{
  string: navigator.userAgent,
  subString: "iPhone",
  identity: "iPhone/iPod"
   },
{
string: navigator.platform,
subString: "Linux",
identity: "Linux"
}
]

};
BrowserDetect.init();

desabilitar o ctrl + j leitor de codigo de barras elgin

como desabilitar o control + j do leitor de codigo de barras elgin.

va na página 16 do manual e passe o leitor em:

1-Start Configuration
2-CR (%7s0+)
3-end configuration
4-save configuration


Referência:
http://dirceuh.blogspot.com/2008/06/desabilitar-o-ctrl-j-leitor-de-codigo.html

quarta-feira, 12 de janeiro de 2011

WebService with NuSOAP

É um conjunto de classes PHP que permite aos desenvolvedores criar e consumir serviços Web baseados em SOAP 1.1, 1.1 e WSDL HTTP 1.0/1.1. Pode ser feito download a partir da página: 
http://sourceforge.net/projects/nusoap/

Instalação:
Depois de ter baixado uma cópia do nusoap.php, basta colocá-lo em sua árvore de código para que você possa incluí-lo em seu código PHP. Alguns usuários colocaram nele um diretório separado lib. Para o meu exemplo, eu coloquei-o no mesmo diretório como o código de exemplo em si.

Exemplos:
Vamos começar com o exemplo simples "Hello world". Isso vai demonstrar a base de clientes de codificação NuSOAP e servidores.
Vamos começar com o código do servidor, já que sem um servidor, não há necessidade de ter qualquer cliente. O servidor SOAP expõe um método único chamado Hello, o que leva um parâmetro de seqüência única de entrada e retorna um string. Felizmente, os comentários dentro do código fornecer uma explicação suficiente! Para os serviços mais simples, tudo o que vai mudar são as funções a ser definido e registrado. 

Nomeie um arquivo como server.php. Seu conteúdo segue abaixo.  
 
require_once('nusoap.php');
// Cria uma instancia do servidor
$server = new soap_server;
// Registrando o metodo criado
$server->register('hello');
// Define o metodo 
function hello($name) {
    return 'Hello, ' . $name;
}
// Usar o request para invocar o servico
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
 O cliente para este serviço segue abaixo. Existem algumas coisas importantes a serem observadas.  
Primeiro, quando a instância do soapclient é criado, o parâmetro especificado é o URL para o serviço. No meu caso, server.php é acessado a partir http://localhost/projeto/webservice. Os serviços que você consome, é claro, estarão localizados em URLs diferentes. 
Em segundo lugar, ao chamar o serviço, o primeiro parâmetro é o nome do serviço. Este deve corresponder ao nome case-sensítive de um método disponível no servidor. Neste exemplo, ele deve corresponder ao método registrados no server.php.  
Finalmente, o segundo parâmetro na chamada é um array de parâmetros que serão passados para o método de serviço SOAP. Como o método de server.php Hello requer um único parâmetro, esse array tem um elemento.

require_once('nusoap.php');
// Criar uma instancia do client
$client = new soapclient('http://localhost/projeto/webservice/server.php');
//Chama o metodo call do SOAP
$result = $client->call('hello', array('name' => 'Scott'));
// exibe o resultado
print_r($result);

// checando faults
if ($client->fault) {
    echo '<p><b>Fault: ';
    print_r($result);
    echo '</b></p>';
} else {
    // Checando erros
    $err = $client->getError();
    if ($err) {
        echo '<p><b>Error: ' . $err . '</b></p>';
    } else {
        print_r($result);
    }
}

//Debugando 
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
Outro exemplo mais completo, que envolve o cadastro de dados de 
clientes no banco de dados. O arquivo server.php segue abaixo:
 
$server = new soap_server();
$server->debug_flag = true;
$server->configureWSDL('MeuNameSpace', 'WSDL');
$server->wsdl->schemaTargetNameSpace='urn:MeuNameSpace';

$server->register('cadastrar', array('entrada'=>'tns:arrCadastro'),  
        array('return'=>'xsd:string'),
 'urn:MeuNameSpace',
 'urn:MeuNameSpace#cadastrar',
 'rpc',
 'encoded',
 ''
); 
$server->wsdl->addComplexType('arrCadastro', 'complexType', 'struct', 'all','',
array(
  'full_name'=>array('name'=>'full_name','type'=>'xsd:string')
  ,'email'=>array('name'=>'email','type'=>'xsd:string')
  ,'dat_nascimento'=>array('name'=>'dat_nascimento','type'=>'xsd:string')
  ,'cpf'=>array('name'=>'cpf','type'=>'xsd:string')
 )
);
function cadastrar($dados=array()){
 $objCliente = new Cliente();
 if($objCliente)
  $id = $objCliente->cadastroWebService($dados);
 return "$id";
}

$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
E o client para testes: client.php
 
$client = new nusoap_client('http://localhost/projeto/webservice/server.php?wsdl&debug=1', 'wsdl');
$err = $client->getError();
if ($err) {
 echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
 echo '<h2>Debug</h2>';
 echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
 exit();
}

$dados = array(
  'full_name' => 'Ademir Braga',
  'dat_nascimento' => '30/01/1984',
  'cpf' => '11111111222',
  'email' => 'ademirbraga100@yahoo.com.br',
  ); 
$result = $client->call('cadastrar', array('entrada' => $dados));

if ($client->fault) {
 echo '<h2>Fault</h2><pre>';
 print_r($result);
 echo '</pre>';
} else {
 $err = $client->getError();
 if ($err) {
  echo '<h2>Error</h2><pre>' . $err . '</pre>';
 } else {
  echo '<h2>Result</h2><pre>';
  // Decode the result: it so happens we sent Latin-1 characters
  if (isset($result['return'])) {
   $result1 = utf8_decode($result['return']);
  } elseif (!is_array($result)) {
   $result1 = utf8_decode($result);
  } else {
   $result1 = $result;
  }
  print_r($result1);
  echo '</pre>';
 }
}
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';

 Este exemplo mostra o cadastro de um cliente no banco de dados, usando o metodo cadastroWebService 
contido na classe Cliente via webservice.

Conclusão:
Usando webservices podemos integrar sistemas diferentes e independentes definindo apenas os campos necessários para utilização do lado do client.

quarta-feira, 8 de dezembro de 2010

Clean Code

O primeiro objetivo dos desenvolvedores quando criam uma funcionalidade é fazê-la funcionar. Tudo bem, está funcionando, mas e o código, como esta? Será que o código que faz tudo funcionar está legível, fácil de ser entendido, ou seja, será que está limpo?  É preciso preocupar-se com o código, garantir que  está legível e bem escrito, pois somente o próprio código pode dizer de forma confiável o que o software realmente faz.

Mas afinal, o que é código limpo?
Em suma um código limpo deve ser:
·         Elegante (distinto)
·         Eficiente
·         Legível
·         Simples
·         Direto
·         Único, sem duplicidades
·         Bem escrito
·         Deve ser escrito cuidadosamente
·         E deve sempre possuir UMA responsabilidade

O código é importante e deve agregar valor ao negócio. Somente um código limpo pode oferecer a qualidade e entendimento que esperamos quando abrimos uma classe. Portanto é necessário que seu código seja limpo e legível para que qualquer um que encontrá-lo possa facilmente entendê-lo evitando perda de tempo e facilitando o trabalho de todos.

Nomes significativos
Vamos começar pelos nomes. Escolhemos nomes para tudo, desde variáveis até métodos e classes, por causa disso devemos escolhê-los bem.
Os nomes devem nos dizer três coisas: Porque existem, o que fazem e como são usados. Devem revelar sua intenção e ser significativos, devem dizer o que estão fazendo e o que significam.
Faça distinções significativas, use nomes diferentes dentro de um mesmo escopo. Nomes como a1, a2, a3 são o oposto de nomes que demonstram intenção. São confusos e não informam nada. Evite também usar abreviações ou trocadilhos, escreva exatamente o que você quer dizer, o nome deve ser auto-explicativo. É comprovado que um desenvolvedor passa muito mais tempo lendo código do que escrevendo, por isso não se preocupe em economizar caracteres ao escolher um nome, o fato de um ser claro e objetivo poupará muito mais tempo do futuro do que os caracteres a menos que você digitar ao escolher um nome curto e ruim.
Métodos e funções
O que os tornam métodos e funções fáceis de se ler e entender? A primeira regra dos métodos é que eles devem ser pequenos, a segunda é que eles devem ser menores ainda.
Métodos devem conter no máximo 20 linhas e seu nível de identação não pode ser maior que dois. Quanto ao conteúdo, um método deve ter somente UMA responsabilidade. É difícil dizer o que é “uma responsabilidade”, mas uma maneira de descobrir se um método está fazendo mais de uma coisa, é tentar extrair uma parte dele em outro método. Se for possível, realmente o primeiro método tinha mais de uma responsabilidade.
Evite passar muitos parâmetros para um método, porque isso pode causar confusão além de dificultar a escrita de testes unitários, pois assegurar que todas as combinações de parâmetros diferentes funcionarão é bem mais trabalhoso. Passar parâmetros booleanos (verdadeiro ou falso) também não é uma boa prática, além complicar a assinatura do método, claramente a função tem mais de uma responsabilidade. Outro detalhe importante  que devemos nos preocupar são os efeitos colaterais, esses efeitos são mentiras. Seu método diz que fará uma coisa, mas faz outras “escondidas”.

Observe o método abaixo:
public boolean checkPassword(String username, String password) {
String passwordStatus = cryptographer.decrypt(password);
if(passwordStatus.equals(“OK”)) {
     Session.initialize();
     return true;
}
return false;
}
O método checkPassword tem o objetivo de verificar a validade da senha, mas além disso está abrindo um sessão, o que não está coerente com a finalidade do método. Não se esqueça, seu método deve sempre ter somente um objetivo.
Comentário
Comentários podem ser úteis se colocados nos lugares certos, mas também podem ser mentirosos e trazer desinformação. Na verdade, o melhor comentário é aquele que não precisa ser escrito. Podemos usá-los de forma benéfica para informar o leitor de alguma conseqüência ou fornecer a intenção de uma decisão tomada, mas um dos principais motivos para você escrever um comentário é porque o código está difícil de ser entendido. Você acha que o código ficou meio confuso e acha melhor adicionar um comentário? Não, você acha melhor refatorar
Quando você pensa em adicionar um comentário em seu código, é um forte indício que ele não está muito bom, não está claro
Não use comentários quando você pode usar métodos ou variáveis,explique-se no código, lembre-se que apenas o código pode dizer o que ele realmente faz
Formatação
A formatação do código é importante, pois se trata da forma de comunicação do desenvolvedor, um código todo bagunçado e sem formatação dificulta o entendimento de quem o está lendo
A legibilidade do código terá profundo efeito sobre todas as mudanças que serão feitas, seu estilo e disciplina sobrevive sobre estas mudanças.
Procure escrever  classes com no máximo 500 linhas, classes menores são mais fáceis de se entender. Já para as linhas de código, tente estabelecer um limite de caracteres por linha. Uma boa identação ajuda a visualizar melhor todo o escopo e facilita a identificação de situações e regras relevantes. Tente manter conceitos relacionados mais próximos verticalmente, para criar um fluxo na leitura do código. Use espaços entre operadores, parâmetros e vírgulas. Evite deixar o código todo grudado.
Tratamento de erro
Quando estamos programando devemos tratar os possíveis erros que nossa aplicação poderá lançar, as coisas podem dar errado e temos que estar certos que nosso código fará o que deve fazer
Prefira lançar uma exception ao invés de retornar um código de erro, estes retornos desorganizam a chamada do método e pode-se facilmente esquecer de verificá-los
Defina o fluxo do método separando as regras de negócio de erros ou outras situações. Para seus erros crie mensagens informativas, mencionando a operação que falhou e o tipo de falha.

Testes unitários
Há alguns anos atrás, pouco se ouvia falar de TDD (Test Driven Development). Para muitos TDD erá apenas trechos de código que garantia que o programa “funcionasse”. Mas essa idéia amadureceu bastante entre todos nós, hoje em dia programar com TDD é um conceito de alto nível, por isso, todos os testes que criamos devem ser escritos com código limpo.
Queremos dizer muito em nossos testes, por isso que eles devem ser legíveis, claros e simples de entender. Um teste com código ruim e difícil de entender é muito mais trabalhoso para se dar manutenção. Cada teste deve possuir apenas um conceito para facilitar seu entendimento, também deve sofrer alterações da mesma maneira que o código que está testando, tudo isso para manter a flexibilidade e a manutenabilidade do código.

Lembre-se que o código do teste é tão importante quanto o código da produção.
Todos sabem que o TDD nos manda escrever o teste antes do código de produção em si, considere essas três regras do TDD:
1.     Você não pode escrever o código até que você tenha criado um teste que falhe.
2.     Você não pode escrever mais testes do que seja suficiente para falhar.
3.     Você não pode escrever mais código do que o suficiente para passar o teste que está falhando.
Se você conseguir seguir essas regras ao desenvolver, você estará praticando TDD corretamente.

Classes
Para começarmos a falar de classes limpas podemos partir da organização das classes. De acordo com os padrões Java, uma classe deve começar com uma lista de variáveis de preferência nesta ordem:
1.     variáveis publicas e estáticas
2.     variáveis privadas e estáticas
3.     variáveis privadas
Depois das variáveis vêm os métodos públicos. Os métodos privados aparecem depois de suas chamadas. Assim como os métodos, as classes também devem ser pequenas. Ninguém gosta de encontrar classes gigantes onde é difícil até mesmo de se encontrar dentro delas. Mas a pergunta é: O quão pequenas elas devem ser?
O nome da classe deve representar a sua responsabilidade. Tentar fazer uma breve descrição da classe, explicando o que ela faz pode ajudar a escolher o nome certo. Esta descrição deve ter no máximo 25 palavras e não  conter palavras como “mas”, “e”, ”ou”, “se”, pois expressam mais de uma coisa mostrando que há mais de uma responsabilidade.
Outra maneira de descobrir o tamanho ideal da classe é analisarmos suas responsabilidades. O Princípio da Única Responsabilidade (Single Responsibility Principle) diz que uma classe deve ter uma, e apenas uma razão para mudar. Quando uma classe possui mais que um motivo para ser alterada é porque provavelmente ela esta fazendo mais coisas do que devia, ou seja, ela têm mais de um objetivo. O princípio nos dá definições de responsabilidade e uma diretriz para o tamanho de uma classe. Tentar identificar responsabilidades nos ajuda a melhorar nosso código e criar melhores abstrações.
Para concluir, queremos nosso sistema com pequenas classes, cada uma com uma única responsabilidade, tendo uma razão para mudar e colaborando com outras para alcançar o comportamento desejado do sistema.

Design emergente

Design emergente é um design que nunca é o final, sempre está em evolução. Para conseguirmos criar boas estruturas de código tornando mais fácil de aplicar princípios como SRP e DIP, e assim facilitar a criação de um de bom design de software, Kent Beck estipulou 4 regras para um design simples (Simple Design):

1. Rode todos os testes

Fazer um sistema testável nos obriga e usar boas práticas como classes e métodos pequenos de apenas uma responsabilidade.
Quanto mais testes fazemos mais e melhores maneiras e princípios seguiremos para evitar o acoplamento de nosso código. Lembre-se, um sistema testável possui sempre todos os seus testes passando. Um sistema que não é testável, não é verificável e assim não pode ser entregue para produção.

2. Remova duplicação

Duplicação é o primeiro inimigo de um bom design, ela representa trabalho e riscos adicionais além de uma maior e desnecessária complexidade. Ela se manifesta em linhas de códigos iguais ou parecidas além de aparecerem nas implementações. Usar padrões como Template Method é uma saída para remover duplicações mais complexas.

3. Expresse sua intenção

Escrever código que nós entendemos é fácil pois estamos concentrados e ligados no problema que estamos tentando resolver. Mas o próximo que pegar o código para fazer manutenção, não estará tão ligado ao problema como você estava quando implementou a solução.
Expressar-se bem no código pode trazer grandes benefícios para o desenvolvimento de um sistema. Além de poupar tempo de quem o mantém. Você pode expressar-se bem em seu código escolhendo bons nomes, deixando métodos e classes pequenas, separando responsabilidades. Lembre-se que você pode sem o próximo a ler este código.

4. Diminua o número de classes e métodos

Sempre que possível, nosso objetivo é manter sistemas pequenos enquanto ao mesmo tempo se mantém  métodos e classes pequenas.
Princípios e boas práticas não substituem a experiência, mas a partir delas pode se dar o primeiro passo para desenvolver um bom design.

Conclusão

Ao longo do tempo, comecei a perceber a diferença que estas técnicas fazem no meu dia-a-dia como desenvolvedor, pois, elas ajudam a pensar de uma forma mais  clara e objetiva sobre o código que escrevo. Pequenas coisas podem fazem grandes diferenças.
Tendo em mente estas observações, passei a escrever códigos mais legíveis, de fácil manutenção e mais eficientes. Sempre que vejo um trecho de código que não está muito legível, sinto-me na obrigação de refazê-lo, tornando-o legível limpo e eficiente.