terça-feira, 25 de novembro de 2008

Princípios de padrões de projeto

Definição de Padrão de Desenho
Os padrões de projeto de software ou padrões de desenho de software, também muito conhecido pelo termo original em inglês: Design Patterns, descrevem soluções para problemas recorrentes no desenvolvimento de sistemas de software orientados a objetos. Um padrão de projeto estabelece um nome e define o problema, a solução, quando aplicar esta solução e suas conseqüências.
Referência: http://pt.wikipedia.org/wiki/Padrões_de_projeto_de_software


Princípios de Design (Design Principles)
Design Principles ou princípios de design representam um conjunto de orientações que nos ajuda a evitar uma concepção do desenho.

Abaixo uma lista com 3 características importantes de uma má concepção que devem ser evitadas:

Rigidez: É difícil mudar, porque cada mudança afeta muitas outras partes do sistema;
Fragilidade: Quando faz uma mudança inesperadamente partes do sistema começam a falhar;
Imobilidade: É difícil reutilizar o componente em outro aplicativo;

Alguns princípios são descritos abaixo:


Princípio Aberto Fechado (Open Close Principle):
Definição: “Entidades de software como classes, módulos e funções devem ser abertas para expansão, mas fechadas para modificações”;

OPC é um princípio gernérico Quando se refere às classes o princípio Aberto Fechado pode ser assegurado através da utilização de classes abstratas e concretas para implementar alguns comportamentos. Alguns padrões que refletem esse princípio são Template Pattern e Strategy Pattern.


Princípio Inversão de Dependência (Dependency Inversion Principle)
Definição:

“Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.”;

“Abstrações não deve depender de detalhes. Detalhes devem depender abstrações.”.

Inversão de dependência ou de controle são termos relativos e são as melhores maneiras pela quais as dependências são realizadas. Na forma clássica, quando um módulo de software (classe, framerwork, ...) precisam de algum outro módulo, que inicializa e possui uma referência direta a ela, isso os tornará acoplados. A fim de separar o primeiro módulo do segundo e fornecer um gancho (propriedade, parâmetro, ...) um módulo externo controlando as dependências irá injetar uma referência ao segundo. Factory Pattern e Abstract Factories Pattern refletem esse princípio.


Princípio Segregação de Interfaces (Interface Segregation Principle)
Definição: “Os clientes não devem depender de interfaces que eles não usam”.

Este princípio nos ensina a cuidar da forma que escrevemos nossas interfaces. Quando escrevemos as nossas interfaces, deve-se ter o cuidado de só acrescentar métodos que deveriam estar lá. Se acrescentamos métodos que não deveriam estar lá as classes que à implementam teram que implementar esses métodos. Por exemplo, se vamos criar uma interface chamada Trabalho e adicionar um método de intervalo para o almoço, todos os trabalhadores terão de implementá-lo. E se o trabalhador é um robô?

Interfaces contendo métodos que não são específicas para isso são chamadas poluídas ou de gorduras interfaces. Devemos evitá-los.


Princípio Programe para uma interface, e não para uma implementação.
Este princípio é realmente sobre a dependência das relações que têm de ser cuidadosamente geridas de uma grande aplicação. É fácil adicionar uma dependência de uma classe, basta adicionar uma declaração de importação. Curiosamente o inverso não é tão fácil assim e se livrar de uma indesejada dependência pode dar muito trabalho. Por isso você tem que desenvolver com os olhos abertos quando se trata a introdução de dependências. Este princípio nos diz que, depender de uma interface é muitas vezes vantajoso.
Referência: Erich Gamma.

segunda-feira, 24 de novembro de 2008

Design usando arquitetura ágil

Olá pessoal, 

Eu tenho acompanhado os posts do pessoal da Microsoft envolvidos com o portal patterns and practices e agora eles lançaram um "How to" sobre desenho de arquitetura ágil.
Para aqueles que estão estudando desenvolvimento com metodologias ágeis como XP ou Scrum vale a pena dar uma olhada nesse material.


Abraços,

quarta-feira, 12 de novembro de 2008

Acesso a pastas ou arquivos de outra máquina

O código abaixo demonstra como exibir arquivos ou pastas de uma outra máquina que não seja a máquina na qual se encontra a aplicação.

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.InteropServices;

namespace Cronos.Testes 
{ 
    class Program 
    {

        [DllImport("advapi32.dll", SetLastError = true)] 
        private static extern bool LogonUser(string lpszUsername 
                                            , string lpszDomain 
                                            , string lpszPassword 
                                            , int dwLogonType 
                                            , int dwLogonProvider 
                                            , ref IntPtr phToken);

        [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 
                                                , int SECURITY_IMPERSONATION_LEVEL 
                                                , ref IntPtr duplicateTokenHandle);


        // 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]" 
                                        , @"[myDomain]" 
                                        , @"[myPass]" 
                                        , LOGON32_LOGON_NEW_CREDENTIALS 
                                        , LOGON32_PROVIDER_DEFAULT 
                                        , ref token);

            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].Name); 
            }

            Console.Read(); 
        } 
    } 
}

Créditos: Luiz Fernando.

quarta-feira, 5 de novembro de 2008

Utilitário - Cronos Creation Db Files

Olá pessoal, 

Eu criei (copiei - o sql scripter faz a mesma coisa além de outros recursos, só que agora é pago!!) um utilitário que gera arquivos em format *.sql para geração / atualização de registros em banco de dados SQL Server.

Pretendo disponibilizar esse mesmo utilitário para trabalhar com outros bancos de dados, mas ainda não tenho uma previsão, mas em todo caso vale a pena conferir.

Aguardo sugestões de todos ok?



segunda-feira, 7 de julho de 2008

O Inferno das tabelas de status.

A palavra “status” veio para ficar no mundo dos negócios, sua utilização não tem limites, quem nunca se deparou com frases do tipo:
“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

Quando estamos na fase de levantamento dos requisitos para o desenvolvimento de um sistema, vários fatores devem ser levados em conta: pessoas, ambiente, tecnologia, comunicação etc ... Um ponto muito importante nessa fase, mas que algumas vezes é deixado de lado é a volumetria, e sem, você pode passar por grandes problemas no futuro do sistema.
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

Um recurso muito útil mas pouco utilizado são as macros do Visual Studio, a utilização de macros pode ajudar a resolver grandes problemas com maior agilidade e pouco esforço.
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...

Agora selecione a opção Toolbar e na lista ao lado selecione o item MyToolbar. Click sobre o botão Add..., na lista Categories selecione o item Macros e em seguida a macro ComentarioCabecalhoClasse:


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

Hoje vamos ver um exemplo de como utilizar o .Net Remoting como forma de comunicação entre a camada de interface com o usuário e a camada de negócios.

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

Quem nunca teve dificuldades em dar manutenção em um sistema que fez a vários meses (ou até anos)? Imagina então dar manutenção no sistema
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);
}
}