Parâmetros de Funções

Série de Maclaurin

O número ideal de parâmetros de uma função é zero. Grandes quantidades de parâmetros tornam mais difícil a manutenção do código. Por isso, caso parâmetros sejam realmente necessários, a melhor escolha é evitar uma quantidade maior que dois.

Devem ser evitados também parâmetros booleanos que modificam o comportamento da função. Por exemplo, no código abaixo a função “DebitarJuros” recebe um parâmetro que indica se o Juros aplicado é Especial:

public void DebitarJuros(bool jurosEspecial)
{
    if(jurosEspecial)
    {
        this.Saldo -= JUROS_ESPECIAL;
    }
    else
    {
       this.Saldo -= JUROS_COMUM;
    }
}

Nesse caso, a maneira mais adequada seria criar dois métodos, um para cada tipo de Juros. Dessa forma, eliminamos o parâmetro e deixamos o código mais fácil de entender. Mesmo sem ver a implementação dos métodos, claramente percebemos que eles aplicam juros diferentes:

public void DebitarJurosEspecial() {...}

public void DebitarJurosComum() {...}

Em geral, quando uma função tem mais de três parâmetros é possível agrupá-los em uma classe, tornando-a mais fácil de ser ententida e alterada:

public void InsereUsuarioNoBancoDeDados(string nome, string login, string senha, DateTime dataNascimento)
{...}

public void AtualizaUsuarioNoBancoDeDados(int id, string nome, string login, string senha, DateTime dataNascimento)
{...}

Os métodos acima recebem as informações a respeito de um usuário para que possam ser inseridas ou atualizadas no Banco de Dados. Note que se, devido a alguma alteração no Banco de Dados, for necessário adicionar mais uma informação sobre o usuário (como o estado civil, por exemplo) precisaremos alterar os dois métodos, adicionando mais um parâmetro:


public void InsereUsuarioNoBancoDeDados(string nome, string login, string senha, DateTime dataNascimento, string estadoCivil)
{...}

public void AtualizaUsuarioNoBancoDeDados(int id, string nome, string login, string senha, DateTime dataNascimento, string estadocivil)
{...}

Note que se agruparmos as informações de um usuário em uma classe, qualquer alteração nessas informações afetará apenas essa classe.

public class Usuario
{
public string Nome { get; set; }
public string Login { get; set; }
public string Senha { get; set; }
public DateTime DataNascimento { get; set; }
}

E os métodos receberão um objeto Usuário como parâmetro:

public void InsereUsuarioNoBancoDeDados(Usuario usuario)
{...}

public void AtualizaUsuarioNoBancoDeDados(Usuario usuario)
{...}

Como vimos, diminuir o número de parâmetro em nossas funções além de deixar o código mais fácil de ser entendido, ajuda quando ocorrerem modificações, tornado mais simples a refatoração.

Anúncios

Comentários de Código

Comentário ruim no códigoGeralmente, quando estamos escrevendo nossos códigos temos a preocupação (ou a necessidade) de explicar certas partes que podem não estar tão claras. Utilizamos, então, comentários para esclarecer o propósito daquela função, variável ou classe.

Muito embora essa prática alcance seu objetivo imediato, ela esconde uma verdade importante: se o código precisa ser explicado, então ele não está bem escrito o bastante; ele é um código ruim.

Além disso, comentários são muitas vezes traiçoeiros. O código muda bastante e na maioria das vezes o programador acaba esquecendo de refletir essas mudanças em seus comentários.

Exemplo 1:


   //Retorna o cliente passando o ID como parâmetro
   public Cliente GetCliente(string CPF) {...}

Note que o programador esqueceu de alterar o nome do parâmetro de ID para CPF em seu comentário, trazendo uma informação errada para o seu código.

Outro uso negativo dos comentários é a redundância de informação, como mostra o exemplo abaixo:

Exemplo 2:


public class Cliente
{
    //Data de Nascimento
    private DateTime dataNascimento;

    //Nome do Cliente
    private string nome;
}

Neste caso, a informação dos comentários não agrega valor algum ao entendimento do código. A melhor escolha seria não utilizá-los.

Na maioria das vezes, um comentário pode ser substituído refatorando (e melhorando) o código. Nos casos em que o comentário for realmente necessário, ele deverá ser curto e direto.

Exemplo 3:

   /* O método ExecuteUpdateAsAdministrator não é Thread Safe */
   public void ExecuteUpdateAsAdministrator() {...}

O exemplo 3 mostra uma boa utilização de comentário, alertando o programador sobre uma consequência do uso do código.

Assim, tente diminuir o uso dos comentários. Refaça o código e altere o nome das entidades. Seu código ficará muito mais fácil de ser entendido.

Mapeando Custom Fields com FluentPS

Enterprise custom fieldsNo post anterior aprendemos como utilizar a biblioteca FluentPS, que facilita o trabalho de manipular informações do Project Server.

Nesse post vamos ver como recuperar informações de campos personalizados do Project Server, os Enterprise Custom Fields.

O que são Enterprise Custom Fields?

Enterprise Custom Fields permitem extender os campos fornecidos por padrão pelo Project Server, podendo ser associados às entidades Projeto, Recurso e Tarefas. Eles são geralmente utilizados para atender a alguma necessidade específica da empresa/organização.

Os Enterprise Custom Fields são armazenados no Banco de Dados do próprio Project Server.

Onde estão os Enterprise Custom Fields?

Configurações do ServidorOs campos personalizados podem ser encontrados no PWA site, através do link Configurações do Servidor.

Agora navegue até a seção Dados da Empresa.

Selecione a opção Campos Personalizados da Empresa e Tabelas de Pesquisa para ver os campos cadastrados do servidor.

Seção Dados da Empresa

Nosso Exemplo

A nossa aplicação vai recuperar os dados do campo Departamento de um determinado projeto. Para isso, vamos criar a entrada Departamento de TI nesse campo.

Observação: lembre que você deve associar ao projeto o valor do campo Departamento que acabamos de criar, utilizando, por exemplo, o Microsoft Project Professional.

Usando o código do post anterior, vamos modificar a classe ProjectInfo. Criaremos a propriedade ProjectDepartment da seguinte forma:

[PSLookupField("9d77d62a-a92e-4d40-adc8-446c90eb7456", LookupTableUid="e7397277-1ab0-4096-b2dd-57029a055ba4",
FieldName = "Departamentos do Projeto", LookupTableName = "Departamento")]
public string ProjectDepartment { get; set; }

Para mapearmos o campo Departamento, utilizamos o atributo PSLookupField, recebendo em seu construtor os seguintes parâmetros: o ID do campo, o ID da tabela de lookup (tabela de pesquisa, em Português), o nome do campo e o nome da tabela de lookup.

Para recuperar o ID do campo, basta clicar no campo

Campo personalizado Departamento do Projeto

e copiar o GUID na parte inferior da página:

ID do campo DepartamentoDa mesma forma, para acessar o ID da tabela de lookup Departamento basta clicar nela,

Tabela de pesquisa Departamento

naveguar até a parte inferior da pagina e copiar o GUID:

GUID da tabela de lookup DepartamentoAgora altere a classe Program.cs para exibir o nome do Departamento associado ao projeto.

Console.WriteLine("Project Department: {0}", project.ProjectDepartment);

Pronto! Agora é só executar o código e o Departamento do projeto será exibido.

Novamente, se quiser mais informações sobre o FluentPS e o mapeamento de Custom Fields, acesse http://www.projectserver2010blog.com

Categorias:.NET, Project Server

Inovecast: Certificação SharePoint 2010

Inove InformáticaNesse mês de Abril, participei do Inovecast, Podcast da Inove Informática, falando um pouco sobre a nova série de certificações para a plataforma SharePoint 2010, juntamente com o Ronaldo Silva que trabalha comigo na Inove.

No podcast, apresentamos os temas mais abordados na certificação 70-573: Microsoft SharePoint 2010, Aplication Development

 

Caso não consiga ouvir o podcast, tente aqui.

Categorias:.NET, SharePoint

Dando nome às coisas

Código não limpoNormalmente quando estamos desenvolvendo algum código não nos preocupamos com o fato de que alguém muito provavelmente irá lê-lo. E na maioria das vezes seremos nós mesmos que o leremos, por motivos diversos: dar manutenção, acrescentar alguma funcionalidade ou corrigir algum erro/bug.

Ler um código é uma tarefa comum na vida de um desenvolvedor. Portanto, é importante mantê-lo legível e compreensível. Quem nunca olhou para um código antigo e se perguntou: “O que diabos essa função faz?”

Pois é, geralmente esquecemos a finalidade ou o funcionamento de um código com o qual não temos contato a algum tempo. Por isso, manter o código o mais compreensível (e legível) possível deve ser encarado como uma regra básica do bom desenvolvedor.


tirinha alterando código - vida de programador

Um código bagunçado certamente atrapalha o entendimento de seu leitor, o que acarreta em mais horas para o compreender e consequentemente, mais tempo para alterá-lo. Um código bem escrito facilita o processo de análise dele por parte do leitor e assim, o seu desenvolvedor não precisará recorrer à sua memória para saber o que ele faz.

Clean Code bookO livro Clean Code de Robert C. Martin (conhecido também como Uncle Bob) fala justamente de como deixar seu código bem escrito, tornando-o limpo. Esse post é totalmente baseado nas ideias desse livro, então qualquer semelhança não é mera coincidência.

Nomeando entidades

O nome das entidades em um código (variáveis, objetos, classes…) deve expressar a funcionalidade dela, o por quê dela ter sido criada. Em outras palavras, o nome deve responder a pergunta: “O que a entidade faz?”

Exemplo 1:

string s = "Domínio\NomeDoUsuário";

A string “s” criada acima não diz nada a respeito da sua funcionalidade. Pior ainda ela não diz nada! É preciso ver o seu conteúdo para saber que ela armazena a informação de uma conta de usuário. Provavelmente quando a referenciarmos posteriormente em nosso código precisaremos voltar a sua declaração para compreendermos o que ela significa.

Exemplo 2:

string userAccountName = "Domínio\NomeDoUsuário";

Agora sim. Em qualquer lugar do código que referenciarmos a nossa string saberemos que ela armazena a informação de uma conta de usário. Note que uma simples mudança de nome deixou o nosso código mais compreensível.

Prefira sempre nomes mais longos para suas entidades. Nomes muito curtos quase nunca descrevem a sua funcionalidade. Além disso, nomes muito curtos (compostos de uma ou duas letras) dificultam a busca. Procurar a string “s” seria muito mais difícil do que procurar a string “userAccountName”, porque provavelmente aparecerá em diversas partes do código.

Exemplo 3:

string dds = "Segunda-feira";

Outro cuidado que devemos ter é com as abreviações. Em geral é melhor evitá-las porque elas não expressam a essência funcional da entidade. No Exemplo 3 o nome “dds” significa “dia da semana”, mas dificilmente alguém que lêsse o código pela primeira vez saberia esse significado (e depois de alguns meses, nem mesmo quem o desenvolveu lembraria!).

Exemplo 4:

string diaSemana = "Segunda-feira";

Alterando o nome da string para “diaSemana” compreendemos facilmente que ela representa o dia da semana, “Segunda-Feira”.

Concluímos, então, que se tivermos pequenos cuidados na hora de criarmos um código podemos deixá-lo mais compreensível, mais fácil de ser lido, mais limpo. Pense nisso e aplique esses conceitos no dia-a-dia, você verá que a leitura do código vai ficar muito mais agradável.

Adicionar funcionalidades a um código ruim é como camuflar uma bomba: você pode deixá-la bonita, enfeitá-la com um laço e até dar a ela um cheiro bom; mas ela ainda é uma bomba e pode explodir a qualquer momento.

Usando FluentPS

fluentPS logo

FluentPS é uma biblioteca open source que tem o objetivo de simplificar o desenvolvimento de aplicações na plataforma Project Server 2010. Ela lembra bastante o FluentNHibernate, bem parecida com ORM (mapeamento objeto-relacional), provendo uma interface para o PSI (Project Server Interface).

No desenvolvimento de aplicações para Project Server sem usar o FluentPS, era preciso adicionar várias referências a WebServices que permitiam o acesso a informações dos arquivos de Projeto que estavam publicados no Portal PWA. Com o FluentPS, essa tarefa não é mais necessária. Toda a comunicação com o Project Server é feita através de objetos compilados na Plataforma .NET.

Agora que sabemos o que é o FluentPS vamos à prática!

Esse exemplo é bem simples e apenas recupera as informações referentes ao ID e Nome dos Projetos que estão publicados no Portal PWA.

Baixe as dlls do FluentPS do site http://fluentps.codeplex.com/. Para esse exemplo estou usando a versão 2.0.

Vamos criar um projeto Console com o nome de FluentPSTestApplication. Adicione as referências para as dlls do FluentPS que você acabou de baixar.

referências fluentps

Configure o a propriedade Target Framework do projeto para .NET Framework 3.5, clicando com o botão direito sobre o projeto e escolhendo a opção Properties.

Versão do .NET Framework

Agora, adicionamos a classe ProjectInfo que mapeará os campos referentes a um projeto do Project Server.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentPS.Attributes;
using FluentPS.Consts;

namespace FluentPSTestApplication
{
public class ProjectInfo
{
[PSEntityUidField(ColumnName=ProjectCustomFieldsColumnNames.PROJ_UID)]
public Guid ProjectUid { get; set; }

[PSEntityUidField(ColumnName=ProjectCustomFieldsColumnNames.PROJ_NAME)]
public string ProjectName { get; set; }
}
}

O atributo PSEntityUidField realiza o mapeamento de um campo padrão de um projeto. Nesse exemplo, os campos padrões são o ID e o Nome do Projeto.

Na classe Program, adicione o seguinte trecho de código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentPS.Services.Impl;
using FluentSP.Services.Impl;
using FluentPS.WebSvcCustomFields;
using FluentPS.WebSvcLookupTable;

namespace FluentPSTestApplication
{
class Program
{
static void Main(string[] args)
{
var logService = new LogService();
var sessionService = new PSSessionService();
var psiContextService = new PsiContextService();
var psiSvcsFactory = new PSISvcsFactory(sessionService, psiContextService);

var lookupTableService = new PSLookupTableService(
logService,
psiSvcsFactory.CreateSvcClient());

var svcCustomFields = psiSvcsFactory.CreateSvcClient();
var svcLookupTable = psiSvcsFactory.CreateSvcClient();
var svcView = psiSvcsFactory.CreateSvcClient();

var environmentService = new EnvironmentService();
var customFieldService = new PSCustomFieldService(logService,
svcCustomFields,
svcView,
environmentService,
lookupTableService);

var projectsService = new PSProjectService(
logService,
lookupTableService,
customFieldService,
psiSvcsFactory.CreateSvcClient());
var projects = projectsService.GetAll();

foreach (var project in projects)
{
Console.WriteLine("Project Name: {0}", project.ProjectName);
Console.WriteLine("Project Uid: {0}", project.ProjectUid);
Console.WriteLine();
}

Console.ReadKey();
}
}
}

Basicamente, o que o código acima faz é instanciar os objetos do FluentPS que servem para mapear os WebServices do Project Server.

O comando abaixo, retorna todos os projetos publicados no Portal do PWA.

var projects = projectsService.GetAll();

Fácil, não? Se você quiser mais informações sobre o FluentPS, acesse o site http://www.projectserver2010blog.com. Exemplo concluído e até o próximo post.

Categorias:.NET, Project Server

Exibir menu QuickLaunch em WebPartPages

Aqui vai uma dica SharePoint rápida.

Quando criamos no SharePoint 2010 uma WebPartPage, uma página que contém WebPartZones (containers para WebParts), o menu QuickLaunch, Menu de Início Rápido em Português, não é exibido.

QuickLaunch menu

Para habilitá-lo nesse tipo de página basta apenas seguir esses 3 passos:

  1. Abrir a página no SharePoint Designer 2010;
  2. Remover o trecho de código:
    <SharePoint:UIVersionedContent ID="WebPartPageHideQLStyles" UIVersion="4"runat="server">
    <ContentTemplate> 
    body #s4-leftpanel {
    display:none;
    }
    .s4-ca {
    margin-left:0px;
    }
    </style>
    </ContentTemplate>
    </SharePoint:UIVersionedContent>
  3. Remover o place holder:
  4. <asp:Content ContentPlaceHolderId="PlaceHolderLeftNavBar" runat="server"></asp:Content>

Categorias:SharePoint