17/11/2009

Melhore seu desktop no Windows 7

Há duas semanas instalei o Windows 7 que tive acesso pelo programa MSDNAA da Microsoft (pra quem não conhece, é um programa de parceria entre a Microsoft e instituições de ensino, que provê acesso dos alunos aos softwares da Microsoft sem nenhum custo – para os alunos pelo menos). Por enquanto, estou adorando o sistema. Muito rápido, bonito e simples. Gostei bastante da nova barra de tarefas e tal.
Mas senti falta de múltiplos desktops, funcionalidade que já existe há muito tempo em outros sistemas operacionais. Pois é, quem já está usando o Windows 7 já deve saber disso, mas eu juro que esperava que a Microsoft fosse incluir esta funcionalidade – na minha opinião essencial para um programador, administrador de rede, ou qualquer pessoal que precise do mínimo de organização em meio às suas dezenas de janelas abertas.

Bom, então fui procurar alguma solução descente na internet para o problema e achei o Dexpot que é simplesmente tudo que eu queria. Ele cria desktops virtuais (até 20) e lhe dá uma gama de configurações (tanta que nem sei) para vc poder customizar ao máximo seus desktops. O programa é leve e tem suporte desde o Windows 2000 até o Windows 7, o legal é que tem alguns efeitos de transição entre os desktops, parecido com esse:

imagem post 3

Bem parecido com um efeito que tem no Ubuntu, quando vc instala o Compiz, tem outros efeitos também mas eu gostei mais deste :) Além disso vc pode ter uma pré-visualização dos seus desktops:

imagem post 4

Claro que se vc tiver mais que 4 desktops vai aparecer aí também… Fica aí a dica o pedido para a Microsoft adicionar isso no próximo Windows (ou mesmo num service pack), ideia é o que não falta: veja esse link e esse também.

Outro aplicativo que achei bem legal e que também adotei (dica do Scott Hanselma) foi a divisão do desktop em sessões, tal como esta:

imagem post 5

Pra fazer isso vc precisa de um outro programinha chamado Fences, com ele vc pode criar várias destas áreas e colocar nomes diferentes, serve como se fosse um contêiner de itens, isso deixa seu desktop bem mais organizado. E se não quiser ficar olhando o tempo todo pra eles, basta dar dois cliques na área vazia do desktop que tudo desaparece (até os ícones), muito legal. E para criar novos “fences” basta clicar arrastar e soltar com o botão direito do mouse, delimitando assim as dimensões do seu novo “fence”.

Bem era isso que tinha pra falar, por hoje é só.

Até a próxima.

11/11/2009

Até quanto C# pode ser considerada uma linguagem funcional?

Estive brincando um pouco com expressões lambda e percebi que simplesmente não dá pra usar recursividade, o detalhe mais importante de todos é que em linguagens funcionais isso é requisito básico. Afinal de contas em linguagem funcional tudo são funções, chamadas de funções e o uso de recursividade neste caso é fundamental.
Testando, o algoritmo recursivo mais vagabundo de todos, o de calculo fatorial, fica assim:

Func<int, int> fat = (b) => (b <= 1) ? 1 : b * fat(b – 1);

Parece bem obvio que isto funciona, mas não funciona… Ao compilar a instrução acima dispara este erro de compilação:
image
Bonito né? Não, eu não achei nem um pouco bonito, que tipo de expressão “lambda” é essa que não permite fazer chamadas recursivas de si mesma?
Tentei novamente, agora usando todo o dinamismo do C# 4.0, que alias, é lindo - mas vou falar sobre isso noutro post – e ficou assim:

dynamic fat = (Func<int, int>)((b) => (b <= 1) ? 1 : b * fat(b - 1));

Pois também não compila! E acusa o mesmo erro de antes – talvez não foi dinâmico o suficiente…
Apelando mais um pouco dá pra “emular” uma chamada recursiva assim:

Func<int, int> fat = null;
fat = (b) => (b <= 1) ? 1 : b * fat(b - 1);

Antes que alguém pergunte: digo “emular” porque na verdade isso não é uma recursão é chamada de delegate – delegate que chama delegate. Isso é recursão? Não!
Nas linguagens funcionais de verdade tal como Lisp, Scheme e Haskell não existe nenhum comando mágico que sirva para fazer iteração (sem for ou while, foreach nem pensar), temos somente que nos apegar as recursões. Veja o exemplo:

(define (fat n) (if (= n 1) 1 (* n (fat (- n 1)))))

Isso aí é meu algoritmo fatorial em Scheme, já deve ter percebido porque as linguagens funcionais não são lá muito populares né? Apesar que se vc estudar um pouco vai ver que são linguagens extremamente simples, mas vamos em frente com outro exemplo:

fat = lambda x: 1 if x <= 1 else fat(x-1) * x

Isso aí agora é Python, pois é, Python é uma linguagem multi-paradigma e dinâmica onde dá para programar de forma estruturada, orientada a objetos ou mesmo como uma linguagem funcional (ver também IronPython). Bem mais fácil de entender…

O que eu quero dizer com todo essa conversa é que a Microsoft não tem intuito de torna C# uma linguagem dinâmica como Ruby (ver também IronRuby), nem totalmente funcional como Lisp (ver também linguagem funcional da Microsoft, o F#). Estas novas características da linguagem tem mais a ver com evolução natural do C# e necessidade de se ter uma ferramenta cada vez mais flexível, deixando o desenvolvimento de software cada vez mais ágil e simplificando a vida dos desenvolvedores.

Então, não pense que o C# vai ser tão dinâmico quanto Python ou tão funcional quanto Lisp, isso nunca vai acontecer. Mas isso não quer dizer que a Microsoft não possa dar um suporte melhor à programação dinâmica e funcional. Apesar que isso poderá mudar em breve, talvez no C# 5.0, vamos esperar pra ver.

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

31/10/2009

Usando parâmetros opcionais no C# 4.0


Olá pessoal, hoje vamos falar um pouco sobre um novo recurso do C# 4.0, os parâmetros opcionais.
Para isto utilizaremos um código bem simples que gera strings, segue:
public string[] GerarString()
{
   
return GerarString("Parâmetros");
}
public string[] GerarString(string str)
{
    return GerarString(str, 10);
}
public string[] GerarString(string str, int qtd)
{
    var lista = new List<string>();
    for (int i = 0; i < qtd; i++)
    {
        lista.Add(str);
    }
    return lista.ToArray();
}
Como vocês estão vendo, aqui utilizei 3 métodos sobrecarregados, onde posso chamá-los passando a string que eu quero gerar e a quantidade de repetições, ou somente a string que eu quero gerar (neste caso a quantidade default é 10), ou mesmo não passar nenhum parâmetro (neste caso a quantidade default é 10 e o string é "Parâmetros").
Bem, não há novidade nenhuma até agora. O fato é que parâmetros default têm o funcionamento parecido com os métodos sobrecarregados e torna a linguagem mais expressiva, vamos ver agora o código a seguir:
public string[] GerarString(string str = "Parâmetros", int qtd = 10)
{
    var lista = new List<string>();
   
for (int i = 0; i < qtd; i++)
   
{
   
    lista.Add(str);
   
}
   
return lista.ToArray();
}
Ficou bem mais simples e bem menor! O que acontece agora é que estamos dizendo ao compilador que se nada for passado no parâmetro str ele assumirá o valor "Parâmetros" e se nada for passado no parâmetro qtd ele assumirá o valor 10. Isso significa que podemos passar ou não os parâmetros (opcionais) e as chamadas ficam idênticas a como fazíamos com a sobrecarga de método:
// sem passar nenhum parâmetro, neste caso assume os defaults
GerarString();
// passando somente o ultimo parâmetro, neste caso somente str assume o default
GerarString(15);
// passando ambos, nenhum parâmetro assume o default
GerarString("Agora tou passando", 30);
Legal, mas temos que ter em mente algumas regrinhas na hora de sair programando com parâmetros opcionais.
  1. É possível especificar quantos parâmetros opcionais você quiser, desde que comece do ultimo para o primeiro.
    1. void Calcular(int a, int b, int c = 10) // isso é permitido
    2. void Calcular(int a = 10, int b, int c) // isso NÃO é permitido
  2. Não é permitido intercalar parâmetros opcionais e não opcionais.
    1. void Calcular(int a = 2, int b, int c = 8) // isso NÃO é permitido
  3. Caso todos os parâmetros do método sejam opcionais é possível escolher quais poderemos passar usando parâmetros nomeados.
    1. Calcular(b: 1); // especifica somente b, enquanto a e c assumem o default
    2. Calcular(b: 5, c: 4); // especifica somente b e c
    3. Calcular(b: 5, a: 10, c: 4); // ou mesmo especificados (a ordem não importa)
  4. O parâmetro default sempre deve ser uma constante.
    1. Calcular(int a, int b, int c = SelecionarC()) // isso NÃO é possível

Como podemos observar existem grandes aplicações para este novo recurso do C#, façam bom uso dele. Espero que tenham gostado.

Tchau e até a próxima.

27/10/2009

Verificando existência de Objetos no SQL Server

Olá, após um longo tempo fora do meu blog volto com força total e neste post vou falar um pouco sobre como podemos obter informações sobre existência de objetos numa base SQL Server. Entenda "objeto" como qualquer coisa que possa ser manipulada no banco tal como tabelas, colunas, constraints, índices, chaves primárias, etc.

No SQL Server existe uma função Object_ID() que é muito útil na hora de descobrir a existência de elementos no banco.

-- Retorno o id do objeto do elemento buscado

if Object_ID('CK_NIVEL') IS NOT NULL

    print 'sim, existe!!!' -- aqui vc faz o que quiser

Como vimos acima o uso da função Object_ID() bem simples e pode ser usado para quase qualquer tipo de objeto que exista – ou não – na base de dados. Só que nem sempre ela é suficiente, por exemplo, se precisarmos então descobrir se existe uma determinada coluna na tabela tal? Para estes casos teremos que usar as tabelas do sistema do SQL Server.

A lista é imensa, mas vou tentar resumir pra vocês somente o que interessa. Vamos lá!

-- Verifica a existência da contraint CK_NIVEL na tabela USUARIO

if exists (select 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where TABLE_NAME='USUARIO' and CONSTRAINT_NAME='CK_NIVEL')

    print 'sim, existe!!!' -- aqui vc faz o que quiser

 

-- Verifica a exitência da coluna POSOLOGIA na tabela MEDICAMENTO

if exists (select 1 from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='MEDICAMENTO' and COLUMN_NAME='POSOLOGIA')

    print 'sim, existe!!!' -- aqui vc faz o que quiser

 

-- Verifica existência da chave estrangeira FK_VENDA na tabela PEDIDO, mas também poderia ser uma chave primária

if exists (select 1 from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME='PEDIDO' and CONSTRAINT_NAME='FK_VENDA')

    print 'sim, existe!!!' -- aqui vc faz o que quiser

 

-- Verifica se existe o indice IX_NOME

if exists (select 1 from sys.sysindexes where name='IX_NOME')

    print 'sim, existe!!!' -- aqui vc faz o que quiser

Na verificação de índices tem uma peculiaridade: a nossa funçãozinha mágica Object_ID() não funciona para índices... Não me pergunte por que, mas é isso.

Espero ter ajudado em algo, se tiver mas algum item para incluir na lista por favor postem aí!!!

Abraços e até a próxima.

21/06/2009

Bluetooth com a API 32feet

Recentemente precisei usar Bluetooth em um projeto da faculdade na cadeira de Arquitetura e Organização de Computadores. Pesquisei bastante procurando alguma API que fizesse o trabalho pesado e me deixasse abstrair um monte de coisas, como Socket e API do Windows, por exemplo. Então encontrei uma biblioteca formidável escrita em .NET chamada 32feet que foi desenvolvida por uma empresa chamada In The Hand (estranho o nome, não é?), mas é isso mesmo. O código fonte desta biblioteca é a aberto e está hospedado no Codeplex.

O 32feet foi muito bem desenvolvido e nos traz facilidades incríveis na hora de manipular dispositivos Bluetooth. Vou mostrar algumas funcionalidades bem legais: detectar dispositivos, pareá-los e enviar um arquivo. Para começar você deve baixar os arquivos necessários e instalá-los corretamente a partir do endereço http://www.codeplex.com/32feet/, referenciar o namespace InTheHand.Net.Personal no seu projeto no Visual Studio e mãos à obra!

Detectando dispositivos

Para começar vamos detectar os dispositivos ao redor, tarefa simples com o 32feet.

BluetoothClient client = newBluetoothClient();

BluetoothDeviceInfo[] arrDevices = client.DiscoverDevices();

    Pronto! Este código funciona perfeitamente e detecta todos os dispositivos que estão próximos, autenticados ou acessados recentemente pelo rádio Bluetooth se precisar filtrar mais o dispositivos retornados pelo método DiscoverDevices, existe uma sobrecarga deste método que possibilita customizar o retorno, informando a quantidade máxima de dispositivos, se vai retornar os autenticados, conhecidos e/ou os desconhecidos (dispositivos novos). Dentro da classe BluetoothDeviceInfo estão todas as informações pertinentes ao dispositivo que foi detectado, onde os principais são DeviceAddress e DeviceName.

Pareando um dispositivo

    A maioria das operações com Bluetooth necessitam do DeviceAddress, que é o endereço identificador do dispositivo, é como o IP para os computadores em rede. Para parear um dispositivo obviamente temos que ter o endereço dele em mãos, aí fica fácil parear, bastando chamar um método.

BluetoothSecurity.PairRequest(device.DeviceAddress, "1");

    Este trecho de código é super simples, o método PairRequest manda um requisição de pareamento para um dispositivo, o primeiro parâmetro é o endereço do dispositivo em questão e o segundo é a chave de pareamento que no meu caso é "1". Este método retorna true se o pareamento ocorreu com sucesso ou false se, por algum motivo, o pareamento não pode ser concluído.

Enviando um arquivo

    O envio de arquivo usei duas classes especiais da biblioteca, ObexWebRequest e ObexWebResponse. OBEX é a abreviação para Object Exchange que é um protocolo que facilita a troca de arquivos binários entre dispositivos (leia mais).

string arquivo = "...URL DO ARQUIVO...";

Uri uri = new Uri("obex://" + device.DeviceAddress.ToString() + "/" + arquivo);

ObexWebRequest request = newObexWebRequest(uri);

request.ReadFile(arquivo);

ObexWebResponse response = (ObexWebResponse)request.GetResponse();

response.Close();

    O uso do Obex é bastante simplificado, pois funciona igual a uma requisição web qualquer. Neste exemplo estou passando o nome do arquivo para o método ReadFile, mas poderia ter feito diferente passando o Stream diretamente para o construtor sobrecarregado ObexWebRequest.

    Bom, acredito que com esta brevíssima introdução deu pra ter idéia de como funciona esta maravilhosa biblioteca. Para quem quiser se aprofundar deixo os links principais:

[]s

10/04/2009

Atalhos do Visual Studio

No Visual Studio existem muitos atalhos bastante úteis. Muitos deles estão listados neste post de André Furtado http://afurtado1980.spaces.live.com/blog/cns!63514833CE40C143!686.entry.

Outro atalho que descobri por acaso há algumas semanas é o CTRL+SHIFT+V que serve para colar pedaços de textos que foram usados recentemente em outras "colagens". Com este atalho não é preciso mais copiar e colar a mesma coisa repetidas vezes, pois o VS guarda na memória o histórico de tudo o que foi colado recentemente, para acessar as colagens anteriores basta teclar CTRL+SHIFT+V várias vezes até chegar no trecho que você quer.

03/03/2009

Competição Info Arena

Recebi uma notícia bem legal hoje, sobre a competição de programação organizada pela INFO.

http://info.abril.com.br/blog/arena/

E aí, vai encarar ?

01/03/2009

Arredondamento de casas decimais

Quando trabalhamos com arredondamento de números reais nos deparamos com algo como:

  • 1,9349 arredondando para 2 casas fica 1,93
  • 1,9351 arredondando para 2 casas fica 1,94
  • E 1,9350 arredondando para 2 casas fica 1,93 ou seria 1,94 ? O correto é 1,94! (arredonda-se para cima)
  • E 1,9250 arredondando para 2 casas fica 1,92 ou seria 1,93 ? O correto é 1,92! (arredonda-se para baixo)

Parece coisa de doido mas não é. Diz a regra “Se o algarismo decimal seguinte for igual a 5, o anterior incrementa-se em uma unidade caso ele seja impar. Caso seja par basta conservar o algarismo” (definição do wikipedia).

Esta regra diminui os erros de arredondamento (mais sobre) em 50%, pois metade das vezes aproxima para cima e metade das vezes aproxima para baixo.

Em .NET quando você usa Math.Round() este comportamento é o padrão, tanto para double quanto para decimal.

O mais legal é que em .NET é possível alterar o comportamento padrão do método Round passando um terceiro parâmetro chamado MidpointRounding que, na verdade, é um enum que pode assumir os valores MidpointRounding.AwayFromZero (arredonda sempre para cima) ou MidpointRounding.ToEven (arredonda pra cima se for ímpar ou mantém o valor se for par).

Aqui vai um print screen de um código em C# executando as operações com MidpointRounding.AwayFromZero, com MidpointRounding.ToEven e sem MidpointRounding.

(clique para ampliar)

 

Para ler mais sobre MidpointRounding vai aí um link.

[]s

14/02/2009

Convenções na passagem de arrays por parâmetro

Esta semana estava eu assistindo aula de Paradigma de Linguagens de Programação quando meu professor – maluquinho da silva – disse que o fato de um array em C não poder ser passado por valor para dentro de uma função era um erro de projeto, porque fere o princípio de ortogonalidade e etc. Pera lá, a primeira vista soa no mínimo estranho dizer que houve erro de projeto numa linguagem tão fantástica e bem sucedida quanto C, mas de fato existiram muitos. Mas acredito que a convenção na passagem de arrays por parâmetro não seja o caso.

Na verdade, quando passamos um array por parâmetro em C, seja lá qual tipo for, o que é de fato passado é o primeiro elemento do array. A partir do primeiro elemento você pode – usando aritmética de ponteiros – achar qualquer outro elemento deste array. Isto explica o porque das sintaxes tão variadas no tratamento dos arrays.

Estas sintaxes funcionam todas sem problemas:

/*
o ponteiro ‘arr’ recebe o endereço do 1º elemento do array
*/
void escreve_tudo(int * arr, int n){
    int i;
    for(i = 0; i < n; ++i)
        printf("%d\n", arr[i]);
}

/*
neste caso ‘arr’ também é um ponteiro para o endereço do 1º elemento do array
*/
void escreve_tudo(int arr[], int n){
    int i;
    for(i = 0; i < n; ++i)
        printf("%d\n", arr[i]);
}

/*
mesmo especificando o tamanho recebido em ‘arr’ a semântica é da vista acima, pois em não existe checagem de limites de matrizes em tempo de compilação – tanto faz passar ou não o tamanho do array
*/
void escreve_tudo(int arr[10], int n){
    int i;
    for(i = 0; i < n; ++i)
        printf("%d\n", arr[i]);
}

A pergunta é: Será mesmo que os projetistas da linguagem C erraram nisto ou será que é um acerto de projeto?

Na minha opinião está mais para acerto de projeto do que para erro. Pois imagine só se todas as vezes que passassemos um array - coisa pouca, uns 1000 elementos só - por parâmetro para uma função ele fosse todo novamente copiado para outra área da memória (mais sobre passagem por valor e referência aqui), imagine agora que esta função fosse uma função recursiva. É isto mesmo, caos total… Daí você pode perguntar: Então não seria melhor apenas criar uma forma de passar um array tanto por valor quanto por referência e aí o programador decidiria o que usar? 
Dúvido que algum programador bem formado e em sã conciência iria usar uma passagem por valor de um array.

Uma prova da inutilidade – e periculosidade - da passagem por valor de arrays é que nenhuma das linguagens mais famosas e utilizadas – tais como Java e C# – têm esta capacidade. Será mesmo que as equipes que implementaram Java e C# deixaram passar um erro de projeto de C? Acredito que não.

Fico por aqui, até mais.

[]s

08/02/2009

Microsoft pode lançar seu próprio smartphone, diz especialista

Quase caí da cadeira quando li esta reportagem:

Os rumores de que a Microsoft vai lançar seu próprio smartphone estão crescendo novamente, em especial após um analista declarar que o aparelho pode ser lançado no GSMA Mobile World Congress (MWC), entre 16 e 19 de fevereiro, em Barcelona. […]

Pelo visto a Microsoft quer ampliar ainda mais o que educadamente chamamos de “fatia do mercado” (em outras palavras: monopólio). Talvez esta seja uma maneira que a Microsoft encontrou de manter o Windows Mobile competitivo no mercado, já que o Android está vindo com força total.

Ver reportagem completa no IDG Now!

[]s