NHibernate - Sessão

Em NHibernate eu uso a singleton pattern para implementar uma classe que me faça a gestão da sessão. 
Este é um exemplo de como essa classe costuma ser:

public class SessionProvider
    {
        private SessionProvider()
        {
        }

        public static SessionProvider Instance { get; private set; }
        private static ISessionFactory sessionFactory;
        static SessionProvider()
        {
            var provider = new SessionProvider();
            provider.Initialize();
            Instance = provider;
        }
        private const string ConnectionString = "Server=localhost;Port=3307;user=root;Password=123;Database=Exemplo";
        private void Initialize()
        {
            var configuration = Fluently.Configure()
            .Database(FluentNHibernate.Cfg.Db.MySQLConfiguration.Standard
                          .ConnectionString(ConnectionString).ShowSql()
            )
            .Mappings(m =>
                      m.FluentMappings
                          .AddFromAssemblyOf<Core.Domain.Property>()
                          .AddFromAssemblyOf<Core.Domain.PropertySubscription>())
            .ExposeConfiguration(cfg => new SchemaExport(cfg)).BuildConfiguration();
            sessionFactory = configuration.BuildSessionFactory();
        }
        public static void GenerateDatabase()
        {
            var configuration = Fluently.Configure()
            .Database(FluentNHibernate.Cfg.Db.MySQLConfiguration.Standard
                          .ConnectionString(ConnectionString).ShowSql()
            )
            .Mappings(m =>
                      m.FluentMappings
                          .AddFromAssemblyOf<Core.Domain.Property>()
                          .AddFromAssemblyOf<Core.Domain.PropertySubscription>())
            .ExposeConfiguration(cfg => new SchemaExport(cfg)).BuildConfiguration();
            var exporter = new SchemaExport(configuration);
            exporter.Execute(true, true, false);
        }
        public ISession OpenSession()
        {
            return sessionFactory.OpenSession();
        }
    }

Esta é uma forma de como lido com a sessão.

using(var session = SessionProvider.Instance.OpenSession())
using (var transaction = session.BeginTransaction())
{
    try
    {
        transaction.Commit();
    }
    catch (Exception e)
    {
        transaction.Rollback();
        throw;
    }
    finally
    {
        session.Close();
    }
}
Posted por Guilherme Cardoso | with no comments
Filed under: ,

RavenDB #2 - Esquema dos documentos

Este artigo é uma continuação da minha aventura em RavenDBhttp://pontonetpt.org/blogs/guilhermecardoso/archive/2011/09/28/ravendb-1-introdu-231-227-o.aspx

Algo que referi no primeiro artigo foi que toda esta ideia de uma bd não relacional, para alguém como eu que só viu sql server e mysql à frente, foi um bocado complicada de perceber, Por isso achei melhor mostrar primeiro um modelo um pouco mais complexo, para também ouvir a opinião de quem já tenha implementado esta base de dados em projectos "reais" e saber se já consegui apanhar bem o conceito!

No primeiro artigo apenas usei um esquema para Newsletters e Comentários. Como os exemplos que tenho visto na net são à base de blogues e lojas de comércio electrónici, neste artigo vou fazer o esquema para uma liga de desporto.

A informação que temos de guardar ér:

  • Detalhes de todas Jornadas (nº da jornada, descrição geral)
  • Resultados dos jogos de todas as Jornadas (incluindo que equipa jogou contra qual, e quais os detalhes de cada uma das equipas nesse jogo)
  • Classificacao das equipas do final de cada jornada 
  • Melhores marcadores de cada jornada
  • Todas as equipas registadas na liga

Neste contexto imaginei uma liga de futebol e o esquema numa base de dados SQL que me lembrei foi este:

Podia ser criada uma tabela de Jogos com os campos Id, Data, Descricao e depois outra tabela de JogosDetalhes com os campos: IdEquipa, GolosMarcados, GolosSofridos, FaltasCometidas, FaltasSofridas, CartoesAmarelos, Cartões vermelhos, Fora (boleano para sabermos se a equipa jogou fora ou em casa). Esta alternativa implicaria o uso de mais uma tabela, e consequentemente mais uniões nas consultas. E neste esquema, cada Jogo apenas teria duas referências a registos da tabela JogosDetalhes (o que não justifica muito a criação de mais uma tabela).

Podem haver outros esquemas mais eficientes e estruturados que este, mas a questão aqui não é essa.

Tentando passar isto para uma esquema para integrar no RavenDB este foi um dos esquemas que mais me pareceu eficiente.

Um exemplo de uma jornada seria este (apenas meti quatro equipas para não ficar demasiado longo no ecrã):

{
            NumeroJornada : 1,
            Classificacao : [
                { Posicao : 1, IdEquipa : "1", NomeEquipa : "Sporting CP", Pontos : 21, GolosMarcados : 30, GolosSofridos: 12},
                { Posicao : 2, IdEquipa : "2", NomeEquipa : "FC Porto", Pontos : 20, GolosMarcados : 30, GolosSofridos: 12},
                { Posicao : 3, IdEquipa : "4", NomeEquipa : "SL Benfica", Pontos : 15, GolosMarcados : 30, GolosSofridos: 12},
                { Posicao : 4, IdEquipa : "3", NomeEquipa : "Braga", Pontos : 214, GolosMarcados : 30, GolosSofridos: 12}    
            ],
            MelhorMarcadorDaJornada : [
                { Posicao : 1, IdEquipa : "1", Nome : "Nuno", Golos : 10},
                { Posicao : 2, IdEquipa : "2", Nome : "Rui", Golos: 9}
            ],
            DescricaoGeral : "Descrição Geral da Jornada",
            Jogos : [
                    {Data : "12/12/2012",
                    Descricao : "Descrição Geral do Jogo",
                    Duracao : "93:24",
                    EquipaCasa : {
                                    Id : "1",
                                    Nome : "Sporting Clube Portugal",
                                    GolosMarcados : 2,
                                    GolosSofridos : 3,
                                    CartoesAmarelos : 0,
                                    CartoesVermelhos : 0,
                                    FaltasCometidas : 2,
                                    FaltasSofridas : 1
                                },
                    EquipaFora : {
                                    Id : "2",
                                    Nome : "Futebol Clube do Porto",
                                    GolosMarcados : 2,
                                    GolosSofridos : 3,
                                    CartoesAmarelos : 0,
                                    CartoesVermelhos : 0,
                                    FaltasCometidas : 2,
                                    FaltasSofridas : 1
                                },
                    },
                    {Data : "12/12/2012",
                    Descricao : "Descrição Geral do Jogo",
                    Duracao : "93:24",
                    EquipaCasa :{
                                    Id : "3",
                                    Nome : "Sport Lisboa Benfica",
                                    GolosMarcados : 2,
                                    GolosSofridos : 3,
                                    CartoesAmarelos : 0,
                                    CartoesVermelhos : 0,
                                    FaltasCometidas : 2,
                                    FaltasSofridas : 1
                                },
                    EquipaFora : {
                                    Id : "4",
                                    Nome : "Braga",
                                    GolosMarcados : 2,
                                    GolosSofridos : 3,
                                    CartoesAmarelos : 0,
                                    CartoesVermelhos : 0,
                                    FaltasCometidas : 2,
                                    FaltasSofridas : 1
                                },
                    }
                    ]
}

Cada documento de Jornada pode parecer um pouco grande, mas eu desenhei esta estrutura para conseguir em client side visualizar jornada a jornada, e em cada uma ter logo "acessíveis" todas as informações sobre elas (após o objecto estar no lado do cliente, o resto é js para brincar com os dados!)

O documento de cada equipa seria algo do gênero:

{[
    {Id : "1", Nome : "Sporting Clube Portugal", AnoFundado : "1906"}
]

A início não pensei neste esquema. Enquanto estava a desenhar a base de dados, continuava a pensar em relacionamentos e chaves primárias, que acabei por desenhar algo semelhante a ter um documento para cada tabela!

Para guardar estes documentos, as entidades poderiam ficar algo assim: 

public class Jornada
    {
        public int NumeroJornada { get; set; }
        public List<Classificacao> Resultados { get; set; }
        public List<MelhorJogadorDaJornada> MelhoresJogadores { get; set; }
        public List<Jogos> Jogos { get; set; }
    }
    public class Classificacao
    {
        public int Posicao { get; set; }
        public int IdEquipa { get; set; }
        public string NomeEquipa { get; set; }
        public int pontos { get; set; }
        public int GolosMarcados { get; set; }
        public int GolosSofridos { get; set; }
    }
    public class MelhorJogadorDaJornada
    {
        public int Posicao { get; set; }
        public int IdEquipa {get;set;}
        public string Nome { get; set; }
        public int Golos { get; set; }
    }
    public class Jogos 
    {
        public DateTime Data { get; set; }
        public string Descricao { get; set; }
        public string Duracao { get; set; }
        public JogosDetalhes EquipaCasa { get; set; }
        public JogosDetalhes EquipaFora { get; set; }
    }
    public class JogosDetalhes
    {
        public int IdEquipa { get; set; }
        public string NomeEquipa { get; set; }
        public int GolosMarcados { get; set; }
        public int GolosSofridos { get; set; }
        public int CartoesAmarelos { get; set; }
        public int CartoesVermelhos { get; set; }
        public int FaltasCometidas { get; set; }
        public int FaltasSofridas { get; set; }
    }
    public class Equipas
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public DateTime AnoFundado { get; set; }
    }
Posted por Guilherme Cardoso | with no comments
Filed under:

RIP Steve Jobs

O tão conhecido Steve Jobs foi declarado como morto.

É claro que pelo Twitter e o resto rapidamente vão saber isto mas achei por bem deixar aqui este post dedicado à memória dele.
No site oficial da Apple podem ler um comunicado: http://www.apple.com/

RIP Steve Jobs

Posted por Guilherme Cardoso | with no comments

RavenDB #1 - Introdução

RavenDB #2 - Esquema dos documentos (13/11/2011)

Recentemente comecei a desenvolver um projecto com uns colegas em que praticamente todos os módulos vão ser desenvolvidos à base de gestão de conteúdos.
Como tenho ouvido falar bastante de RavenDB, e por ser uma base de dados orientada a documentos, decidi implementá-la neste projecto.

Assim vou começar a escrever uma série de artigos sobre RavenDB à medida que for desenvolvendo este projecto (e aprendendo mais sobre esta base de dados claro!).

Página do Projecto: http://ravendb.net/
Blog do Ayende (muitos artigos úteis!): http://ayende.com/blog 

O que é RavenDB?

Em primeiro lugar é importante referir que esta base de dados foi desenvolvida para a plataforma .NET.

Quem já lidou com ORMs (NHibernate, EF, etc) e recorreu a LINQ para escrever queries certamente vai-se adaptar bem à API do RavenDB. 

Ao contrário de SQL Server, MySQL, Oracle, etc, o RavenDB não é é uma base de dados SQL. Não contem o esquema típico de tabelas, relacionamentos entre tabelas, enfim, aquilo a que eu sempre me habituei quando ouvia a falar de Base de Dados! Ele armazena documentos no formato JSON, independentemente da estrutura deles (ou seja, não temos de obedecer à estrutura das tabelas por exemplo). Não lhe interessa se um documento tem ou não determinada propriedade. 

Para percebermos melhor isto vamos usar um cenário de um blog com artigos/comentários: numa base de dados SQL nós iríamos criar uma tabela para os artigos e outra tabela com os comentários dos artigos. Poderíamos também criar outra tabela para o rating dos artigos.
Um exemplo de um documento guardado do artigo seria algo semelhante a isto: 

{
  "Titulo": "Titulo do Artigo",
  "Corpo": "Corpo do Artigo",
  "DataCriacao": "0001-01-01T00:00:00.0000000+00:00",
  "Comentarios":
                {
                   "Autor" : "Nome do Autor",
                   "Corpo" : "Corpo do Comentário"
                },
                {
                   "Autor" : "Nome do Autor",
                   "Corpo" : "Corpo do Comentário"
                }
}

Nota: Para quem não está familiarizado com o formato JSON recomendo que leia este artigo: http://www.json.org/js.html

Além de  guardar o documento, o Raven guarda informações metadata. No exemplo que estamos a seguir, ele iria guardar:

Metadata
Raven-Entity-Name Artigo
Raven-Cl-Type Projecto.Entidades.Artigo, Projecto

Details
ETag (número!)
Last-Modified 9/28/2011 3:06:00 AM

(no final do artigo vou mostrar um exemplo para criar este documento com esta metadata).

Como já deu para perceber até este ponto, o Raven guarda documentos num formato válido JSON. Caso queiramos guardar dados binários podemos usar attachments (anexos).
Ao contário dos documentos, os anexos não são lidados como objectos num formato JSON (isto para não termos de codificar os dados binários para podemos guardar numa propriedade do documento, por exemplo uma fotografia).


Instalação do RavenDB

O meu primeiro comentário no Twitter relativamente ao RavenDB foi mesmo: First impression of #RavenDB: I love the simplicity of setting up an project w/ RavenDB. With a few lines of code i've got it running ;)

De facto é mesmo impressionante a facilidade com que conseguimos correr esta base de dados. Em três passos:

E voilá! A interface do RavenDB foi desenvolvida em Silverlight e é bastante atractiva e funcional. Na linha de comandos que é aberta conseguimos monotorizar os request à base de dados. Por defeito, o servidor vai correr na porta 8081
Se preferirem instalar a base de dados como um service do Windows basta executar o Raven.Server.exe com o parâmetro install (linha de comandos: RavenDB-Build-X\Server\Raven.Server.exe /install).

Exemplo Prático

Apesar de este artigo ser apenas uma introdução a esta base de dados vou deixar aqui um exemplo muito simples de como podemos inserir um novo documento. Daqui a poucos dias vou escrever mais a explicar isto.

public class RavenRepository
    {
        private static DocumentStore _documentStore;
        public static DocumentStore Document
        {
            get
            {
                if (_documentStore == null)
                {
                    _documentStore = new DocumentStore() { Url = "http://localhost:8081" };
                    _documentStore.Initialize();
                }
                return _documentStore;
            }
        }
    }
// ENTIDADES
public class Artigo
    {
        public string Titulo { get; set; }
        public string Corpo { get; set; }
        public DateTime DataCriacao { get; set; }
        public List<Comentario> Comentarios { get; set; }
    }
public class Comentario
    {
        public string Autor { get; set; }
        public string Corpo { get; set; }
    }
// CAMADA DE DADOS
public class ArtigoDAL
    {
    private DocumentStore _documentStore = RavenRepository.Document;
    public Output Add(Artigo obj)
        {
            using(var session = _documentStore.OpenSession())
            {
                session.Store(obj);
                session.SaveChanges();
            }
        }
    }

Aproveito também para deixar um link útil ;) http://ravendb.net/documentation/

Posted por Guilherme Cardoso | 6 comment(s)
Filed under:

Javascript - Aplicar uma flag "isDirty" a um objecto

Hoje estive a ver com um colega do trabalho (um tal de Morais!) uma forma de saber em Javascript se as propriedades de um objecto tinham sido alteradas ou não.

Já há por aí frameworks que nos facilitam a vida neste tipo de situações, mas mesmo assim vou deixar um exemplo muito básico de uma solução que nos lembrámos. 

function Professor(){
this.Nome;
this.DataNascimento;
this.isDirty=false;
this.dirtyList = new Array();
this.setValue = function(propriedade, valor) {
                if(this.propriedade != valor) {
                this.propriedade = valor;
                this.dirtyList.push(propriedade);
                this.isDirty=true;
                }
};
}
var novo = new Professor();
console.log(novo.isDirty);
novo.setValue("Nome", "Guilherme");
console.log(novo.isDirty);

Infelizmente ainda não dá para "confiar" no uso de getters e setters em Javascript por uma questão de compatibilidade de browsers (once again, thank you dear MS...), mas dá para dar a volta usando um método para alterar a propriedade e tendo uma flag que nos avise se algo foi alterado como estou a fazer no exemplo de cima. A array dirtyList é útil para saber que propriedades foram alteradas.

Posted por Guilherme Cardoso | 2 comment(s)
Filed under:

Visual Studio 2008 - Remover Projectos Recentes

Quando o Visual Studio é iniciado, na tab Recent Projects aparece uma listagem com os últimos projectos que foram abertos.

Na versão 2010 para remover projectos desta listagem só é preciso dar um click no botão direito do rato e ir a "Remove From List", como podem ver nesta imagem:

Já nas outras versões do VS a conversa é outra. Como esta listagem está guardada em chaves no regedit do Windows, é preciso ir ao editor de registos (iniciar -> executar -> regedit.exe) e navegar até: HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\ProjectMRUList

Aqui temos a listagem dos projectos. As chaves são criadas pela forma "File1", "File2", "File3", etc. Se removermos a chave File3 é preciso alterar o nome das outras chaves seguintes (4, 5, etc) para que se mantenham em ordem, caso contrário o VS só vai mostrar até á File2.

Posted por Guilherme Cardoso | with no comments
Filed under:

MSDeploy.exe - Problema a gerar o package com o VS 2010 e MWD 2.1

Num projecto em que foi usado o Visual Studio 2010 com o  Microsoft Web Deploy 2.1, o package que foi gerado para instalar a aplicação por linha de comandos deu-me o seguinte erro a instalar noutra máquina:

 

ERROR: The system was unable to find the specified registry key or value. msdeploy.exe is not found on this machine. Please install Web Deploy before execute the script.

Please visit http://go.microsoft.com/?linkid=9278654

=========================================================

=========================================================

 

A início ainda pensei que não tivesse mesmo instalado o MSDeploy na máquina, depois de ver que tinha tentei reinstalar mas continuava na mesma, 
Depois de ler uns artigos é que reparei que o .cmd que estava a ser gerado, estava a procurar a versão 1 do MWD no registo do windows, e dava-me erro por causa disso (abrindo o .cmd num editor de texto é algo semelhante a isto):

if "%MSDeployPath%" == "" (

for /F "usebackq tokens=2*" %%i  in (`reg query "HKLM\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1" /v InstallPath`) do (

if "%%~dpj" == "%%j" ( 

set MSDeployPath=%%j

)))

 Alterando aquele "1" para "2" resolveu-me o problema. Se for preciso verificarem mesmo qual a versão que têm instalada podem usar o regedit e procurar o registo: HKLM\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\
Depois é só confirmar qual a pasta que está criada dentro do MSDeploy (1 ou 2). 

Posted por Guilherme Cardoso | with no comments
Filed under:

Arquitectura de 3 Camadas

A arquitectura de 3 camadas ou 3-Tier Architecture é uma arquitectura de desenvolvimento baseada em separar uma aplicação em 3 camadas: User Interface, Business Layer e DataAcess Layer.

Implementar a lógica da aplicação na camada Business Layer pode aumentar bastante a reusibilidade de uma aplicação. Como?

Imaginem o seguinte cenário:
um cliente pede para que seja desenvolvida uma aplicação Web para gerir o armazém dele. Desenvolvemos um website, é validada a informação antes de ser enviada para a base de dados, e tudo está a funcionar muito bem. 3 meses depois o cliente pede que seja desenvolvida outra aplicação mas para dispositivos mobile só para a consulta dos pedidos em transporte. O que vai acontecer se estamos a fazer as validações, chamadas à base e dados e outros processos todos no code behind das páginas (webforms) ou mesmo que esteja tudo numa classe, mas hà parâmetros dos métodos que precisamos de alterar, desta vez precisamos de utilizar webservices (e por aí adiante).
Como fazer este novo projecto? "Copiar -> Colar" grande parte dos métodos?
Se a aplicação tivesse separada em camadas, uma solução seria criar apenas webservices que acedessem à camada de negócio, retornassem os dados e apenas a apresentação (User Interface) seria diferente, adaptada a dispositivos móveis)

  1. User Interface - Camada apresentada ao utilizador. 
    Podem ser páginas aspx, um aplicativo silverligth, etc. É importante relembrar que tudo que for incluído aqui vai ser exposto ao utilizador, o que é uma grande preocupação a nível de vulnerabilidades da aplicação. Por exemplo, construir queries em javascript (nem sei como é possível ter lido um artigo a retratar isso) é uma vulnerabilidade a injecção SQL, enviar dados como a sessão do utilizador e outros dados que podem ser mantidos no lado do servidor deve ser evitado
  2. Business Layer - Camada do negócio da aplicação.
    Nesta camada eu são recebidos os dados do utilizador, feitas as validações necessárias, tratamento de erros, etc.
  3. Data Acess Layer - Camada que vai aceder à nossa fonte de dados. Se a aplicação usar um ORM (ie: nHibernate, EF) é nestas camadas que são construídas as instruções SQL, instruções LINQ, chamadas a stored procedures, abrir e fechar as ligações à base de dados, etc.


Analisando esta arquitectura num exemplo muito básico.

UI

<label for='loginUtilizador'>Utilizador:</label> <input type='text' id='loginUtilizador' /> </br>
<label for='loginPassword'>Utilizador:</label> <input type='text' id='loginPassword' /> 
<input type='button' value='Autenticar' onclick='Login();' />
<script type="text/javascript">
function Login() {
$.ajax({
   type: "POST",
   url: "Webservices/Utilizador.asmx/Autenticacao",
   data: "{ 'utilizador' : '" + utilizador + "', 'password' : '" + password + "'}",
   success: function(msg){
     alert(msg.d);
   }
 });
}
</srcript>

Business

internal class UserService {
private UserData _userData = new UserData(); 
public string Autenticar(string utilizador, string password) {
     // aqui pdemos encriptar a password caso ela esteja assim guardada na base de dados
     // validamos a variável utilizador e password
     bool resultado = _userData.Autenticar(utilizador, password);
     if(resultado) {
     // criamos uma sessão de autenticação por exemplo
     } 

        return (resultado) ? "Autenticação realizada com sucesso" : "Login ou Password incorrectos";
    } 
}

 Data

internal class UserData {
    public bool Autenticar(string utilizador, string password) {
        // ligação à base de dados, enviar os dados para a autenticação e retornar uma mensagem
        return true;
    } 
}

WebService

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Utilizador : System.Web.Services.WebService
{
    private UserService _userService = new UserService();
    
    [WebMethod]
    public string Autenticar (string utilizador, string password)
    {
        return _userService.Autenticar(utilizador, password);
    }
}

Eu tenho por hábito usar sufixos para as Entidades de cada camada. AlunosService, AlunosData, ProfessoresService, ProfessoresData, etc.
Torna a leitura do código um pouco mais fácil para programadores que não tenham trabalho no projecto.

 

Microsoft .NET: Architecting Applications for the Enterprise (PRO-Developer) 

Pela recomendação do João Manso deixo aqui o link a este livro.

  • Build testability, maintainability, and security into your system early in the design
  • Expose business logic through a service-oriented interface
  • Choose the best pattern for organizing business logic and behavior
  • Review and apply the patterns for separating the UI and presentation logic
  • Delve deep into the patterns and practices for the data access layer
  • Tackle the impedance mismatch between objects and data
  • Minimize development effort and avoid over-engineering—and deliver more robust results
Amazon: http://www.amazon.co.uk/Microsoft-NET-Architecting-Applications-PRO-Developer/dp/073562609X

 

 

Posted por Guilherme Cardoso | 2 comment(s)
Filed under: ,

TSQL - Cláusula Where com variávens nulas

Esta dica é muito simples mas não deixa de útil, principalmente se estivermos a concatenar strings para casos em que uma variável possa ser nula e queiramos usá-la numa cláusula Where!
Por exemplo: 

DECLARE NVARCHAR @SQL = 'SELECT ... FROM ...'

IF(@IDAluno IS NOT NULL)
     SET @SQL = @SQL + '' WHERE [IDAluno] = ' + CAST(@IDAluno AS NVARCHAR)

 Além de eu próprio já ter feito o exemplo de cima, já vi alguns artigos com uso semelhante.
Uma melhor solução seria: 

SELECT ...
FROM ...
WHERE ([IDAluno] = @IDAluno  OR @IDAluno IS NULL)

Um obrigado ao Paulo Moreira pelo conselho ;)

Posted por Guilherme Cardoso | 2 comment(s)
Filed under:

QUnit - Testes Unitários em Javascript

English version of this article: http://geekswithblogs.net/guilhermecardoso/archive/2011/10/15/qunit---client-side-unit-testing-with-tdd.aspx
Link Github: https://github.com/guilhermegeek/QUnitSample

Como tenho o hábito de escrever testes unitários para o código que escrevo decidi pesquisar um bocado sobre este tema mas em relação a client side. 
De algumas frameworks que vi aquela que escolhi foi o QUnit. É utilizado pela equipa da jQuery para testar os códigos deles, e sinceramente foi aquela que mais me pareceu fácil de configurar e é-me familiar aos testes que tenho escrito com o NUnit (para C#: http://www.nunit.org)..

Neste artigo vou mostrar um exemplo básico de como pode ser usado.

Para utilizar o QUnit é preciso recorrer á framework jQuery: http://docs.jquery.com/Downloading_jQuery
O QUnit está disponível no GitHub: https://github.com/jquery/qunit

Começamos por declarar os scripts na head da página. Podemos usar a folha de estilo disponibilizada pelo pessoal do QUnit. É apenas um ficheiro css e o código usado é limpo e simples de perceber.

<link href="/Styles/qunit.css" rel="Stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.6.1.min.js" type="text/javascript"></script>
<script src="/Scripts/qunit.js" type="text/javascript"></script>  

A seguir vamos construir um objecto para retornar o estado do erro e a mensagem. Algo assim:

function OutputJS() {
      this.Mensagem = null;
      this.Codigo = null;
}

Isto é opcional claro. Eu apenas uso este objecto porque facilita bastante o meu trabalho quando faço a verificação do estado de erro.

Para acabar as configurações de defeito do QUnit só nos falta definir os elementos html onde ele vai mostrar os estados dos testes:

<h1 id="qunit-header">Testes Unitários</h1>  
<h2 id="qunit-banner"></h2>  
<h2 id="qunit-userAgent"></h2>  
<ol id="qunit-tests">

Feito isto vamos escrever o nosso primeiro teste!
Seguindo o conceito de TDD (a início o teste é escrito para dar erro, e só depois escrevemos o código que vai ser testado e então verificamos se o teste deixa de dar erro) vamos escrever este teste:

function Deve_Validar_Codigo(codigoAluno) {
        resultado.Codigo = false;
        resultado.Mensagem = "O código de aluno deverá ter no mínimo 4 caracteres.";
        return resultado;
}

Como podem ver o teste vai devolver falso (o tal conceito de TDD). 
É agora que o QUnit entra. Como se trata de Javascript, a forma mais fácil de correr o teste é no evento $(document).ready() (quando a página é carregada). No entanto podem associar isto a um evento de um botão com um select onde tenham todos os testes que querem testar por exemplo.

<script type="text/javascript">
    $(document).ready(function () {
        module("Validação");
        test("Validar Código de Aluno", function () {
            var teste = Deve_Validar_Codigo("CD122");
            ok(teste.Codigo, teste.Mensagem);
        });
    }); 
</script>

module: permite-nos separar os testes em módulos (categorias)
test: nome dado ao teste
ok(): um dos vários tipos de assertions disponíveis do QUnit para os testes.O ok() espera que o primeiro parâmetro tenha o valor boleano true, e caso não tenha mostra a mensagem de erro do segundo parâmetro.

O teste Deve_Validar_Codigo() esta a devolver o objecto OutputJS que tem as propriedades Codigo e Mensagem. Assim, se o teste.Codigo for falso é mostrada a teste.Mensagem. É por isso que digo que utilizar um objecto deste tipo é bastante útil!

Para correr o teste basta abrir a página (onde colamos o código do test("Validar Código de Aluno", function ()) e o resultado vai ser este:

Como era de esperar o nosso teste deu erro. Vamos então alterar o método Deve_Validar_Codigo() para conseguirmos validar o código de aluno:

function Deve_Validar_Codigo(codigoAluno) {
    var resultado = new OutputJS();
    if (codigoAluno.length < 4) {
        resultado.Codigo = false;
        resultado.Mensagem = "O código de aluno deverá ter no mínimo 4 caracteres.";
    }
    else {
        resultado.Codigo = true;
        resultado.Mensagem = "Código de aluno validado com sucesso";
    }
    return resultado;
}

Se voltarmos a correr o teste o resultado já vai ser este:

E voilá!

A documentação do QUnit pode ser encontrada no site do JQuery, e lá conseguem ver mais tipos de assertions e outros tipos de opções úteis como testes assíncronos: http://docs.jquery.com/Qunit

Posted por Guilherme Cardoso | with no comments
Filed under: ,

Code Review - novo Q&A da Stack Exchange

Quem não conhece o Stackoverflow? Eu adoro o Stackoverflow, é óptimo para encontrar respostas a dúvidas que tenhamos e também ajudar-mos outros. Mas o que muitas vezes eu acabava por fazer era pedir pedir reviews de códigos que escrevia mas não tinha a certeza se estava a seguir o caminho certo.

Parece que veio aí outro Q&A da Stack Exchange: o CodeReview http://codereview.stackexchange.com/

Como o próprio nome sugere, este site serve para revisões de código. Submeter código que por qual seja razão achemos que possa ou deva ser melhorado e ler as opiniões de outros programadores.

O site ainda está numa fase beta, mas parece estar no bom caminho.

Posted por Guilherme Cardoso | with no comments

C# - Verificar se código é corrido por Testes Unitários

Por vezes pode ser-nos útil saber-mos se determinado código está a ser corrido por testes unitários (no caso de sessões ou dependências externas por exemplo).
Fica aqui um método muito útil para nunit (para as restantes frameworks de unit testing basta alterarem o nome da assembly).

Classe:

public static class UnitTestValidator
    {
        private static bool _runningFromNUnit = false;
        static UnitTestDetector()
        {
            foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (assem.FullName.ToLowerInvariant().StartsWith("nunit.framework"))
                {
                    _runningFromNUnit = true;
                    break;
                }
            }
        }
        public static bool IsRunningFromNunit
        {
            get { return _runningFromNUnit; }
        }
    }
Posted por Guilherme Cardoso | with no comments
Filed under: ,

Situação Profissional

Nas últimas semanas fui a várias entrevitas de emprego na área de consultoria, e grande parte dessas entrevistas consegui-as através deste blog. Recebi emails de empresas que entraram em contacto comigo por seguirem a comunidade pontonetpt e terem visto a minha situação profissional.

Mudei-me hà uma semana para Lisboa e já estou a trabalhar com a empresa Agap2. 

Quero assim deixar aqui um especial agradecimento a todos que têm mantido a comunidade pontonetpt ao longo deste tempo e também ao Rui Jarimba, que me ajudou bastante neste processo todo de encontrar algo.

Obrigado!

Posted por Guilherme Cardoso | with no comments

Json.NET - Json framework para .NET

o Json.NET é uma framework muito boa para quem tem de lidar com objectos Json a serem enviados por chamadas AJAX por exemplo. No caso específico do MVC .NET, temos a facilidade de retornar objectos JsonResult (o que nos facilita bastante a vida!). Mas para quem tem de fazer algo em Webforms, consegue o mesmo efeito recorrendo ao Json.NET

Uma dica que dou: criem uma classe (ie: RetornarJson) com algumas propriedades importantes que tenham de receber no lado do cliente (ie: Erro (bool), Mensagem (string), JsonRetornado (string)), e devolvam esta classe nas chamadas realizadas pelo cliente como Json.. Eu estou a utilizar algo semelhante num projecto e está a tornar-se muito produtivo. Poupa-me bastante tempo de desenvolvimento, e além de conseguir retornar o que precisar em Json (preciso sempre de serializar claro) consigo saber se correu tudo bem no lado do servidor e qual a mensagem de erro se existir.

Algo muito bom nesta framework é a facilidade de popular-mos um objecto (neste caso o Objecto1 seria um objecto criado por mim) que esteja serializado:

string json = "objecto Json retornado pelo cliente";
Objecto1 objecto = Newtonsoft.Json.JsonConvert.DeserializeObject<Objecto1>(json);

Algo que é importante destacar no Json.NET é a forma como ele lida com erros. Não temos obrigatóriamente de "apanhar" com excepções se tentar-mos popular um objecto e a coisa correr para o torto! Esta framework vem bem preparada e permite-nos lidar com isto: http://james.newtonking.com/projects/json/help/SerializationErrorHandling.html

Para quem está familirizado com LINQ, também nos é introduzido o LINQ  to JSON, assim como é possível converter Json em XML (e vice-versa). Hà muito mais a falar acerca desta framework, mas nada melhor que dar uma espreitadela nela ;)

Página do projecto: http://json.codeplex.com/
Documentação: http://james.newtonking.com/projects/json/help/ 

Aproveito para agradecer ao Paulo Morais por me ter sugerido esta framework!

Posted por Guilherme Cardoso | with no comments
Filed under: , ,

ASP.NET MVC - Custom Authorization Attribute

Por vezes precisamos de alterar o comportamento da autorização numa aplicação. No meu caso precisei de fazê-lo para implementar a autenticação num projecto com a access token do Facebook.

Podemos implementar as nossas próprias regras recorrendo à interface IAuthorizationAttribute e fazer o override ao AuthorizeCore. Este método è boleano, e retorna verdadeiro caso o utilizador tenha permissões ou falso senão tiver.

Um exemplo simples:

public class CustomAuthorizeAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (new Services.UserService().IsAuthenticated())
            {
                return true;
            }
            return false;
        }
    }

No service UserService tenho um método para verificar se o utilizador tem permissões (IsAuthenticated()).

Depois só preciso de usar o atributo [CostumAuthorize] nos controllers/actions.

[CustomAuthorize]
        public ActionResult EditarPerfil()
        {
        
        }

O utilizador apenas poderá ver a action Perfil se tiver as permissões necessárias.
Podem ver mais informações sobre a class AuthorizeAttribute aqui: http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx

Posted por Guilherme Cardoso | 2 comment(s)
Filed under:
Mais Entradas Página seguinte »