Archive for February, 2009
Testando a engine de blog com BDD
Continuando o projeto de uma engine de Blog, resolvi dar início ao plano de testes unitários.
Optei por utilizar a abordagem Behavior Driven Development, o que alguns chamam de uma evolução do TDD.
O interessante desta abordagem é que o código da base de testes fica limpo, focado nas regras de negócio.
Quando algum teste falhar, dificilmente o programador perderá tempo entendendo porque o teste parou de funcionar e o quê precisa ser consertado.
Para ajudar a testar os objetos de maneira desacoplada, resolvi adotar o framework Rhino Mocks.
Para aplicar o BDD utilizei o NBehave, que neste caso está apoiado sobre o NUnit.
Ainda estou estudando como implentar mocks de maneira adequada e também amadurecendo a utilização das técnicas de BDD.
Mas gostei bastante do resultado.
using NBehave.Narrator.Framework;
using NBehave.Spec.NUnit;
using NUnit.Framework;
using Rhino.Mocks;
using Specification = NUnit.Framework.TestAttribute;
namespace MyCompany.Web.Blog.Tests
{
[TestFixture]
public class Author_publishing_entries : SpecBase
{
private IBlogContext context;
private Entry entry;
private Story story;
private MockRepository mocks;
[Story]
public override void MainSetup()
{
base.MainSetup();
PrepareContext();
story = new Story("Publishing");
story.AsA("blog author")
.IWant("to be able to publish an entry")
.SoThat("it can be shared with a reader");
}
private void PrepareContext()
{
entry = new Entry("someTitle", "someSlug", "someIntro",
"someContent", null);
mocks = new MockRepository();
context = mocks.StrictMock<IBlogContext>();
var blog = mocks.Stub<IBlog>();
var author = mocks.PartialMock<Author>();
author.Blogging = blog;
Rhino.Mocks.SetupResult.For(context.GetBlog())
.Return(blog);
Rhino.Mocks.SetupResult.For(context.CurrentAuthor())
.Return(author);
mocks.ReplayAll();
}
[Specification]
public void Attempting_to_publish()
{
var blog = context.GetBlog();
var author = context.CurrentAuthor();
story.WithScenario("publishing an entry")
.Given("the blog under use", () => blog.ShouldNotBeNull())
.And("the author is blogging", () => author.ShouldNotBeNull())
.When("he attempts to publish an entry", () => author.Publish(entry))
.Then("the blog engine is comunicated", () =>
blog.AssertWasCalled(b => b.SubmitEntry(entry)));
}
}
}
p>
using System.Collections.Generic;
using NBehave.Narrator.Framework;
using NBehave.Spec.NUnit;
using NUnit.Framework;
using Rhino.Mocks;
using MyCompany.Web.Blog.Specifications;
using Specification = NUnit.Framework.TestAttribute;
namespace MyCompany.Web.Blog.Tests
{
[TestFixture]
public class Blog_receiving_entries : SpecBase
{
private IBlogContext context;
private Entry validEntry;
private Entry entryWithInvalidTitle;
private Entry entryWithInvalidSlug;
private Entry entryWithInvalidContent;
private List<Entry> invalidEntries;
private Story story;
private MockRepository mocks;
[Story]
public override void MainSetup()
{
base.MainSetup();
PrepareContext();
story = new Story("Receiving entries");
story.AsA("Blog engine")
.IWant("to receive entries")
.SoThat("I can show them to a reader");
}
private void PrepareContext()
{
const string validTitle = "validTitle",
validSlug = "validSlug", validContent = "validContent";
const string intro = "intro";
const List<Tag> tagsRelated = null;
const string invalidTitle = "",
invalidSlug = "", invalidContent = "";
validEntry = new Entry(validTitle, validSlug,
intro, validContent, tagsRelated);
entryWithInvalidTitle = new Entry(invalidTitle,
validSlug, intro, validContent, tagsRelated);
entryWithInvalidSlug = new Entry(validTitle,
invalidSlug, intro, validContent, tagsRelated);
entryWithInvalidContent = new Entry(validTitle,
validSlug, intro, invalidContent, tagsRelated);
invalidEntries = new List<Entry>();
invalidEntries.AddRange(new Entry[]
{
entryWithInvalidTitle,
entryWithInvalidSlug,
entryWithInvalidContent
});
mocks = new MockRepository();
context = mocks.StrictMock<IBlogContext>();
var blog = mocks.PartialMock<Blog>();
var repository = mocks.Stub<IBlogRepository>();
blog.Repository = repository;
Rhino.Mocks.SetupResult.For(context.GetBlog())
.Return(blog);
mocks.ReplayAll();
}
[Specification]
public void Receiving_valid_entries()
{
var blog = context.GetBlog();
story.WithScenario("receiving a valid entry")
.Given("the blog under use", () =>
blog.ShouldNotBeNull())
.When("it receives a valid entry", () =>
blog.SubmitEntry(validEntry))
.Then("the entry is accepted", () =>
blog.Entries.Contains(validEntry).ShouldBeTrue());
}
[Specification]
public void Receiving_invalid_entries()
{
var blog = context.GetBlog();
story.WithScenario("receiving an invalid entry")
.Given("the blog under use", () =>
blog.ShouldNotBeNull())
.When("it receives an invalid entry", () => { })
.Then("the entry is rejected", () =>
invalidEntries.ForEach(invalidEntry =>
typeof(BlogException).ShouldBeThrownBy(() =>
blog.SubmitEntry(invalidEntry))));
}
}
}
Microsoft Certified Professional
No último dia de 2008 me tornei MCP (Microsoft Certified Professional).
Isto mesmo, foi em 31 de dezembro.
Eu explico.
Comprei o voucher na promoção Second Shot.
Mas para utilizar a promoção eu precisava prestar o exame até o final de 2008.
Foi o que eu fiz.
Foram dezenas de horas de estudo, mas valeu a pena.
Nem precisei da segunda chance.
O exame 70-536 é apenas o primeiro passo para quem se interessar pelas certificações .NET da Microsoft.
Nos próximos meses pretendo dar continuidade à caminhada.
Se você está almejando se certificar também, aí vão algumas dicas:
- Se informe sobre as certificações no site da Microsoft. O que não falta é opção.
- Existem materiais publicados pela própria Microsoft, direcionados aos exames das certificações.
- Estude.
Para mim bastou o estudo focado no livro direcionado ao exame.
Um ponto interessante é que os exames exigem o domínio da tecnologia abordada, o que ajuda a aprofundar o seu conhecimento.
Boa sorte !
Ou melhor, bom estudo.
NHibernate in Action – review

NHibernate in Action
Li o livro há uns quinze ou vinte dias, deve ter levado umas 10 horas.
Achei bastante interessante a abordagem proposta. A todo momento são destacadas práticas recomendadas ou não quando usado o NHibernate.
NHibernate in Action cobre muita coisa no que diz respeito ao framework, o suficiente para servir de referência para quem trabalha ou visa trabalhar com ele.
É interessante que o leitor já possua conhecimento sobre o que é um ORM e principalmente, experiência com desenvolvimento .NET.
Após ler este livro você:
- Conhecerá os principais conceitos de persistência e mapeamento objeto/relacional;
- Entenderá porque este framework é muito bem visto por aqueles que utilizam-se da abordagem ORM no desenvolvimento de aplicações .NET;
- Entenderá a arquitetura do NHibernate, sabendo utilizar a API sem grandes problemas;
- Será capaz de traçar estratégias de mapeamento visando um aproveitamento eficaz de seu banco de dados, realizar mapeamentos complexos envolvendo por exemplo herança, conhecer o recurso de cache do NHibernate, entre outras coisas;
- Possivelmente se peguntará porque continuar fazendo acesso a dados na mão, caso você ainda o faça.
Concluindo, um livro de foco bem definido, capaz de iliustrar sua abordagem através de situações enfrentadas no dia-a-dia de desenvolvedores de software.
ORM é uma técnica que possibilita a redução de código de infra-estrutura escrito em uma aplicação, possibilitando à equipe de desenvolvimento manter o foco no negócio envolvido pelo software. Aplicações que aplicam técnicas e princípios da orientação a objetos possuem uma interação com sistemas de banco de dados relacionais pouco natural.
ORM tornou-se a ferramenta certa para aqueles que querem tratar mais de objetos (que representam o mundo real, através de estado e comportamento) e menos de dados relacionais.
Desenhando um sistema de Blog
Há algumas semanas resolvi desenhar um sistema de Blog, para praticar alguns conceitos e tecnologias que venho adotando.
Dado o meu interesse por Domain-Driven Design, só há uma parte do sistema a ser projetada incialmente: o domínio.
Um blog é um sistema simples, em sua essência.
Algo como uma ferramenta online de publicação de textos.
Os textos são publicados por um autor, e a idéia é, obviamente, que eles sejam lidos por um leitor.
O leitor obtém os textos do blog de diversas maneiras. Pode estar procurando por posts recentes, de um determinado mês, pode se interessar por um post em especial, desejando ler o conteúdo completo.
Pode também procurar posts relacionados a determinado assunto.
Guiado por estas idéias, cheguei ao meu modelo inicial.
O modelo ainda não aborda muitas coisas, mas já contém o suficiente para dar um pontapé inicial no projeto:
Vale ressaltar que estou apenas levando em consideração a abordagem DDD, e que em nenhum momento esta abordagem implicará em limitar a minha criatividade ou comprometer a simplicidade de meu sistema.
Fica para posts futuros o aprofundamento do projeto, onde abordarei alguns aspectos da arquitetura que será utilizada e começarei a colocar a mão na massa.
Comentários e sugestões são muito bem vindos.
Inauguração do blog
Este é o primeiro post de meu blog.
Meu nome é Rafael Noronha e sou desenvolvedor de sistemas, focado na tecnologia .NET, da Microsoft.
Você pode saber mais sobre mim aqui.
Discutirei neste blog assuntos relacionados a desenvolvimento de software
Para mim desenhar e codificar software assemelha-se mais a um trabalho artístico do que a uma atividade de engenharia, sendo esta constantemente utilizada em comparações impostas à minha atividade (possivelmente sua também).
Tenho como interesse otimizar as práticas realizadas por mim e aqueles que trabalham comigo. Buscar sempre melhores resultados, o que requer constante aperfeiçoamento e reciclamento. Espero carregar isto sempre comigo.
Espero que o blog viabilize a troca de idéias e experiências entre mim e profissionais atuantes no setor, servindo como ferramenta útil na luta pelos meus objetivos.
Feita a inauguração, em breve os primeiros posts oferecendo algum conteúdo de interesse (ou não !).
Já adianto que pretendo falar sobre processos de desenvolvimento, arquitetura, tecnologias, frameworks, etc.
Até lá.
