sexta-feira, 8 de janeiro de 2010

Brincando com delegates – Partes II

Dando continuidade com o assunto delegate hoje vou mostrar um cenário bem interessante de se aplicar o Func. Recursividade.

Vamos analisar o código abaixo:

public class Task
{
private IList<Task> _subTasks;
public Task Parent { get; set; }

public Task()
{
this._subTasks = new List<Task>();
}

public void AddSubTask(Task subTask)
{
if (subTask == null)
throw new ArgumentNullException("subTask");

if (IsMyParent(subTask))
throw new InvalidOperationException("Task cannot be my parent.");

this._subTasks.Add(subTask);
}

private bool IsMyParent(Task task)
{
if (task.Parent != null && task.Parent == this)
return true;

return IsMyParent(task._subTasks);
}

private bool IsMyParent(IList<Task> subTasks)
{
return subTasks.Any(c => c == this IsMyParent(c._subTasks));
}
}

Veja que o método IsMyParent tem uma sobrecarga para verificar se a tarefa infomada no parâmetro existe nas listas dos filhos das tarefa pai, mas perceba que o método só é criado para atender a necessidade da recursividade. Será que não tem como fazer tudo uma coisa só? Opa… claro que tem.

Agora vamos ver como criar o mesmo método mas dentro do escopo do IsMyParent.

//Versão 2
private bool IsMyParent(Task task)
{
if (task.Parent != null && task.Parent == this)
return true;

Func<IList<Task>, bool> isMyParent = null;
isMyParent = delegate(IList<Task> subTasks)
{
return subTasks.Any(c => c == this isMyParent(c._subTasks));
};

return isMyParent(task._subTasks);
}


Agora a verificação na lista de sub tarefas faz parte do escopo do método.

Por se tratar de um método recursivo temos que definir um valor para o delegate antes de implementá-lo, é por essa razão que temos a declaração e a implementação do isMyParent separadas.

segunda-feira, 4 de janeiro de 2010

O que eu faço nas férias? Estudar…

Minhas férias estão acabando, e estou aproveitando os últimos dias para estudar, pois é nerd.

Bom aqui vai alguns vídeos que eu achei interessante no site da InfoQ do Greg Young que eu recomendo.

http://www.infoq.com/presentations/greg-young-unshackle-qcon08
http://www.infoq.com/presentations/TDD-in-a-DbC-World-Greg-Young.

Brincando com delegates – Parte I

Bom primeiramente feliz ano novo.

Nesses últimos meses foi difícil manter o blog, infelizmente foi muito difícil manter o foco no trabalho, estudos e blog ao mesmo tempo.
Mas como em todo ano que se inicia costumamos traçar metas, uma das minhas é publicar conteúdo com mais regularidade.

Um recurso bem legal das novas versões do .Net é o delegate, principalmente a partir do 3.0. Abaixo vou colocar um exemplo de como utilizar o delegate do tipo Action.


//Versão 1
private void mtcDate_DateChanged(object sender, DateRangeEventArgs e)
{
DateTime date = this.mtcDate.SelectionEnd;

this.dtpInitital.Value = new DateTime(date.Year
, date.Month
, date.Day
, this.dtpInitital.Value.Hour
, this.dtpInitital.Value.Minute
, this.dtpInitital.Value.Second);

this.dtpFinal.Value = new DateTime(date.Year
, date.Month
, date.Day
, this.dtpFinal.Value.Hour
, this.dtpFinal.Value.Minute
, this.dtpFinal.Value.Second);

this.lblSelectedDate.Text = date.ToShortDateString();
}

O controle dtpInitital e dtpFinal são do mesmo tipo, perceba que eu tive que repetir o mesmo código para cada controle. Pra não ter que fazer isso, podemos criar um método para executar as alterações nessárias no valor dos controles da seguinte forma:
private void mtcDate_DateChanged(object sender, DateRangeEventArgs e)
{
DateTime date = this.mtcDate.SelectionEnd;

ChangedDate(this.dtpInitital, date);
ChangedDate(this.dtpFinal, date);

this.lblSelectedDate.Text = date.ToShortDateString();
}

private void ChangeDate(DateTimePicker control, DateTime date)
{
control.Value = new DateTime(date.Year
, date.Month
, date.Day
, control.Value.Hour
, control.Value.Minute
, control.Value.Second);
}

No exemplo acima criamos o método ChangeDate para realizar as alterações nos controles que passamos no parâmetro, mas tivemos que criar um método que será chamado sempre pelo mesmo método, agora veja a mesma solução com delegate.
private void mtcDate_DateChanged(object sender, DateRangeEventArgs e)
{
DateTime date = this.mtcDate.SelectionEnd;

Action<DateTimePicker> changedDate = null;

changedDate = delegate(DateTimePicker control)
{
control.Value = new DateTime(date.Year
, date.Month
, date.Day
, control.Value.Hour
, control.Value.Minute
, control.Value.Second);
};

changedDate(this.dtpInitital);
changedDate(this.dtpFinal);

this.lblSelectedDate.Text = date.ToShortDateString();
}

Perceba que agora colocamos o método dentro do escopo do evento, não temos a repetição de código que tivemos no primeiro controle e nem criamos um método no escopo da classe que será chamado sempre pelo memso lugar.

sexta-feira, 23 de outubro de 2009

Modelo anêmico realmente é ruim?

Eu sempre costumo dizer para o pessoal que se você não enxerga o problema não tem por que aplicar uma solução.

O mesmo vale para o modelo anêmico, se você não consegue enxergar os problemas dessa modelagem com certeza você não vê valor nenhum nas outras formas de modelar o domínio.

Com certeza você vai dizer que conhece aplicações desenvolvidas com modelo anêmico e que funcionam muito bem, e com certeza isso é verdade, da mesma forma que conheço aplicações procedurais que funcionam muito bem. Então o que nos motiva a não ter modelos anêmicos?

Quando você decide pelo modelo anêmico você tem que estar ciente que você esta abrindo mão de vários benefícios que o OO pode lhe proporcionar. Fowler diz o seguinte:

“The fundamental horror of this anti-pattern is that it's so contrary to the basic idea of object-oriented design; which is to combine data and process together. The anemic domain model is really just a procedural style design, exactly the kind of thing that object bigots like me (and Eric) have been fighting since our early days in Smalltalk. What's worse, many people think that anemic objects are real objects, and thus completely miss the point of what object-oriented design is all about.”

http://martinfowler.com/bliki/AnemicDomainModel.html

Ele reforça a idéia de que o modelo anêmico não é OO, podemos ver essa afirmação na prática trazendo o clássico exemplo do carro para o mundo do modelo anêmico. Quando você modela um carro geralmente você faz algo assim:


public class Carro
{
private int _posicaoAtual;

public void Andar()
{
this._posicaoAtual += 10;
}
}

Agora no mundo anêmico o carro ficaria assim:

public class Carro
{
private int _posicaoAtual;

public int PosicaoAtual
{
get{ return this._posicaoAtual;}
set{ this._posicaoAtual = value;}
}
}

public class BLCarro
{
publicvoid Andar(Carro carro)
{
carro.PosicaoAtual += 10;
}
}


Perceba que agora criamos um “andador de carro” isso faz algum sentido? Creio que não.
Mas se o modelo anêmico é um anti-padrão, por que temos o DTO (Data Transfer Object Pattern)?

Modelo anêmico não tem nada haver com DTO, eu falo que DTO é um mal necessário, ele foi criado para realizar transporte de dados, não para transporte entre as camadas lógicas como se tem feito com os modelos anêmicos.

Um fator que motiva a utilização do modelo anêmico é o acesso a dados, mas acredite esse problema tem solução, você pode utilizar o Repository ou Active Record.

Active Record with Castle
http://www.castleproject.org/activerecord/index.html

Using Repository and Unit of Work patterns with Entity Framework 4.0

http://blogs.msdn.com/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx

NHibernate and the Unit of Work Pattern
http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/10/nhibernate-and-the-unit-of-work-pattern.aspx

Outro fator que confunde um pouco a cabeça do pessoal é que se tem um caminho fixo para se chegar ao banco de dados com o modelo anêmico sendo UI > BL > DL utilizando o modelo o anêmico para trafegar os dados entre a camada, com uma entidade como fica esse caminho?

Pra não fugir do costume vou soltar a frase “cada caso é um caso” você pode por exemplo utilizar um façade para ter acesso ao domínio. Ex.: UI > Façade > Domínio.

sexta-feira, 9 de outubro de 2009

Personalizando o toString em enums

Os enumerados são, sem dúvida, grandes ferramentas para auxiliar e padronizar o desenvolvimento de aplicativos. Eu, por exemplo, o considero excelente para sumir com os famosos números mágicos (magic numbers) dentro das entidades, ex:


//Antes
productionOrder.State = 3;
//Depois
productionOrder.State = ProductionOrderState.Canceled;

Porém, uma desvantagem do enum é quando você quer exibir o texto do valor contido no enum. Ex.:
ProductionOrderState productionOrderState = ProductionOrderState.Canceled;
Console.Writeline(productionOrderState);
//Print: Canceled


Como fazer para imprimir "Production Order is Canceled" no lugar de Canceled?
Abaixo vai uma dica bem simples de como fazer isso. Primeiro copie o código abaixo:
public struct Described<T> where T : struct
{

private T _value;

public Described(T value)
{
_value = value;
}

public override string ToString()
{
string text = _value.ToString();
object[] attr = typeof(T).GetField(text).GetCustomAttributes(typeof(DescriptionAttribute), false);

if (attr.Length == 1)
text = ((DescriptionAttribute)attr[0]).Description;

return text;
}

public static implicit operator Described<T>(T value)
{
return new Described<T>(value);
}

public static implicit operator T(Described<T> value)
{
return value._value;
}
}
Fonte: Post StackOverFlow (http://stackoverflow.com/questions/796607/how-do-i-override-tostring-in-c-enums)
Agora no seu enum implemente o atributo Description, do namespace System.ComponentModel em cada item do enum:
public enum ProductionOrderState
{
[Description("Production Order is Open")]
Open,
[Description("Production Order is Canceled")]
Canceled
}

Para obter a descrição do valor do enum faça o seguinte:
Described<ProductionOrderState> status = ProductionOrderState.Open;
Console.WriteLine(status);
//Print: Production Order is Open

Veja que a classe Described não influencia em nada o funcionamento do enum, veja o teste abaixo:

Described<ProductionOrderState> status = ProductionOrderState.Open;
Console.WriteLine(status);
ProductionOrderState other = status;
Console.WriteLine(other);

Mas ainda não é o suficiente certo? A descrição esta hard code como vamos fazer quando tiver que alterar a descrição? E para multi idioma como ficaria?

Para resolver esse problema crie um Resource no seu projeto e coloque nele as descrições que precisa para o seu enum.

resource

Para obter o valor do Resource nos items do enum podemos utilizar uma classe disponível no Enterprise Library (http://msdn.microsoft.com/en-us/library/cc467894.aspx), faça referência no seu projeto a dll Microsoft.Practices.EnterpriseLibrary.Configuration.Design, dentro dela você contará com o atributo SRDescription.

Troque no seu enum o attribute Description pelo SRDescription informando o nome do Resource que você criou e o nome da chave do resource que você criou, ex:
public enum ProductionOrderState
{
[SRDescription("Sts_Open", typeof(Resources))]
Open,
[SRDescription("Sts_Canceled", typeof(Resources))]
Canceled
}

Prontinho, agora temos disponível um meio prático de obter e personalizar as descrições dos nossos enums.

DDD: Como validar entidades de negócio

Eu respondi uma pergunta sobre como é realizada as validações de entidade de negócio no DDD.
No mesmo post eu coloquei um exemplo obtido no livro do Tim McCarthy.

No exemplo abaixo é gerado uma exceção caso a entidade não esteja válida.


public sealed class Address
{
private string street;
private string city;
private string state;
private string postalCode;

public Address(string street, string city, string state, string postalCode)
: this(street, city, state, postalCode, true)
{
}

private Address(string street, string city, string state, string postalCode,
bool validate)
{
this.street = street;
this.city = city;
this.state = state;
this.postalCode = postalCode;
if (validate)
{
this.Validate();
}
}

private void Validate()
{
if (string.IsNullOrEmpty(this.street)
string.IsNullOrEmpty(this.city)
string.IsNullOrEmpty(this.state)
string.IsNullOrEmpty(this.postalCode))
{
throw new InvalidOperationException("Invalid address.");
}
}
}

Já no exemplo abaixo é verificado se a lista de regras quebradas esta preenchida, caso ela esteja vazia a entidade esta ok.
public class Company : EntityBase
{
private string name;
private string abbreviation;
private Address headquartersAddress;
private List<Address> addresses;
private string phoneNumber;
private string faxNumber;
private string url;
private string remarks;

public Company()
: this(null)
{
}

public Company(object key)
: base(key)
{
this.name = string.Empty;
this.abbreviation = string.Empty;
this.headquartersAddress = null;
this.addresses = new List<Address>();
this.phoneNumber = string.Empty;
this.faxNumber = string.Empty;
this.url = string.Empty;
this.remarks = string.Empty;
}

public string Name
{
get { return this.name; }
set { this.name = value; }
}

protected override void Validate()
{
// The Company must have a name
if (!string.IsNullOrEmpty(this.name))
{
this.BrokenRules.Add(new BrokenRule("", ""));
}
}
public ReadOnlyCollection<BrokenRule> GetBrokenRules()
{
this.Validate();
return this.brokenRules.AsReadOnly
}
}

Mas os exemplos acima demonstram uma forma mais "genérica" de como realizar essa validação. Por que genérica? Por que podemos ter vários tipos de validações para uma mesma entidade dentro de processos específicos.

Imagine por exemplo que para cadastrar um cliente você não precise do CPF, mas para finalizar um processo de compra essa informação passe a ser necessário, se você chamar o método "Validate" da classe cliente com o CPF em branco ele vai dizer que esta válido, mas para o processo de compra isso não é verdade.

As validações colocadas na própria entidade de negócio, geralmente são utilizadas nos processos de CRUD para garantir que todos os campos obrigatórios estejam preenchidos e de forma adequada. Mas cada processo de negócio necessita de informações específicas de cada entidade, por tanto, ele deve se preocupar em garantir essas informações.

Na prática o que eu quero dizer com isso? Que se o processo precisa do campo CPF do cliente, o processo (ou um serviço referente ao processo) é responsável em verificar se o CPF esta preenchido e não o cliente.

Conclusão, nossos métodos referentes a processos como o de compra, por exemplo, devem fazer mais do que simplesmente persistência de banco de dados (Insert e Update) mas também
garantir com que as entidades estejam com estado adequado.

quinta-feira, 10 de setembro de 2009

DDD: Enviar e-mail, onde vai esse negócio?

Já me deparei com essa pergunta em vários lugares e por isso mereceu um post no meu blog.

A resposta a essa pergunta é: Por que você precisa enviar e-mail?
Eu sei que é muito feio responder uma pergunta com outra pergunta mas nesse caso isso se faz necessário por que ela tem relação direta na solução do problema.

Geralmente eu sugiru como solução a criação de um serviço, mas eu percebo que as pessoas ainda não sabem direito como seria esse serviço e isso acontece por que a primeira coisa que vem a mente são os serviços de domínio;

No capítulo sobre “Services” do livro Domain-Driven Design: Tackling Complexity in the Heart of Software do Evans ele define os serviços da seguinte forma:

“This pattern is focused on those SERVICES that have an important meaning in the domain in their own right, but of course SERVICES are not used only in the domain layer. It takes care to distinguish SERVICES that belong to the domain layer from those of other layers, and to factor responsibilities to keep that distinction sharp.”

Ele deixa claro que podemos ter serviços em outras camadas fora a camada do domínio, mas ele ressalta a importância de se distinguir exatamente a atividade necessária para decidir o melhor local para o serviço.

Por exemplo, se para o seu envio de e-mail tiver envolvendo regras de negócio você provavelmente terá um serviço de negócio interagindo com um serviço de infraestrutura.

No livro Evans cita como exemplo o processo de transferêcia bancária. Após a camada de aplicação solicitar para a camada de domínio a transferência e obter confirmação que o processo foi realizado com sucesso, ela invoca um serviço da camada de infraestrutura para notificar os usuários envolvidos.

Resumindo, enviar e-mail é uma atividade de infraestrutura mas o motivo, ou negócio, influência diretamente na solução adotada.

quarta-feira, 9 de setembro de 2009

Boas práticas também serve para camada de interface sabia?

Quando falamos em padrões e boas práticas é muito comum pensarmos nas camadas de persistência, negócio, infraestrutura etc. Mas será que aplicamos esses mesmos princípios na camada de interface?
Alguns exemplos simples de como deixamos essas práticas de lado quando estamos trabalhando na camada de interface:


1) Preciso popular um ComboBox com uma lista de cidades. O procedimento mais comum nesse caso é o de "arrastarmos" o controle na tela, chamamos o método apropriado para trazer as cidades e preenchemos o controle com as cidades. Só que se tivermos 10 telas que precisamos exibir um ComboBox com cidades nós iremos repetir essa operação 10 vezes. Não teremos duplicidade de código? E se a forma de popular o ComboBox com as cidade por qualquer motivo tiver que ser alterada? Quanto tempo vamos ter que desprender para fazer essa alteração?

2) Muitas vezes precisamos gerar uma quantidade de código muito grande para tratar um determinado controle (TextBox, ComboBox, Button, etc...) e todo esse código fica misturado com o código de processo da tela (Cadastrar Cliente, Cadastrar Usuário, etc...). Se isolássimos o controle como um novo controle, será que não seria mais fácil a manutenção?

Com os recursos de interface rica, estamos produzindo cada vez mais código nas interfaces para proporcionar uma melhor experiência do usuário com o nosso sistema, e com isso também temos uma maior dificuldade em gerenciar esse código todo, por tanto, é cada vez maior a necessidade de se aplicar todos esses princípios e boas práticas na camada de interface.

Você já parou para analisar quanto tempo você desprende só para construir uma interface? Você já parou para analisar o quanto das alterações solicitadas pelo usuário estão diretamente ligadas a recursos de interface?

Utilizar MVC e criar controles personalizados são excelentes ferramentas para nos ajudar a gerenciar essa complexa estrutura que é a camada de interface, pense nisso quando estiver construindo suas interfaces.

quarta-feira, 17 de junho de 2009

MVC ou MVP?

Eu conheço uma galera interessada em padrões de projeto mas como acontece com todo mundo (inclusive comigo) algumas dúvidas e confuções acabam surgindo.

Foi me passado o seguinte trecho do livro Patterns of Enterprise Application Architecture do Fowler. (Se você não leu, deveria!)

“The view is only about display of information; any changes to the information are handled by the third member of the MVC trinity: the controller. The controller takes user input, manipulates the model, and causes the view to update appropriately”

Combinado com a definição dada no livro o seguinte exemplo de MVC foi passado:

http://www.codeproject.com/KB/tips/ModelViewController.aspx?fid=1194034&select=2878520#xx2878520xx

Bom, qual o problema?
O problema é que o exemplo passado no link não é MVC, pelo menos não na versão purista, mas sim MVP.

Mas como eu sei a diferença?

Analise comigo o trecho do código no exemplo da classe CalcController:

public void OnClick( int number )
{
    view.Total = model.SetInput(number).ToString();
}

No exemplo, a controller além de atualizar a Model ainda informa a View da alteração que a Model sofreu.

Apesar do trecho citado do livro do Fowler não ser incisivo em relação a interação entre a Model e a View, no MVC a Model notifica a View através de eventos quando seu estado é alterado.

O exemplo na verdade utiliza uma versão adaptada do MVC conhecida como MVP (Model View Presenter), cuja principal diferença é a controller alterando a Model e notificando a View das alterações feitas.

Veja o exemplo apresentado no site da SUN sobre MVC:
http://java.sun.com/developer/technicalArticles/javase/mvc/

Mas existe algum problema com isso?
Tecnicamente não, os dois funcionam muito bem, o problema esta na fato de estar usando um padrão achando que esta usando outro.

Eu particularmente prefiro utilizar o MVP, principalmente quando se pensa em DDD eu procuro deixar somente código referente a regras de negócio no domínio.

Fica esse alerta pra quem esta começando a utilizar esses padrões, principalmente por que outros estão surgindo como MVVM por exemplo, já pensou se a gente não saber a diferença entre eles?

sexta-feira, 5 de junho de 2009

Definições – Assunto importante

 

Olá pessoal,
Já faz algum tempo que fico sem postar no meu blog, minha volta para o Coral Kemuel tem tomado bastante tempo :)

Se você estuda ou estudou em qualquer lugar com certeza você já usufruiu da maravilha que é pesquisar assuntos no Google.

Um professor amigo meu chamado Renato (vulgo “Presuntinho”) me dizia que a internet é uma grande fonte de informação mas não de conhecimento, pode ter certeza, isso é verdade.
Quando você resolve aproveitar conteúdo de internet para seus trabalhos, acadêmicos ou não, você deve tomar muito cuidado.

Uma situação muito comum para consultar o “pai” Google é para se pegar definições, pois bem, eu me deparei com algumas que particularmente considero bizarras. Não vou colocar QUEM escreveu, isso não é o importante, o importante é o QUE.

“O flex é um jquery com recursos de transferencia assycornima de dados, suporte a chat sem a necessidade de um código fonte pesado, inumeros controles não disponiveis em ajax, de código aberto e compativel com asp.net (e java, e php, e ruby).”

Pois é, no texto acima o cara tentou dar uma definição do adobe flex. Abaixo segue a definição dada pela própria adobe:

“O Flex é uma estrutura de código aberto altamente produtiva e gratuita para a criação e manutenção de aplicativos Web expressivos implantados de maneira consistente nos principais navegadores, desktops e sistemas operacionais.”
Fonte: http://www.adobe.com/br/products/flex/?promoid=BOZRZ

Agora vamos ver uma definição que foi dada para OOP:

“O OOP é uma técnica de programação de forma estruturada com a finalidade de reaproveitar o código existente e implementar novas classes quando necessário.”

Usar o termo “programação estruturada” na definição de programação orientada a objetos na minha opinião é um equívoco, veja o que eu peguei do wikipéia:

“(A programação estruturada) Foi a forma dominante na criação de software entre a programação linear e a programação orientada por objetos.” Fonte: http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_estruturada

Agora imagina o “campeão” apresentando um trabalho na faculdade na frente “do professor” dando definição de OOP e no meio na frase ele solta “programação estruturada”. O que será que ele vai dizer?

Minha recomendação para evitar esses problemas? Leia, leia muito. Leia livros cite referências, autores …

Comunidade .Net precisamos evoluir nesse sentido leiam as discussões no GUJ sobre DDD e veja como eles se preocupam com definições.