Páginas

domingo, 25 de julho de 2010

Abusos dos design patterns

Recentemente recebi de um colega de trabalho um link de um artigo escrito por Rockford Lhotka, criador do framework de desenvolvimento de aplicações CSLA .NET.

Neste arquivo, ele comenta sobre o mau uso dos design patterns nas aplicações.

Ele condena o uso de padrões sem critério algum, ou seja, quando se faz o uso deles apenas por se “achar bonito”, sem se preocupar em realmente identificar um problema a ser resolvido. Isso acontece muito, principalmente quando se lança uma tecnologia nova ou um pattern se torna popular. Temos a tendência de nos “regogizarmos mentalmente” quando fazemos algo complexo.

Em resumo, o artigo cita que se deve:

  1. Utilizar patterns quando se tem um problema a resolver e o padrão se aplica.
  2. Utilizar o padrão quando suas qualidades superarem suas desvantagens (sim, nenhum pattern é perfeito, todos têm seu lado ruim).
  3. Combinar padrões simples para enfrentar problemas complexos.
  4. Quando usado um padrão, ter certeza que todos os desenvolvedores e analistas envolvidos no projeto tenham entendimento dele.
  5. Tomar cuidado com a multiplicidade e dependência que o uso de determinados padrões de nível complexo possam trazer à sua aplicação (faz parte da análise de custo vs. benefício).

Sem mais demoras, o link para o artigo é este:

http://www.lhotka.net/weblog/OnTheUseAndMisuseOfPatterns.aspx.

[]’s

quinta-feira, 15 de julho de 2010

Roger Waters + David Gilmour: novas esperanças?

image

http://www.davidgilmourblog.com/2010/07/hoping-foundation.html

Esta notícia foi muito animadora! No sábado passado, 10/07/2010, David Gilmour e Roger Waters tocaram juntos em um evento de caridade, voltado para crianças palestinas (http://www.hopingfoundation.org/).

As músicas que foram tocadas foram “To Know Him Is To Love Him” (usada na passagem de som do Pink Floyd), “Wish You Were Here”, “Comfortably Numb” e “Another Brick in the Wall (Part Two)”.

Em 2010 e 2011, Roger Waters fará uma turnê em comemoração dos 30 anos do álbum “The Wall”. Será que cabe uma visita ao Brasil? Quem sabe, com David Gilmour junto?

Esperança é a última que morre…

[]’s

domingo, 4 de julho de 2010

Windows Image Acquisition

Windows Image Acquisition (WIA) é uma API da Microsoft para manipulação de dispositivos como câmeras e scanners.
Tive o interesse em pesquisar esta API para a criação de um windows service em .NET que fique tirando fotos de tempos em tempos de quem está usando o computador e mandando para um site ou e-mail. Isso é bem útil no caso de roubo de notebooks…, pelo menos se pode ter a foto do maldito ladrão!
O que vou colocar aqui é um exemplo de código que faz a captura de uma imagem. Uma coisa bem simples, mas que deu um pouco de trabalho até entender legal como é que funciona essa API.
Antes de começar, é necessário dizer que esta API não funciona com todos os dispositivos. Bom, basicamente e teoricamente irá funcionar com dispositivos que estejam listados em Painel de Controle –> Scanners e câmeras. Por causa disso, esse exemplo que vou passar não funcionou no meu desktop, que possui uma webcam da marca Bright. No entanto, funciona no meu netbook, que possui uma webcam embutida (Acer).
Bom, a primeira coisa a se fazer é baixar o SDK desta biblioteca do site da Microsoft. Note que isso só é necessário com o Windows XP, pois o Vista já vem com ela instalada. As instruções de instalação vêm junto do pacote (não se esqueça de fazer isso senão não irá funcionar!).
Vamos criar uma tela simples Windows Form que apresente uma foto recém tirada. Um detalhe que esta API é COM, não é nativa .NET. Neste caso, precisaremos trabalhar com interop. Nada complicado, bastando fazer uma referência ao Microsoft Windows Image Acquisition v2.0.
image
Todo o código abaixo foi colocado em um evento de clique de botão (é uma aplicação para testes apenas, então não vou me preocupar muito com boas práticas de programação). Outro detalhe é que importei os namespaces WIA, System.IO e System.Diagnostics neste exemplo.
A primeira coisa a ser feita é obter o ID do dispositivo que iremos utilizar. Como falei antes, está é uma API para uso de vários dispositivos, e precisamos escolher apenas um. Quando usamos a classe WIA.CommonDialog nos é exibida uma tela onde escolhemos qual dispositivo usar (essa tela é do Windows, não temos o controle dela). Um detalhe importante é que eu não consegui fazer a instância dessa classe através simplesmente de
CommonDialogClass class1 = new CommonDialogClass();


, pois quando fazia isso o Visual Studio me retornava o erro “Interop type 'WIA.CommonDialogClass' cannot be embedded. Use the applicable interface instead.”. Resolvi isso através de late binding.

O retorno desta seleção é um objeto do tipo Device, de onde podemos obter seu identificador único (ID).

// Escolhe o dispositivo que será usado para tirar a foto
string deviceId = string.Empty;
ICommonDialog class1 = (ICommonDialog)Activator.CreateInstance(Type.GetTypeFromProgID("WIA.CommonDialog"));
Device d = class1.ShowSelectDevice(WiaDeviceType.UnspecifiedDeviceType, true, false);
if (d != null)
deviceId = d.DeviceID.ToString();
MessageBox.Show(string.Format("O identificador do dispositivo é {0}", deviceId));


imageimage


Com o ID em mãos, podemos conectar no dispositivo que será usado. Um detalhe importante é que eu não precisaria fazer isso, pois já obtive uma referência a um Device quando selecionei através da tela anterior. Mas é bom fazer isso já que como meu código vai rodar num windows service, não é interessante que fique sendo exibido sempre qual dispositivo utilizar.


// Faz conexão com o dispositivo
IDeviceManager manager = (IDeviceManager)Activator.CreateInstance(Type.GetTypeFromProgID("WIA.DeviceManager"));
Device device = null;
foreach (DeviceInfo info in manager.DeviceInfos)
{
if (info.DeviceID == deviceId)
{
device = info.Connect();
break;
}
}


Agora vem a parte principal, que é tirar a foto. Isso é feito através do envio de uma execução de comando através da instância da classe Device. O guid {AF933CAC-ACAD-11D2-A093-00C04F72DC3C} é padrão para comando de “tirar foto”, e existe outros mais. Outra coisa que notei neste código é que ele demora bastante para rodar, uns 7 segundo até a foto ser tirada. Por isso coloque um cronômetro (StopWatch) no código para saber sempre quanto tempo a execução levou. Não sei como resolver isso, se é que dá para resolver, mas para o tipo de serviço que eu quero fazer, não vejo problemas por enquanto…


// Envia o comando para a câmera tirar uma foto
Stopwatch watch = new Stopwatch();
watch.Start();
Item item = device.ExecuteCommand("{AF933CAC-ACAD-11D2-A093-00C04F72DC3C}"); // CommandID.wiaCommandTakePicture
watch.Stop();
MessageBox.Show(string.Format("Foram necessários {0} milissegundos para tirar a foto.", watch.ElapsedMilliseconds.ToString()));


imageimage


Com o retorno da execução da foto, recebemos como retorno uma instância da classe Item, que é o item resultante do processo que foi feito. No nosso caso, uma foto. Com este objeto, podemos transferir seu conteúdo para uma instãncia da classe WIA.FileImage. E com este objeto, podemos chamar o método SaveFile para armazenarmos em disco. Isso eu faço para poder exibí-la em um controle do tipo PictureBox.


// Salva a foto temporáriamente para exibição
foreach (string format in item.Formats)
{
if (format.ToUpper() == "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}")   // ImageFormat.Jpeg.Guid
{
WIA.ImageFile imagefile = item.Transfer(format) as WIA.ImageFile;
string filename = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".jpg");
if (!string.IsNullOrEmpty(filename))
{
imagefile.SaveFile(filename);
try
{
this.pictureBox1.Load(filename);
}
finally
{
File.Delete(filename);
}
}
}
break;
}


Bom, com isso terminamos, certo? Não, ainda não…, a foto que tiramos ainda ficou armazenada na cãmera, precisamos removê-la para não ficar ocupando memória desnecessária. Para fazer isso, basta percorrer os itens do Device e remover o que tiver o mesmo ID da foto que foi tirada (Obs. Note que essa coleção de itens não começa com elemento na posição zero, mas sim na 1).


// Remove a foto que ficou armazenada
if (device.Items.Count > 0)
{
int indice = 1;
foreach (IItem i in device.Items)
{
if (i.ItemID == item.ItemID)
break;
indice++;
}
device.Items.Remove(indice);
}

Agora sim terminamos este exemplo. Agora vou começar a fazer o windows service que espero nunca precisar ter que realmente usar, rs.

Boas fotos!

[]’s

sábado, 3 de julho de 2010

Vulnerabilidades de um Tiger

Achei interessante esta imagem, que mostra a lista de pontos fracos de um Tiger (tanque de guerra alemão, da Segunda Guerra Mundial).

O link original desta imagem é http://www.lonesentry.com/articles/ttt_tigervulnerability/index.html, onde é explicado que ela se trata de uma tradução americana de um jornal sovietico. Na época em que foi publicado, os americamos haviam encontrado este carro de combate apenas algumas poucas vezes, durante batalhas contra o Afrika Korps e durante a invasão da Itália.

ttt_tiger_vulnerability