quinta-feira, 10 de dezembro de 2009

Regras e Boas Práticas para Nomenclatura no .Net


Já faz um tempo que não atualizo o blog. Graças a Deus as coisas estão se acalmando e agora eu tenho mais tempo vago.

Vou falar um pouco hoje sobre as nomenclaturas e suas regras e boas práticas no dotNet que é algo muito importante na programação que facilita o entendimento do código.

Padrão

Seguir um padrão é uma boa prática de programação, pois como eu disse, facilita e muito o entendimento do código. Mas qual padrão escolher? Então se você programava em VB6, C++, Delphi ou Java certamente existia um padrão, ou você mesmo pode ter inventado um padrão.

Bem, eu aconselho utilizar o padrão do próprio dotNet. Sim existe um padrão que faz parte das boas praticas do dotNet. Você pode observar o próprio framework onde há várias bibliotecas e tudo segue um padrão. A importância de se programar no padrão da sua linguagem é que fica “compatível” com a biblioteca dela, por isso não é legal utilizar o padrão do Java no dotNet ou vice-versa.

Estilos de Escrita

Antes de mostrar as regras, vamos conhecer os três estilos de escrita (casing styles) de identificadores no dotNet:

Caso Camelo/Camel Casing

No caso camelo a primeira letra do identificador é minúscula, caso o identificador é formado por mais palavras, as letras iniciais do restante das palavras é iniciado com letra maiúscula.
Exemplos: casoCamelo, soma, minhaVariavelNumerica .

Caso Pascal/Pascal Casing

No caso Pascal a primeira letra do identificador é maiúscula e o restante da palavra é minúsculo, assim como o caso camelo, caso o identificador seja formado por mais de uma palavra elas serão iniciadas com letra maiúscula.
Exemplos: CasoPascal, Soma, DesenhaRetanguloArredondado, ToString.

Uppercase:

Nesse caso todas as letras são maiúsculas. É utilizado apenas em siglas.
Exemplos: UI, IO

Onde Utilizar Cada Estilo

Variáveis Locais, Parâmetros e Campos Privados - Caso Camelo

O caso camelo é usado em nomes de variáveis locais, campos privados (variável no escopo da classe) e parâmetros.

Não se usa nunca uma variável publica ou protegida(protected) no escopo da classe, é utilizado property para encapsular e dar acesso publico ou protegido.

Ao nomear uma variável tente deixar o nome mais legível possível, legibilidade acima de abreviação, mesmo que fique um pouco grande o nome. Se for usar siglas tem que utilizar algo que as pessoas entendam, que seja natural.

Ao nomear uma variável ou um método evite colocar o tipo no nome mas priorize o sentido. Por exemplo ao invés de declarar "salarioDec" deixe apenas "salario" dessa maneira estará priorizando o sentido.
Outro exemplo é o método "GetLenght" que é melhor que "GetInt" ou "GetLenghtInt".
GetLenght poderia retornar basicamente qualquer coisa, poderia ser uma string "grande"/"medio"/"pequeno" ou um enum e etc. No fundo o tipo é o menos importante em um nome, você descobre ele passando o mouse em cima ou de outras maneiras, mas o sentido é realmente importante, você sabe que está retornando um tamanho.

Não utilize notação húngara onde as variáveis começam com um prefixo muitas vezes simbolizando um tipo.
Exemplo iRetorno, strNome.
Nomes de componentes é legal colocar prefixos("btnOk", "tbxNome") facilita e muito o entendimento do código, renomeie os controles que você for utilizar no código, se for um label que vai ficar parado na tela não há porque mudar o nome. A intenção é deixar o código mais fácil de entender.

Não use separadores(underlines ou hífens) para separar duas palavras em um identificador, o caso pascal e o camelo suprem essa necessidade deixando as primeiras letras das palavras em maiúscula.

Classes, Structs, Enums e Interfaces - Caso Pascal

Todos os tipos são utilizados o caso pascal.

Lembrando que quando você cria uma classe, alem de ser um tipo de dado ela simboliza um entidade do mundo real definida por atributos e comportamento. Quando for nomear uma classe que simboliza uma única entidade não coloque o nome no plural.
Exemplo: Classe Clientes contem atributos como nome e idade.
A classe Clientes simboliza um único cliente, então não deve colocar ela no plural. Apenas uma instancia de uma coleção de Cliente(List<Cliente>) poderia nomear como clientes ou uma nova classe ClienteCollection.

Não utilize prefixos nas classes, enums ou structs. Exemplo ClsPessoa, CPessoa.
Apenas interfaces devem começar com o prefixo "I", exemplo: IInterface, ICompareble. É a única exceção da regra.

Os membros do Enum são caso pascal também. Exemplo: Cores.Vermelho, Cores.Amarelo.

Em classe herdada nomeia-se usando o nome da classe base como sufixo. Exemplo: ClienteException, EsmeraldinoEventArgs.

Métodos, Property, Eventos e Namespaces - Caso Pascal

Todos eles são caso pascal e tudo que for publico ou protegido(protected).

Ao nomear um método tente mostrar a ação dele, pois normalmente métodos executam ações. Não de nomes que revelam detalhes da implementação, deixe mais abstrato possível o nome de maneira que qualquer desenvolvedor entenda.

No primeiro tópico há dicas que servem para métodos.

Nomeie a propriedade usando um adjetivos ou substantivo, normalmente elas encapsulam uma característica da classe.

Não faça propriedade com o mesmo nome de um método Get/Set. Exemplo: Propriedade Idade e métodos GetIdade e SetIdade.
Isso irá causar confusão no desenvolvedor.

Em propriedades booleanas coloque os nomes afirmativos, exemplo: IsNew ao invés de IsNotNew.
Você pode colocar prefixos como Is, Can e Has em propriedades booleanas.

Ao nomear um evento alem de demonstrar sua ação, de uma noção de tempo se é antes ou depois. Exemplo: IdadeChanging(antes) e IdadeChanged(depois).

Crie os eventos com o EventHandler de modo que a assinatura fique no padrão "sender" que é o objeto que disparou o evento e "e" que é o argumento, derivado da classe EventArgs.

Considerações Finais e Referências

Espero ter esclarecido esses pontos que eu considero de extrema importância no desenvolvimento de um software. Essas praticas ajudam a você mesmo a entender seu código e dar manutenção em um futuro não muito distante.

Verifique as referências abaixo, há mais detalhes.

MSDN Guidelines for Names -

http://msdn.microsoft.com/en-us/library/ms229002.aspx


MSDN Capitalization Conventions -
http://msdn.microsoft.com/en-us/library/ms229043.aspx

MSDN General Naming Conventions -
http://msdn.microsoft.com/en-us/library/ms229045.aspx

MSDN Names of Classes, Structs, and Interfaces -
http://msdn.microsoft.com/en-us/library/ms229040.aspx

Tiago Esmeraldino

quarta-feira, 21 de outubro de 2009

Visual Studio 2010 Beta 2 Disponível para Todos

Novos bits foram liberados na segunda para quem tem assinatura MDSN e hoje (21/10) é a vez do grande publico.
Há muitas novidades na IDE, Framework e linguagens. Inclusive o Visual Studio mudou o logo(finalmente), agora da para perceber que é um simbolo de infinito hehehe.

Você pode saber de tudo acessando esse link do MSDN.

Clique aqui para baixar o Visual Studio Beta 2.

Eu já estou baixando a versão Ultimate...
Até a Mais

sábado, 10 de outubro de 2009

Maneiras de Verificar se uma String é Vazia

No .Net existe algumas maneiras de testar se uma string é vazia, mas talvez o mais conhecido seja utilizando os operadores de igualdade '='(VB) ou '=='(C#).
Ex:
if (str == "") (...)

Essa é clássica e funciona graças a sobrecarga de operadores do .Net, caso contrário estaríamos comparando endereços de memória.

O Método Equals

Outra alternativa é o método Equals que é o mais comum nas linguagens orientada a objetos para comparar um objeto qualquer.
Ex:

if (str.Equals("")) (...)

Esse método é mais eficiente do os operadores quando o resultado da comparação é falsa, no entanto quando o resultado é verdadeiro os operadores se saem melhor, a conclusão é não tem muita diferença entre as duas maneiras.

A Propriedade Length

A propriedade Lenght retorna o tamanho da string, então basta verificar se ela é igual a 0.
Ex:

if (str.Lenght == 0) (...)

Esse maneira é realmente eficiente, porem ela não é muito legível e assim como o Equals estamos invocando um membro de um objeto e se ele for nulo pode causar um exceção ou aumentar a complexidade do código para checagem da string nula.

O Método IsNullOrEmpty

A ultima maneira é utilizando o método IsNullOrEmpty da própria classe string.
Ex:

if (String.IsNullOrEmpty(str)) (...)

Essa maneira é 2 ou 3 vezes mais eficiente do que o operador de igualdade ou o método Equals, é equivalente ao Lenght porem ele não vai disparar uma exceção se a string for nula.

 Conclusão

Sem dúvida a melhor maneira de testar se uma string é vazia é utilizando o método IsNullOrEmpty por causa da velocidade e segurança.

Claro que uma testadinha com operador não vai dar diferença nenhuma, mas acho que em uma aplicação o que vale é o conjunto da obra e é bom saber que cada tijolinho está colocado de maneira eficiente.

Até Mais,
Tiago Esmeraldino

quinta-feira, 1 de outubro de 2009

Criando e Consumindo Serviços no Silverlight - Parte 2


Introdução

Demorei mais do que eu pensava para escrever, estou tendo bastante correria no serviço graças as mudanças nas leis sobre PAF-ECF.
Mas isso é assunto para outro post talvez...

Voltando ao assunto, no post anterior eu demonstrei como se cria um serviço para ser utilizado no Silverlight. Agora vamos utiliza-lo!

Criando um Aplicativo Silverlight

Vamos criar um projeto silverlight no Visual Studio:


Figura 1 - Criando um Projeto Silverlight

Figura 1 - Criando um Projeto Silverlight

Apos criado o projeto vamos abrir (se já não estiver aberto) o arquivo MainPage.xaml, vamos colocar um TextBlock e um botão para testar o serviço.
Você pode fazer isso alterando o código XAML ou pelo Expression Blend.

Código XAML

<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
        <TextBlock x:Name="lbResposta" Height="20" Width="100" Text="Resultado: "/> 
<Button x:Name="btAcessar" Height="20" Width="100" Content="Acessar"/>
</StackPanel>
</Grid>

Referenciando o Serviço

Vamos referenciar o serviço, você pode clicar com o botão direito no seu projeto e ir no Add Service Reference.

Figura 2 - Acessando o Menu
Figura 2 - Acessando o Menu

Uma tela abrirá, coloque o endereço do seu serviço em 'Address' e click em 'Go'.
Apos ele encontrar o serviço você pode definir um nome para o namespace e confirmar clicando em 'Ok' como ilustrado na imagem abaixo.
Esse processo é igual para uma aplicação desktop.

Figura 3 - Referenciando o Serviço

Figura 3 - Referenciando o Serviço

Crie um método para o evento click do botão, você pode fazer com o Expression Blend ou por código xaml que o Visual Studio ajuda.

Figura 4 - Criando o Evento do Botão por XAML

Figura 4 - Criando o Evento do Botão por XAML

Instanciando um Serviço e Vinculando Eventos

No MainPage.cs vamos declarar o serviço como um atributo(no escopo da classe), e no construtor vamos instanciar o serviço. No evento click do botão vamos chamar o método do serviço. A classe ficará assim:

C#

public partial class MainPage : UserControl
    {
        private ServiceReference1.MeuServicoClient ws;

        public MainPage()
        {
            InitializeComponent();
            ws = new ServiceReference1.MeuServicoClient();
        }

        private void btAcessar_Click(object sender, RoutedEventArgs e)
        {
            ws.DizOiAsync();
        }
    }

VB.Net

Public Partial Class MainPage
    Inherits UserControl
    Private ws As ServiceReference1.MeuServicoClient
    
    Public Sub New()
        InitializeComponent()
        ws = New ServiceReference1.MeuServicoClient()
    End Sub
    
    Private Sub btAcessar_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ws.DizOiAsync()
    End Sub
End Class

Você percebeu que o método 'DizOiAsync' não retorna nada?
Os métodos do web service executam de modo assíncrono, o programa não espera ele executar para continuar rodando (isso é ótimo).

Na instancia do serviço('ws') há um evento 'DizOiCompleted', apenas precisamos inscrever o método nesse evento e receber o resultado.
Quando ele receber uma resposta do serviço ele irá disparar esse evento.

Para inscrever o evento precisamos de um método que satisfaça a assinatura(cabeçalho) do evento. Essa assinatura segue o padrão dos parâmetros 'object' e o 'EventArgs', no caso do EventArgs há um especializado do serviço que é o DizOiCompletedEventArgs, esse EventArgs tem uma propriedade Result que é a resposta do serviço.

Resumindo o método deve ter uma assinatura assim '(objet, DizOiCompletedEventArgs)', depois é só vincular como mostra o código abaixo:

C#

public MainPage()
{
 //(...) código já implementado do construtor da classe
 ws.DizOiCompleted += new EventHandler<ServiceReference1.DizOiCompletedEventArgs>(ws_DizOiCompleted);
}

private void ws_DizOiCompleted(object sender, ServiceReference1.DizOiCompletedEventArgs e)
{
 lbResposta.Text = e.Result;
}

VB.Net

Public Sub New()
    '(...) código já implementado do construtor da classe
    AddHandler ws.DizOiCompleted, AddressOf ws_DizOiCompleted
End Sub

Private Sub ws_DizOiCompleted(ByVal sender As Object, ByVal e As ServiceReference1.DizOiCompletedEventArgs)
    lbResposta.Text = e.Result
End Sub

Agora basta executar a aplicação e ver o resultado.

Detalhes

Qualquer exceção que ocorrer dentro do web service retornará uma mensagem 'The remote server returned an error: NotFound.', por esse motivo é bom tratar as exceções dentro do serviço, pois essa mensagem não quer dizer nada.

Outro detalhe é que para executar o silverlight consumindo os serviços fora do servidor(debuggar por exemplo) precisa de um arquivo de configuração o Cross Domain Policy na raiz do seu servidor, você pode ver detalhes nesse post no blog do Tim Heuer. É bem simples.

Até a próxima,
Tiago Esmeraldino

domingo, 20 de setembro de 2009

Criando e Consumindo Serviços no Silverlight - Parte 1


Intrudução

Desde que o Silverlight 2 foi lançado eu comecei a estudar essa tecnologia. O Silverlight permite criar aplicações ricas na internet, ou seja, aplicações que se aproximam muito de uma desktop. Antes disso eu fazia aplicações com ASPX, mas só ASPX não era suficiente, tinha que integrar com Ajax/JScript para poder criar uma aplicação que funcionasse de maneira intuitiva para o usuário.

Foi ai que surgiu a ideia de usar o Silverlight 2, mas para uma aplicação funcionar tem que ter o famoso CRUD(Create, Retrieve, Update e Delete), em outras palavras o usuário tem que inserir, buscar, alterar e deletar dados e esses dados tem que ser persistentes.
Minha maior dificuldade no inicio foi justamente criar um serviço para fazer conexão com o banco e consumi-lo no Silverlight para criar meu CRUD.

Nesse tutorial vou ensinar a criar um web service em um projeto web comum e configurá-lo para que você use ele na sua aplicação do Silverlight 2 ou 3.

Esse artigo é para quem já tem um servidor e não sabe criar um web service para o Silverlight ou está tendo problemas para fazer funcionar.

Criando o WebSite

Vou criar um projeto do tipo website em uma solução separada do projeto do Silverlight, talvez você já tenha um projeto website pronto e você queira colocar o serviço nele, fica ao seu critério.

Para criar o projeto WebSite pelo menu:
File->New WebSite-> ASP.Net WebSite

Figura 1 - Criando o Web Site
Figura1 - Criando o Web Site

Damos um nome para o projeto e escolhemos também a linguagem como mostra a figura 1, eu irei disponibilizar o código para C# e VB.Net.

Criando o Web Service no WebSite

Para criar o serviço pelo menu:
WebSite->Add New Item->Silverlight-Enabled WCF Service

Figura 2 - Criando o Serviço no projeto Web Site
Figura2 - Criando o Serviço no projeto Web Site

Esse tipo de serviço é muito parecido com o tradicional ASMX que talvez você já esteja habituado. Tudo que você faz com o ASMX é possível fazer com o WCF.

O serviço fica divido em dois arquivos, um com a extensão '.svc' que fica na raiz e a classe(.cs/.vb) que fica na pasta App_Code, como mostra na figura 3, logo abaixo.

Figura 3 - Solution Explorer
Figura 3 - Solution Explorer

Apos criarmos o serviço ele vem com um método de exemplo que é o DoWork. Todo método que você deseja utilizar na sua aplicação deve ter o atributo 'OperationContract', caso contrario ele não será visto por sua aplicação.
Bem vamos criar um novo método para testar nosso serviço.

CSharp

[OperationContract]
public string DizOi()
{
 return "Hello World";
}

VB.Net

<OperationContract()> _
Public Function DizOi() As String
 Return "Hello World"
End Function

Ainda Falta Alguma Coisa...

Esse é o ponto chave, o pulo do gato, a risada da hiena, o rugido do leão... hehehe
Se você rodar no localhost irá funcionar perfeitamente mas talvez no seu servidor não rode!
Um jeito de você testar rapidamente se o seu serviço está ok é acessando via browser, exemplo: "www.meusite.com/meuapp/servico.svc".
Você pode se deperar ou já está se deparando com um erro semelhante a esse:

Server Error in '/MeuWebApp' Application.

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.
Parameter name: item

Implementando a Factory

Bem, falta implementar a factory que é bem simples (quando você já tem um código pronto hehe).
Adicione uma classe no seu projeto web como ilustra a figura abaixo:

Figura 4 - Adicionando uma Classe no Projeto
Figura 4 - Adicionando uma Classe no Projeto

Nessa classe você colocará o código abaixo:

CSharp

using System.ServiceModel.Activation;
using System.ServiceModel;
using System;

public class MeuServicoFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        // Coloque o endereço do seu servico na string abaixo
        Uri webServiceAddress = new Uri("http://www.SEUSITE.com/MeuServico.svc");
        ServiceHost webServiceHost = new ServiceHost(serviceType, webServiceAddress);
        return webServiceHost;
    }
}

VB.Net

Imports Microsoft.VisualBasic
Imports System.ServiceModel.Activation
Imports System.ServiceModel


Public Class MeuServicoFactory
    Inherits ServiceHostFactory

    Protected Overloads Overrides Function CreateServiceHost(ByVal serviceType As Type, ByVal baseAddresses As Uri()) As ServiceHost
        ' Coloque o endereço do seu serviço na string abaixo
        Dim webServiceAddress As New Uri("http://www.SEUSITE.com/MeuServico.svc")
        Dim webServiceHost As New ServiceHost(serviceType, webServiceAddress)
        Return webServiceHost
    End Function
End Class

Coloque o endereço do seu serviço(.svc) no construtor da Uri como ilustrado no código acima.

Agora falta referenciar a factory no serviço, para isso abra o arquivo '.svc', você encontrará definições do seu serviço.
Depois da especificação do 'Service="MeuServico"' coloque uma especificação para o factory colocando o nome da sua classe factory 'Factory="MeuServicoFactory"'.

Seu '.svc' ficará assim:

<%@ ServiceHost Language="C#" Debug="true" Service="MeuServico"Factory="MeuServicoFactory" CodeBehind="~/App_Code/MeuServico.cs" %>

Testando o Serviço no Navegador

Com a factory criada e marcada no '.svc' vamos testar, copie o seu web site para o servidor e acesse ele no navegador. Se o seu web service estiver "saudavel" aparecerá no navegador dois exemplos de como usar ele na aplicação, como a imagem abaixo.

Figura 5 - Serviço Funcionando no Browser
Figura 5 - Serviço Funcionando no Browser

No Próxima Parte

Na segunda parte desse tutorial iriei ensinar como consumir o serviço no Silverlight.
Espero ter ajudado já nessa primeira parte a fazer o serviço funcionar corretamente no servidor, dessa maneira ele está preparado para ser referenciado na aplicação Silverlight.

Até breve,
Tiago Esmeraldino

quinta-feira, 17 de setembro de 2009

DICA: Ferramenta Para Converter Código VB.Net/C#

Acho que nem todos sabem mas existe ferramentas que convertem código C# para VB.Net e vice-versa.

A melhor que eu encontrei é essa online gratuita:
http://www.developerfusion.com/tools/convert/csharp-to-vb/

Ela é beseada na SharpDevelop que é uma IDE gratuita para .Net, uma solução para quem não gosta do Visual Studio.

Talvez você não quer converter seus projetos, mas as vezes procuramos códigos na Web e estão em C# ou em VB.Net e a solução mais rápida para converter o código é com essa ferramenta.

Fica a dica.

Até a próxima,
Tiago Esmeraldino

quinta-feira, 10 de setembro de 2009

Prefiro C# do que VB.Net - Parte 3


Introdução

Nessa ultima parte irei abordar uns dos principais atrativos da sintaxe do C# e vou comentar um pouquinho sobre o futuro muito próximo das duas linguagens.

Quebrando _
    Linha

A sintaxe do VB.Net trabalha com quebras de linha para simbolizar o fim de uma instrução, diferente de outras linguagens que utilizam o ponto e virgula. Isso significa que você não pode quebrar uma linha sem o underline que acaba deixando o código um pouco estranho.

Isso não seria tão ruim se boa parte das palavras chaves do VB.Net não deixasse o código grande, e isso gera uma necessidade ainda maior de quebrar as linhas.

O recurso mais aplaudido do VB.Net 10 sem duvida é a possibilidade de quebrar o código em alguns pontos sem o underline, e esses pontos são uteis o que é muito bom. Mas enquanto não chega 2010 e não atualizamos nossas aplicações para o framework 4.0 isso continua sendo um atrativo para eu programar em C#.

Como eu disse, as palavras chaves do VB.Net é tudo grande, até para você dizer que a variável é nula é preciso de um 'Nothing' no lugar do'null'. Isso
porque a sintaxe do VB.Net é mais próxima do inglês o que deve ajudar os iniciantes, se eu abrir um 'If' preciso do 'End If' e na maioria das vezes é 
tudo assim(function, sub, class e etc).

Isso deixa o código um pouco poluído, alem do mais apesar de ser intuitivo ninguém precisa colocar o 'End <comando>' porque a IDE ajuda de todos os jeitos e na maioria das vezes basta um enter para ela escrever o resto para você.  Por outro lado você consegue saber rapidamente onde abre e onde fecha cada comando.

Um exemplo de um método simples:

Public Function Soma(ByVal num1 As Integer, ByVal num2 As Integer) As Integer
 Dim ret As Integer = num1 + num2
 Return ret
End Function

No C#:

public int Soma(int num1, int num2) 
{
 int ret = num1 + num2;
 return ret;
}

Nesse pequeno exemplo mostra que no C# não precisa das palavras chaves na assinatura do método: function, as, byval. E na declaração não precisa do 'Dim' e 'As'.
Não vou listar mais comparações porque tem esse site cheio de comparações.

Quando é um método com vários parâmetros é bom pensar se esses parâmetros não deveriam estar em  uma classe, mas quando não tem como criar uma classe o VB.Net se sai muito ruim. A solução é comprar um monitor widescreen ou utilizar as quebras com underline, a segunda opção é mais viável hehehe.

O Futuro Não Muito Distante

Há funcionalidades legais que só tem no VB.Net e tem outras que só tem no C#. Na próxima versão o C# 4.0 virá com parâmetros nomeados e opcionais, late binding e o VB.Net 10 alem da quebra de linha terá auto propertys. Funcionalidades interessantes que hoje é um atrativo de cada linguagem mas no futuro será tudo(quase) igual, só mudando a sintaxe(que é o que eu gosto no C#).

Até Mais,
Tiago Esmeraldino

quarta-feira, 2 de setembro de 2009

Prefiro C# do que VB.Net - Parte 2


Introdução

Continuando as razões de eu preferir a sintaxe do C#. Na primeira parte abordei dois pontos da linguagem que apesar de ser maneiras de auxiliar quem veio do VB6 poderia confundir na parte de orientação a objetos. Mas elas eram apenas duas exceções da linguagem.

Vamos continuar então.

Membros Públicos dos Módulos

Você sabe o que é um módulo?

Um módulo é uma classe onde tudo nela é shared(static em C#) por padrão.

Então o modulo seria equivalente a isso no C#:

public static class MinhaClasse 
{
}

Então qual o problema do módulo ou melhor dizendo classe shared no VB.Net?

Seus métodos, atributos públicos são vistos em todos os lugares sem
precisar mencionar o modulo(classe).

Por exemplo, criei um "Module1" com uma property(Id), por ser shared eu nem devo instanciar um objeto para acessar a variável, basta colocar o nome da classe ou modulo assim:

 Module1.Id = 1

Mas no VB.Net você consegue setar a property sem nem ao menos colocar o nome da classe na frente, ou seja, você está numa classe totalmente diferente e pode utilizar os membros de um modulo como se você estivesse dentro do modulo:

Id = 1  

Você pode estar se perguntando, o que tem de errado nisso?
Vou dar um exemplo: Um programador cria um “MdlGlobal”, modulo com propósito de conter variáveis e métodos globais, e coloca lá variáveis e métodos que ele quer que seja acessados por toda aplicação, mas para não confundir com membros de outras classes acabaram colocando prefixos nos nomes para dizer que é Global, exemplo: GlobalUsuarioID, GlobalVariavelX (e etc)

Isso acaba deixando tudo mais confuso, se fosse obrigatório o nome do modulo não precisaria de prefixos: MdlGlobal.UsuarioID, MdGlobal.VariavelX

Não ficou mais fácil? Alem de deixar os nomes menos carregados você sabe rapidamente da onde está vindo o método ou atributo.

Da para deixar de usar módulos criando uma classe e colocando os membros como shared, é uma alternativa.
É fato que quando usamos shared deixamos o código menos orientado a objetos, mas nem mencionar a classe daí já é demais.

Método/Método()

No VB.Net na passagem de parâmetros de métodos é obrigatório colocar os parênteses a não ser quando não há parâmetros.

Dim letras As Object = "a b c d e f g"
Dim array As String() = letras.ToString.Split

O exemplo acima talvez não esteja confuso, porque os métodos ToString e Split tem nomes intuitivos, da para entender que está executando dois métodos. Mas quando o programador coloca um nome nada a ver para um método? Um nome que deveria ser de um atributo? Bem, no Visual Studio basta passar o mouse em cima para descobrir, mas não deixa de ser confuso as vezes.

Mas isso pode ficar mais confuso combinado com as genérics que é o próximo tópico.

Generics com Parênteses

As generics são muito utilizadas, com ela tem um ganho muito bom em performance e em segurança.

Vamos declarar então uma lista de usuários.

Dim usuarios As List(Of Usuario)

Eu declarei usuarios como List(Of T), o T é a genéric que vai ser o meu tipo Usuario.
Ok, eu não instanciei ainda a minha lista.

usuarios = New List(Of Usuario)

Pronto, instanciei uma lista, nesse momento um método é executado, que é o construtor da classe. Por não ser obrigatório o uso de parênteses pode dar a impressão de que '(Of T)' que é a generic é o construtor ou que o construtor nem existe.

Dim usuarios As New List(Of Usuario)(100)

Veja agora, você não acha que isso é bizarro? Estou passando um parâmetro para o construtor da lista e ficou com quatro parênteses na minha declaração.
No C# ficaria assim:

List<Usuario> usuarios = new List<Usuario>(100);

No C# as generics ficaram menos confusas ou ao menos não tem como confundir com o construtor da classe.

Índices com Parênteses

Os indexadores no VB.Net também usa parênteses para acessar os índices de arrays e coleções em geral.

Exemplo:

x = numeros(1)

Estou atribuindo o valor da posição 1 para a variável ‘x’.
Nenhuma confusão até agora, pois o meu array está com um nome que sugere que é um array ou uma lista e ainda está em camelCasing que é uma boa pratica.

Digamos então que o programador não segue boas práticas:

x = SomaNumeros(1)

O que é SomaNumeros? O programador colocou um nome ambíguo, que para ele deve significar muita coisa e fazer todo o sentido do mundo.
Será que é uma lista ou array com resultados de uma soma ou é um método? Descobriremos somente se olharmos a definição, e isso não é bom.

A sintaxe do C# utiliza colchetes para indexar, então não tem erro:

x = SomaNumeros[1];

Declarando Arrays

Quantas posições estou alocando com a declaração abaixo?

Dim numeros(10) As Integer

A resposta é onze!
No VB.Net ele aloca de zero até o número especificado, que no caso é dez.

No C# alocaria de zero a nove dando sentido ao número explicito da declaração. 

Isso induz o programador deixar de usar o endereço zero desperdiçando memória.

Mas você quer ver como isso pode ficar estranho?

Dim numeros(0) As Integer

Declarei acima um array de apenas uma posição com o número zero.

Chegando ao Fim da Parte 2

Eu abordei nessa segunda parte pontos da sintaxe do VB.Net.
Quando escrevemos um código limpo, com bons nomes nas variáveis e bem documentado não há confusão alguma independente da linguagem.
Então é bom nos disciplinar para fazer um código que facilite a manutenção.

Há mais ponto que me incomoda na linguagem, mas ficará para a terceira parte.

Até Mais,
Tiago Esmeraldino

sábado, 29 de agosto de 2009

Prefiro C# do que VB.Net - Parte 1


Introdução

Vou começar escrevendo no blog algumas razões de preferir o C# ao invés do VB.Net ao desenvolver uma aplicação. Deixo claro que isso é uma comparação de sintaxe da linguagem e sintaxe cada um tem sua preferência, por isso vou explicar o porquê de eu preferir o C#.

O Visual Basic.Net tem uma sintaxe simples e ainda vem por padrão com o Option Strict Off, esses dois fatores combinado ainda com o Visual Studio torna o VB.Net uma linguagem muito fácil de se programar. É realmente uma maravilha para os iniciantes e isso é um grande mérito da linguagem.

Mas há pontos na sintaxe que você pode se meter em incríveis confusões. Parece até um filme de sessão da tarde não é mesmo? Vamos ver onde estão essas tais confusões e como podemos tentar evitá-las tornando o código mais “profissional” possível.

Falando em deixar o código mais “profissional” é isso que o C# normalmente te obriga, e muitas das confusões no VB.Net podem ser resolvidas com o Option Strict On que evita uma série de erros, deixando seu código mais bonito e rápido, acredite vale a pena ligar o amiguinho.

A sintaxe do VB.Net pode deixar você confuso e quebra até conceitos de orientação a objetos, vou explicar mais abaixo.

Construtor Padrão Fora do Padrão

Quando você cria o “Form1” pelo Visual Studio, você está criando uma classe, Ok? Essa classe descende da classe System.Windows.Forms.Form e está divida em duas partes, uma fica o código do Design(no arquivo Form1.Designer.vb) gerado normalmente pela ferramenta que tem o método InitializeComponent e a outra a sua implementação(no arquivo Form1.vb).

O método InitializeComponent é quem inicializa todos seus componentes, se ele não for executado nada vai aparecer na tela, mas onde ele é chamado? Resposta: No construtor que fica escondido.
Isso é confuso, pois você não vai encontrar a chamada do método a não ser que você implemente um construtor, então basta escrever a assinatura do construtor e dar um enter para o Visual Studio preencher o conteúdo que estava oculto para você.

Public Sub New()
        ' This call is required by the Windows Form Designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
End Sub

Só para deixa claro, toda classe tem um construtor, e quando você não implementa ele fica com o construtor padrão que por sua vez não tem nenhuma instrução dentro dele. Mas no VB.Net qualquer form que você crie, o construtor padrão não é mais padrão.

Parece Shared Mas Não é Shared

Ainda falando sobre os forms do VB.Net, como você executa o método Show no seu “Form1”?

Um form é uma classe, e caso você queira usar um método dessa classe, você precisa criar uma instancia do form, a não ser que o método do form seja Shared(static em C#, Java...) certo?

Bem, no VB.Net você consegue chamar um método que não é shared sem instanciar um objeto, isso vale apenas para as classes que descendem da classe Form, ou seja, todos os formulários que você cria.
O VB.Net deixa você chamar qualquer método da classe "Form1" sem necessidade de instanciar por questões de retrocompatibilidade com o VB6:

Form1.Show()

O correto seria:

Dim frm As New Form1()
frm.Show()

No primeiro caso é criado automaticamente uma instancia do "Form1" e depois é executado o método Show, más você não fica com a referencia dessa instancia como é no segundo caso onde está armazenada a referencia na variável 'frm' e você tem um controle total daquela instancia e pode até criar várias instancias de um único form.

Chegando ao Fim da Parte 1

Quando comecei a aprender orientação a objetos fiquei confuso nos dois casos acima. Não fiz nenhuma comparação direta com o C# porque simplesmente não acontece isso nele. Há mais casos ainda que irei abordar nos próximos posts e se você não sabe o que o Option Strict faz e nem sabe sobre métodos shared e construtores fique tranqüilo que irei abordar nos próximos posts também.

Até a próxima,
Tiago Esmeraldino