ALM Rangers

Usando o modelo de objeto do cliente do Team Foundation Server

Willy-Peter Schaub
Brian Blackman

Baixar o código de exemplo

Neste artigo vamos apresentar o modelo de objeto do cliente do Visual Studio Team Foundation Server (TFS) e criar a base para uma nova série de artigos do Visual Studio ALM Rangers com foco nas orientações práticas e cenários de codificação comuns com o TFS.

Recapitulando, os ALM Rangers são um grupo de especialistas que promovem a colaboração entre os grupos de produtos do Visual Studio, o Microsoft Services e a comunidade MVP (Microsoft Most Valuable Professional) lidando com a funcionalidade ausente, eliminando os fatores que impedem a adoção e publicando as melhores práticas e diretrizes baseadas em experiências reais.

O Visual Studio TFS diz respeito ao gerenciamento do ciclo de vida do aplicativo (ALM). Diz respeito a capacitar equipes para colaborar, planejar, controlar, projetar, desenvolver, criar e armazenar suas soluções de forma efetiva e segura. Trata da produtividade e de trazer o ALM ao alcance de desenvolvedores de software profissionais, sejam de uma organização pequena, de nível médio ou grande, ou estejam usando um processo formal, ágil ou personalizado, ou trabalhando como equipes virtuais ou rigidamente acopladas. Neste artigo, vou explorar os conceitos de arquitetura básicos que você precisa entender para trabalhar com o TFS e, mais importante, ampliar seus recursos.

Por que a extensibilidade é importante

O TFS inclui ganchos e mecanismos para expandir e aprimorar o produto com novos recursos. Esses novos recursos lhe permitem personalizar a solução ALM do TFS para se adequar ao seu ambiente e para ampliar o TFS com recursos personalizados e comportamentos não criados no produto padrão.

O TFS é uma solução multicamadas, que pode ser acessada de forma programática usando os modelos de objeto adequados. Como mostrado na Figura 1, o modelo de objeto inclui um modelo de objeto de cliente e um de servidor, que podem ser usados para ampliar a camada do cliente ou do aplicativo, respectivamente. Neste artigo, vamos nos concentrar no modelo de objeto de cliente.

Visual Studio Team Foundation Server Architecture
Figura 1 Arquitetura do Visual Studio Team Foundation Server

Embora seja tecnicamente possível acessar os serviços Web ou a camada de dados diretamente, é altamente recomendável acessar os recursos do TFS e os dados através dos modelos de objeto relevantes, conforme mostrado na Figura 1.

Vamos voltar um pouco e explorar a ideia do modelo de objeto do TFS e seus namespaces, que vamos nos referenciar neste artigo e no download do código de exemplo que o acompanha.

O modelo de objeto é o conjunto de classes logicamente decompostas em namespaces e fisicamente distribuídas em um conjunto de assemblies. O modelo de objeto do cliente do TFS é um termo geral que se refere a todas as classes públicas disponíveis nos assemblies Microsoft.TeamFoundation.*.dll.

Os namespaces organizam classes e recursos do TFS em itens similares, o que pode ser comparado ao uso de um gabinete de arquivamento. Cada gaveta representa um modelo de objeto. Cada pasta dentro de cada gaveta representa um namespace, e o conteúdo de cada pasta representa as classes. Bem como um gabinete de arquivamento, o namespace lhe permite categorizar e subsequentemente localizar classes relevantes de forma mais fácil e rápida.

Vamos nos concentrar em começar e criar um cliente usando o modelo de objeto do TFS para se conectar aos serviços Web do TFS. Os serviços do TFS oferecem suporte a recursos específicos como controle de versão, controle de itens de trabalho e eventos.

Configurando um ambiente de desenvolvimento

Vamos usar a linguagem C# e o IDE do Visual Studio É possível também trabalhar com o modelo de objeto com outras linguagens e ambientes, como o Windows PowerShell.

Atualmente, o uso do modelo de objeto do cliente do TFS precisa de uma instalação do SKU cliente, como o Team Explorer, na máquina de desenvolvimento. No futuro, o modelo de objeto do cliente do TFS estará disponível como uma instalação de cliente autônoma.

O Team Explorer está incluído em todas as edições do Visual Studio, exceto Express. Quando tiver o Visual Studio e o TFS instalados, inicie o Visual Studio, conecte-se a um servidor TFS e confirme se você tem permissões de criar, ler, atualizar e excluir (CRUD) para itens de trabalho e controle de código-fonte.

Para este artigo e a maior parte do trabalho de desenvolvimento, usamos um máquina virtual (VM) pública fornecida por Brian Keller da ALM Developer Evangelism Team na Microsoft (disponível em bit.ly/VS2010RTMVHD para a versão Visual Studio 2010 e aka.ms/VS11ALMVM para a versão Visual Studio 2012). Se você baixar a mesma VM, os códigos de exemplo devem funcionar. Se usar o código no seu próprio servidor, poderá ser necessário algumas alterações.

Para trabalhar com o código de exemplo deste artigo, serão necessárias referências aos assemblies .NET Framework do TFS listadas posteriormente. Você obtém esses assemblies ao instalar o Team Explorer.

Práticas recomendadas e diretrizes

Ao desenvolver aplicativos cliente usando o modelo de objeto do TFS, use as seguintes diretrizes:

Use a API do cliente TFS embora a API chame os serviços Web. Acessar as interfaces do serviço Web diretamente não é oficialmente suportado. O modelo de objeto do cliente do TFS ajuda com a autenticação, compatibilidade com diversas versões de servidores, representação, autenticação de dois fatores usando credenciais de cliente e um punhado de outras coisas além de fornecer abstrações limpas e de alto nível nas interfaces do serviço Web. Para alguns clientes (por exemplo, um aplicativo Ruby on Rails sendo executado em *nix), a camada do serviço Web é a única opção. Se você estiver nessa categoria, vale a pena verificar o SDK do Java (consulte bit.ly/irHxgm).

Onde possível, execute operações recursivas em vez de enumerar cada item individual. Por exemplo, exclua a pasta em vez de excluir cada arquivo individual. Essa diretriz nos faz lembrar de algo que aprendemos de Don Box quando participamos de sua sessão na TechEd em Nova Orleans quando tínhamos cabelos bem compridos e não trabalhávamos para a Microsoft: “O tráfego de rede é ruim.” Participamos de sua sessão sobre chamadas de procedimento remotas. Naquele tempo, o código C era usado, mas o que não mudou foi a importância de sua declaração. O tráfego de rede é ruim! Alguns desenvolvedores ainda não aprenderam isso, ou estão aprendendo do modo mais difícil com clientes e consultores reclamando sobre mau desempenho na rede.

Para adotar o mantra “o tráfego de rede é ruim”, tente enviar operações não recursivas em lote e solicite apenas as URLs de download de que precisa, quando precisar delas. Alguma porção do código de exemplo fornecido irá ignorar essa diretriz em tentativas de demonstrar recursos da API.

Ao passar um caminho para uma API, use o caminho do servidor em vez do caminho local. Faça isso porque o último precisa ser convertido no caminho do servidor. Essa conversão exige que o espaço de trabalho do chamador seja identificado, o mapeamento seja carregado, o mapeamento adequado seja determinado e assim por diante, antes de finalmente obter o caminho do servidor.

Use um padrão otimista com suas operações. Assim como com banco de dados, suponha que será bem-sucedido em uma operação de gravação e capture a exceção. Por exemplo, em operações que usam o serviço de controle de versão, não gaste tempo precioso verificando o item antes de operar nele, pois o arquivo poderia ser excluído e, portanto, sua necessidade de manipular exceções seria também. Assim, suponha o melhor e esteja preparado para o pior.

Outra ferramenta para descobrir onde há tráfego de rede ruim é o Microsoft Network Monitor. Não codifique na rede ou depure a rede sem ele. Nenhum pacote pode se esconder dessa ferramenta, e a verdade será revelada. Você pode baixar o Microsoft Network Monitor nos downloads da Microsoft (bit.ly/mMmieH).

Quando estiver em uma associação e não souber por quê, ou como ou por quanto tempo as coisas estão funcionando, ative o rastreamento dos métodos Web. O rastreamento lhe mostrará quais métodos Web são chamados pela API. Ele fornece detalhes como o que foi chamado, a duração da chamada e a resposta SOAP. O rastreamento é ativado pela modificação de seu arquivo application .config na seção system.diagnostics, conforme mostrado na Figura 2. Um exemplo de saída que você encontra em seu arquivo de log está na Figura 3. No entanto, se quiser examinar a carga de SOAP, precisará usar uma ferramenta como o Microsoft Network Monitor.

Figura 2 Habilitando o rastreamento em seu arquivo de configuração

<?xml version ="1.0"?>
  <configuration> 
    <system.diagnostics>
      <switches>
        <add name="TeamFoundationSoapProxy" value="4" />
        <add name="VersionControl" value="4" />
      </switches>
      <trace autoflush="true" indentsize="3">
        <listeners>
          <add name="rangerListener"    
            type="Microsoft.TeamFoundation.TeamFoundationTextWriterTraceListener,
            Microsoft.TeamFoundation.Common, Version=10.0.0.0, Culture=neutral,
            PublicKeyToken=b03f5f7f11d50a3a"
            initializeData="c:\almrangertracing.log" />
          <add name="performanceListener" 
            type="Microsoft.TeamFoundation.Client.PerfTraceListener,
            Microsoft.TeamFoundation.Client, Version=10.0.0.0, Culture=neutral,
            PublicKeyToken=b03f5f7f11d50a3a" />
        </listeners>
      </trace>
    </system.diagnostics>
  </configuration>

Figura 3 Rastreamento de método Web com dados de desempenho

03/17/2012 12:10:14 (pid 2936, tid 4820, 11636 ms) Web method response: [http://servername/tfs/myCollection/VersionControl/v1.0/repository.asmx] QueryWorkspace[VersionControl] 3 ms
03/17/2012 12:10:14 (pid 2936, tid 4820, 11637 ms) CreateWebRequest() -- Uri: http://servername:8080/tfs/myCollection/VersionControl/v1.0/repository.asmx
03/17/2012 12:10:14 (pid 2936, tid 4820, 11637 ms) request.AutomaticDecompression: GZip
03/17/2012 12:10:14 (pid 2936, tid 4820, 11637 ms) Web method running:
http:// servername:8080/tfs/myCollection/VersionControl/v1.0/repository.asmx] UpdateWorkspace[VersionControl]
03/17/2012 12:10:14 (pid 2936, tid 4820, 11658 ms) HTTP headers:
Content-Length: 896
Cache-Control: private, max-age=0
Content-Type: application/soap+xml; charset=utf-8
Date: Sat, 17 Mar 2012 16:10:12 GMT
Server: Microsoft-IIS/7.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET

Compreendendo os assemblies e namespaces

Muitos assemblies e namespaces são expostos pelo modelo de objeto do TFS. Nem todos os assemblies serão abordados nesta série de artigos, apenas os namespaces mais importantes e mais frequentemente usados. Além dos namespaces do TFS comuns, listaremos os principais namespaces do .NET em que o uso do modelo de objeto do TFS tem dependências.

Um padrão comum será conectar-se ao Servidor de configuração do Team Foundation ou uma coleção e listar os servidores registrados ou listar os projetos. Essas tarefas comuns de cliente exigem as seguintes referências: 

// Needed for TfsConfigurationServer
using Microsoft.TeamFoundation.Client;
// Needed for Catalog Resources such as types
using Microsoft.TeamFoundation.Framework.Common;
// Needed for other Catalog Resouces such as nodes
using Microsoft.TeamFoundation.Framework.Client;
// Needed for use of the Version Control service
using Microsoft.TeamFoundation.VersionControl.Client;

O uso de cada um dos serviços disponíveis também exigirá as mesmas referências, como Microsoft.TeamFoundation.VersionControl.Client para o Serviço de controle de versão. Trabalhar com itens de trabalho poderia exigir referências a:

  • Microsoft.TeamFoundation.WorkItemTracking.Client
  • Microsoft.TeamFoundation.WorkItemTracking.Common
  • Microsoft.TeamFoundation.WorkItemTracking.Proxy

A Figura 4 mostra os principais assemblies incluídos com o SDK do TFS, que são encontrados em Arquivos de Programas\Microsoft Visual Studio 10.0\Common7\IDE under ReferenceAssemblies\v2.0 and Private-Assemblies in terms of TFS 2010, ou em Arquivos de Programas (X86)\ ... em um sistema operacional de 64 bits.

Figura 4 Assemblies do SDK do TFS

Namespace

o = Microsoft.TeamFoundation

Descrição
o.client O namespace e os assemblies associados fornecem as interfaces para se conectar ao TFS e para acessar dados relacionados aos projetos da equipe e às coleções de projetos da equipe.
o.framework.client O namespace e os assemblies associados expõem as APIS para visualizar e gerenciar o conteúdo do Registro do TFS, os planos de trabalho, o repositório de propriedades genérico, as assinaturas de eventos, namespaces de segurança, serviços, coleções de projetos da equipe, catálogo e objetos Lab Management.
o.framework.common O namespace e os assemblies associados definem objetos comuns como permissões, exceções e constantes.

 (Observação: o código de exemplo padrão fornecido foi criado e testado com o modelo de objeto do TFS 2010 lançado, recuperando os assemblies referenciados de …\Arquivos de Programas (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0. Para usar o novo modelo de objeto do TFS 11 beta, apenas remova as referências do assembly Microsoft.TeamFoundation.*e as adicione novamente de …Arquivos de Programas (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0 e recompile os aplicativos de exemplo. Você pode usar qualquer um dos modelos de objeto para se conectar aos servidores TFS 2010 e 2012 usando os exemplos padrão.)

Se estiver procurando pela solução de exemplo completa e mais exemplos de códigos do Visual Studio ALM Rangers, ou se quiser contribuir com seus próprios exemplos, visite-nos em bit.ly/M0oyQt.

Nossa primeira aventura de programação

Lembre-se, você precisará das seguintes referências para se conectar a um servidor TFS:

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Client;

Você poderia também ter uma dependência no namespace System.Net para passar credenciais de rede para alguns métodos sobrecarregados, conforme mostrado no código a seguir:

NetworkCredential myNetCredentials =
  new NetworkCredential("Administrator", "P2ssw0rd");
ICredentials myCredentials = (ICredentials)myNetCredentials;

NetworkCredentials são úteis se estiver usando a VM pública do TFS. Depois de ter as referências, é possível conectar-se a um servidor TFS por meio de diversas abordagens diferentes. Você pode se conectar ao servidor de configuração, onde pode obter uma lista de coleções que passam o URI e as credenciais do seu servidor:

Uri tfsUri = @"http://servername:8080/tfs";
TfsConfigurationServer configurationServer =
  new TfsConfigurationServer(tfsUri, myCredentials);

Uma melhor abordagem é solicitar ao usuário as credenciais passando UICredentialsProvider, como mostrado aqui:

TfsConfigurationServer configurationServer =
  new TfsConfigurationServer(tfsUri, new UICredentialsProvider());

Segunda abordagem—Conectando-se a um novo servidor de configuração

Aqui está uma abordagem alternativa quando estiver executando o processo com as credenciais adequadas e quiser evitar ter de se conectar a um novo servidor de configuração:

TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
// Once you have your connection then you can
// get a list of collections on the server
// Get the catalog of team project collections
ReadOnlyCollection<CatalogNode> collectionNodes;
collectionNodes = configurationServer.CatalogNode.QueryChildren(
  new[] { CatalogResourceTypes.ProjectCollection },
  false, CatalogQueryOptions.None);
foreach (CatalogNode collectionNode in collectionNodes)
{
  // Add each collection to the combo box
  cbTPC.Items.Add(collectionNode.Resource.DisplayName);
}

O exemplo anterior exige que você digite um URI em um controle de edição na caixa de diálogo. No próximo exemplo, leremos a lista de servidores registrados no cliente. Servidores registrados são os servidores TFS que foram adicionados ao Visual Studio através de sua caixa de diálogo Connect to Team Foundation Server, conforme mostrado na Figura 5.

Registered Team Foundation Server Dialog Box
Figura 5 Caixa de diálogo do Team Foundation Server registrado

Para ler os servidores registrados no cliente, será necessário uma referência a Microsoft.TeamFoundation.Client. No código a seguir, os servidores registrados no cliente são lidos e adicionados a uma caixa de combinação (mostrada na Figura 6):

List<RegisteredProjectCollection> registeredTPCs;
// Get all registered collections on this machine
registeredTPCs = new
  List<RegisteredProjectCollection>((
    RegisteredTfsConnections.GetProjectCollections()));
foreach (var projectCollection in registeredTPCs)
{
  // Add each registered team project collection to the combo box
  cbRegColl.Items.Add(projectCollection.Uri);
}

Reading Registered Servers
Figura 6 Lendo servidores registrados

Terceira abordagem—Conectando-se a um URI de coleção conhecido

Além de se conectar a um servidor, se souber o URI da coleção, você pode se conectar a ela diretamente. A Figura 7 mostra essa terceira abordagem—conectar-se a um URI de coleção conhecido.

Figura 7 Conectando-se a um URI de coleção conhecido

NetworkCredential myNetCredentials =
  new NetworkCredential("Administrator", "P2ssw0rd");
ICredentials myCredentials = (ICredentials)myNetCredentials;
// Connect to the tpc hosting the version-control repository
TfsTeamProjectCollection tpc =
  new TfsTeamProjectCollection(new Uri(cb.Text),
  myNetCredentials);
// Get the version control service
vcServer = tpc.GetService<VersionControlServer>();
var teamProjects =
  new List<TeamProject>(vcServer.GetAllTeamProjects(false));
// List the team projects in the collection and add to list box
foreach (TeamProject projectNode in teamProjects)
{
  // Add list or team projects to list box
  lbProjects.Items.Add(projectNode.Name);
}

Os próximos exemplos demonstram o uso de alguns dos recursos do serviço de controle de versão. Quando tiver as referências ao servidor e uma referência ao serviço de controle de versão (consulte a Figura 7), poderá usar algumas das APIs, como obter uma lista de arquivos no servidor ou alterações pendentes. O código a seguir usa a referência do serviço de controle de versão para solicitar todos os arquivos XAML no servidor e adicioná-los a uma caixa de listagem:

// List all of the XAML files on the server
ItemSet items = vcServer.GetItems("$/*.xaml", RecursionType.Full);
foreach (Item item in items.Items)
{
  // Add each file to the list box
  lbAll.Items.Add(item.ToString());
}

O primeiro parâmetro para o método GetItems é o caminho da pasta. No código de exemplo, o caminho é a raiz, e todos os arquivos XAML serão retornados em todas as pastas. Na Figura 8, vê-se que os detalhes do arquivo são mostrados quando você seleciona um desses arquivos.

Get All XAML Files and Show File Details
Figura 8 Obter todos os arquivos XAML e mostrar os detalhes do arquivo

Se quiser ver uma lista de arquivos com alterações pendentes e adicioná-los a uma caixa de listagem, use o código na Figura 9. Nesse código a API QueryPendingSets está sobrecarregada, e esse exemplo usa a sobrecarga do método que permite consultar com base em ItemSpecs, que é uma matriz que representa o que consultar. Nesse caso, estamos pedindo as alterações pendentes de apenas uma pasta no servidor. Também filtraremos as alterações pendentes de um espaço de trabalho e usuário específicos. O último parâmetro instrui a API para que ela nos forneça as informações para que possamos baixar o arquivo. Se não tivermos nenhum plano de usar as informações, considere então o mantra “o tráfego de rede é ruim” e passe false.

Figura 9 Obter PendingChanges

ItemSpec[] itemSpecs = new ItemSpec[1];
// You can filter the path to a project and folder
// using $/ProjectName/Folder...
ItemSpecs[0] =
  new ItemSpec(@"$/Tailspin Toys/Development/Iteration 2",
  RecursionType.Full);
// Your options for filtering are the Workspace Name,
// User Name and the previous path in the ItemSpec
String qryWSName = @"WIN-GS9GMUJITS8";
String queryUserName = @"administrator";
bool includeDownloadInfo = true;
PendingSet[] pendingSet = vcServer.QueryPendingSets(
  itemSpecs, qryWSName, qryUserName, includeDownloadInfo);
foreach (PendingSet ps in pendingSet)
{
  // Add pending changes to list box
  lbPendingChanges.Items.Add(ps.ToString());
}

O serviço de controle de versão oferece muitos mais recursos que não foram abordados neste artigo. Tentamos aguçar seu apetite e iniciá-lo na conexão com o servidor e no uso do serviço de controle de versão.

Em artigos futuros, continuaremos a investigar o modelo de objeto do cliente do TFS e a apresentar diferentes cenários de programação como trabalhar com itens de trabalho, controle de versão, compilações e uma maior integração através do modelo de objeto do servidor Visual Studio TFS.

Brian Blackman é consultor principal junto à equipe Microsoft Services Partner ISV, concentrando-se em afetar o sucesso dos parceiros ISV em engenharia e no mercado. Ele tem um MBA e é um CSM, CSP, MCSD (C++), MCTS e Visual Studio ALM Core Ranger. Ele passa seu tempo escrevendo código, criando e dando workshops, e consultoria em várias concentrações e tudo relativo a ALM.

Willy-Peter Schaub é gerente de programas sênior da equipe Visual Studio ALM Rangers do Microsoft Canada Development Center. Desde meados da década de 1980, tem se empenhado em buscar a simplicidade e a facilidade de manutenção na engenharia de software. Leia seu blog em blogs.msdn.com/b/willy-peter_schaub e siga-o no Twitter em twitter.com/wpschaub.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Jeff Bramwell, Bill Essary, Mike Fourie, Bijan Javidi, Jim Lamb e Patricia Wagner