Páginas

segunda-feira, 27 de dezembro de 2010

Instalando Windows 7 – problema de HD / partição

Tenho um computador com 2 HD, e que estavam sendo utilizados da seguinte forma:

  • HD1:
    • Drive C:\ – Windows Vista
    • Drive D:\ – Arquivos
  • HD2:
    • Drive F:\ – Arquivos

Decidi instalar o Windows 7 nele. Fiz meus backups, coloquei o DVD do Win7 na máquina e dei boot. Na hora de escolher a partição, formatei a partição que estava instalado o Windows Vista e a informei para utilizada. Foi quando o setup do Win7 começou a reclamar de “Setup was unable to create a new system partition or locate an existing system partition”…

Que diabos era isso, o Vista estava funcinando ok nesta partição há uns 3 ou 4 anos…

Busquei na internet (sorte que eu estava com um netbook ao lado), e encontrei a solução: desliguei o segundo HD, aquele que tinha a partição F:\. Com isso, consegui escolher a partição para efetuar a instalação. Achei a solução estranha, mas o importante é que está funcionando…

Obs. Essa solução eu encontrei na seguinte thread de fórum: http://arstechnica.com/civis/viewtopic.php?f=15&t=83939.

Vamos ver se eu tenho mais algum problema nessa instalação…, neste exato momento está há 83%…

[]’s

segunda-feira, 6 de dezembro de 2010

O pior é impossível? – parte 3

Desta vez vamos deixar a seção de “Pérolas do Desenvolvimento” mais voltada para a especificação.

Na UML, um diagrama de sequência é a representação gráfica da troca de mensagens entre objetos, mostrando essa interação durante o tempo de execução da funcionalidade. O que agrega neste diagrama é saber a sequência de acontecimentos, para podermos programar corretamente o comportamento esperado do sistema.

Só que pra isso precisamos de mais detalhes…vejam o diagrama abaixo. O que ele agrega para nós? Nada, é a mesma coisa que falar “usuário usa o sistema”. Não dá detalhes de quais objetos estão envolvidos na funcionalidade (generalizou-se o objeto “Aplicação” como todos os objetos internos do sistema).

Documentação boa é documentação que tráz valor ao desenvolvimento. Se não trouxer, só serve pra engordar o orçamento do projeto.

image

Obs. Não coloquei aqui, mas tem também o fluxo alternativo dessa funcionalidade…, que é igual ao fluxo básico…

[]’s

quarta-feira, 24 de novembro de 2010

Obras Completas de Carl Barks

Finalmente, após alguns anos colecionando e gastos “caros” no Mercado Livre, consegui completar minha coleção das Obras Completas de Carl Barks.

Carl Barks foi o criador de vários personagens da Disney, entre eles o Pato Donald e o Tio Patinhas. Ele foi fonte de inspiração não apenas para pessoas que trabalham com quadrinhos mas também outros artistas. Um exemplo é Steven Spielberg. A cena inicial de Indiana Jones, onde ele é perseguido por uma rocha rolante, é baseada na história “As Cidades do Ouro”, de 1954.

Coleção das Obras Completas de Carl Barks

sexta-feira, 27 de agosto de 2010

O pior é impossível? – parte 2

Continuando a série de “pérolas do desenvolvimento”, temos esta chamada a um web service. Veja que forma inovadora de efetuar a chamada: através de um post http! Não há mais necessidade de se criar proxies!

E o pior de tudo, isso funciona!

Obs. Este método retorna um XML. Veja que é feito um tratamento no retorno obtido, para modificar HTML para que esteja num formato correto. Vários replaces…

perola

quarta-feira, 11 de agosto de 2010

Composite e Chain of Responsibility

Pessoal,

saiu outro artigo meu na .NET Magazine 76, ainda a respeito de design patterns: nesta edição, eu abordo os padrões Composite e Chain of Responsibility.

[]’s

.NET Magazine 76

domingo, 1 de agosto de 2010

MVP – Passive View

O MVP é um padrão para a construção de aplicações que interagem com o usuários (User Interface) que tem dois objetivos principais:

  1. Separar as responsabilidades na camada de apresentação, ou seja, o que é da tela e o que é da lógica de negócio do aplicativo.
  2. Facilitar os testes,  permitindo que os mesmos sejam automatizados.

O pattern MVP pode ser separado em duas categorias: Passive View e Supervising Controller. A diferença entre os dois é o grau de testabilidade que cada um provê. Hoje iremos ver alguns detalhes da primeira categoria, com foco na questão de separação de responsabilidades.

Diagrama de classes MVP

A idéia aqui é separarmos o que o que é da apresentação e o que é da lógica de acesso aos objetos do domínio de negócios. O diagrama acima mostra como temos essa separação entre as classes que compõe a estrutura básica do MVP Passive View. Do lado da camada de apresentação, temos a classe View, que no final das contas será uma tela WPF ou uma página ASP.NET. Do lado da lógica de negócios, temos a classe Model, que representa os dados que serão exibidos pela aplicação. Na intersecção das duas camadas está a interface IView, que veremos em breve deve ser implementada por todas as views (telas ou páginas) e a classe Presenter. A classe Presenter funciona como um meio-de-campo entre a camada de apresentação e a lógica de negócios.

Antes de prosseguirmos com um exemplo, vamos notar como é o relacionamento entre no diagrama acima. A classe Presenter é referenciada diretamente por View, mas Presenter não conhece View. Na verdade, ela conhece apenas a interface IView que é implementada por View, e é dessa forma que a conversa entre as duas ocorre. Por isso que este pattern é conhecido como Passive View, pois a view é manipulada, indiretamente, pela classe Presenter. Veja que em nenhum momento View acessa diretamente Model, o que provê a separação entre as camadas.

Vamos comentar o exemplo criado para ilustrar. Ele é uma tela fictícia de consulta de preços de ações (Bolsa de Valores), onde o usuário irá informar o código da ação (conhecido por “ticker”), e a aplicação retornará o valor atual da cotação. É claro que, como um exemplo, vou gerar estes valores de forma aleatória, para simplificar. Abaixo está como eu organizei a solution. Temos quatro projetos aqui:

  • MVP.Domain – É o projeto que contém os objetos de negócio (Model). Numa solução distribuída do “mundo real”, estas classes ficariam hospedadas em um servidor de componentes e poderiam, por exemplo, serem expostas através de serviços WCF.
  • MVP.Presentation – Este projeto faz parte da camada de apresentação / serviços e contém a classe que fará o meio-de-campo entre a interface e a chamada aos componentes de negócio.
  • MVP.Task – No nosso exemplo, este projeto contém os componentes que compõem a camada de serviços de apresentação. Esta camada também faz um papel intermediário entre a camada de apresentação e a camada de componentes de negócios. Para o MVP, podemos considerá-la como uma abstração da classe Model (que está presente no exemplo em MVP.Domain).
  • MVP.WPFUI – Este projeto é a camada de apresentação em si, e é composto de uma tela construída em WPF.

Solution

Começaremos pela interface que representa IVew: IStockSearchView. Esta interface possui algumas propriedades que ajustam valores, ou seja, que recebem valores e os colocarão em “algum lugar”. Veja que neste momento não interessa que lugar seja esse.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MVP.Presentation
{
public interface IStockSearchView
{
string Ticker { set; }
double Price { set; }
string Message { set; }
}
}


Em seguida temos a classe Presenter: StockSearchPresenter. Lembre-se que ela é o meio-de-campo com a interface e a classe Model. Olhe que interessante: no construtor de Presenter recebe-se um objeto que implementa IStockSearchView, e esta instância é armazenada em uma propriedade privada. No método SearchStock, que efetua a pesquisa de uma determinada ação, é o modelo (Model) é acessado através da classe StockSearchTask (camada de serviços da apresentação), e o resultado obtido é atribuído na view. Quem quer que seja este objeto que implementa IStockSearchView, ele está recebendo os valores passivamente. O que será que será feito com estes dados?



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MVP.Task;

namespace MVP.Presentation
{
public class StockSearchPresenter
{
private IStockSearchView _view = null;
private StockSearchTask _task = new StockSearchTask();

public StockSearchPresenter(IStockSearchView view)
{
_view = view;
}

public void SearchStock(string ticker)
{
StockInfoVO info = _task.SearchStock(ticker);
_view.Price = info.IsValid ? info.Price : 0;
_view.Message = info.Message;
_view.Ticker = info.IsValid ? info.Ticker : ticker;
}
}
}


Antes de prosseguir, vamos dar uma olhada na camada de serviços de apresentação e o modelo de negócios.



StockSearchTask é uma classe que acessa os componentes de negócio. Neste nosso exemplo, é uma chamada simples, mas na “vida real” esta chamada poderia ter sido feita através de um Web Service. Note que aqui a classe Task está fazendo uma abstração de como nós estamos acessando a camada de negócios. Veja também que ela faz uso de uma classe do tipo Value Object (StockInfoVO), ou seja, um objeto criado simplesmente para servidor de conteiner de informações, ou seja, este objeto não possui operações (comportamento).



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MVP.Domain;

namespace MVP.Task
{
public class StockSearchTask
{
public StockInfoVO SearchStock(string ticker)
{
StockInfoVO info = new StockInfoVO();
StockManager manager = new StockManager();
Stock stock = manager.SearchForStock(ticker);
info.IsValid = stock != null;
if (info.IsValid)
{
info.Ticker = stock.Ticker;
info.Price = stock.Price;
}
else
info.Message = "Stock not found!";
return info;
}
}
}


Outro detalhe importante deste objeto do tipo VO é que ele também ajuda a separar a camada de apresentação da de negócios, fazendo com que os tipos que nesta última existam não sejam conhecidos pela interface gráfica.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MVP.Task
{
public struct StockInfoVO
{
public string Ticker;
public double Price;
public bool IsValid;
public string Message;
}
}


Agora vamos a fundo no projeto dos componentes de negócio. Temos a classe Stock, que representa uma ação. Ela armazena o ticker da ação e possui um método que retorna seu preço (que aqui, como falamos, retorna um número aleatório).



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MVP.Domain
{
public class Stock
{
public string Ticker { get; set; }
public double Price
{
get
{
// Gera um preço aleatório
Random random = new Random(Environment.TickCount);
return random.NextDouble() * 100;
}
}
}
}


Também temos a classe StockManager, que é responsável pelo gerenciamento das classes Stock. Aqui ela funciona como um agrupador de várias instâncias de Stock para nosso exemplo simples (temos apenas algumas empresas relacionadas aqui…, Petrobrás, Vale, Lojas Renner, etc.). O que ela faz, efetivamente, é manter uma lista dessas empresas em memória, e quando chamado o método SearchForStock(string), ele retorna uma dessas instâncias, caso ela exista (senão retorna null).



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MVP.Domain
{
public class StockManager
{
private static List _stocks = new List()
{
new Stock(){ Ticker = "PETR3"},
new Stock(){ Ticker = "VALE5"},
new Stock(){ Ticker = "LREN3"},
new Stock(){ Ticker = "GGBR4"},
new Stock(){ Ticker = "ITUB3"},
};

public Stock SearchForStock(string ticker)
{
Stock stock = (from s in _stocks
where s.Ticker == ticker.ToUpper()
select s).FirstOrDefault();
return stock;
}
}
}


Por fim, temos a própria tela em WPF. Veja que ela implementa IStockSearchView. As implementações das operações definidas nessa interface fazem a atribuição dos valores aos controles visuais que estão na ela (labels, por exemplo). No evento de clique do botão, temos a chamada a classe Presenter: No seu construtor, passamos a própria instância da tela (this). Executando o seu método SearchStock, passamos as informações necessárias a StockSearchPresenter para que ela possa acessar o modelo de negócios e trazer as informações que queremos.



Tela em WPF



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using MVP.Presentation;

namespace MVP.WPFUI
{
///
/// Interaction logic for MainWindow.xaml
///

public partial class MainWindow : Window, IStockSearchView
{
public MainWindow()
{
InitializeComponent();
}

public string Ticker
{
set { txtTicker.Text = value; }
}

public double Price
{
set { lblPrice.Content = string.Format("{0:c}", value); }
}

public string Message
{
set { lblMsg.Content = value; }
}

private void btnSearch_Click(object sender, RoutedEventArgs e)
{
StockSearchPresenter presenter = new StockSearchPresenter(this);
presenter.SearchStock(txtTicker.Text);
}
}
}


Vimos aqui como fazer a separação entre a apresentação e o serviços de negócio, mas qual seria o esforço se precisássemos colocar essa funcionalidade em outra plataforma, por exemplo uma plataforma web? A criação da página seria bem simples, como podemos ver no código abaixo. Basta apenas fazer com que a própria página ASP.NET implemente IStockSearchView, acertar o que deve ser mudado quando suas propriedades forem chamadas e colocar o que deve ser feito quando o botão de pesquisa é clicado.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MVP.Presentation;

namespace MVP.ASPNETUI
{
public partial class _Default : System.Web.UI.Page, IStockSearchView
{
protected void Page_Load(object sender, EventArgs e)
{

}

public string Ticker
{
set { txtTicker.Text = value; }
}

public double Price
{
set { lblPrice.Text = string.Format("{0:c}", value); }
}

public string Message
{
set { lblMsg.Text = value; }
}

protected void btnSearch_Click(object sender, EventArgs e)
{
StockSearchPresenter presenter = new StockSearchPresenter(this);
presenter.SearchStock(txtTicker.Text);
}
}
}


Página ASP.NET



Com isso, percebemos como é feita a separação de responsabilidades entre a camada de apresentação e a camada de negócios. Com isso, temos menos código rodando na tela / página, o que facilita a manutenção e migração de plataforma dos sistemas que construímos.



Outra vantagem importante mas que não cobri neste post é a facilidade com que podemos criar testes automatizados nos sistemas, utilizando técnicas de mock.



[]’s

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

segunda-feira, 7 de junho de 2010

Krav Maga e Guinness!

PHOTO_9494098_7691_4764480_ap_420X315

http://community.guinnessworldrecords.com/_A-maior-aula-de-defesa-pessoal/BLOG/2376153/7691.html?widgetId=321868

No dia 28 de Maio, a comemoração do centenário de Imi Lichtenfeld reuniu em Copacabana 2212 alunos de Krav Maga, entre eles eu! Neste dia, entramos para o Guinness Book como a maior aula de defesa pessoal do mundo.

Gostei muito de ter participado. É bom quebrar a rotina de vez em quando. Foi a primeira vez que estive no Rio, e achei a cidade muito bonita.

[]’s

terça-feira, 25 de maio de 2010

O pior é impossível?

Sabemos que hoje a TI é uma das áreas que tem a melhor relação entre salário e tempo de aprendizado / experiência. O que quero dizer é que hoje uma pessoa que tem um mínimo necessário de instrução já consegue trabalhar recebendo um salário razoável. Isso, entre outras coisas, causado pela falta de regulamentação que temos na nossa categoria.

Com isso, várias pessoas que ainda não estão preparadas são atraídas para este ramo, e isso só traz desvantagens, como sistemas mal projetados e codificados. Isso se traduz em dores de cabeça para os demais analistas e programadores. Dou como exemplo a imagem abaixo, que foi tirada da vida real.

Vamos entender o problema que há nesse código.

Temos uma classe X (retirei os nomes e namespaces para evitar que a pessoa fique chateada), que será exposta em um serviço WCF. Podemos perceber isso pois ela é decorada com (ambos!) os atributos Serializable e DataContract. Ou seja, instâncias dessa classe serão trafegadas pela rede, seja através de TCP, HTTP ou qualquer outro binding disponível nesse framework, nas chamadas do serviço.

Agora perceba o que há dentro da classe. Temos membros que são instâncias de classes do ASP.NET (camada de interface da aplicação), como System.Web.UI.Page e HttpSessionState! O que foi feito foi acoplar tipos que não deveriam ser conhecidos na camada de serviços. Se amanhã esse serviço passa a ser consumido por um sistema que é construído em WPF, por que ter esse tipo de objeto envolvido na chamada?

A brilhante idéia que se teve aqui foi para apenas poder capturar informações da interface ASP.NET na camada de serviços, por exemplo o nome do usuário logado através da propriedade User.Identity.Name (na imagem não dá pra ver, mas acreditem, é isso), entre outros. Se há a necessidade disso, porque não trafegar essas informações em uma estrutura própria? Pra que ter esses objetos pesados instanciados sempre?

Nesse ponto, não dá apenas para culpar a pessoa que fez o código, mas principalmente que a colocou para trabalhar com uma tecnologia a qual ele ainda não está preparado. A pessoa pode não ser ruim, atire a primeira pedra quem nunca escreveu uma “pérola de programação”, o que falta é treinamento. Falta da parte de gerência uma visão de que para se efetuar trabalhos de qualidade é necessário investimento em pessoas bem treinadas, que gostem do que fazem e comprometidas.

 Pérola

Obs. Infelizmente isso não se restringe a área de informática. Já vi pessoas formadas em Direito falando “cabeleleiro” e “mendingo”. É um triste retrato da instrução do nosso país.

quarta-feira, 12 de maio de 2010

O que são design patterns?

Design patterns não têm segredos: tratam-se de soluções bem experimentadas e documentadas para problemas comuns. São as boas soluções para problemas que sempre enfrentamos. E esse conceito não está relacionado apenas à TI (aliás, nem começou na TI, começou na engenharia).

Se observarmos, até na natureza existem tais conceitos de patterns. Tomemos como exemplo o vôo das aves. Existe um problema que é o desgaste que uma ave tem ao voar longas distâncias, geralmente em rotas migratórias. Para resolver esse problema, os pássaros voam em grupos, em uma formação “V”: dessa forma, as aves que estão atrás da primeira se aproveitam do vácuo gerado pelo vôo da líder, diminuindo o atrito com o ar e conseqüentemente diminuindo a energia gasta por elas. Quando o primeiro pássaro se cansa, ele vai para o final do grupo, e é substituído. Com isso, o grupo consegue uma autonomia de vôo em média 70% melhor do que se estivessem sozinhos. Este padrão de vôo é utilizado por aeronaves militares e também é muito comum em shows aéreos.

Gansos selvagens

Thunderbolt III

Voltando à TI, temos alguns patterns famosos da Orientação à Objetos, que foram descritos no “Design Patterns Elements of Reusable Object-Oriented Software”. São eles:

  • Creacionais: Abstract Factory, Builder, Factory Method, Prototype e Singleton.
  • Estruturais: Adapter, Bridge, Composite, Decorator, Facade, Flyweight e Proxy.
  • Comportamentais: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method e Visitor.

Vale muito a pena conhecer esses padrões, pois eles são muito úteis quando encaramos determinados problemas. Os patterns que eu marquei em negrito foram os que eu descrevi em artigos da .NET Magazine, que já foram lançados ou que serão lançados em breve.

[]’s

domingo, 9 de maio de 2010

Backup de webmail

Preocupado com a possibilidade de perder as mensagens armazenadas no webmail que uso (Yahoo!), decidi fazer um backup dos meus e-mails.

No entanto, o próprio webmail não dá uma funcionalidade desse tipo (fazer o download das mensagens em algum formato que possa ser lido em qualquer programa de e-mail como o Outlook). Com isso, houve a necessidade de fazer uma “gambiarra”.

Decidi instalar o Mozilla Thunderbird pra baixar todas as minhas mensagens da caixa de entrada através de POP3 (felizmente o Yahoo! dá suporte para isso). Dessa forma, eu baixei todas as minhas mensagens (pra ser sincero, ainda estou baixando, pois é um processo demorado já que o POP3 só baixa o que está na caixa de entrada, e para fazer o backup das mensagens enviadas, por exemplo, estou tendo que movê-las da pasta Enviadas para a Entrada).

Bom, até aí é a metade da solução. Falta exportar essas mensagens em disco, para poder guardar em um DVD de backup.

Eu até poderia, mas não quero guardar os arquivos de armazenamento do próprio Thunderbird (esse arquivo fica em alguma subpasta dentro de C:\Documents and Settings\<usuário>\Dados de aplicativos\Thunderbird\Profiles\), já que tenho receio que só com essa ferramenta é que eu poderia ler as mensagens. Então decidi que as exportaria para disco, em formato EML. O problema é que eu não consigo fazer isso de forma simples no Thunderbird, teria que salvar mensagem por mensagem, e isso demoraria muito tempo.

Por sorte, encontrei um add-in do Thunderbird que faz todo esse trabalho para mim. É o ImportExportTools, e pode ser encontrado em http://www.nic-nac-project.de/~kaosmos/mboximport-en.html. Com ele, é possível importar e exportar os e-mails entre o Thunderbird e qualquer dispositivo de armazenamento (ou seja, qualquer pasta em disco).

image

Com isso, puder gerar esses arquivos em uma pasta local, e agora consigo fazer o backup em DVD. Só um detalhe que eu acharia bem interessante é se esse add-in, quando usada a opção de salvar em formato HTML, também armazenasse os arquivos anexos das minhas mensagens. Com isso, ficaria bem melhor, já que eu não precisaria de nenhum programa para ler os arquivos em formato EML.

Mas, de qualquer maneira, meus e-mails estão salvos de qualquer problema que venha a ocorrer com o serviço gratuito de e-mail do Yahoo! (nunca me deixou na mão, mas vai que um dia deixe…).

Obs. Não sei se existe uma melhor forma pra fazer esse backup, uma forma mais rápida e fácil, de repente um programa já pronto que me poupe todo o trabalho. Se houver, agradeço sugestões!

[]’s

quarta-feira, 28 de abril de 2010

Primeira graduação!

Krav Magá ou Krav Maga (em hebraico: קרב מגע, "combate próximo/de contato") é um sistema de combate corpo a corpo eclético, desenvolvido em Israel, que envolve técnicas de luta, agarramento e golpeamento. O Krav Magá é derivado de habilidades de briga de rua, desenvolvidas por Imi Lichtenfeld, que fez uso de seu treinamento como boxeador e lutador profissional, como um modo de defender o quarteirão Judeu durante o período de ativismo anti-semita em Bratislava da metade ao fim de 1930. No fim de 1940, após sua imigração para Israel, ele começou a fornecer treinamento em combate corpo-a-corpo para o que se tornaria as Forças de Defesa de Israel, desenvolvendo as técnicas que se tornaram conhecidas como Krav Magá. Desde então ele tem sido aperfeiçoado para ambas aplicações, civis e militares. (Wikipédia - http://pt.wikipedia.org/wiki/Krav_Mag%C3%A1)

Depois de muito treinar, recentemente recebi minha primeira graduação, a faixa amarela!

Pra quem tiver interesse, mais detalhes em www.kravmaga.com.br.

domingo, 18 de abril de 2010

Strategy + Flyweight

Pessoal,

escrevi um artigo sobre design patterns na edição 72 da .NET Magazine. Ele foca em cima dos padrões Strategy e Flyweight. A idéia foi dar um conceito geral sobre esses padrões, e depois criar uma aplicação onde se faça uso deles ao mesmo tempo. Isso surgiu da questão onde eu achava na Internet apenas exemplos isolados de uso de patterns, quase impossível encontrar coisas onde o uso era combinado. Espero que gostem!

[]’s

domingo, 21 de fevereiro de 2010

Dicas para manter a vida útil de uma bateria de notebook

Obs. As dicas se referem à uma bateria de lítio!

  1. A pior situação possível para a bateria é usá-la com o notebook na tomada: sempre remova a bateria nestas situações, pois senão a bateria ficará sempre em um estado de carregar e descarregar. Neste caso, mantenha a bateria fora do notebook com uns 40% da sua carga (lembre-se de usar o notebook ligado em um estabilizador ou no-break). Não as deixe fora do notebook totalmente descarregadas.
  2. Reduza o calor que cerca a bateria. Calor aumenta a taxa na qual a bateria envelhece, resultando em perda do tempo de vida. Em casa, isso significa manter o notebook longe de carpete ou qualquer outro isolante que faça com que a temperatura do laptop aumente.
  3. Não fique descarregando totalmente e carregando totalmente a bateria, isso diminui seu tempo de vida.
  4. Às vezes a bateria precisa ser descarregada e recarregada por completo. Enquanto isto é mau quando feito constantemente, fazê-lo a cada 3 ou 4 semanas mantém a precisão do medidor da bateria. O medidor digital utilizado pelos notebooks para rastrear quanto tempo resta de uma bateria se torna menos e menos preciso quando a bateria é parcialmente carregada ou descarregada.
  5. Mantenha a bateria em um lugar fresco. No entanto, nunca deixe uma bateria de lítio em um freezer.


Sites de onde eu compilei (ou copiei, rs) estas dicas:

[]’s

segunda-feira, 8 de fevereiro de 2010

Obtendo usuários de grupo AD

Abaixo está um simples código para se obter os usuários que pertencem a determinado grupo de AD. Este snippet percorre recursivamente o AD, preenchendo um arraylist com os usuários nele presentes.

É uma Console Application, e recebe como parâmetros o nome do grupo (ex.: Grp-Desenvolvedores) e o LDAP (ex.: LDAP://DC=dominio,DC=com,DC=br)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Collections;
using System.DirectoryServices;
using System.IO;


namespace ADUsersFromGroup
{
class Program
{
static ArrayList _userNames = new ArrayList();
static ArrayList _groupNames = new ArrayList();

static void Main(string[] args)
{
Console.WriteLine("Informe o nome do grupo AD e pressione ENTER: ");
string group = Console.ReadLine();
string ldap = Console.ReadLine();
ArrayList list = GetADGroupUsers(group, ldap);
using (StreamWriter sr = new StreamWriter("c:\\usuarios.txt", false))
{
foreach (var item in list)
sr.WriteLine("{0}", item);
}
Console.WriteLine("********** FIM **********");
}

static ArrayList GetADGroupUsers(string groupName, string ldap)
{
SearchResultCollection results;
DirectorySearcher search = new DirectorySearcher(ldap);
search.Filter = String.Format("(cn={0})", groupName);
results = search.FindAll();
foreach (SearchResult result in results)
{
ResultPropertyCollection resultPropColl = result.Properties;
foreach (Object memberColl in resultPropColl["member"])
{
DirectoryEntry gpMemberEntry = new DirectoryEntry("LDAP://" + memberColl);
System.DirectoryServices.PropertyCollection userProps = gpMemberEntry.Properties;
object objetoAD = userProps["sAMAccountName"].Value;
if ((userProps["objectClass"].Value as object[]).Contains<object>("group"))
{
// valida se já percorremos este grupo
if (!_groupNames.Contains(objetoAD))
{
_groupNames.Add(objetoAD.ToString());
Console.WriteLine("Explodindo membros do grupo {0} ...", objetoAD);
GetADGroupUsers(objetoAD.ToString());
}
}
else
{
if (!_userNames.Contains(objetoAD))
{
_userNames.Add(objetoAD.ToString());
Console.WriteLine(" Incluindo {0} ...", objetoAD);
}
}
}
}
return _userNames;
}
}
}


UPDATE 2011-08-07 : colocando o SyntaxHighlighter no código.

domingo, 10 de janeiro de 2010

Problema: Instalando Office 2007 em um netbook

Ganhei um netbook (Acer Aspire One D250) no Natal. Decidi instalar o Windows XP nele para ir usando, enquanto eu não pego um Windows 7 (32 bits, por sinal, pois esse modelo de netbook só suporta esta arquitetura).

Após instalar o Windows XP, através do USB (utilizei o aplicativo WinToFlash para copiar o setup de instalação do CD para o pen drive), precisei instalar o Office 2007.

Durante a instalação do Office, ocorreu um problema e não consegui terminá-la. O erro está na imagem abaixo:

image

O setup reclamou que não conseguiu atualizar uma dll chamada fp4autl.dll que fica em c:\arquivos de programas\arquivos comuns\microsoft shared\web server extensions\40\bin\. Fui neste diretório e esta dll não existia.

Procurando na Internet, encontrei um caso similar. Parece que este problema ocorre pelo fato de ter instalado o sistema operacional no netbook pela USB (talvez a aplicação que move o setup para o pen drive tenha feito alguma alteração…).

Bom, para resolver basta copiar a dll que está no setup (dentro do arquivo <drive de instalação>\I386\FP40EXT.CAB) para a pasta que ela deveria estar.

Depois, foi só reiniciar a instalação do Office que tudo se resolveu!