Como gastar dinheiro com TI impunemente

15, fevereiro, 2011 egomesbrandao Sem comentários

Se você é responsável por alguma área de TI, coordenador, gerente, diretor e tem uma pequena verba sobrando,  que tal torrar? Afinal,  se você não gasta toda a sua verba, no ano que vem vão diminuí-la, certo? O problema é que não pode dar na cara, se você simplesmente torrar essa grana em um happy hour com a equipe, comprar cadeiras melhores ou um segundo monitor para cada desenvolvedor, isso pode levantar suspeitas e te acusarem de não saber controlar sua verba. Então seguem abaixo algumas sugestões. Espero que lhe ajude na ascenção de sua carreira! Se você for promovido, deixe seu depoimentos nos comentários. Segue abaixo o manual: Como torrar sua verba de TI de maneira “responsável”:

Atualize os seus softwares

Caro e não palpável:  a compra de software é uma maneira de você gastar e ninguém ver onde. Você pode comprar várias e várias licenças, hoje em dia não vem nem mais a caixinha que ocupava espaço, e gastar muito dinheiro com isso. Para gastar bem gaste com a moda, compre ALM! Várias licenças de Team Foundation vão custar uma bela grana e simplesmente não use-as. Pelo menos não totalmente, para não dar na cara, use somente o controle de versão, todas as outras funcionalidades podem ser esquecidas, não precisa usar o build automático, tracking, etc…
Ganhe um Bônus adquirindo o VS.Net Ultimate e não treine os desenvolvedores para usar as facilidades que ele oferece, aliás… o TFS não vai estar funcionando mesmo.

Contrate um gerente de projetos

Aqui é “double damage”! Além de gastar dinheiro com um profissional para tomar conta de outros, os desenvolvedores, no caso, pois eles não tem a menor idéia do que fazer, precisam de uma babá e às vezes trabalhar na base do chicote; esse integrante do time vai reagir de forma contrária ao time, vai introduzir ruído, marcar extensas reuniões, vai sentar ao lado de um dev para ver o que está acontecendo e ajudar no código; ou seja, vai atrasar seu projeto ou piorar as manutenções de software. Traduzindo:  mais tempo, que é mais dinheiro, mais gastos. Se você além de double quer um bônus com essa aquisição, peça um que seja PMP, certificado claro, pois a hora é mais cara e ele vai trazer um livros de regras junto para aplicar no seu processo.

Processo

Se você não tiver um processo você já tem muito gasto, atrasos, comunicação falha, e por aí vai. Mas, instalando um processo você pode gastar ainda mais!! Vá para o mercado, procure profissionais gabaritados em processos, e peça uma avaliação, afinal você quer ter mais visibilidade do projeto, ter certeza que estão fazendo a coisa certa e quer controlar se a galera esta indo pro banheiro dormir no vaso depois de uma noite de balada na terça-feira, e para isso terá que gastar mais. Planilhas de horas, ou um software, documentação abrangente, validações, reuniões de planejamento, análise do problema; tudo isso deve estar contemplado no processo. Ganhe bônus instalando uma ferramenta de controle do processo.
Já tem um processo na empresa? Então mude! Escolha um da moda e obrigue sua adoção, lembre-se de contratar um consultor para isso! A mudança do projeto deve ocorrer durante o projeto em andamento e não se preocupe, coloque tudo o que puder, as pessoas devem se adaptar,  e não o contrário.

Contrate pessoas

Se você acha que ainda esta gastando pouco,  nada é mais caro do que a contratação de pessoas. Principalmente pessoas que não estão comprometidas com a empresa, portanto abuse dos terceiros, eles podem te dar um bônus em gastos se você contratá-los com “horas abertas”. A contratação de mais pessoas vai prejudicar sua comunicação no projeto e provavelmente vai dobrar seu tempo de desenvolvimento, isso mesmo, vai dobrar! Se isso não é custo suficiente,  peça certificados; os profissionais com certificação vão lhe garantir um gasto extra, já que como pessoas com mais conhecimento vão te cobrar mais.

Se você não tem uma verba sobrando… Mantenha seu ambiente com um clima péssimo, infra-estrutura ruim, máquinas velhas, isso fará com que as pessoas não queiram trabalhar, logo elas vão produzir pouco ou nada e o projeto vai atrasar. Algumas vão se demitir então poderá contratar novos, mais alinhadas com as diretrizes da empresa. Depois poderá pedir mais verba para consertar o andamento do projeto… Volte ao início e aplique as propostas apresentadas.

Se você é desenvolvedor e leu esse texto… bazinga!

Categories: agilidade Tags: ,

Manifesto Ágil completa 10 anos

10, fevereiro, 2011 egomesbrandao 3 comentários

Hoje o Manifesto Ágil completa 10 anos. Nesse tempo muita coisa mudou, evoluiu, ou não!

10 anos na indútria da TI é muito tempo. Muita tecnologia nasceu e outras tantas morreram, muitos aplicativos foram desenvolvidos, alguns de sucesso incrível outros nem tanto, e outros que pareciam não deixar de existir,  nunca foram engolidos por inovações. Mas, desenvolver software ainda é uma incógnita para muitos do mercado.
Pode ser muito tempo para a TI, mas, historicamente falando, 10 anos é pouco tempo para analisarmos grandes mudanças.

Fazer software ainda é para muitas empresas sofrível! E é curiosa essa afirmação, pois em um segmento em que mudanças acontecem da noite para o dia, novas tecnologias são desenvolvidas frequentemente, elas não são absorvidas pela própria indústria que as cria. É como se as empresas de telefonia não fizessem uso do telefones para se comunicar.

O manifesto ágil focou em pessoas, interação, mudanças e colaboração. Mas poucas foram as empresas que conseguiram absorver esses conceitos. Por que? Muito antes do manifesto, Ricardo Semler mudou a cultura da sua empresa, a Semco. Quando a TI nem falava de trabalho remoto (famoso Home Office), colaboração entre indivíduos, ambiente de trabalho… A Semco já mudava essas formas antiquadas de pensar. Não foi fácil, mas se operários de fábrica conseguiram ter flexibilidade no horário de trabalho, por que profissionais que não estão presos a uma linha de produção ainda não conseguiram?

Os ambientes colaborativos na internet 2.0 aparecem aos montes, são ferramentas de redes sociais, aplicativos profissionais, até mesmo CRM já tem internamente sua rede social (veja o Salesforce Chatter), mas todas essas facilidades a um click de distância de qualquer indivíduo com acesso a grande rede são barrados por firewalls de empresas preocupadas com produtividade. Essas mesmas empresas são aquelas que minam a produtividade de seus funcionários proporcionando um ambiente tão ruim de trabalho que é desanimador querer resolver algum problema. Veja o vídeo do Jason Fried da 37Signals no TED (Why work doesn’t happen at work).

O ágil esta na moda hoje! É legal a empresa ser ágil, só pela palavra já é legal, ter um framework do tipo Scrum, esse então todo mundo parece usar, mas realmente fazer uso, difícil… O Giovanni Bassi da Lambda3 recentemente escreveu um post com o título Que fique claro: não se “instala” agile, diferentemente do que pensam muitos “gerentes” por aí, que acham que é só chamar um “consultor”, fazer 3 dias de cursinho, e bora usar o Scrum.

Infelizmente a mudança cultural defendida pelo movimento ágil vai demorar a acontecer em muitos lugares, pois a cultura da falta de colaboração entre indivíduos, falta de valoriazação do trabalho, más práticas, é a realidade de muitas empresas, e pior, educaram vários indivíduos assim… Deseducar será um longo processo para elas. Quem hoje consegue se livrar de toda essa carga cultural negativa vai surfar a onda.

Categories: agilidade Tags: ,

Sobre o LG GW550 com Windows Mobile 6.5 (Começando 2010)

23, fevereiro, 2010 egomesbrandao 50 comentários

Estou atrasado em posts, desculpem aí! O fim de 2009 foi corrido e 2010… Bom o ano começa só depois do carnaval certo? Hehe… Não, mas eu só consegui começar a escrever agora.

Ainda não vou voltar ao ABC App, neste post vou descrever minha primeira experiência com o Windows Mobile. Comecei a escrever esse post no próprio celular, usando o One Note.

Finalmente entrei na era da computação móvel, estou bastante atrasado mas resolvi ir com calma… Me recuso a pagar quase R$2000 em um iPhone quando no USA são U$300,00 a U$400,00; é mais que o triplo do valor e eu não vou fazer um plano de R$600,00 pra ter míseros R$400,00 de desconto no aparelho! Recentemente teve uma promoção interessante da Oi, no plano de R$400,00 o aparelho saia de graça!

Outro aparelho interressante no momento é o Samsung Galaxy com o SO Android, com GPS, acelelômetro, câmera de 5Mp, tela sensivel a toque e uma infinidade de aplicativos pela loja do Google; mas e se eu não usar tudo isso? O valor esta em R$1200,00 pelo conjunto até que não é muito, mas surgiu uma promoção legal na Vivo um Samsung com Windows Mobile 6.1 por R$200!!! (No plano de 100 minutos + 50Mb de Internete) Sendo desenvolvedor na plataforma .Net seria uma boa. Na loja não tinha mais o aparelho e me ofereceram um LG Sm@rt (GW550) nas mesmas condições, e melhor com Win Mobile 6.5! Resolvi experimentar, seguem minhas considerações:

  • Um objetivo meu era substituir meu MP3 player, estava cansado de levar celular e o player no bolso, trabalhando perto de casa então é mais vantagem ir de ônibus ouvindo algo ou lendo e viajo muito de ônibus 3 ou 4 horas, e se não estou lendo estou ouvindo podcast. Por enquanto o aparelho esta me servindo, coloquei alguns podcasts e músicas, mas uma coisa que me faz falta é a possibilidade de colocar um timer pra desligar a música, o player eu programava 20 min. e colocava de baixo do travesseiro e pronto (será que consigo desenvolver algo? Olha a oportunidade aí). Um ponto ruim é o fone de ouvido que não para na orelha e pior não consigo substituí-lo, já que ele não usa uma entrada comun de fone, tipo PI, e sim é um mini USB modificado, por que não seguir um padrão LG?
  • Gosto de bater fotos, mas carregar uma câmera seria ter o mesmo problema que o player, essa já é melhor que a do último que era VGA, mas 3.2 sem flash e sem uma boa lente não ajuda muito… Porém serve para fotos que você não precisa de uma qualidade extraordinária, uma aplicação da camêra é bater foto de um livro que eu gostei em uma livraria para depois procurar ele para comprar.
  • Queria poder acessar a internet, mas isso seria uma exceção, já que passo a maior parte do tempo no escritório ou em casa com acesso, por isso eu precisava de wi-fi, em casa poderia acessar e-mail sem ligar computador e em lugares públicos acharia um ponto de acesso, até em ônibus rodoviarios já existe wi-fi. Ponto negativo: cursor. Para movimentar o mouse a tecla direcional é horrível, vi um Blackberry que tinha uma bolinha, daquelas de notes antigo.O Skype para Win Mobile é muito legal, novamente em casa posso falar por ele sem precisar de um computador.
  • Uma função legal é ler e até mesmo editar algum documento, baixo muito PDF e até mesmo DOC, é melhor do que ficar carregando vários livros. Ler um DOC é legal, pois o texto fica fluido e se encaixa melhor na tela, embora tenha que ficar dando page down bastante vezes, já que a tela é pequena. O PDF é ruim, pois ele tem largura fixa, daí você tem que ficar dando zoom para poder ler alguns pontos e voltar para poder ir para outros lugares na página. Ponto negativo: não consigo criar um novo DOC ou XLS, embora consiga editar
  • Duração da bateria, isso é um problema, parece durar uns 2 dias se não usar nada, mas usando o Media Player já diminui pra caramba o tempo de bateria, várias vezes me pego sem energia quase no fim do dia, e daí posso deixar de receber ligações! O conector que serve para o fone de ouvido é o mesmo para conectar no computador e dar recarga, ou seja não é mini USB padrão, o que me impede de compartilhar o cabo de alguém para recarregar o aparelho. Aliás a carga pela USB é extremamente demorada.
  • A questão do Windows Mobile deixar os programas na memória é ruim, o aparelho vai ficando lento e é necessário tirá-los de lá na mão.
  • Ponto muito positivo: é plataforma Windows! E existe um mini framework do .Net para ele, ou seja na prática o desenvolvedor .Net é um desenvolvedor Mobile também. Já pensei em alguns programinhas para fazer, já que não existem muitas opções no Windows Mobile Market e principalmente não em português.

Escreverei mais sobre desenvolvimento no Windows Mobile no futuro.

Categories: Mobile, microsoft Tags: , ,

ABC App – 04 Exceções

9, novembro, 2009 egomesbrandao Sem comentários

Ia deixar para escrever sobre o assunto depois, mas pra começar bem a semana vou usar o comentário do Tucaz e fazer um Refactoring no código e tratar Execeptions, ou Exceções!

exceção
ex.ce.ção
sf (lat exceptione) 1 Ato ou efeito de excetuar. 2 Desvio de regra, de lei, de princípio ou de ordem. 3 A coisa excetuada; aquilo que se desvia da regra. 4 Prerrogativa, privilégio. 5 Pessoa cujo modo de pensar ou de proceder se afasta do comum e usual. 6 Dir Alegação jurídica, constituindo defesa indireta (difere da contestação, que é defesa direta), pela qual o réu pretende baldar a ação intentada. E. declinatória, Dir: a que visa a declinar a competência do juiz ou tribunal ao qual foi apresentada a demanda. E. dilatória, Dir: a que pretende apenas demorar a demanda. E. peremptória, Dir: a que de todo e definitivamente afasta a demanda.

Conforme a definição acima do Michaelis, exceção é um desvio da regra. Na classe Customer da camada de DAL, quando fazemos acesso ao banco de dados para buscar um ou mais usuários, a EntLib abre uma conexão e executa o comando Select, essa é a regra, mas e quando o banco de dados não esta disponível? Ou se alguém renomeou ou apagou a tabela que esta na nossa query? Isso são exceções, e se não tratarmos, o sistema para de funcionar! Para testar é só desligar o banco de dados (parando o serviço SQL Server Browser) e rodar o nosso software.

Existem várias correntes de pensamento sobre Exceptions

Devemos tratar Exceptions como conexões a banco de dados, mas se um usuário do sistema cadastrar um número inválido de CPF devemos lançar uma Exeception? Devemos criar nossas próprias Execeptions para o nosso sistema? Onde devemos tratar? Muitas perguntas, algumas vão ficar sem respostas no momento, o objetivo desse post será fazer o Refactoring, e o primeiro será na conexão do banco.

Tratamento de Exceptions

No .Net é usado a tríade Try-Catch-Finally, o código passível de erro e que pode vir a lançar uma exceção é colocado no bloco do Try, no Catch é onde se pegam as execeções, e o Finally serve para finalizar alguma operação, limpar alguma variável,  e, muitas vezes,  ele não é usado, mas no nosso primeiro exemplo já faremos uso dele.
Uma regra que devemos sempre atentar é: nunca, NUNCA, colocar um método inteiro dentro de um bloco Try, não há necessidade de colocar criação de variáveis! Teste somente o que pode dar um erro. Além disso,  o código fica mais elegante.

No código da classe Customer da camada de DAL o que pode dar erro? O mais óbvio seria quando o DataReader estivesse sendo carregado, se nessa hora o banco de dados cair o nosso software vai pro espaço! Como no método AdaptToList ainda usamos o DataReader (ele fica aberto para popularmos o objeto Customer)  vamos colocar a linha de ExecuteReader e a de chamada do AdaptToLista dentro do Try. Para fazer isso,  vamos usar o recurso de Refactoring da IDE :  selecione as duas linhas, clique CTRL, e no menu de contexto escolha Surrond With…

Fazendo um Surrond With no código

Fazendo um Surrond With no código

Escolha a opção “tryf”, conforme figura abaixo, repare que este é um atalho para um Snippet, então quando estiver escrevendo código usando este atalho economiza tempo!

Escolha "tryf"

Escolha "tryf"

O código estará dentro do bloco Try, veja outras alterações no código abaixo e em seguida o por quê

public Domain.Customer GetCustomerById(int customerId)
        {
            IDataReader dr = null;
            IList<Domain.Customer> lstCustomers = null;

            string sql = "select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid";

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, "customerid", DbType.Int32, customerId);

            try
            {
                dr = db.ExecuteReader(cmd);
                lstCustomers = AdaptToList(dr);
            }
            catch (System.Data.SqlClient.SqlException exsql)
            {
                throw new Exception(exsql.Message);
            }
            catch {
            }

            finally
            {
                if (!dr.IsClosed)
                    dr.Close();
            }

            return ((lstCustomers != null) || (lstCustomers[0] != null)) ? lstCustomers[0] : null;
        }
}

Listagem 01

Movi a declaração do DataReader para o início do método, pois podemos deixar dentro do Try, já que o Finally não iria enxergar esse objeto e depois é só mover a linha que faz a verificação se o DataReader estiver aberto para dentro do Finally, ocorrendo ou não um erro o Finally sempre é executado e daí ele ficará responsável por fechar o DataReader.
O Tucaz também fez um comentário sobre setar o CommandBehavior para CloseConnection, o que faria a conexão com o banco ser fechada após fecharmos o DataReader, mas a EntLib cuida disso pra gente! Veja o código fonte, e essa é a parte legal de usar essa biblioteca da MS, pois com o acesso ao fonte vemos as boas práticas sendo aplicadas, aquelas que se encontram no Guia de Acesso a Dados.
O Catch vazio vai pegar todo o tipo de exceção, então é bom especializarmos o Catch, por isso eu também coloquei para pegar a SQLException.

Aplique esse Refactoring no método GetCustomers() também.

OK… E vamos fazer isso também quando é criado o Database na classe BaseDAL, pois se o banco de dados estiver fora do ar vai dar um erro. É só executar os mesmos passos em cima da única linha que temos no único construtor da classe. E vai ficar assim:

    public abstract class BaseDAL
    {
        public EntLib.Database db { get; set; }

        public BaseDAL()
        {
            try
            {
                db = EntLib.DatabaseFactory.CreateDatabase("Connection String");
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {

            }
        }
    }

Listagem 02
E agora temos que exibir esses erros lá na nossa interface de usuário, aqui vai o código de como vai ficar:


namespace ABCApp.Console
{
    class Program
    {
        static void Main(string[] args)
        {

            ABCApp.Domain.Customer c;

            ABCApp.DAL.Customer dalCustomer = new ABCApp.DAL.Customer();

            try
            {
                c = dalCustomer.GetCustomerById(1);
                System.Console.WriteLine(c.CustomerId.ToString() + " - " + c.FirstName.ToString() + " " + c.LastName.ToString());
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
            }

            System.Console.ReadKey();

            try
            {
                IList<Domain.Customer> lstCustomer = dalCustomer.GetCustomers();

                foreach (Domain.Customer customer in lstCustomer)
                {
                    System.Console.WriteLine(customer.CustomerId.ToString() + " - " + customer.FirstName.ToString() + " " + customer.LastName.ToString());
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
            }
         �
            System.Console.ReadKey();
        }
    }
}

Vamos testar? Para isso desligue o seu SQL Server! Vá no menu Iniciar > Microsoft SQL Server 2008 > Configuration Tools > SQL Server Configuration Manager, entre na ferramenta.  Pare o serviço SQL Server Browser, daí não deve ser possível conectar na base. Rodando a aplicação devem ser impressas mensagens de erro onde deveriam aparecer dados!

Bom… Isso foi só para começarmos a colocar um controle sobre os locais onde podem ocorrer Exceptions, esse não é o mundo perfeito, e nem será a última vez que irei falar sobre o tema. Mas por que não ler alguns links sobre isso? Aí vai:

http://unplugged.giggio.net/unplugged/post/Como-tratar-erros.aspx

http://msdn.microsoft.com/en-us/library/dd203116.aspx (Esse é sobre o bloco de Exceptions da EntLib, mais pra frente vamos usar ele)

http://www.developerfusion.com/article/5250/exceptions-and-performance-in-net/ (discute a questão de performance ao lançar exceções)

http://yoda.arachsys.com/csharp/exceptions2.html (também sobre performance)

http://www.artima.com/interfacedesign/AbnormalConditions.html

http://apparch.codeplex.com/ (aqui tem um vídeo sobre o tema)

Fico por aqui… Na quinta-feira post sobre objetos anêmicos…

O código deste post esta no Change Set 36605.

Categories: abcapp Tags: , , , ,

ABC App – 03 Fazendo um Refactoring na DAL

4, novembro, 2009 egomesbrandao 3 comentários

No post anterior,  iniciamos a contrução da ABC App, construindo uma camada de Domínio e uma camada de DAL. Antes de continuarmos a desenvolver, vamos aplicar um Refactoring?

Eu não gosto de termos em inglês para coisas que podemos falar em português, mas no caso do Refactoring eu abro uma exceção, normalmente o que se fala é Refatoração, mas essa palavra para mim é um termo matemático. O correto, IMHO, seria dizer Re-fabricar, mas fico com o termo em inglês.

E o que podemos fazer?

Vamos seguir usando Baby Steps, daqui por diante pequenos passos, ou seja , faço Refactoring e testo, Refactoring e testo, então não corro o risco de fazer uma grande alteração e me perder no código alterado e o sistema não funcionar. A primeira coisa para alterar é a criação da conexão com o BD, como será recorrente em toda classe DAL, podemos criar um classe base que todas dessa camada herdem e,  assim,  centralizarmos o código. Então,  primeira coisa, crie uma classe BaseDAL, como abaixo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using System.Data.Common;
using System.Resources;
using EntLib = Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{

    public abstract class BaseDAL
    {
        public EntLib.Database db { get; set; }

        public BaseDAL()
        {
            db = EntLib.DatabaseFactory.CreateDatabase("Connection String");
        }
    }
}

Listagem 01

A classe BaseDAL não poderá ser instanciada, só poderá ser herdada. Com isso, ganhamos um único ponto de conexão com o Banco de Dados, que será muito útil quando quisermos controlar um transação, outro ponto é no reuso de código. Para usarmos essa classe vamos herdar ela na classe Customer da DAL. Não se esqueça de apagar a linha indicada, pois agora usaremos o objeto Database da classe BaseDAL. Lembram-se do código abaixo?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Domain = ABCApp.Domain;

using System.Data;
using System.Data.Common;
using System.Resources;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{
    public class Customer : BaseDAL
    {
        public Domain.Customer GetCustomerById(int customerId)
        {
            //Apague a linha abaixo
            //Database db = DatabaseFactory.CreateDatabase("Connection String");

            string sql = "select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid";

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, "customerid", DbType.Int32, customerId);

            IDataReader dr = db.ExecuteReader(cmd);

            Domain.Customer c = new Domain.Customer();

            while (dr.Read())
            {
                c.CompanyName = dr["companyname"].ToString();
                c.CustomerId = Convert.ToInt32(dr["customerid"]);
                c.EmailAddress = dr["emailaddress"].ToString();
                c.FirstName = dr["firstname"].ToString();
                c.LastName = dr["lastname"].ToString();
                c.MiddleName = dr["middlename"].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr["modifieddate"]);
                c.Phone = dr["phone"].ToString();
            }

            if (!dr.IsClosed)
                dr.Close();

            return c;
        }
    }
}

Listagem 02

Se já tivéssemos escrito mais classes DAL, o impacto dessa alteração seria muito maior. Então , seguindo nossso mantra de pequenos passos, vamos executar o código e saber se ele continua funcionando como o esperado.
Sendo o retorno igual ao que você tinha antes de modificar o código, então passamos neste Refactoring!
Vamos continuar implementando outros métodos na nossa classe DAL, o próximo interessante é retornar uma coleção de clientes. Podemos retornar todos os clientes e basicamente o método seria o mesmo do anterior mas sem o parâmetro de customerId e sem a linha de parâmetro no Command, vou criar então o método GetCustomers e que irá me retornar uma lista tipada de objetos, segue:

public IList<Domain.Customer> GetCustomers()
        {
            List<Domain.Customer> lstCustomers ;

            string sql = "select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer";

            DbCommand cmd = db.GetSqlStringCommand(sql);

            IDataReader dr = db.ExecuteReader(cmd);

            lstCustomers = new List<Domain.Customer>();

            while (dr.Read())
            {
                Domain.Customer c = new Domain.Customer();

                c.CompanyName = dr["companyname"].ToString();
                c.CustomerId = Convert.ToInt32(dr["customerid"]);
                c.EmailAddress = dr["emailaddress"].ToString();
                c.FirstName = dr["firstname"].ToString();
                c.LastName = dr["lastname"].ToString();
                c.MiddleName = dr["middlename"].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr["modifieddate"]);
                c.Phone = dr["phone"].ToString();

                lstCustomers.Add(c);
            }

            if (!dr.IsClosed)
                dr.Close();

            return lstCustomers;
        }

Listagem 03

E para testar o código acima vamos escrever as seguintes linhas no nosso método Main no Projeto Console, logo abaixo da última linha já existente do nosso teste anterior:

            IList<Domain.Customer> lstCustomer = dalCustomer.GetCustomers();

            foreach (Domain.Customer customer in lstCustomer)
            {
                System.Console.WriteLine(customer.CustomerId.ToString() + " - " + customer.FirstName.ToString() + " " + customer.LastName.ToString());
            }

            System.Console.ReadKey();

Listagem 04

O código acima chama o método da DAL e retorna uma coleção de Clientes. Se aparecerem  várias centenas de Clientes,  está certo!
O código escrito até agora. Será que é possível aplicar um Refactoring para melhorar algo? Bom, tem algo bem evidente, uma duplicação de código, os dois métodos fazem a leitura do DataReader e populam um objeto Customer, e um deles ele adiciona a uma lista de objetos já que o retorno são vários. Podemos centralizar esse código para que quando for preciso adicionar uma nova Propriedade a classe Customer seja preciso alterar somente em um lugar, então vou criar o método AdaptToList que irá receber um DataReader e retornar uma lista tipada de Customer:

public IList<Domain.Customer> AdaptToList(IDataReader dr)
        {

        }

Listagem 05

O código da listagem 05 está praticamente pronto. Mova o código que se encontra na listagem 03, da linha 11 até 27 para dentro do método AdaptToList, e adicione a última linha, conforme a listagem 06! E repare que na inicialização da coleção Customer a declaração estava em outra linha,  então acrescente o tipo antes.

        public IList<Domain.Customer> AdaptToList(IDataReader dr)
        {
            List<Domain.Customer> lstCustomers = new List<Domain.Customer>();

            while (dr.Read())
            {
                Domain.Customer c = new Domain.Customer();

                c.CompanyName = dr["companyname"].ToString();
                c.CustomerId = Convert.ToInt32(dr["customerid"]);
                c.EmailAddress = dr["emailaddress"].ToString();
                c.FirstName = dr["firstname"].ToString();
                c.LastName = dr["lastname"].ToString();
                c.MiddleName = dr["middlename"].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr["modifieddate"]);
                c.Phone = dr["phone"].ToString();

                lstCustomers.Add(c);
            }

            return lstCustomers;
        }

Listagem 06

Para funcionar só é preciso chamar o método AdaptToList no método GetCustomers,  também alterei para que a lstCustomer fosse baseada em uma IList<T>, conforme a listagem abaixo:

        public IList<Domain.Customer> GetCustomers()
        {
            IList<Domain.Customer> lstCustomers = null; 

            string sql = "select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer";

            DbCommand cmd = db.GetSqlStringCommand(sql);

            IDataReader dr = db.ExecuteReader(cmd);

            lstCustomers = AdaptToList(dr);

            if (!dr.IsClosed)
                dr.Close();

            return lstCustomers;
        }

Listagem 07

Mais um pequeno passo, e mais um teste! Se rodou e continuou funcionando é por que o seu Refactoring foi bem feito! O que falta? Bem, se AdaptToList foi contruído para economizar código devemos usá-lo também no método GetCustomerById, mas nesse último método ele retorna apenas um Customer e não uma lista. Podemos então usar um artifício: pegar somente o primeiro item da lista para retornar, conforme listagem abaixo: 

public Domain.Customer GetCustomerById(int customerId)
        {
            IList<Domain.Customer> lstCustomers = null;

            string sql = "select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid";

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, "customerid", DbType.Int32, customerId);

            IDataReader dr = db.ExecuteReader(cmd);

            lstCustomers = AdaptToList(dr);

            if (!dr.IsClosed)
                dr.Close();

          �
            return ((lstCustomers != null) || (lstCustomers[0] != null)) ? lstCustomers[0] : null;
        }

Listagem 08

Na listagem 08 está o método GetCustomerById como deve ficar, a mudança do List<Domain.Customer> para IList<Domain.Customer>, a chamada do método AdaptToList e o pulo do gato que é o uso do operador ternário para retornar somente o primeiro item da coleção, ou seja um objeto Customer, ou um null, não vamos discutir agora se retornar nulo é uma boa opção ou não!

Vou finalizar o post por aqui, para não ficar muito grande, resumindo o que fizemos aqui: Refactoring!
Melhoramos o nosso código, parece que não é necessário fazer isso agora, mas sempre que possível é interessante a fazer, no caso criamos uma classe para cuidar inicialmente da conexão com o banco de dados e como criamos outro método que populava a classe Customer criamos um método para cuidar especificamente disso.

O código deste post encontra-se no Change Set 35524, dúvidas e sugestões por favor comentem!

Referências:

Wikipedia Refatoração

Wikipedia Refactoring

Wikipedia Code Refactoring

Categories: Sem categoria, abcapp Tags: , ,

ABC App – 02 Populando objetos sem uso de Dataset

27, outubro, 2009 egomesbrandao Sem comentários

Finalmente começando o código mesmo!

Objetivo: Popular um objeto simples com dados do banco sem fazer uso de Dataset

O que é necessário: Visual C# Express, MS SQL Express 2K8, banco de exemplo Adventure Works 2K8, MS Enterprise Library 4.1

Preparando o ambiente: Para quem nunca instalou o banco de exemplo Adventure Works, ele se encontra no CodePlex neste link aqui, mas tem uma pegadinha! Se não instalou o SQL Express Advanced, é um download maior, você não tem SQL Full Text Filter (veja se tem no Configuration Manager do SQL, é um serviço) e daí a instalação automática das bases de dados vai falhar, você terá que rodar os scripts manualmente, mas vai ter que alterar algumas variáveis. Então é melhor você ter a versão SQL Full Text Search, que está aqui. Usaremos somente o LT, que é mais enxuto em quantidade de tabelas, mas totalmente compatível com sua versão completa.
Quanto à MS Enterprise Library 4.1, ela é encontrada aqui, quando terminar o instalador vai perguntar se deseja compilar, responda Sim.

Pronto?

Se imaginarmos que estamos em um ambiente real de negócio nos já temos o BD, que é o Adventure Works, o que precisamos fazer é contruir uma classe de Customer (Cliente) que vai ser populada com os dados da tabela Customer do BD, dentro de um projeto Class Library que eu chamei de ABCApp.Domain:

namespace ABCApp.Domain
{
    public class Customer
    {
        public int CustomerId { get; set; }
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
        public string CompanyName { get; set; }
        public string EmailAddress { get; set; }
        public string Phone { get; set; }
        public DateTime ModifiedDate { get; set; }
    }
}

Como o nosso objetivo aqui é não usar Dataset e também agora não iremos usar ORM (não sabe o que é? espere próximos posts), vamos usar ADO.Net, mas para facilitar as coisas vamos usar a MS Enterprise Library (que chamarei daqui em diante de EntLib). Vamos criar então um novo projeto que será a nossa DAL, Data Access Layer, camada de acesso a dados:

using ABCApp.Domain;

using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{
    public class Customer
    {
        public Customer GetCustomerById(int customerId){

        }
    }
}

Repare que eu já adicionei duas referências, uma à EntLib, na janela Add Reference procure por Enterprise Library Data Access Application Block; e adicionei uma referência ao meu projeto ABCApp.Domain.
A primeira é para poder usar o bloco de acesso a dados da EntLib, e isso só vai ocorrer nesse projeto de DAL, que é minha camada de acesso a dados, a camada de Domain não vai saber onde os dados estão sendo persistidos!
E a segunda referência é porque o objeto que eu quero popular está na camada de domínio da aplicação.

Antes de continuarmos escrevendo a DAL, precisamos configurar como a EntLib irá fazer a conexão com o BD, e antes de fazermos isso precisamos adicionar um novo projeto a Solution, vamos adicionar um projeto do tipo Console para testarmos o código, por hora, por que existem maneiras melhores de fazer isso, mas não será feito nesse post. A Solution deverá ficar assim:

A Solution deverá estar parecida com essa figura

A Solution deverá estar parecida com essa figura

Insira um arquivo do tipo App.config no novo projeto, é nele que iremos configurar a conexão com o BD, e para isso existe uma ferramente que é integrada ao VS.Net no momento da instalação da EntLib, mas como estou fazendo na versão Express vamos usar a ferramenta externa que também é instalada, procure no menu Inicar: Microsoft Patterns & Practices > Enterprise Library 4.1 – October 2008 > Enterprise Library Configuration, e você terá a seguinte tela:

 EntLibConfiguration

Quando abrir a janela, vá em File > Open, e procure pelo arquivo App.config criado no projeto Console. Na pasta Connection String você pode criar várias conexões, mas no momento só precisamos de uma, apague as outras e crie uma nova, do lado direito da tela em General > ConnectionString preencha com as informações de localização do SQL Express, BD, senha, … o padrão. Salve o arquivo, feche, e ao voltar ao VS.Net Express ele vai pedir para recarregar o arquivo App.config, se ele ficou aberto.

Agora finalmente vamos codificar o acesso ao BD, segue abaixo.

using Domain = ABCApp.Domain;

using System.Data;
using System.Data.Common;
using System.Resources;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace ABCApp.DAL
{
    public class Customer
    {
        public Domain.Customer GetCustomerById(int customerId)
        { �
            Database db = DatabaseFactory.CreateDatabase("Connection String");

            string sql = "select customerid, firstname, middlename, lastname, companyname, emailaddress, phone, modifieddate from saleslt.customer where customerid = @customerid";

            DbCommand cmd = db.GetSqlStringCommand(sql);

            db.AddInParameter(cmd, "customerid", DbType.Int32, customerId);

            IDataReader dr = db.ExecuteReader(cmd);

            Domain.Customer c = new Domain.Customer();

            while (dr.Read())
            {
                c.CompanyName = dr["companyname"].ToString();
                c.CustomerId = Convert.ToInt32(dr["customerid"]);
                c.EmailAddress = dr["emailaddress"].ToString();
                c.FirstName = dr["firstname"].ToString();
                c.LastName = dr["lastname"].ToString();
                c.MiddleName = dr["middlename"].ToString();
                c.ModifiedDate = Convert.ToDateTime(dr["modifieddate"]);
                c.Phone = dr["phone"].ToString();
            }

            if (!dr.IsClosed)
                dr.Close();

            return c;
        }
    }
}

Explicando o código acima

Primeiramente repare nos Using, eu acrescentei uma referência ao projeto ABCApp.Domain, pois é lá que esta a classe que eu quero popular; e ao System.Data e System.Data.Common, pois vou usar o objeto Command e o DataReader do ADO.Net.
Na linha 14 eu estou criando o “BD”, essa DatabaseFactory vai criar automáticamente uma Connection para mim, através da minha ConnectionString configurada, e através desse objeto vamos interagir com o BD. A vantagem é que a EntLib vai cuidar da conexão para a gente, abrir, fechar, e outras coisas!
O objeto Command já é conhecido de quem já programou com ADO.Net, o legal aqui é que na linha 20 é criado um objeto de parâmetro, normalmente se concatenaria o código na string mas não é uma prática muito recomendada.
A grande diferença aqui é o uso do Data Reader, como não estamos usando um DataSet, vamos puxar os dados do BD e popular um objeto, que é feito na linha 22, então é só ler o objeto dr e ir populando os dados depois de inicializado o nosso objeto de Domain.

Para testar é só escrever o código abaixo no Main do nosso projeto Console.

static void Main(string[] args)
        {

            ABCApp.Domain.Customer c;

            ABCApp.DAL.Customer dalCustomer = new ABCApp.DAL.Customer();

            c = dalCustomer.GetCustomerById(1);
     �
            System.Console.WriteLine(c.CustomerId.ToString() + " - " + c.FirstName.ToString() + " " + c.LastName.ToString());

            System.Console.ReadKey();
        }

Qual a vantagem de usarmos isso tudo?

Bom, primeiramente estamos programando realmente em OO, temos um objeto de domínio, a camada de acesso a dados esta isolada do resto, e principalmente não estamos usando DataSet!

Se você quiser baixar o código esta disponível no CodePlex – ABCApp e baixe o Change Set – 33351.

No próximo post (assine o feed para acompanhar) vou mostrar o que podemos fazer de interessante tendo esse objeto de domínio e vou fazer um Refactoring para darmos uma melhorada no código já, pois a idéia aqui era mostrar mais o acesso através da EntLib e como fazer sem o uso de DataSet. Até lá!
Críticas, sugestões, dúvidas são sempre bem-vindas, use o recurso de comentário do blog, a sua dúvida pode ser a de outro, e fica disponível para todos!

Categories: .net, abcapp Tags: , , ,

Novo feed, assine… daqui a pouco novo post!

26, outubro, 2009 egomesbrandao Sem comentários

Pessoal,

Estou mudando o endereço do feed, se você assinou mude para:

http://feeds.feedburner.com/egomesbrandaoblog

Obrigado por continuar lendo, e daqui a pouco sai novo post: Como acessar dados sem usar Dataset.

Categories: Sem categoria Tags:

Sobre a reunião do DNA, PMI X Scrum, e podcast

29, setembro, 2009 egomesbrandao 7 comentários

Antes de postar o próximo post do ABC App eu quero comentar sobre dois acontecimentos.

Dia 26 de setembro aconteceu mais uma reunião do grupo DNA (.NetArchitects), o tema foi PMI X Scrum. O objetivo era fazer uma mesa redonda em que cada um dos lados tivesse defensores em que apresentassem a sua defesa pelo uso de um ou do outro. Infelizmente,  do lado do PMI nossos convidados não apareceram, o nosso grupo DNA, é praticamente 100% a favor do Scrum, então dois se ofereceram para defender a visão do PMI:  André Dias (http://blogs.msdn.com/andredias/, siga @andrediasbr) e Victor Cavalcanti (http://www.cavalcante.net, siga @vcavalcante), do lado do Scrum ficou o Giovanni Bassi (http://unplugged.giggio.net, siga @giovannibassi).
Fora a frustração evidente do André e do Victor, de ter que defender o PMI o papo foi muito legal. O que tirei da conversa:

  • O PMI é velho! Hoje estamos cada vez mais dinâmicos, aplicações são escritas por pessoas que não são desenvolvedores em suas horas vagas, arrancando pedaços de participação de mercado de empresas, e por conta disso,  precisamos de mais velocidade; então por quê continuar com algo que é lento? Onde precisamos de controle vamos controlar, onde não precisamos de controle não vamos controlar! (do manifesto ágil: Individuals and interactions over processes and tools)
  • Se precisamos cada vez mais de velocidade , é por que precisamos de software pronto o mais rápido possível, tanto para atender uma demanda de mercado, como uma mudança de negócio de uma empresa; então por quê perder tempo com o que não é essencial? Com o que não vai trazer ROI? Vamos entregar! (do manifesto ágil: Working software over comprehensive documentation)
  • Se precisamos de software rápido e funcionando, precisamos de pessoas capacitadas, treinadas, focadas, interessadas para desenvolver. Então por quê não valorizamos esses profissionais? Por quê esprememos deles coisas inúteis como cumprimento de horário, vestuário, entre outras coisas? Vamos deixar as pessoas trabalharem confortavelmente, vamos investir nos bons profissionais, vamos recompensar quem traz ganhos para a empresa! (do manifesto ágil: Individuals and interactions over processes and tools)
  • Para isso tudo acontecer precisamos ser dinâmicos, não nos fechar, não entrarmos em uma bolha, tratar funcionários e clientes como parceiros; Por quê então tornamos eles nossos inimigos? Vamos construir pontes, ao invés de derrubá-las! (do manifesto ágil: Responding to change over following a plan)

Scrum é isso, nada mais que isso, o que falta aí é documento Product Backlog e as cerimônias de planejamento, reunião diária, e de finalização do Sprint. Precisamos mais do que isso para entregar um software? Não precisamos escrever extensos documentos que nunca serão lidos, não precisamos ficar montando cronogramas de coisas que não podemos prever, não precisamos ter alguém para mandar, só precisamos deixar que foi contratado para fazer o trabalho… trabalhar!

Quem quiser saber o que rolou na reunião veja pelo link do livemeeting, o André Dias também fez um post muito legal, tem até uma colagem de uma conversa com o @RenatoFerracini que rolou no twitter.

O outro assunto é sobre o mais novo episódio do podcast do .NetArchitects , que falamos sobre a profissão de Arquiteto, o assunto foi muito legal e vamos voltar a falar sobre ele com certeza! Assine o feed, ouça e comente!

Ainda essa semana sai o próximo post…

Categories: Sem categoria Tags:

A falácia do desenvolvimento em 3 camadas

10, setembro, 2009 egomesbrandao Sem comentários

O desenvolvimento em 3 camadas, pedido em tantas vagas de emprego, em projetos de software, tanto discutido e difundido em fórums, livros e revistas de TI é uma verdadeira falácia!

falácia1
fa.lá.cia1
sf (lat fallacia) 1 Qualidade de falaz. 2 Engano, logro, burla. 3 Sofisma.

sofisma
so.fis.ma
sm (gr sóphisma) 1 Lóg Raciocínio capcioso, feito com intenção de enganar. 2 Argumento ou raciocínio falso, com alguma aparência de verdade. 3 pop Dolo, engano, logro.

Antes de começarmos a codificar alguma coisa, é bom um pouco de história para nos situarmos ! O termo foi difundindo erradamente. Vamos começar do começo e por partes, ou camadas , se preferir. :P

Tive um primeiro contato com o termo desenvolvimento em camadas por volta do ano 2000. Na época, uma das linguagens mais usadas era o Visual Basic 6.0, o Java estava crescendo, e o Delphi era bem usado. A Microsoft recomendava o uso de ADO, presente no pacote MDAC, em detrimento ao DAO. O objetivo era ir no banco o mais tarde possível, pegar os dados e fechar a conexão o mais cedo possível. Surgiu então o Win DNA (Windows Distributed interNet Applications Architecture), como o link diz é um nome marketeiro para tecnologias que já existiam mas foram agrupadas em uma arquitetura (COM, COM+, antigo MTS; ADO, ActiveX, ASP). Na época a minha bíblia era o livro Mary Kirtland, posteriormente li também o livro do Fábio Câmara.

A arquitetura Win DNA

A MS,  então,  comecou a divulgar a divisão de responsabilidades. A maioria dos programadores VB na época não usava nem o conceito de Classe, isso passou a ser mais demonstrado nos exemplos e no próprio livro, mas como o VB não era verdadeiramente OO não surtiu muito efeito. Até mesmo a divisão em DLL’s não era comum, o que mais se via eram executáveis gigantescos ou vários gigantescos por módulo!

O acesso aos dados era feito usando-se o RecordSet do ADO, criava-se um, ia no banco de dados, populava ele, fechava-se a conexão e usava na aplicação. A arquitetura,  então, era os Formulários (Form) no EXE e DLL’s;  A escrita do CRUD ficava em uma DLL. Na época,  a MS incentivava o uso massivo de Stored Procedures. E começou um movimento para tirar a lógica de negócios da camada de apresentação, ainda na fase dessa arquitetura era muito comum ter regras no banco de dados, mas falava-se em colocar essas regras em DLL’s também, então a camada de apresentação chamava uma DLL que continha algumas regras, que chamava a DLL de CRUD, que populava um RecordSet e retornava pela cadeia até a tela do usuário.

As coisas mudam no .Net

Com a vinda do .Net tivemos uma migração de algumas aplicações de maneira automática por meio de Wizards, alguns programadores também começaram a programar em VB.Net ou foram para o C#, uma linguagem mais de “gente grande” por ser mais parecida com Java. Porém,  o paradigma é diferente! VB 6.0 não é puramente OO, VB.Net sim! Aliás, o VB.Net é somente a sintaxe do VB 6.0, ele é uma linguagem em cima de outra plataforma.

Mas as pessoas são acostumadas a hábitos e,  o desenvolvimento em .Net foi feito da mesma maneira que vinha sendo feito no VB 6.0: lógica separada dos dados.

O paradigma OO nos diz: Cada classe determina o comportamento (definido nos métodos) e estados possíveis (atributos) de seus objetos, assim como o relacionamento com outros objetos. (fonte: Wikipedia)

Na arquitetura Win DNA os dados ficavam em um RecordSet e o comportamento em funções de uma classe em uma DLL, o RecordSet passeava pela aplicação e,  se ela fosse um controle de Estoque uma função recebia o RecordSet, percorria ele para ver se algum item estava zerado para gerar um novo pedido.

Na arquitetura OO não existe essa separação, o que eu quero mostrar com os próximos posts é que ao termos objetos de domínio, estamos facilitando o desenvolvimento por deixarmos tudo agrupado (comportamento + estado), a facilidade de manutenção será muito maior. Outra coisa, o uso de DataSet’s deixa o código também mais confuso, usando classes POCO o código será muito mais fácil de entender e leve.

Continue acompanhando!

Categories: .net, abcapp Tags:

ABC App – 01

25, agosto, 2009 egomesbrandao Sem comentários

Ano passado comecei um projeto no CodePlex para mostrar o padrão MVC em Windows Forms para quem ainda não conhece. Mas o projeto ficou parado, mudei de .Net 2005 para .Net 2008 e o projeto não andou, esse ficou pesado, mas acho que é hora de começar me mexer!

Resolvi que não vou focar em MVC, vou usar o projeto para escrever sobre boas práticas, coisas que uso no meu dia- a-dia, então mudei o nome dele novamente (hehe) e ficou assim: ABC App.

Aqui no blog vou usar a categoria abcapp para publicar os posts referentes a essa série.

O código fonte deste projeto está hospedado no CodePlex em ABCApp, e , como o projeto é para quem também está iniciando então vou usar as ferramentas Express da Microsoft, Visual C# Express 2008. Vou usar também o TortoiseSVN, é só baixar o arquivo MSI e instalar. Antes , para acessar o CodePlex usando o TortoiseSVN era necessário o uso do  SvnBridge, desenvolvido pela equipe do site, agora não é mais necessário. Todo o projeto tem uma URL para ele, do ABCApp é https://abcapp.svn.codeplex.com/svn.

Eu criei o projeto na pasta Projects que o VS.Net cria dentro da pasta Documentos do Usuário.

Depois que você instalou o TortoiseSVN é possível baixar em qualquer lugar o projeto, basta clicar com o botão direito do mouse dentro de uma pasta vazia, e escolher a opção “SVN Checkout” do menu de contexto.

Conforme o projeto for evoluindo é só atualizar o fonte, para isso clique com o botão direito do mouse dentro da pasta e escolha “SVN Update”.

Quem tem uma licença do VS.Net, pode baixar aqui o Team Explorer, ele não vai funcionar com as versões Express, infelizmente!

Para quem quer saber mais sobre o Subversion e Tortoise , saiu uma matéria na edição 07 de Fevereiro/Março da Mundo.Net, e aqui você pode baixar um livro sobre o Subversion.

Próximo post vou começar a desenvolver o aplicativo e vou começar a falar de uma maneira de desenvolver usando objetos de negócio acessando o banco de dados sem o uso de Dataset’s!

Categories: .net, abcapp Tags: , , ,