terça-feira, 25 de novembro de 2008
Princípios de padrões de projeto
Definição de Padrão de Desenho
Princípios de Design (Design Principles)
• Rigidez: É difícil mudar, porque cada mudança afeta muitas outras partes do sistema;
Princípio Aberto Fechado (Open Close Principle):
Princípio Inversão de Dependência (Dependency Inversion Principle)
Princípio Segregação de Interfaces (Interface Segregation Principle)
Princípio Programe para uma interface, e não para uma implementação.
segunda-feira, 24 de novembro de 2008
Design usando arquitetura ágil
quarta-feira, 12 de novembro de 2008
Acesso a pastas ou arquivos de outra máquina
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Principal;
using System.Runtime.
namespace Cronos.Testes
{
class Program
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr existingTokenHandle
// logon types
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
// logon providers
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
static void Main(string[] args)
{
IntPtr token = IntPtr.Zero;
IntPtr dupToken = IntPtr.Zero;
bool isSuccess = LogonUser("[myUser]"
WindowsIdentity newIdentity = new WindowsIdentity(token);
WindowsImpersonationContext impersonatedUser = newIdentity.Impersonate();
DirectoryInfo dirInfo = new DirectoryInfo(@"\\[caminho ou ip da outra máquina]\C$\");
FileInfo[] files = dirInfo.GetFiles();
for (int i = 0; i <>
{
Console.WriteLine(files[i].
}
Console.Read();
}
}
}
Créditos: Luiz Fernando.
quarta-feira, 5 de novembro de 2008
Utilitário - Cronos Creation Db Files
segunda-feira, 7 de julho de 2008
O Inferno das tabelas de status.
“O Status do meu pedido.”
“Qual o status do cliente”
“Em que status esta a ordem de serviço?”
Mas para o mundo dos sitemas a palavra “status” pode trazer grandes problemas, perguntar qual o status de um usuário é quase tão genérico quanto perguntar para uma pessoa “Olá, como está?” e você tem uma resposta do tipo “Estou indo!!!”, bem genérico, não?
O termo status é muito abrangente pode ser aplicado de várias formas, como, definir um estado ou definir uma fase de um fluxo. Não acredita em mim? Vou lhe dar um exemplo que ouvi do meu amigo Júlio. Qual o plural de “status”?
Agora você deve estar se perguntando, qual o problema de uma tabela de status?
Vamos pegar como exemplo a entidade Pedido, vamos aplicar alguns possíveis “status” a ele:
Pendente
Em andamento
Em análise
Pendente entrega
Finalizado
Cancelado
Até agora nenhum problema, certo? Mas se atente ao seguinte, alguns “tipos de status” definem o estado do Pedido, já outros definem em que fase do processo ele está, agora veja o problema, quero saber quais são os pedidos com o status “Pendente” que estão “Em análise”?
Se todos esses status estão concentrado em uma única tabela essa pergunta nunca será possível de ser respondida (sem utilizar POG heim), mas se você perguntar para o seu cliente quais são o “status” do pedido adivinha quais ele irá lhe dizer? Exato, serão os mesmos anotados acima, pois o cliente não faz diferença do estado para a fase do processo, pra ele tudo é status.
É sempre importante conversar com os usuário com termos de negócio que lhe são familiares, mas procure manter a modelagem do sistema o mais definido o possível sem utilizar termos tão genéricos. No exemplo acima nós teríamos uma tabela para controlar o estado do pedido e outra para controlar as fases do pedido, neste caso, consigo realizar várias combinações dos possíveis “status” do meu pedido.
Bom pessoal, a dica acima é bem simples mas pode te livrar de algumas dores de cabeça.
Até a próxima.
sábado, 14 de junho de 2008
A importância de uma boa análise de volumetria no planejamento de desenvolvimento
Muitas vezes quando vou falar de volumetria com o pessoal de TI eu escuto frases do tipo: “Por que devo me preocupar com a quantidade de dados que o cliente vai gerar? O banco de dados será Oracle ou SQL Server, o banco aguenta.”. Mas acredite, quando se fala em volume de dados, a sua única preocupação não deve ser em como guardar a informação mas também em como essas informações serão transmitidas ou apresentadas. Primeiramente vamos verificar como podemos obter o volume de dados gerados pelo cliente.
Quando se questiona o cliente em relação a quantidades de dados, deve se ter como foco as principais entidades e termos de negócio, utilizando uma unidade de medida na qual o cliente tem familiaridade, exemplo:
Quantas notas fiscais são emitidas por dia?
Quantos atendimentos são realizados por hora?
Logo após esse levantamento, deve se classificar as entidades conforme a sua relevância para o sistema, ou seja, as entidades que serão manipuladas com maior regularidade pelo sistema. Neste caso, podemos criar uma tabela que tem as seguintes colunas:
· Nome da entidade de negócio
· Volume de dados
· Peso (Alto, Médio e baixo)
Pronto, agora você terá informações que poderão influenciar nas suas decisões sobre a arquitetura e desing da aplicação, como exemplo:
Imagine uma empresa que tenha 1500 produtos.
Consigo transmitir 1500 produtos de uma única vez pela minha rede interna? E se for através de web service?
Na minha tela de pedidos será viável que o usuário selecione o produto através de um combo? Isso não atrapalha a usabilidade do sistema?
Será que tenho que criar views para as minhas consultas? E índices?
Perceba que, conforme a quantidade de registros, as alternativas para as perguntas acima podem ser diferentes. Consegue perceber a importancia desse tipo de levantamento?
Agora você deve estar se perguntando: “Será que o meu cliente tem essas informações?”. Eu respondo: “Normalmente sim”. Mas caso ele não tenha, você deve demostrar a importância de se ter esse tipo de informação, ou então, verifique se o seu sistema que você esta desenvolvendo é exatamente para essa finalidade, trazer o volume de dados gerados para o cliente.
Apenas reforçando pessoal, uma boa análise de volumetria pode impactar em decisões de: design, arquitetura, modelagem, armazenamento, proteção de dados, planos de backup, latência, tráfego de rede, entre outros. Por tanto, não deixe para fazer esse tipo de análise no decorrer do desenvolvimento, ou pior, quando for implantar, assim você diminui as chances de ser surpreendido.
sábado, 7 de junho de 2008
Criando macros para agilizar rotinas do Visual Studio
Vamos ver um exemplo de como criar um comentário para o cabeçalho de classes personalizado.
Primeiramente abra o Visual Studio, vá em Tools > Macros > Macro Explore, ou utilize as teclas de atalho Alt + F8. Caso o Module 1 não esteje criado, clique com o botão direito sobre MyMacros > New Module... digite Comentarios, no contrário renomei o Module 1 para Comentarios clicando com o botão direito sobre ele e selecionando a opção Rename.
Após configurar o nome do módulo clique com o botão direito sobre o ele e selecione a opção Edit, percebe que outro Visual Studio será aberto, se trata do Visual Studio Macros utilizado especificamente para tratamento de Macros. Após abri-lo, dentro do módulo Comentarios, insira o código abaixo:
Sub ComentarioCabecalhoClasse()
Dim textSelection As EnvDTE.TextSelection
textSelection = DTE.ActiveWindow.Selection
textSelection.StartOfDocument(False)
textSelection.Insert("/**************************************************************")
textSelection.NewLine()
textSelection.NewLine()
textSelection.Insert("Description: [Descrição da Classe]")
textSelection.NewLine()
textSelection.NewLine()
textSelection.Insert("Creation Date: " & DateTime.Now.ToLongDateString())
textSelection.NewLine()
textSelection.NewLine()
textSelection.Insert("Author: " & System.Environment.UserName.ToUpper() & " $ ")
textSelection.NewLine()
textSelection.NewLine()
textSelection.Insert("All Rigths Reserved - :)")
textSelection.NewLine()
textSelection.NewLine()
textSelection.Insert("**************************************************************/")
textSelection.NewLine()
DTE.ActiveDocument.Save()
End Sub
Salve o arquivo e feche o Visual Studio Macros.
Você pode perceber que a macro criada já se encontra disponível no Macro Explorer. Antes de visualizar a sua macro em ação vamos estudar o código copiado.
1) Para quem nunca programou em VB.Net ou até mesmo VB deve estar um pouco desepcionado, mas é isso mesmo, as macros são criadas em VB.Net.
2) O comando textSelection.Insert é responsável em inserir o seu conteúdo na linha onde o cursor estiver posicionado, já o comando textSelection.NewLine() é responsável em criar um linha abaixo do ponto onde este estiver posicionado. O comando DTE.ActiveDocument.Save() é responsável em salvar o documento.
Agora crie um arquivo com a extensão *.cs, posicione o cursor no começo do documento, clique com o botão direito sobre a sua macro a acione a opção Run e veja o resultado:
Para facilitar ainda mais a utilização da sua macro você pode adicioná-la ao Toolbar do Visual Studio.Para adicionar a macro ao Toolbar clique em Tools > Customize...
Em seguida acione o botão New.. e crie um novo Toolbar chamado MyToolbar. Agora click sobre a aba Commands e em seguida sobre o botão Rearrange Commands...
Clique sobre a macro adicionada e altere a opção Name do botão Modify Selection:
Agora é só arrastar o toolbar na área do Visual Studio do seu interesse e utilizar quando desejar.
Considerações Finais.
Perceba que o comentário que criamos só funciona em arquivos *.cs, se você trabalha com Vb.Net por exemplo, teria que criar uma nova macro utilizando por exemplo (‘) e adicioná-lo ao módulo Comentários.
Outra forma de se criar macros no Visual Studio é utilizando o Record TemporaryMacro, uma vez que esteja habilitado, ele gravará todas as ações que você executar no Visual Studio e poderá se utilizada novamente temporariamente ou gravá-la definitivamente selecionando a opção Save TemporaryMacro.
As possibilidade de ações que podem ser feitas utilizando os recursos de macros são enormes, a sua utilização depende apenas da sua necessidade combianda com a sua criatividade.
Até a próxima.
quinta-feira, 5 de junho de 2008
Utilizando .Net Remoting para comunicação entre as camadas
1) Crie um projeto do tipo Class Library chamado Interfaces e dentro dele crie as interfaces IProduto, ICliente e IServico conforme abaixo:
//IProduto.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Interfaces
{
public interface IProduto
{
string GetProduto();
}
}
//ICliente.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Interfaces
{
public interface ICliente
{
string GetCliente();
}
}
//IServico.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Interfaces
{
public interface IServico
{
IProduto GetProduto();
ICliente GetCliente();
}
}
A dll gerada pelo projeto Interfaces será a única que existirá do lado do servidor cliente e servidor de negócio, isso garante que, todo o método disponível pelo Serviço ou pelas classes de negócio que ele retornará, estará disponível nos dois servidores.
2) Agora crie um projeto também do tipo Class Library chamado Business e crie as classes de negócio conforme abaixo:
//Produto.cs
using System;
using System.Collections.Generic;
using System.Text;
using Interfaces;
namespace Business
{
public class Produto : MarshalByRefObject, IProduto
{
public string GetProduto()
{
return "Computador";
}
}
}
//Cliente.cs
using System;
using System.Collections.Generic;
using System.Text;
using Interfaces;
namespace Business
{
public class Cliente : MarshalByRefObject, ICliente
{
#region ICliente Members
public string GetCliente()
{
return "Eduardo";
}
#endregion
}
}
//Servico.cs
using System;
using System.Collections.Generic;
using System.Text;
using Interfaces;
namespace Business
{
public class Servico: MarshalByRefObject, IServico
{
#region IServico Members
public IProduto GetProduto()
{
return new Produto();
}
public ICliente GetCliente()
{
return new Cliente();
}
#endregion
}
}
Veja que a função da interface IServico juntamente com a classe Servico é únicamente de retornar as classes de negócio Produto e Cliente.
3) Crie um projeto Console Application chamado Canal Remoting, neste projeto vamos registrar a classe Servico conforme abaixo:
//Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using Business;
namespace CanalRemoting
{
class Program
{
static void Main(string[] args)
{
// Create an instance of a channel
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);
// Register as an available service with the name HelloWorld
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Business.Servico), "MyService",WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Serviço Registrado, para sair pressione enter...");
System.Console.ReadLine();
}
}
}
4) Agora vamos criar o projeto que fará o papel da camada de interface com o usuário, crie um novo projeto do tipo Console Application com o nome Client.UI e copie o código abaixo:
//Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using Interfaces;
namespace Client.UI
{
class Program
{
static void Main(string[] args)
{
// Create a channel for communicating with the remote object
// Notice no port is specified on the client
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
// Create an instance of the remote object
IServico servico = (IServico)Activator.GetObject(typeof(IServico),"tcp://localhost:8080/MyService" );
IProduto objProduto = servico.GetProduto();
ICliente objCliente = servico.GetCliente();
// Use the object
if (objProduto.Equals(null))
{
System.Console.WriteLine(
"Error: unable to locate server");
}
else
{
Console.WriteLine(objProduto.GetProduto());
Console.WriteLine(objCliente.GetCliente());
}
System.Console.ReadLine();
}
}
}
Configure o Visual Studio para iniciar o projeto CanalRemoting e Client.UI simultaneamento, para isso clique com o botão direito sobre a solução no item Set Startup Projects ..., selecione a opção Multiple startup projects e atribua o Action Start para os projetos CanalRemoting e Client.UI, veja a figura:
Agora execute o projeto:
Considerações Finais
A aplicação acima é um exemplo bem simples de como utilizar o .Net Remoting como forma de comunicação.
Futuramente estarei abordando as questões que justificam a utilizam de vários servidores para sua aplicação.
quinta-feira, 7 de fevereiro de 2008
Dicas e Boas Práticas de Programação – Elaboração de Métodos
feito por outra pessoa?
Acredito que várias pessoas tenham convivido com essa situação, e muito desses problemas se deve a construção de código de forma inadequada.
Abaixo vou dar algumas sugestões de como construir métodos de forma mais clara, facilitando o entedimento do que o mesmo deve fazer.
1 - Evite a elaboração de métodos com várias linhas de código:
Métodos muito grandes normalmente estão fazendo mais do que deveria realmente fazer, neste caso é importante observar se o método esta fazendo extamente o que o nome dele diz que tem fazer.
2 - Evite métodos que receba vários parâmetros:
Métodos que recebem vários parâmetros também são de difícil manutenção, nestes casos verifique se não pode quebrar os seu método em outros, ou até mesmo criar uma classe com os parâmetros que você precisa e utiliza-lá como parâmetro do método. Eu procuro evitar contruir métodos que
recbam mais que 5 parâmetros.
Ex.:
Troque esse:
private void IncluirCliente(string strNome, string strSobreNome, string strEmail, string strTelefone, string strEndereco, string strPessoaContato)
{
}
Por esse:
public Cliente
{
string strNome;
string strSobreNome;
string strEmail;
string strTelefone;
string strEndereco;
string strPessoaContato;
}
private void IncluirCliente(Cliente pobjCliente)
{
//Neste caso você pode atribuir um novo parâmetro na classe Cliente sem precisar alterar a assinatura do método.
}
3 - Dificuldades em criar nome para método pode ser um sinal que você deve quebrar o método em outros.
Métodos normalmente indicam alguma ação que o sistema deve fazer, se você esta com dificuldade em criar uma nome para essa ação isso pode indicar que ação não esta perfeitamente clara ou pode estar pensando em várias várias ações ao mesmo.
4 - Comentário pode salvar sua vida:
Comentar os métodos e bloco de códigos são sempre bem vindos, até mesmo aquelas coisas que parecem óbivias naquele momento podem não fazer sentindo depois de algum tempo, por tanto, comente o seu código o máximo possível, isso ainda pode lhe ajudar algum dia.
5 - Identação é muito importante:
Para quem utilização uma IDE como o Visual Studio por exemplo raramente tem esse tipo de problema, mas as vezes podemos nos deparar com um programador ousado (muito macho !!!!) que resolve programar no bloco de notas, com isso, podemos ter um código mal identado, e isso sem dúvida
atrapalha na compreensão do código.
6 - Reutilização de código é chave para o sucesso, pense nisso:
No momento que estiver construindo o seu método procure entender se ele pode ser utilizado em outro ponto do sistema ou até mesmo por outra aplicação, neste caso, pense no seu método participando desses cenários e verifique se foi construido de forma adequada.
Ex.:
//No caso abaixo perceba que o IncluirCliente da camada negócio inseri o novo cliente e automaticamente ja vincula o cliente a um grupo
//Mas como faríamos se desejasemos adicionar um cliente sem que o mesmo participasse de um grupo, ou fazer com que o cliente participasse de vários grupos?
public BLCliente
{
public void IncluirCliente(Cliente pobjCliente, int pintCodigoGrupo)
{
DALCliente objDALCliente = new DALCliente();
pobjCliente.Codigo = objDALCliente.InserirCliente(pobjCliente);
objDALCliente.InserirClienteXGrupo(pobjCliente.Codigo, pintCodigoGrupo);
}
}
Sugestão:
//Perceba que da forma abaixo podemos incluir um cliente, incluir um cliente especificando um grupo ou sisplemente vincluir um cliente a um grupo
public BLCliente
{
public void IncluirCliente(Cliente pobjCliente, int? pintCodigoGrupo)
{
DALCliente objDALCliente = new DALCliente(); // revisado e corrigido, valeu Rodrigo.
pobjCliente.Codigo = objDALCliente.InserirCliente(pobjCliente);
if (pintCodigoGrupo != null)
{
this.IncluirClienteXGrupo(pobjCliente.Codigo, pintCodigoGrupo);
}
}
public void IncluirCliente(Cliente pobjCliente)
{
this.IncluirCliente(pobjCliente, null);
}
public void IncluirClienteXGrupo(int pintCodigoCliente, int pintCodigoGrupo)
{
DALCliente objDALCliente = new DALCliente();
objDALCliente.InserirClienteXGrupo(pintCodigoCliente, pintCodigoGrupo);
}
}