Páginas

quarta-feira, 26 de outubro de 2011

Como fazer undo-checkout em arquivos de um outro usuário

Hoje tivemos que remover os arquivos que estavam em checkout para uma das pessoas que trabalham com a gente. Só que o detalhe é que a máquina que essa pessoa usou para fazer o checkout, e consequentemente as informações que ficam no workspace, não estavam mais disponíveis (a máquina foi trocada, e a antiga sabe-se lá onde está).
Então, como desfazer os checkouts existentes?
A maneira que encontramos foi, utilizando um usuário administrador dentro do team project, fazer a remoção do checkout através de linha de comando (tf.exe).
Primeiramente, buscamos o nome do workspace que estava associado ao usuario, através do comando abaixo. Retornaram duas ocorrências, que são a máquina antiga e a máquina nova. Essa informação será importante depois.

C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>tf workspaces /owner:acroberto
Collection: tfs.intra.cliente.com.br\TPC
Workspace     Owner     Computer      Comment
------------- --------- ------------- -----------------------------------------
ESTACAO18     acroberto ESTACAO18
ESTACAO19     acroberto ESTACAO19


Em seguida, fizemos uma listagem dos arquivos que estavam em checkout no team project (chamamos de SISTEMA). Veja que jogamos o resultado da consulta em um arquivo texto dentro do c:\.

C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>tf status $/SISTEMA /recursive /user:* /server:tfs.intra.cliente.com.br\TPC >> c:\tf.log 

Ignoring the /server option.


Agora vem o comando importante. Usando o nome do workspace + login do usuário + diretório base a partir de onde os arquivos com checkin se encontravam, executamos o comando tf undo. Note o uso do parâmetro /recursive, que faz com que seja feita a busca em todas as subpastas do diretório inicial.

C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>tf undo /workspace:ESTACAO18;acroberto $/SISTEMA/CLIENTE-SISTEMA-interno /recursive

Pronto, os arquivos foram liberados, efetuando o undo-checkout. Para conferir, rodei novamente o comando tf status, para pegar todos os arquivos em checkout. Só sobrou um que eu mesmo estava trabalhando.


C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>tf status $/SISTEMA /recursive /user:* /server:tfs.intra.cliente.com.br\TPC 
Ignoring the /server option. 
File name         Change User    Local path
----------------- ------ ------- ----------------------------------------------
$/SISTEMA/CLIENTE-SISTEMA-interno/CLIENTE.SISTEMA.Batch
AtualizarDados.cs ! edit falgouw C:\Documents and Settings\FALGOUW\My Documents\Projetos\SISTEMA\CLIENTE-SISTEMA-interno\CLIENTE.SISTEMA.Batch\AtualizarDados.cs
1 change(s)

[]’s

Pérola: como dificultar o tratamento de erro de aplicações

Vamos dar uma olhada no método abaixo, que foi pego de uma situação real (mudei os nomes de variáveis para evitar que reclamem que o coloquei aqui). Nesta aplicação, há uma necessidade de sincronizar dados de usuários, buscando dados do sistema A e atualizando no sistema B.

public static void AtualizarUsuarios()
{
    try
    {
        using (BatchFacade batchFacade = new BatchFacade())
        {
            List<Usuario> usuariosSistemaA = batchFacade.ListarUsuariosSistemaA().GetRegistros<List<Usuario>>();
            List<Usuario> usuariosSistemaB = batchFacade.ListarUsuariosSistemaB().GetRegistros<List<Usuario>>();
            foreach (Usuario usuarioA in usuariosSistemaB)
            {
                Usuario usuarioB = usuariosSistemaA.Find(delegate(Usuario u)
                {
                    return u.SIAP.Equals(usuarioA.Codigo.ToString());
                });
                if (usuarioB != null && UsuarioModificado(usuarioA, ref usuarioB))
                {
                    batchFacade.AtualizarUsuario(usuarioB);
                }
            }
        }
    }
    catch
    {
        throw new ApplicationException("Falha ao atualizar os dados dos usuários");
    }
}

Esta aplicação possui um tratamento de erro genérico, que grava no eventlog todos os erros que ocorrem no sistema. Agora imaginem que ocorra um erro durante o processamento deste método: neste caso, a execução irá cair no block catch, e uma exception do tipo ApplicationException será lançada, com o texto "Falha ao atualizar os dados de usuários".
Agora imaginem vocês, com um erro em ambiente de produção, tendo apenas essa mensagem para descobrir o problema que está acontecendo. É nessas horas que a gente tem vontade de matar quem programa nas coxas, apenas se importando em entregar a funcionalidade e nem ligando para a pessoa que irá cuidar dessa tranqueira do sistema.

O simples fato de obter a exception original e passá-la como inner exception da ApplicationException que estamos lançando já ajuda, pois na rotina de tratamento de erros genérico podemos pegar os detalhes que ajudarão em muito identificar o problema. Neste caso, o problema era uma informação que vinha faltando no banco de dados.

[]'s

domingo, 23 de outubro de 2011

Limitações ao se trabalhar com o TFS 2010

Ao se trabalhar com o TFS, existem algumas limitações que devem ser levadas em consideração na hora de criar team projects ou work items. É importante conhecer isso para não ter problemas na hora de decidir como estruturar seus projetos (Nenhuma limitação listada é impeditiva para se trabalhar com o TFS, é só se preparar e evitar as situações que elas possam ocorrer ou serem necessárias).
[]’s

Renomear um Team Project

Renomear team projects
Após a criação de um team project (repositório de código-fonte, atividades do projeto, etc.) não é possível renomeá-lo. Uma vez escolhido o nome, será este para sempre, então tome cuidado ao escolher. Caso contrário, se realmente você quiser “renomear”, terá que criar um novo team project e migrar todo o conteúdo do anterior…

Mover work items entre Team Projects e Team Project Collections

Mover work items entre team projects
Não é possível mover work items entre team projects diferentes, visto que os process templates entre eles podem ser diferentes.

Mover Team Projects entre Team Project Collections

Mover team projects entre team project collections
Da mesma forma que os work items, não é possível mudar de lugar um team project. Isso porque pode ocorrer problemas com os IDs gerados para os artefatos armazenados, como work items e changesets.

Gerenciar work items no Excel ou Project ou tirar relatório de vários Team Projects

Manipular ou visualizar informações de diversos team projects ao mesmo tempo
Não é possível gerenciar os work items de vários team projects ao mesmo tempo em uma mesma planilha do excel, por exemplo. A visualização dos work items deve ser feita team project por team project. O mesmo vale para relatórios no sharepoint, por exemplo. Um de cada vez…

Rastrear merges entre vários Team Projects

Ver histórico de merges entre diferentes team projects
Não é possível visualizar o histórico para merges que são feitos entre branchs de team projects distintos. Mesmo porque, não é recomendado trabalhar dessa forma.

Links de work itens entre diversos Team Projects

Associar work items entre team projects
Por último, cada team project é uma unidade isolada. Isso quer dizer que não é possível relacionar work items entre team projects diferentes.

quarta-feira, 19 de outubro de 2011

Uso de static em OOP: escolhendo a arma correta

Já vi sistemas desenvolvidos em linguagens orientadas a objetos em que todos os métodos das classes eram estáticos. Uma vez perguntei para uma pessoa o motivo dela estar programando dessa maneira. Ela não soube me responder.

Bom, por que não devemos colocar static em todos os métodos? Para mim, a melhor resposta é comparar o uso de métodos static com o uso de baionetas.

Baioneta montada em um M-16

Antes do uso da pólvora, as guerras eram travadas geralmente em combate corpo-à-corpo, com o uso de objetos cortantes como espadas ou machados.

No final do século XVIII, na França, começaram a ser produzidas as primeiras baionetas. Baioneta é uma arma branca de curto alcance que pode ser presa na ponta de um fuzil. Dessa maneira, em situações especiais como combate próximo (trincheiras) ou simplesmente falta de munição, os soldados possam utilizar suas armas de fogo como lanças.

Mas é claro que atualmente, na maioria das situações, é preferível utilizar fuzis com o objetivo que eles foram criados: disparar projéteis!

E o que isso tem a ver com orientação a objetos e uso de métodos estáticos? Antes da orientação a objetos, os programas eram codificados levando-se em consideração o paradigma procedural, que é basicamente o jeito que trabalhamos quando usamos métodos estáticos: sub-rotinas manipulando estruturas de dados. Isso é diferente da orientação a objetos, onde as sub-rotinas e estruturas de dados são “mesclados” em objetos.

Pois bem, utilizar métodos estáticos em programação orientada a objetos (descontroladamente, que fique bem claro) é como se estivéssemos retrocedendo e utilizando uma ferramenta de forma arcaica, sem obter seus principais benefícios. É a mesma coisa que utilizar um rifle equipado com uma baioneta como lança sendo que você tem munição de sobra e está em campo aberto! O uso desregrado de métodos estáticos mata o que a OOP tem de melhor: polimorfismo, herança, etc. É claro que em casos especiais iremos precisar de métodos estáticos, mas isso tende a ser exceção.

Concluíndo, o uso de métodos estáticos em linguagens orientadas a objetos como C# ou Java não é errado, desde que se saiba o que está fazendo. Dê preferência ao uso de métodos de instância em OOP para tirar o melhor proveito, mas principalmente dê preferência ao bom-senso…

[]’s

terça-feira, 18 de outubro de 2011

Pérola: como remover caracteres de uma string

Encontrei este código no qual o desenvolvedor queria remover os pontos, traços e barras de um CNPJ formatado (de "12.345.678/0001-00" para "12345678000100"):

string estab = string.Empty;
char[] delimitadores = new char[] { '.', '/', '-' };
string[] partes = lblCNPJEstabelecimento.Text.Split(delimitadores, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < partes.Length; i++)
    estab = estab + partes[i];
} 

Bizarro...

Para remover uma única ocorrência, o método Replace é indicado: http://msdn.microsoft.com/en-us/library/fk49wtc1.aspx

Outra alternativa é utilizar regular expressions:
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.replace%28v=VS.100%29.aspx

O link abaixo possui um extension method para remover vários caracteres: http://www.csharptricks.com/blog/2006/10/remove-characters-from-string-cnet.html

Mantenham o código simples e limpo...

[]'s

segunda-feira, 17 de outubro de 2011

Nota rápida: Concatenando valores com caractere de separação em C#

Abaixo está um exemplo rápido de como concatenar um array de strings em uma única string, separando esses valores por um caractere.

[TestMethod]
public void TestarConcatenacao01()
{
    var arr = new[] { "s1", "s2" };
    var s = string.Join(";", arr);
    Assert.AreEqual("s1;s2", s);
}

[TestMethod]
public void TestarConcatenacao02()
{
    var arr = new string[] { };
    var s = string.Join(";", arr);
    Assert.AreEqual(string.Empty, s);
}

[TestMethod]
public void TestarConcatenacao03()
{
    var arr = new[] { "s1" };
    var s = string.Join(";", arr);
    Assert.AreEqual("s1", s);
} 

string.Join substituí com uma linha um código que acabei de ver, onde eram feitos um foreach e vários condicionais para conseguir o mesmo objetivo (umas 5 linhas, no mínimo).

[]'s