segunda-feira, 6 de dezembro de 2010

Session Management no Azure

Cuidado você que usa o objeto Session no seu código ASP.NET. O Azure não implementa “sticky sessions” ou “server affinity” para seus web roles: a cada acesso seu usuário pode ser atendido por uma instância diferente. Então o mesmo usuário pode ser atendido por instâncias diferentes do seu web role no Azure, e se você usa o modo default de gerenciamento de sessão (“InProc”), então seu código irá dar pau:

image

A Microsoft publicou o projeto AspProviders Sample (parte do Windows Azure Samples) que contém um provider para armazenamento de sessões ASP.NET no Storage do Azure. Há também a possibilidade de armazenamento em um BD no SQL Azure.

O importante é lembrar que, se você deseja ter mais de uma instância de um web role no Azure, o que é altamente desejável por aumentar a disponibilidade e a escalabilidade da aplicação, você tem que usar um provider para armazenamento das sessões, e você tem que programar “consciente” disto: por exemplo, todas as classes que forem ser colocadas em sessão necessariamente terão que ser serializáveis. É uma programação um pouco mais trabalhosa, mas o custo x benefício vale a pena.

sexta-feira, 3 de dezembro de 2010

LinqPad Conectado ao Azure Table Storage

  1. Siga os passos nesse outro post que usa o LinqPad para acessar o Development Storage.
  2. Altere o código da consulta para o seguinte:
StorageCredentialsAccountAndKey cak = new StorageCredentialsAccountAndKey(
"NOME_CONTA", // Nome da sua conta no ATS
"ACCESS_KEY" // Primary/secondary access key – pegue no portal do Azure (http://windows.azure.com)
);
CloudStorageAccount account = new CloudStorageAccount(cak, false);
// “ContextoDados" é sua classe de contexto, derivada de TableServiceContext
var contexto = new ContextoDados(account.TableEndpoint.AbsoluteUri, account.Credentials);

var resultado = contexto.Log; // Aqui entra sua consulta Linq
Console.Write(resultado);

sexta-feira, 19 de novembro de 2010

ECO Developers 2010 & Encontro de Arquitetos Brasília

Ontem eu e o Luti palestramos no ECO Developers 2010. Demos uma visão geral do Azure como plataforma de desenvolvimento, mostrando seus principais elementos de arquitetura, e fizemos um demo mostrando a capacidade de escalabilidade de aplicações na nuvem, aumentando o processamento de uma aplicação de testes simplesmente aumentando o número de máquinas virtuais que executavam a aplicação, sem intervençao no código da mesma. O pessoal gostou!

De tarde fui ao Encontro de Arquitetos Brasília, na Microsoft. Palestras do Markus Christen sobre Private Clouds e do Waldemir Cambiucci sobre Patterns para Public Clouds. Excelentes apresentações, e pelo público foi legal ver que já tem empresas empresas grandes (.gov também!) de “olho nas nuvens” aqui em Bsb!

Nossa palestra no ECO Developers, sobre “Windows Azure & Green IT”, foi disponibilizada no TwitCam pelo Bruno Kenj. Em breve vamos disponibilizar também o código fonte da nossa aplicação exemplo para download. Aproveitem, e qualquer dúvida, é só mandar!

[]s,

GB

terça-feira, 26 de outubro de 2010

WebCast: Desenvolvendo com Sandboxed Solutions no SharePoint 2010

Meu último Web Cast no MSDN, falando sobre o que são Sandboxed Solutions no SharePoint 2010, suas vantagens e exemplo de implementação, já está na MSDN: https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=pt-BR&EventID=1032456921&CountryCode=BR. Dê uma olhada e me mande suas dúvidas!

Azure Development Storage não reconhece ponto decimal em valores double

Gravei em uma tabela do Development Storage do Azure uma entidade que tem uma propriedade do tipo double. O valor dessa propriedade era 123,45. Quando recarreguei a entidade do Dev Storage, ao ler o valor da propriedade, obtive 12.345. Aparentemente o Dev Storage estava “ignorando” o ponto decimal que eu tinha colocado ao armazenar o valor. Mas como a gente já tinha visto este comportamento em outras situações, e sempre era relativo ao “Regional Settings” sendo usado, tentei por aí.

DISCLAIMER: Não tente isto em casa. Manipular diretamente o BD do Development Storage é altamente “des-recomendado”.

Bem, abri o BD do Development Storage no SQL Management Studio, e achei uma tabela chamada “TableRow”, que contém as entidades que gravamos no dito cujo. Na coluna Data, estão gravadas as propriedades da entidade, formatadas como um documento XML. E o valor gravado lá era “123.45” – ou seja, o Dev Storage armazenou corretamente o valor; o problema aparentemente era na leitura. Pra confirmar isso, mudei o valor “na mão” (leia DISCLAIMER acima) para “123,45” e a aplicação retornou o valor que eu esperava.

Não consegui um jeito de mudar a cultura usada pelo Development Storage, para ver se com isto ele lia os valores de forma correta; mas um workaround simples é mudar, no Painel de Controle, na parte de configurações regionais, o separador decimal de “vírgula” para “ponto”. Aí você reinicia o Dev Storage e ele passa a ler corretamente os valores double. (No Windows 7 as configurações regionais para o separador decimal ficam em Painel de Controle > Relógio, Idioma e Região > Alterar o formato de data, hora ou número > Configurações adicionais).

Coloquei um bug no Connect sobre isto (o link está aqui mas parece que as entradas do Connect agora só são acessíveis se você se inscrever no programa do respectivo produto). Vamos ver o que o pessoal da MS responde.

sexta-feira, 22 de outubro de 2010

Papai Noel dos Correios 2010

Acho difícil encontrar uma iniciativa mais valiosa que esta. Então vale a pena dar uma pausa no trabalho pra divulgar a mensagem. A mensagem é da Diretoria Regional dos Correios em Brasília, mas existem postos em todos os estados. Veja a lista no site dos Correios.
Papai Noel dos Correios 2010
clip_image001As cartas para o Bom Velhinho já estão chegando.

clip_image002
Como acontece todos os anos, as crianças escrevem para o Papai Noel, Bom Velhinho, depositando a esperança de ver seus sonhos realizados.
Os Correios disponibilizam essas cartinhas à população para que sejam adotadas e a entrega fica sob a nossa  responsabilidade.
clip_image003
As cartas têm os mais variados tipos de pedidos: boneca, carrinho, bola, material escolar, cesta básica, mas o principal é o sonho que cada criança deposita nessas cartas.
clip_image004
A Casa do Papai Noel já começou suas atividades.
E contamos com você para ajudar a realizar muitos sonhos.
clip_image005
As cartas podem ser escolhidas na Casa do Papai Noel dos Correios
Os presentes às cartas adotadas serão entregues pelos Centros de Distribuição Domiciliária dos Correios  nas Cidades Satélites e Entorno durante o mês de dezembro
clip_image006
Junte-se aos ajudantes do Papai Noel e venha contribuir para  um Natal melhor para muitas crianças.
Você pode contribuir como voluntário, indo à Casa do Papai Noel ler cartas, adotá-las, embrulhar presentes,  entregar presentes nos CDDs, trabalho é o que não falta e sua ajuda será muito útil e bem vinda.
Casa do Papai Noel  dos Correios
W3 508 Norte, Bl. D, 2º andar
Para adotar cartas
de 03 a 27/11
de 2ª a 6ª de 12h às 17h
sábado dia 27/11
de 8h às 12h
Entrega de presentes para as cartas adotadas
Até o dia 04/12
de 2ª a 6ª de 12h às 17h
sábado dia 04/12 de 8h às 12h
Não haverá atividade na Casa do Papai Noel dias 15 e 30/11
clip_image007
Contamos com você!
Diretoria Regional em Brasília
clip_image008

Semana BPOS de WebCasts

Semana que vem a Microsoft irá realizar uma série de eventos sobre BPOS (Bussiness Productivity Online Services), que é um conjunto de serviços para colaboração e messaging rodando na nuvem. De acordo com o site do BPOS, “e-mail, Web conferencing, instant messaging, document collaboration and workflow”, ou seja, Exchange, Live Meeting, Office Communicator e SharePoint. Uma ótima pedida para pequenas e médias empresas que querem a agilidade que estes serviços dão aos negócios, mas que não tem como justificar ou suportar uma equipe de TI para mantê-los.

Os webcasts sobre BPOS serão:

25/10 - 12h00 - Semana na Nuvem com o BPOS - Visão Geral do BPOS
26/10 - 12h00 - Semana na Nuvem com o BPOS - Planejando a Implementação do BPOS em sua organização
27/10 - 12h00 - Semana na Nuvem com o BPOS - Criando sua conta trial no BPOS e Visão Geral da Central de Administração
28/10 - 12h00 - Semana na Nuvem com o BPOS - Instalando e Configurando o Directory Synchronization
29/10 - 12h00 - Semana na Nuvem com o BPOS - Migrando o Exchange Server 2007 para o Exchange Server Online

E pra você que está chegando aqui depois da realização, lembre-se que a gravação deles fica disponível no mesmo link.

Aconselho a fazerem o trial – gratuito - e verem os benefícios que o BPOS pode trazer à sua empresa, ou para seus clientes!

quarta-feira, 20 de outubro de 2010

Standby no Windows 2008

Pra quem tem notebook, o standby é uma maravilha. Você está no meio de uma tarefa, com 17 janelas abertas, e tem que parar pra ir pegar as meninas na escola e ir pra casa. Pra evitar ter que fechar tudo quando desligar o note, basta coloca o Windows em standby: o HD pára de girar e seu cabeçote de leitura/escrita é recolhido, o que evita danos ao mesmo quando, ao entrar em casa, você joga a mochila com o note no sofá. A CPU entra em sleep e o cooler pode ser desligado, o que evita que o note frite dentro da mochila. Por fim, entrar e sair de standby é muito mais rápido do que de hibernação, pois na hibernação a RAM é escrita em disco e o computador é efetivamente desligado, o que requer um boot e a leitura da RAM de disco para que o Windows possa continuar.

Só que meu boot de testes pro SharePoint é Windows 2008. Por default, o standby vem desabilitado no Windows 2008, pois sendo ele um sistema operacional para servidores, a Microsoft - com razão - achou que as consequências para a sua rede não seriam boas se um servidor entrasse em standby depois de um tempo de inatividade. Mas como esse meu boot é pra testes, eu quero poder botar o bichinho em standby.

Pra isso, basta criar um atalho apontando pra seguinte linha de comando:

%windir%\System32\rundll32.exe powrprof.dll,SetSuspendState Standby

Simples assim. Dá até pra criar links para shutdown, logoff, reboot e hibernate: http://blogs.msdn.com/b/baliles/archive/2010/06/08/tips-amp-tricks-enable-standby-in-windows-2008-r2-server.aspx.

quarta-feira, 13 de outubro de 2010

LinqPad4: Ferramenta free de consultas Linq também funciona no Azure Tables!!!

Então. Estava eu precisando debugar uma consulta Linq que a aplicação estava mandando pro Development Storage do Azure. Coloquei um breakpoint em cima da danada, e na hora que não veio o que eu queria, copiei ela pro clipboard e joguei na Watch1 pra poder alterar seu texto e ver o resultado desta alteração. Mas a janela de Watch não gostou do Linq na expressão: Expression cannot contain query expression.

image

Na Immediate Window, mesma coisa. Como ganhei um bônus de 2 dias no prazo da próxima entrega do projeto, fui procurar alguma ferramenta que me permitisse escrever e executar uma consulta Linq no Azure Tables. E aí achei o LinqPad4.

O LinqPad4 deixa você escrever um programa em uma linguagem (na versão 4 ele suporta C#, VB.NET, F# e SQL), e executa este programa na conexão de dados que você especificou. Ele contém funcionalidades que permitem ver o resultado de consultas Linq. E permite você declarar variáveis, colocar referência a assemblies, e incluir namespaces. Então ficou fácil fazer com que ele consulte o Azure Tables:

  1. Se vou fazer uma consulta Linq nas tabelas no Azure Tables, preciso instanciar a classe que serve como contexto de acesso às tabelas. Então na janela das propriedades da consulta (Query > Query Properties), coloco uma referência ao assembly que tem minha classe de contexto de dados (“Projeto1”.AcessoDados.dll, na figura – os personagens usam nomes fictícios pois nosso cliente tem muito carinho pelo nome fantasia que ele bolou para o produto):
    image
  2. Ainda nessa janela, na tab “Additional Namespace Imports” coloco namespaces que vou usar na consulta – a mesma funcionalidade do using do C#.

E pronto! Agora posso escrever e executar consultas Linq nas tabelas do Development Storage:

image

Explicando o código:

Linha 1: Preciso dos dados de conexão com o Development Storage. Eles estão em Microsoft.WindowsAzure.CloudStorageAccount.DevelopmentStorageAccount.

Linha 2: Preciso instanciar a classe de contexto da aplicação, informando como ela deve se conectar ao Azure. Para consultar as tabelas no Development Storage, crio uma instância da minha classe de contexto usando a assinatura
ContextoDados(string baseAddress, Microsoft.WindowsAzure.StorageCredentials credentials). Esta assinatura está presente na minha classe de contexto pois é herdada de Microsoft.WindowsAzure.StorageClient.TableServiceContext.

Linhas 3-6: É a consulta Linq.

Linha 7: O LinqPad tem uma funcionalidade de escrever um List<T> como uma tabela no painel “Results”, o que permite você visualizar de forma fácil e rápida o resultado da consulta Linq.

O site do LinqPad é http://www.linqpad.net. Tem versões para o Framework 3.5 e 4.0, e é for free.

sexta-feira, 8 de outubro de 2010

Como passar lista de objetos de classe derivada para método que recebe lista objetos de classe base

Se você tem um método que recebe um parâmetro List<T>, e quer passar para este método uma lista List<T1>, aonde T1 é derivada de T, então continue lendo. (Se não, pode voltar ao que você estava fazendo ;-)

Criei o seguinte método:
public static void IncluiEntidades(List<EntidadeAzureTable> entidades)
{
...
}
EntidadeAzureTable é a classe base de várias outras na aplicação. Este método recebe uma lista de entidades e as grava nas respectivas tabelas (no Azure Table Service).

Pois bem, criei uma lista de objetos de uma classe derivada e tentei passá-la para o método acima:

List<DocumentoSaida> documentos; // DocumentoSaida deriva de EntidadeAzureTable
documentos = ...;
AzureTables.IncluiEntidades(documentos);
O compilador do C# não deixou passar, retornando o seguinte erro de compilação:

Argument 1: cannot convert from 'System.Collections.Generic.List<DocumentoSaida>' to 'System.Collections.Generic.List<EntidadeAzureTable>'

Ele “não entendeu” que DocumentoSaida herda de EntidadeAzureTable. Aparentemente, se um método recebe um parâmetro que é uma lista de objetos de uma classe, não posso passar uma lista de objetos de uma classe derivada neste parâmetro.

Para resolver este problema, podemos utilizar generic type constraints: criar um método genérico, e usar a palavra-chave where para colocar uma restrição no parâmetro de tipo do método. Mudei a declaração do método para

public static void IncluiEntidades<T>(List<T> entidades)
     where T : EntidadeAzureTable
{
   ...
}
e o compilador entendeu o que eu estava querendo fazer.

quinta-feira, 16 de setembro de 2010

Mensagens de Erro do Azure Tables

O Azure Table Storage, ou Azure Tables, ou ainda ATS, é um mecanismo de acesso a dados via REST, baseado em HTTP. Chique, hein? Poizé, basicamente isso quer dizer que você acessa dados no ATS mandando comandos em pacotes HTTP request para o servidor, e ele responde enfiando os dados em um pacote HTTP response e mandando de volta pra você.

Como HTTP é o idioma de comunicação, quando acontece um erro, faz sentido que este erro seja retornado como um código de erro HTTP. E aí as coisas podem ficar um pouco “estranhas” de interpretar. Por exemplo, se você, navegando na Internet, acessa uma URL que não existe, o servidor retorna um erro 404 – Page Not Found. Em REST, se você tenta acessar uma linha que não existe, é retornado o erro 404 – Resource Not Found. Faz sentido, mas da primeira vez que acontece, a gente fica parado olhando pra tela e imaginando o que diabos aquele erro 404 significa, porque “eu tô acessando uma tabela, e não uma pagina na Internet, uai”.

Já coloquei 2 posts sobre essas peculiaridades das mensagens de erro do Azure, que apareceram quando começamos a estudá-lo aqui na empresa. Mas agora que estamos fazendo um projeto cuja camada de dados é o Azure Tables, e estamos codificando pesado em cima dele, estão aparecendo mais destas “peculiaridades”. Então vou lista-las aqui, na esperança que poupe vários “uai’s” pro pessoal mexendo com o Azure.

1. As exceções DataServiceRequestException e DataServiceClientException

Quando acontece um erro de acesso a dados no ATS, geralmente a exceção retornada é do tipo DataServiceRequestException. E a mensagem de erro é “An error occurred while processing this request”. Esta exceção mais genérica encapsula uma exceção mais específica, do tipo DataServiceClientException. Esta exceção contém, na sua propriedade Message, um documento XML que descreve o erro ocorrido. Algo neste estilo:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <code>EntityAlreadyExists</code>
    <message xml:lang="pt-BR">The specified entity already exists.</message>
</error>

O interessante deste XML é o elemento code, que “quase” especifica o quê realmente aconteceu. “Quase” porque este código deve ser interpretado de acordo com a ação que a aplicação estava executando no momento do erro. Por exemplo, o código InvalidInput pode significar que durante a gravação de uma entidade, foi detectado que ela tem uma propriedade de um tipo de dados que não é suportado pelo Azure Tables; OU pode significar que foi feita uma consulta a uma tabela que acabou de ser criada, e sendo assim, ela não tem sua estrutura de colunas definida. Mas o importante é verificar o quê veio neste elemento code do XML contendo a mensagem de erro, e interpretar eta informação.

2. Códigos de erro e possíveis causas

A seguir está a listagem dos códigos de erro com os quais já esbarramos, e o que a aplicação estava tentando fazer quando o erro foi gerado.

Código de Erro
(valor do elemento code)
Possíveis Causas
ConditionNotMet - Erro de acesso concorrente. A aplicação leu uma entidade; ao tentar alterar ou excluir esta entidade, ela já havia sido alterada por um comando de gravação de dados em outro contexto.
EntityAlreadyExists - Erro de chave primária. A aplicação tentou inserir uma entidade em uma tabela, e já existe na tabela outra entidade com os mesmos valores de Partition Key e Row Key da entidade sendo inserida.
InternalError - Uso de operadores Linq não suportados pelo Azure Table Storage. (O caso com o qual esbarramos foi recuperar todas as entidades nas quais uma propriedade string começava por um determinado valor. Nada de like, nem operadores de desigualdade (> e <), nem de string.StartsWith() – que foi quem gerou o erro).
InvalidInput - Gravação de entidade que tem propriedade cujo tipo não é suportado pelo ATS.
- Gravação de entidade que foi anexada ao contexto (TableServiceContext.AttachTo()), mas que está com a propriedade ETag nula.
- Consultas Linq em uma tabela que ainda não sofreu nenhuma inserção de entidades.
- Consultas Linq que usam tipos anônimos. Tivemos que fazer uma consulta que trazia as entidades desejadas do Azure, e em cima destas entidades, fazer outra consulta usando os tipos anônimos. Aí tudo funcionou ok.
- Gravação em batch (SaveChanges(SaveOptions.Batch)) na qual havia 2 ou mais entidades com as mesmas Partition e Row Key.
ResourceNotFound - Consulta Linq que usa condição de igualdade nas propriedades PartitionKey e RowKey da tabela sendo consultada (where entity.PartitionKey == “…” && entity.RowKey == “…”) e que não retornam linhas. (Consultas que usam condição em outras propriedades retornam uma lista vazia)
- Erro de acesso concorrente. A aplicação leu uma entidade; ao tentar alterar ou excluir esta entidade, ela já havia sido excluída por um comando de gravação de dados em outro contexto.
- Consulta Linq em tabela que não existe no ATS.
TableAlreadyExists Encontrado durante chamada a CloudTableClient.CreateTablesFromModel(). Aparentemente chamadas concorrentes a este método podem gerar esta exceção. Colocamos uma chamada a CreateTablesFromModel() no construtor estático da nossa classe de contexto de acesso a dados. Quando aumentamos o número de instâncias do role no Azure para 2, uma das instâncias subia ok, e a outra gerava esse erro.
TableBeingDeleted Idem a TableAlreadyExists acima.
OutOfRangeInput Gerado ao gravar uma entidade que tinha uma propriedade DateTime não inicializada. O valor mínimo de uma propriedade DateTime no Azure é 01/jan/1601 00:00:00, mas um valor DateTime não inicializado no C# contém a data 01/jan/0001. Não deu pau no DevStorage porque ele converte valores menores que 01/jan/1753 pra 01/jan/1753, mas o ATS não faz isso.

3. Como extrair o código de erro da exceção DataServiceClientException

Primeiro criamos um enum cujos nomes de elemento são exatamente iguais aos códigos de erro retornados pelo ATS.


public enum CausaErrosDataServiceException
{
    EntityAlreadyExists,
    ConditionNotMet,
    InvalidInput,
    ResourceNotFound,
    Desconhecido
}

Depois criamos uma funcão que:
- Recebe uma exceção qualquer;
- Procura por uma exceção interna do tipo DataServiceClientException;
- Uma vez que ache esta exceção, extrai o valor do elemento /error/code presente no XML da mensagem de erro, o transforma num dos valores do enum acima, e retorna este valor.

/// <summary>
/// Traduz uma exceção acontecida no Azure para um dos valores do enum CausaErrosDataServiceException.
/// </summary>
/// <param name="erro">Exceção ocorrida no acesso ao Azure.</param>
/// <returns></returns>
public static CausaErrosDataServiceException CausaErro(Exception erro)
{
    // Procura na pilha de exceções um erro da classe DataServiceClientException
    while (!(erro is System.Data.Services.Client.DataServiceClientException) && (erro != null))
        erro = erro.InnerException;
    if (erro == null) return CausaErrosDataServiceException.Desconhecido;

    // Neste momento já foi encontrado um erro do tipo DataServiceClientException, então a propriedade Message
    // contém um XML válido descrevendo o erro
    CausaErrosDataServiceException causa;
    try
    {
        XmlDocument xmlErro = new XmlDocument();
        xmlErro.LoadXml(erro.Message);
        // O XML descrevendo um erro usa o namespace http://schemas.microsoft.com/ado/2007/08/dataservices/metadata, então
        // é necessário criar um XmlNamespaceManager para poder referenciar os nós do documento no XPath
        XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlErro.NameTable);
        namespaceManager.AddNamespace("n", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
        // Faz consulta XPath para recuperar o elemento "<code>", que contém uma constante determinando a causa do erro
        string s = xmlErro.SelectSingleNode("/n:error/n:code", namespaceManager).InnerText;
        // Traduz esta constante para o enum CausaErrosDataServiceException
        causa = (CausaErrosDataServiceException)Enum.Parse(typeof(CausaErrosDataServiceException), s);
    }
    catch
    {
        causa = CausaErrosDataServiceException.Desconhecido;
    }
    return causa;
}

À medida em que você for esbarrando com mais códigos de erro do Azure, você pode acrescenta-los no enum com os códigos de erro, para que eles sejam reconhecidos pela função CausaErro().

quarta-feira, 15 de setembro de 2010

Dev@SrNimbus: Modelar x Estimar

(Eu vou juntar os posts “Dev@SrNimbus” depois em algum lugar, mas estou encontrando algumas “verdades quase evidentes” que é o tipo de coisa que vale a pena registrar. A verdade quase evidente é aquela que todo mundo, após lê-la, diz “mas isso é evidente!”. É. É evidente, mas você só se toca pro fato depois que alguém mostrou ele pra você.)

A seção 8 apresenta uma forma de estimar, priorizar e planejar um projeto de desenvolvimento de software […]. Contudo, você deve manter em mente que […] estas questões são em grande parte irrelevantes até que o seu time tenha aprendido a entregar, de forma consistente, um produto de qualidade que traga valor ao cliente.

Visual Studio Tem System: Better Software Development for Agile Teams, Section 8

Não adianta esforços para melhorar o seu processo de criação e gerenciamento de estimativas se você ainda não tem um processo bem definido para o levantamento e implementação destas funcionalidades. O processo de levantamento e implementação é a base para o processo de estimativas e priorização. O primeiro fornece dados para o segundo. Se o primeiro não está produzindo dados sólidos, o segundo processo, por melhor que seja, não gerará resultados satisfatórios.

Em uma metodologia Ágil, que é a que escolhemos implementar aqui na Sr. Nimbus, o processo de levantamento e implementação de funcionalidades necessita a incorporação de várias práticas na cultura da empresa:

  • Uso de mecanismo de controle de versão;
  • Build e integração frenquentes;
  • TDD;
  • Modelagem da aplicação.

Hoje já fazemos o TDD razoavelmente bem, e fazemos o uso “comum” do TFSCC - Team Foundation Source Code Control, o mecanismo de controle de versão do TFS. Sempre li sobre a prática “build & integrate often” de Agile, mas só recentemente, ao ter que integrar o trabalho executado em 3 frentes distintas do projeto, vi o valor que esta prática pode trazer. No quesito “modelagem”, ainda fazemos isto de forma completamente artesanal, sem nenhum processo que embase esta prática.

Então, por mais doída que seja esta afirmação, ainda não estamos em um ponto para desenvolver um processo formal de estimativa de esforço. Claro que estimamos, mas de forma informal, e não raramente, estas estimativas contém uma variação grande. O que estamos buscando é uma forma de diminuir esta variação – e a formalização de um processo de estimativa ajudará nisto. Mas a principal lição aqui é que esforços para a formalização do processo de estimativas e priorização só produzirão resultados concretos após a incorporação das 4 práticas citadas acima no nosso processo de levantamento e implementação de funcionalidades. Esse vai ser nosso “roadmap” para a implementação de um processo de gerenciamento do ciclo de vida de um projeto de software.

sexta-feira, 3 de setembro de 2010

Criar link "Executar como Administrador"

O Visual Studio requer que ele seja executado como administrador para você poder rodar aplicações dentro do Development Fabric e/ou usando o Development Storage do Azure. Para evitar ter que clicar com botão direito e selecionar "Executar como Administrador" toda vez que você vai rodar o VS, modifique o link do Visual Studio para já executar automaticamente como Administrador. Nas propriedades do link, selecione o botão "Avançados", e marque a opção "Executar como administrador":



(De qualquer modo, ainda aparece aquela mensagezinha irritante "Deseja que o programa a seguir faça alterações nesse computador?" do UAC - User Access Control, ou Controle de Conta de Usuário. Você pode desabilitar o UAC no Painel de Controle > Sistema e Segurança > Alterar Configurações de Controle de Conta de Usuário, mas fique avisado de que seu computador fica menos protegido porque blábláblá blábláblá blábláblá.)

quinta-feira, 26 de agosto de 2010

Como apagar um work item do TFS

O TFS 2010 não tem na sua interface gráfica um comando para apagar um work item. Isso pode ser um incômodo em algumas situações, como p.e., quando você criou o work item como filho do "pai errado". Para apagar um work item do TFS é necessário rodar uma ferramenta de linha de comando. Em C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE, execute
witadmin destroywi /id:215 /collection:http://servidortfs:8080/tfs/DefaultCollection
aonde "215" é o Id do work item a ser apagado, "servidortfs" é o nome do seu servidor TFS, e "DefaultCollection" é o nome da coleção de projetos aonde seu projeto está.

segunda-feira, 23 de agosto de 2010

exFat: Um sistema de arquivos melhor para pendrives

Outro dia fui transferir um arquivo VHD de 8 Gb com uma instalação de SharePoint 2010 dentro. Não consegui copiar o arquivo pro meu pendrive de 16 Gb, apesar de haver espaço livre. O problema é que FAT32 (que é o sistema de arquivos comumente usado em pendrives e outras mídias removíveis) só suporta arquivos de até 4 Gb. ("só" e "4 Gb" na mesma frase. Caraca, e meu primeiro HD tinha 10Mb. Tô ficando velho...)

Bem, achei o tal de exFat na caixa de opções de sistema de arquivos da tela de formatação do pendrive. Basicamente o exFat é o FAT32 com limites aumentados (tamanho do arquivo de 4Gb para 16 Eb, ou bi-lhões de Gb; número de arquivos em um subdiretório de 65.000 para 2.7 milhões; tamanho da partição de 32 Gb para 512 Tb), e com melhorias internas de performance para lidar com fragmentação - o que é comum em mídias removíveis, aonde toda hora gravamos, apagamos e regravamos coisas. Ótima opção pra seu pendrive novo, ou até praquele HD externo que você carrega pra cima e pra baixo na mochila. Só tem que lembrar das restrições: leitura nativa só do Vista SP1 pra cima e Windows 7 (isso provavelmente inclui o 2008). No XP e no 2003 pode ser acessado via instalação de um update. Outros SO's, nem pensar... Mas como todas as minhas máquinas são Windows, pra mim tá ótimo.

Erro ao iniciar Azure Development Storage

Quando fui executar o Develpment Storage do Azure na minha máquina, deu pau. Só que o link pra disparar o DevStorage chama uma aplicação de linha de comando, e só dá pra ver que a aplicação mostra uma mensagem de erro de 5 linhas e fecha. E o arquivo LNK pra disparar o DevStorage não diz qual é a linha de comando executada.
Dica 1: Para disparar o Development Storage do Azure "na mão", entre em um prompt de linha de comando do Azure (Iniciar > Todos os Programas > Windows Azure SDK > Windows Azure SDK Command Prompt), e rode o comando csrun /devstore.
(Obviamente esta dica deve ser precedida da Dica 0: Para o Azure funcionar na sua máquina, instale o Windows Azure Tools for Visual Studio)

Ok. Aí consegui ver a mensagem de erro:
Encountered an unexpected error from the devstore: Unable to start Development Storage.
Error Details: Failed to start Development Storage: the SQL Server instance 'localhost\SQLExpress' could not be found. Please configure the SQL Server instance for Development Storage using the 'DSInit' utility in the Windows Azure SDK.

É, nada melhor do que conseguir ler a mensagem de erro pra solucionar o erro. Como já tenho um SQL Server instalado na minha máquina, rodei dsinit /sqlinstance:. (dsinit /sqlinstance "doispontos" e "ponto", pois "ponto" designa a instância default não-nomeada do SQL Server), e o Development Storage rodou.


Update: Essa mesma solução funcionou para sintomas diferentes. Criei uma conta para outro usuário que vai trabalhar na máquina. Na hora que ele logou e tentou iniciar o Dev Storage, apareceu uma tela de setup e depois de um tempo apareceu a mensagem “Falha durante a instalação”. Executei o mesmo procedimento acima e o Dev Storage rodou.

Dicionário online gratuito: Wikcionário

http://pt.wiktionary.org/

Foi lá que descobri que passei um sério risco ao mandar um e-mail para a equipe de projeto. Eu ia perguntar se ele discordavam de mim, só que:

dis.cor.dar
1.ter opinião oposta à de outra pessoa

e

des.cor.dar transitivo
1.(Portugal) Nas touradas, cortar a medula espinhal do boi.

Imagina se alguém não gosta das minhas idéias e resolve descordar de mim...

terça-feira, 17 de agosto de 2010

Entrevista com GB ;-)

Olha a criatividade desse povo: recebi um convite pelo Twitter para uma entrevista. Pela cara o convite foi gerado por um robozinho. E o site - Who-Hub.com - é um site de coletânea de entrevistas. Cada idéia...

Na entrevista dou uma geral nas idéias que tenho na área de tecnologia, e a participação da Sr Nimbus nisso. Ela está em http://www.who-hub.com/gbuchoa.

sexta-feira, 6 de agosto de 2010

Dev@SrNimbus: Scrum & TDD

Hola.

A Sr. Nimbus é uma empresa jovem, porém com uma grande bagagem. Atuando como “mão-de-obra sócia”, eu (GB) e o Luciano (Luti) trazemos nossa experiência de trabalho em desenvolvimento – eu estive por 17 anos na Hepta Tecnologia, uma das principais parceiras Microsoft no Brasil, trabalhando com consultoria, desenvolvimento e instrutoria. O Luti também esteve por lá, mas o que mais pesa no currículo dele são os 3 anos como Field Engineer em SQL Server na própria Microsoft, reconhecidos recentemente com o título de MVP (Most Valuable Professional) em SQL Server, um dos poucos aqui no Brasil.

Digo isto porque o assunto que vou abordar necessita mais do que somente a parte acadêmica. Como empresa de desenvolvimento de soluções, e após ter visto mais de um projeto com uma boa equipe naufragar por não ter metodologia e não ter um gerenciamento efetivo, nós criamos nosso processo de desenvolvimento de soluções. E o resultado está muito interessante. Tão interessante, de fato, que resolvi compartilhar um pouco da nossa experiência, na esperança que o relato de nossos acertos (e erros também, claro) venham a ser úteis para quem chegar a ler isto.

Quando fomos criar nosso processo de desenvolvimento, nos preocupamos basicamente com os seguintes pontos:
  1. Agilidade. Uma empresa pequena não tem muitos “recur$o$”. Temos que fazer nosso tempo render!
  2. Qualidade. Acho que *todas* as empresas do mercado falam em “fazer com qualidade”. São raras as que entregam com qualidade. Estranhamente, a qualidade não aparenta mais ser um diferencial, pois o cliente já está acostumado a promessas que não são cumpridas. Mas a qualidade não deixou de ser um diferencial; ela é um diferencial “a longo prazo”. Seu cliente, como gerente de uma área de TI, certamente vai reparar no seguinte: Dos sistemas que temos,
    - qual é o sistema que “explode” menos na cara do usuário?
    - qual é o sistema que experimenta o mínimo de downtime?
    - qual é o sistema que responde mais rápido a solicitação de implementação de novas funcionalidades? E sem quebrar as funcionalidades que existiam antes?
  3. Transparência. O cliente investe dinheiro em nós para receber uma ferramenta que melhore o seu trabalho. Para onde este dinheiro está indo? Será que ele vê a ferramenta crescer, desde quando ela era apenas uma lista de funcionalidades, passando pelas primeiras releases, aonde ele fica meio frustrado (“pô, pensei que ia ter mais coisa…”) até a ferramenta começar a se tornar algo útil no trabalho dele? Ele se envolve? É parte da equipe, se envolvendo com a definição de rumos do trabalho? Ou fica só em pé na amurada, pronto pra pular fora caso algo dê errado e apontar o dedo pra você?
Existem muitos outros aspectos que devem ser considerados ao se criar um processo de desenvolvimento de software, mas temos que começar em algum lugar. Levando estes 3 aspectos em conta: fazer o mais rápido possível, mantendo uma barra de qualidade alta, e mostrando isto para o cliente, selecionamos duas disciplinas – um framework de gerenciamento de projetos e uma prática de desenvolvimento de software – que, na nossa opinião, permitem alcançar quase que naturalmente estes objetivos. Estas disciplinas são o Scrum e o TDD.

Scrum

O Scrum é um framework para gerenciamento de projetos focado na entrega de produtos, ao invés de focar em fases ou marcos, como é comum para outros frameworks. Para saber mais sobre o Scrum, o melhor é ir direto na fonte, o site Scrum.org, fundado por Ken Schwaber, um dos criadores do Scrum. O Guia do Scrum é uma publicação gratuita, que dá uma visão rápida de 20 páginas do Scrum. Uma visão mais rápida ainda é fornecida pelo site ScrumAlliance:

  • O Product Owner cria uma lista priorizada de características desejadas para o produto, que é chamada de Product Backlog.
  • É iniciada uma iteração, chamada de Sprint, com uma reunião de Planejamento da Sprint (Sprint Planning). A equipe de projeto, ou Time, seleciona um pequeno grupo dos itens mais prioritários do Product Backlog, que irão constituir o Sprint Backlog, e decidem como implementar estes itens, acrescentando detalhes ao Sprint Backlog.
  • O Time tem um período de tempo fixo – a duração da Sprint - para implementar estes itens. Uma Sprint deve durar de 2 a 4 semanas. O Time deve selecionar os itens do Sprint Backlog de forma tal que a execução do Sprint Backlog caiba dentro da duração escolhida para a Sprint.
  • Diariamente, o Scrum Master (o “coordenador” do Time) organiza uma reunião rápida (Daily Scrum, de onde vem o nome do framework), de 10-15 minutos, aonde cada membro do Time responde a 3 perguntas: Quais dos itens do Sprint Backlog você fechou ontem? Em quais itens do Sprint Backlog você vai trabalhar hoje? Você vê algum impedimento para completar o seu trabalho de hoje? Isto ajuda a manter o Time focado na entrega dos produtos da Sprint, e torna visível qualquer possível impedimento, permitindo que ele seja tratado o mais cedo possível.
  • No final da Sprint, o trabalho realizado deve ser “potencialmente entregável” (“potentially shippable”, de acordo com o Scrum Guide): pronto para ser entregue a um cliente, ser comercializado, ou poder ser mostrado a um patrocinador do projeto.
  • A Sprint acaba com uma Revisão da Sprint (com o cliente) e uma Retrospectiva da Sprint (internamente ao Time, para correções e melhorias no processo).
  • O ciclo se reinicia com uma nova reunião de Planejamento da Sprint.
Estes ciclos se repetem até que o produto seja considerado completo o suficiente, o orçamento acabe, ou seja alcançada uma deadline considerada “final” para o projeto. Independente do fato que provoca o término do projeto, Scrum guia o trabalho de forma que o trabalho mais importante esteja completado quando o projeto termina.
Texto adaptado de “What is Scrum”, http://www.scrumalliance.org/pages/what_is_scrum
Scrum se adapta bem a dois de nossos pontos iniciais: agilidade, pois é um framework “sem frescura”, com poucos artefatos, e artefatos que você pode imediatamente ver que são úteis; e transparência, ao tornar visível qualquer problema o mais cedo possível, tanto dentro da equipe (no daily scrum) quanto para o cliente (na Sprint Review). Uma outra característica que nos atraiu no Scrum é que a natureza dinâmica e incremental do Product Back e dos Sprints Backlogs permite que se comece o desenvolvimento sem que se tenha feito um levantamento completo dos requisitos do sistema. Isto é um pecado capital em outras metodologias, mas tem funcionado bem:
  • Isto permite que nós entremos no desenvolvimento o mais cedo possível.
  • Desenvolver logo permite que mostremos resultados para o cliente cedo.
  • Mostrar resultados cedo – e frequentemente - aumenta o envolvimento do cliente com o projeto, e permite que qualquer desvio de rumo seja alcançado com pequenos ajustes.
(Sim, há uma grande questão aqui. Temos um orçamento pré-aprovado e um prazo fixo dentro do qual estamos trabalhando. Ou seja: Não foi necessário apresentar valor global ou cronograma para o projeto inteiro. Como eu poderia fazer isto sem ter feito um levantamento detalhado? Esta será uma pergunta a responder “nos próximos capítulos”)

TDD – Test Driven Development

Scrum traz agilidade e transparência, mas ainda precisávamos de algo que nos desse qualidade. O TDD – Test Driven Development, ou Desenvolvimeno Orientado a Testes – entrou no nosso processo com este objetivo. O TDD é uma prática de desenvolvimento de software na qual você codifica pequenos programas que testam o seu código antes de codificar o código a ser testado. Um pequeno exemplo:

O sistema deve bloquear a conta de um usuário que erre o login 3 vezes seguidas, para evitar ataques ao login deste usuário.”

Testes:

Usuario.Cadastra(“gilberto.uchoa@srnimbus.com.br”, “1234”); 
// Testa credencial incorreta 
if (Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “6789”) == true) 
    throw new Exception(“Credencial incorreta passou validação”); 
// Testa credencial ok 
if (Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “1234”) == false) 
    throw new Exception(“Credencial correta não passou validação”); 
// Erra 2 vezes o login. Na 3a vez o login correto deve ser aceito 
Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “xxxx”); 
Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “yyyy”); 
if (Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “1234”) == false) 
    throw new Exception(“Credencial correta não passou validação com 2 tentativas erradas”); 
// Erra 3 vezes o login. Na 4a vez, o login correto deve ser barrado 
Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “xxxx”); 
Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “xxxx”); 
Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “yyyy”); 
if (Usuario.Valida(“gilberto.uchoa@srnimbus.com.br”, “1234”) == true) 
    throw new Exception(“Credencial correta deveria ser barrada após 3 tentativas erradas”);

Neste ponto, a classe Usuario ainda nem existe. Mas já tenho um código que a testa. Isto traz vários benefícios:
  1. Os testes que codifiquei representam as “situações importantes” da classe Usuario. Isto define um nível de qualidade que deve ser alcançado pelo código a ser construído para a classe.
  2. Já tenho um teste automatizado para a classe Usuario. Posso alterar o código e verificar se a classe continua funcionando após a alteração – basta rodar o teste.
  3. A classe Usuario ainda não existe, mas ao codificar o teste, “inventei” que ela terá um método bool Valida(string, string), para validar uma credencial. Ou seja, os testes geram o meu Diagrama de Classes (quais serão as classes de alto nível da aplicação e seus respectivos membros).
O ponto 1 garante um nível de qualidade na criação do código (que será tão alto quanto meus testes forem exigentes).

O ponto 2 protege a estabilidade do produto frente a mudanças no código. Isto é importantíssimo para o Scrum: como os itens do Product Backlog só são detalhados quando entram em uma Sprint, detalhes descobertos em uma Sprint podem causar modificações no código já pronto em Sprints anteriores. Se você está usando TDD, não importa: modifique o código, re-execute os testes, e verifique se tudo continua ok (ou veja que há algo errado, e use a informação dos testes para fechar rapidamente na causa do erro).

O ponto 3 mostra como a escrita dos testes cria a modelagem de classes da aplicação. Você cria as classes e seus membros ao efetivamente usá-los em código, o que traz uma grande probabilidade de que esta seja uma boa modelagem.

Isto É Tudo?

Não. Há vários aspectos de um processo de desenvolvimento de software que não são cobertos no espaço {Scrum + TDD}. Mas considere o seguinte:
  • Scrum mantem o projeto andando, com revisões frequentes para correção de rumo, e com entrega de produtos.
  • TDD cria um nível de qualidade, e protege este nível, além de ter um efeito colateral valioso: gerar a especificação das classes do código.
Temos que começar em algum lugar. Se você conseguir criar na sua organização um processo que naturalmente faz o barco andar, facilita detectar e corrigir desvios de rumo, e permite criar e manter um nível aceitável de qualidade, parabéns. Sua organização já faz mais do que produzir código de qualidade incerta, de forma não-controlada, e gerenciar a insatisfação do cliente com a forma de trabalho, e do usuário o produto do trabalho – o que é uma situação comum no mercado atual. Caso este seja o seu caso, se revolte :-). Revoluções, quando bem motivadas, são uma boa coisa. Procure formas de melhorar, e avalie o uso da dupla Scrum + TDD como um início para a melhoria no seu processo de desenvolvimento de software.

terça-feira, 3 de agosto de 2010

Listar arquivos com check out no TFS

O Visual SourceSafe tinha uma opção de menu bem legal: "Status Search", que permitia ver todos os arquivos "checautados" por alguém. O TFS Source Control Explorer não tem esta opção (ainda, espero) na sua interface, mas existe um utilitário de linha de comando chamado TF.EXE que faz isto.

Abra um prompt de comando, e vá para o diretório %Program Files%\Microsoft Visual Studio 10.0\Common7\IDE (%Program Files% em Windows de 64 bits é o diretório "Program Files (x86)"), e execute a seguinte linha:

tf status $/...ponto_raiz_da_verificação /recursive /user:*

Se houver aquivos checautados por alguém, eles serão listados.

sábado, 17 de julho de 2010

Curto-circuito no C#!!!

A seguir está um código que recebe duas strings, e se a conversão de ambas para valores int for feita com sucesso, realiza um processamento qualquer. Se qualquer uma das conversões falhar, o processamento não é executado, e a conversão inválida deve ser escrita em um log de erros.


int int1 = -1, int2 = -1;
if (int.TryParse(string1, out int1) && int.TryParse(string2, out int2))
{
// Conversões ok - usa os valores em int1 e int2
}
else
{
// Pelos menos uma das conversões falhou - loga o erro
if(int1 == -1) LogaErro("Erro ao converter string1");
if(int2 == -1) LogaErro("Erro ao converter string2");
}


Testei o código com string1 = "XX" e string2 = "000001". E o erro que apareceu no log foi "Erro ao converter string2"!!!


[...Tire alguns momentos para revisar o código e tentar ver o que deu errado...]


O problema é que C# realiza a avaliação de uma expressão booleana em "curto-circuito" (shor-circuit boolean evaluation), ou seja, a expressão é executada até o ponto no qual se conheça seu resultado; os "pedaços" restantes da expressão não são executados. Se string1 = "XX" e string2 = "00001", ao executar a linha

if (int.TryParse(string1, out int1) && int.TryParse(string2, out int2))

o primeiro int.TryParse() falha, já que "XX" não é um número válido. E duas coisas acontecem:

Coisa 1: Como o primeiro int.TryParse() retornou falso, o resultado da expressão já é conhecido, pois (falso && qualquer coisa) é falso. Então o segundo int.TryParse() não roda.

Coisa 2: Quando int.TryParse() falha, ele coloca 0 (zero) como valor do inteiro que armazenaria o resultado da conversão (o segundo parâmetro).

Como resultado da coisa 1, int2 permance com o valor inicial -1. Como resultado da coisa 2, int1 recebe 0. Então quando o else é executado, o programa entende que a conversão de string1 (valor "XX") deu certo, enquanto que a conversão de string2 (valor "000001") deu errado! De forma geral, devem ser evitadas na expressão booleana de um if chamadas que modificam dados, pois como C# usa avaliação booleana em curto-cirtuito, pode ser que nem todas as partes da expressão sejam avaliadas, o que podem causar resultados imprevisíveis no código.

Para corrigir o código inicial, devemos então fazer as chamadas a int.Parse() antes do if:


int int1, int2;
bool conversao1ok = int.TryParse(string1, out int1);
bool conversao2ok = int.TryParse(string2, out int2);
if (conversao1ok && conversao2ok)
{
// Conversões ok - usa os valores em int1 e int2
}
else
{
// Pelos menos uma das conversões falhou - loga o erro
if(!conversao1ok) LogaErro("Erro ao converter string1");
if(!conversao2ok) LogaErro("Erro ao converter string2");
}

domingo, 20 de junho de 2010

Máquina de Testes usando Boot de um VHD

A Microsoft disponibiliza uma VM de testes do SharePoint 2010, com um monte de coisas instaladas. Mas se você quer fazer uma instalação do zero, uma ótima opção é fazer boot de um VHD. Meu notebook "só" tem 4GB de RAM, então eu podia dedicar 2.5, 3GB no máximo para a VM do SharePoint. Se fosse só o SharePoint Foundation, até ia.

(Dica: dentro da VM do SharePoint, restrinja o uso de memória do SQL Server para algo em torno de 400Mb. Como é pra testes, isto não vai impactar a performance do SharePoint, e evita que o SQL Server engula toda a memória da VM. Isto vale para qualquer ambiente de testes do SharePoint, não só pra VM da MS)

Bem, o SP Foundation até consegue rodar em 2GB RAM, mas se você subir a VM de testes da MS, que tem o SharePoint Server + Office 2010 + Visual Studio 2010 + ..., aí o pobre do note senta. Aí entra essa alternativa de boot from VHD.

Encontrei essa estória ao procurar a VM de testes do SharePoint, e é muito legal. Basicamente, você cria um VHD, que é um arquivão que contém um disco para uma máquina virtual do Virtual PC ou Hyper-V, e dá um boot na sua máquina subindo como sistema operacional host o Windows que está instalado no VHD. Você não vai subir uma VM; sua máquina vai enxergar o VHD como se fosse um disco físico, e dar boot por ela. A grande vantagem de usar o boot pelo VHD é que todo o hardware da sua máquina é usado para rodar este boot; não é como no caso de uma máquina virtual, no qual ela divide o hardware com o sistema operacional host. A opção de boot pelo VHD também suporta os discos diferenciais (differencing disks) que o Virtual PC e o Hyper-V suportam, o que é outra ótima funcionalidade para um ambiente de testes: você cria um VHD diferencial em cima de uma instalação base, destrói o SharePoint no VHD diferencial com testes, e depois é só jogar esse VHD diferencial fora e criar outro, e você tem uma instalação SharePoint zerada na mão.

Criei um ambiente de testes para o SharePoint 2010 com um VHD de disco diferencial seguindo os seguintes passos:
  1. Usando o artigo "Boot W2K8 from VHD within W7", criei um VHD bootável com uma instalação de Windows 2008. Instalei o SharePoint, Office, Visual Studio e etc etc etc.
  2. Depois criei um disco diferencial em cima do VHD do passo 1. Em um command prompt de administrador, entre no diskpart e use o comando
    create vdisk file=c:\testedif.vhd parent=c:\teste.vhd, onde testedif.vhd é o VHD diferencial e teste.vhd é o VHD base criado no passo 1.
  3. Em seguida, criei a entrada no boot manager da minha máquina com o bcdedit, que é um comando para o gerenciamento das entradas no boot manager. Em um prompt de comando de administrador faça o seguinte:
    a. Use bcdedit /copy {current} /d "descrição" para copiar sua entrada de boot atual para uma nova entrada. O bcdedit /copy mostra o ID da nova entrada de boot; copie-a para o clipboard, ela será necessária para os próximos comandos.
    b. Rode o seguinte para apontar a nova entrada de boot para o seu VHD:
    bcdedit /set {boot_identifier} device vhd=[c:]\path_to_vhd\vdhfile.vdh
    bcdedit /set {boot_identifier} osdevice vhd=[c:]\path_to_vhd\vhdfile.vhd
    bcdedit /set {boot_identifier} detecthal yes

    (boot_identifier é o ID da nova entrada gerada no passo a;
    vhd_file.vhd é o arquivo VHD diferencial criado no passo 2;
    e [c:]\... tem que ser escrito assim mesmo, entre colchetes)

E pronto. Sua máquina agora terá uma nova entrada de boot apontando para o VHD com a instalação de testes do SharePoint. Quando você tiver destruído o suficiente esta instalação, dê boot pelo sistema operacional "normal", apague o VHD diferencial gerado no passo 2 e crie outro com o mesmo nome. Como a entrada de boot aponta para o VHD pelo nome, ela vai pegar seu novo arquivo diferencial zerado. (Eu já deixei uma cópia do arquivo diferencial zerado junto com o VHD base, que copio por cima do diferencial sendo usado quando quero zerá-lo). Super prático e você usa todo o hardware da máquina para rodar o SharePoint. Agora o SharePoint Foundation no notezinho de 4GB roda que nem uma bala; o SharePoint Server ainda dá umas engasgadas, principalmente logo depois do boot, mas roda muito melhor do que dentro de uma VM. Quando eu colocar mais 2GB de RAM no bichinho aposto que as engasgadas somem ;-)

Só lembrando, essa parada de boot pelo VHD só funciona para Windows 7 Ultimate e Enterprise, e Windows 2008 R2.

sexta-feira, 18 de junho de 2010

MSDN WebCast: Acesse os dados de sua organização através do BCS

Meu primeiro webcast com o pessoal da Microsoft foi nesta terça passada, dia 15/6, sobre o Business Connectivity Services do SharePoint 2010. Segundo a opinião (isenta) do meu sócio, compadre e amigo das peladas de 2a e sábado, o Luti, ficou legal ;-)

Fora um vacilo lamentável da minha parte, perdendo o som do microfone 5 minutos antes do evento - no que fui prontamente ajudado pelo Rogerio Jerez, que me abriu um canal para fazer a apresentação pelo telefone - acho que tudo correu bem.

Se você quiser uma visão geral sobre o BCS e alguns exemplos de como usã-lo para manipular dados da sua organização dentro de uma instalação SharePoint, o endereço é https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=pt-BR&EventID=1032449978&CountryCode=BR. Espero que seja útil!

sexta-feira, 23 de abril de 2010

SharePoint 2010 Liberado Para o Mercado

Sim: SharePoint 2010 "LPM", ou RTM, se vocês acharem uma tradução melhor para Release-To-Manufacturing... http://blogs.msdn.com/sharepoint/archive/2010/04/16/sharepoint-2010-reaches-rtm.aspx

segunda-feira, 29 de março de 2010

Wireless (e Aero) não funciona(m) no Windows 2008

Rarara vai mexer no que você não conhece. Instalei o Windows 2008 no note novo (uma das opções pra instalar a VM de demo do SharePoint 2010). Baixei os drivers do Windows 7 64 bits lá do site da Dell e as coisas foram funcionando beleza. Só que o bichinho não conectava na rede sem fio. A placa tava lá, com iconezinho na bandeja do sistema, sinal "excelente", dizia o Windows 2008, mas nenhuma rede aparecia listada. Depois de 2h e meia baixando e tentando drivers, esbarrei com um artigo na Internet que basicamente me informou que a parte de wireless, como várias coisas no Windows 2008, são agora "features" (pronuncia-se "fítchurs", olha que coisa mais chique). E se a fítchur não está habilitada, você pode instalar 457 drivers de rede que o bichinho não vai nem ver as redes sem fio em volta de você, quanto mais se conectar a uma delas.

Bem, você pode olhar o artigo do iluminado que me ensinou isso, mas basicamente é:

Start > Administrative Tools > Server Manager > Fítchurs > Add New Fítchur > Wireless LAN Service. E pronto, seu computador volta a ver as redes sem fio que haviam sumido...

(Enquanto você está na tela de Add New Feature, talvez você queira também habilitar a "Desktop Experience", que faz o seu Windows 2008 ficar com a cara do Windows 7 - basicamente habilita o Aero no bichinho. Ah e não se esqueça de habilitar e colocar para startup automático o serviço Themes, senão o Aero não funciona).

Ferramentas freeware para trabalhar com arquivos ISO

Estou sempre me esquecendo dessas pragas, então vou deixar anotado aqui. Vai que ajuda mais alguém também.
  • Ferramenta freeware de montagem de ISO como unidade de CD-ROM: MagicDisc.
    Use arquivos ISO como se fossem CD's/DVD's.
  • Ferramenta de geração e gravação de ISO: ImgBurn
    Gere ISO's a partir de arquivos da sua máquina; grave um CD/DVD com o conteúdo de um arquivo ISO.

Todas já testei em Windows 7 32 e 64 bits. Vou testar no W2008 e coloco um update nesse post depois.

Update: MagicDisc funciona no Windows 2008 64
bits.

quarta-feira, 24 de março de 2010

Webcast de SharePoint 2010: Nova data

Após um adiamento no fim de semana passado, por problemas intermitentes nos servidores do Live Meeting, meu webcast sobre o SharePoint 2010 foi remarcado para 01 de maio. Nos vemos lá.

sexta-feira, 19 de março de 2010

WebCast SharePoint 2010 - Lista dos links apresentados

A seguir está a lista dos links apresentados no webcast "SharePoint 2010 - Uma Visão Geral", com vários recursos interessantes para quem está avaliando a nova versão do SharePoint:

segunda-feira, 8 de março de 2010

Microsoft Community Day: Webcast "Sharepoint Server 2010 - Visão Geral"

Mais pro fim do mês irei apresentar o webcast "Sharepoint Server 2010 - Visão Geral", uma rápida introdução ao SharePoint 2010. Como o assunto é muito grande e o tempo é pouco, a palestra irá apresentar aspectos legais do SharePoint 2010 em relação à versão 2007 - desde a nova "Fluent User Interface" até desenvolvimento de Web Parts no Visual Studio 2010. Espero seguir após ela com palestras mais focadas, esmiuçando um assunto específico em mais detalhes.

quarta-feira, 24 de fevereiro de 2010

SharePoint: Minha página customizada não pega o tema do site

Se você criou e/ou customizou páginas em um site SharePoint 2007, e ao mudar o tema do site esta mudança não apareceu nas páginas customizadas, uma possível causa é a ausência do controle ASP.NET que inclui na página as folhas de estilo do tema selecionado. Coloque na seção

<asp:Content ContentPlaceHolderId="head">

do código da página o seguinte:

<SharePoint:Theme runat="server">

Isto faz com que o SharePoint emita no HTML gerado para a página a tag <link> que inclui na página os estilos do tema selecionado para o site.

sexta-feira, 12 de fevereiro de 2010

SharePoint 2010: ambiente de testes

Quem está interessado no SharePoint 2010 e quer montar um ambiente de desenvolvimento pra testar o bichinho, aí vão alguns links úteis:
Destes, o mais interessante é o VHD com o ambiente de teste. Pra quem não conhece, um VHD (ou Virtual Hard Drive) é um arquivo que serve como disco de uma máquina virtual que roda no Virtual PC, Virtual Server ou Hyper-V. Neste caso, você terá que usar o Hyper-V, pois o SharePoint 2010 só tem versão de 64 bits, e nem o Virtual PC nem o Virtual Server rodam VM de 64 bits. Caso você não tenha um Windows 2008 à mão (o Hyper-V só roda no 2008), pode fazer download do Hyper-V Server 2008 R2 - uma versão do Windows 2008 com somente o necessário pra subir o Hyper-V e rodar VM's. Free. Mas não tem interface gráfica - você vai ter que ter uma segunda máquina pra conectar no Hyper-V Server, montar a VM e conectar nela pra trabalhar.

Quem tem uma máquina boa - Quad Core com 8GB de RAM - pode instalar um 2008 e criar a VM lá dentro mesmo. Mas pra mim, com um desktop Pentium D (isso mesmo ;-) e 6GB de RAM, o Hyper-V Server deu uma performance aceitável. Depois conectei nele com o netbook Intel Atom (isso mesmo ;-)) da mulher e comecei a trabalhar.

O VHD de teste do SharePoint 2010 é bem completo. Na verdade são 2 VHD's: um com o SharePoint Server 2010 e "penduricalhos": Visual Studio 2010, Designer 2010, um AD, Office 2010, SQL Server 2008 com Reporting e Analisys Services, e vários sites já criados e populados pra servir de exemplo. O segundo contém basicamente um Exchange Server 2010 rodando, pra testar cenários com integração via messaging.

Não se esqueça de que a máquina rodando a VM - Windows 2008 ou Hyper Server - tem que ser de 64 bits, ou a VM não vai subir.
PS: Dê uma olhada nesse post também: "Máquina de testes usando Boot de um VHD". Fazer uma máquina de testes dando boot por um VHD aumenta sensivelmente a performance do ambiente de testes, porque só há um sistema operacional rodando, ao invés de dois, que é o que acontece quando você roda uma VM.

terça-feira, 2 de fevereiro de 2010

Usando Microsoft.SharePoint.dll para listar o ID das listas de um site

Ao migrar um site de uma web application para outra via o backup do SharePoint Designer (menu Site > Administration > Backup Web Site), várias web parts que eu tinha convertido para XSLT mostravam uma mensagem "estranha":
The server returned a non-specific error when trying to get data from the data source. Check the format and content of your query and try again. If the problem persists, contact the server administrator.
Quando você converte uma web part que mostra uma lista para XSLT, o SharePoint coloca na página um controle do tipo WebPartPages:DataFormWebPart para mostrar os dados da lista. Este controle designa a lista cujos dados devem ser mostrados através de seu ID (cada lista no SharePoint ganha um GUID como identificador, que é armazenado na propriedade ID da lista). Pois bem, quando migrei o site para seu novo local, as listas foram recriadas, e logicamente ganharam IDs diferentes. E aí as web parts que faziam referência a elas via ID pararam de funcionar.

Sendo um geek empolgado, resolvi testar o uso de Microsoft.SharePoint.dll para fazer um aplicativozinho de linha de comando que listasse os IDs das listas de um site. Ridiculamente fácil. O código está a seguir, e é um exemplo legal pra dar uma idéia do uso das classes no namespace Microsoft.SharePoint. Pra quem quiser só usar a ferramenta, é só baixar o seguinte arquivo e rodá-lo no seu servidor SharePoint: SPListId.zip.


Imports Microsoft.SharePoint

Module Module1

Sub Main()
Try
Console.WriteLine()
If My.Application.CommandLineArgs.Count = 0 Then
Console.WriteLine("SPListId - Lista os ID das listas de um site")
Console.WriteLine("Copyright (c) 2010 SrNimbus. No rights reserved ;)")
Console.WriteLine("Uso: SPListId url_do_site")
Return
End If
' A classe System.Uri auxilia na manipulação de endereços de rede
Dim urlSite As Uri = New Uri(My.Application.CommandLineArgs(0))
' A classe Microsoft.SharePoint.SPSite representa uma site collection do SharePoint
Dim siteCollection As New SPSite(urlSite.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped))
' A classe Microsoft.SharePoint.SPWeb representa um site dentro de uma site collection
Dim site As SPWeb = siteCollection.OpenWeb(urlSite.AbsolutePath)
Console.WriteLine("Listas em {0}:", urlSite.OriginalString)
Console.WriteLine("------------------------------------")
' A classe SPList representa uma lista do SharePoint
For Each lista As SPList In site.Lists
Console.WriteLine("{0}: {{{1}}}", lista.Title, lista.ID.ToString().ToUpper())
Next
Console.WriteLine("------------------------------------")
Catch erro As Exception
Console.WriteLine("Ooops:")
Console.WriteLine("{0} - {1}", erro.Source, erro.Message)
Finally
Console.WriteLine()
End Try
End Sub

End Module

Lembre-se de colocar uma referência a Microsoft.SharePoint.dll para poder compilar o projeto. Ela está na máquina do SharePoint, em %ProgramFiles%\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI.

quarta-feira, 20 de janeiro de 2010

Guia Rápido para Content Deployment no SharePoint 2007

Estava eu ralando para preparar uma turma do curso 50149 - SharePoint Operations, ...

Parêntesis: fique longe deste curso. O autor tentou abordar um MUNDO de assuntos relativos à operação de uma instalação SharePoint, mas não entra em detalhes sobre *nenhum* dos assuntos abordados. Isto deixa os alunos extremamente frustrados e/ou desinteressados - o que é sempre triste para mim, como instrutor... (sem contar o lado dos alunos!!!)

Bem, estava eu preparando a aula do capítulo de Content Deployment, e esbarrei com este guia de um cabôco da Máicro chamado Stefan Gossner (ótimo blog sobre SharePoint!). Ele dá uma visão rápida e organizada sobre os principais assuntos relacionados a Content Deployment. Boa leitura para quem está iniciando no assunto. Até o momento, o guia cobre os seguintes assuntos:

Part 1 - The Basics
Part 2 - The Basics continued
Part 3 - Configuration
Part 4 - Communication
Part 5 - Quick Deployment
Part 6 - Logging
Part 7 - Change Token Basics
Part 8 - Job and Change Token

A parte 1 tem um índice com link para os outros posts. Aproveite!