Blog updates

September 30, 2009

Well, after some time wondering around I finaly decided to update the blog. I had a hard time in the process of changing my job and getting used to its rules. Also I had some personal problems at the same time, so I was really without any idea on what to write about.

Now the tide is changing back to normal so I’m planning to start posting useful stuff again. I’m really appreciating the project that I’m working on, it has a kindly nice architecture and the code is fairly uncoupled. It gives perfect conditions to create well coded unit tests. At first unit tests was beating me. I was having some problems on what to test, and how exactly code it. Had to take a time focusing on studying this. My complains about those tests was my difficulty to cover most cases. I was writing code but didn’t know what to test. So I used the TDD approach, so tests turned out something more understandable again.

After a little bit more expertise on unit tests, I’ll post something nice regarding that. I read a really useful post from Karl Seguin, where he explains and exposes some of his thoughts on unit tests. It worths reading.


AutoMapping with Per Entity Convention

April 1, 2009

Fluent NHibernate have a nice AutoMapping feature, where you can set some conventions to represent  how your entities are mapped to the database.  It allows you to make projects with NHibernate easily without the hard work with mapping files.

Today I was trying to make a little tweak on only one of my entities which behaves different from the others. Almost every entities in my domain have its Id property generated by Identity. The one I wanted to tweak has its Id property assigned instead of generated. So I did some dig around looking for a way to do this. It was pretty hard and time consuming  to find a solution, but I finnaly found something useful. That’s what I’ll show now:

Suppose we have a class Visitor and Employee:


public class Visitor
{
    public string Id { get; set; }
    public string Name { get; set; } 
    public string Email { get; set; }  
} 

public class Employee
{

    public string Id { get; set; }
    public string Name { get; set; } 
    public Department Department { get; set; }  
} 
 

Our employee Id is generated by identity while Visitor is assigned.

Here’s the automapping configuration with the conventions:


public AutoPersistenceModel Generate()
{
    AutoPersistenceModel mappings = AutoPersistenceModel
        .MapEntitiesFromAssemblyOf<Visitor>()
        .Where(GetAutoMappingFilter)
        .ConventionDiscovery.Setup(GetConventions())
        .WithSetup(GetSetup())
        .UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();

        return mappings;
}

private Action<IConventionFinder> GetConventions()
{
    return c =>
            {
                c.Add<PrimaryKeyConvention>();
            };
}

public class PrimaryKeyConvention : IIdConvention
{
    public bool Accept(IIdentityPart id)
    {
        return true;
    }

    public void Apply(IIdentityPart id)
    {
        id.ColumnName("Id")
            .WithUnsavedValue(0)
            .GeneratedBy.Identity(); //Here we are saying to generate our entities Id by identity.
    }
} 

This way both Visitor and Entity will have its id generated by identity based on our primary key convention. To make only the Visitor entity assigned instead of generated we can use the .ForTypesThatDeriveFrom<T>(Action<AutoMap<T>>) method:

 


public AutoPersistenceModel Generate()
{
    AutoPersistenceModel mappings = AutoPersistenceModel
        .MapEntitiesFromAssemblyOf<Visitor>()
        .Where(GetAutoMappingFilter)
        .ConventionDiscovery.Setup(GetConventions())
        .WithSetup(GetSetup())
        .UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>()
        .ForTypesThatDeriveFrom<Visitor>(autoMap => autoMap.Id(v => v.Id).GeneratedBy.Assigned());  //This will make visitor have its Id assigned.

        return mappings;
}

By using .ForTypesThatDeriveFrom we can tweak the behavior of any entity to be different from conventions.
Well, maybe this will help somebody. If you know a better way of doing this, let me know.

Introducing SharpArchitecture Service Layer

February 17, 2009

Well, in this post I’ll present my approach on creating a Service Layer to be used within your project along with SharpArchitecture Library. As discussed in this post, I don’t think its a good practice to let the controller talk directly with the repository. The controllers are specific to the MVC pattern and the MVC library, which means that if we put validation rules within the controllers, it will be pretty hard to migrate our project to be used on winforms for example.

A service layer would control the business rules and validation logic, while being responsible for communicating with the repository.

I’ve changed the Northwind Project’s source code  that comes with the SharpArch a little bit to show how I’ve implemented my own Service Layer.

The ServiceBase class:


using System.Collections.Generic;
using Northwind.Core.Validation;
using SharpArch.Core.DomainModel;
using SharpArch.Core.PersistenceSupport;
using SharpArch.Core.CommonValidator;
using SharpArch.Data.NHibernate;

namespace Northwind.Services
{
    public abstract class ServiceBase&amp;lt;RT, T, IdT&amp;gt; : IRepositoryWithTypedId&amp;lt;T, IdT&amp;gt;
        where RT : IRepositoryWithTypedId&amp;lt;T, IdT&amp;gt;
        where T : IEntityWithTypedId&amp;lt;IdT&amp;gt;, IValidatable
    {
        public RT repository;

        #region IRepositoryWithTypedId&amp;lt;T,IdT&amp;gt; Members

        public virtual IDbContext DbContext
        {
            get { return repository.DbContext; }
        }

        public virtual void Delete(T entity)
        {
            OnActionExecuting();

            repository.Delete(entity);

            OnActionExecuted();
        }

        public T Get(IdT id)
        {
            return repository.Get(id);
        }

        public List&amp;lt;T&amp;gt; GetAll()
        {
            return repository.GetAll();
        }

        public List&amp;lt;T&amp;gt; FindAll(IDictionary&amp;lt;string, object&amp;gt; propertyValuePairs)
        {
            return repository.FindAll(propertyValuePairs);
        }

        public T FindOne(IDictionary&amp;lt;string, object&amp;gt; propertyValuePairs)
        {
            return repository.FindOne(propertyValuePairs);
        }

        public virtual T SaveOrUpdate(T entity)
        {
            OnActionExecuting();

            try
            {
                Validate(entity);
                entity = repository.SaveOrUpdate(entity);

                OnActionExecuted();
            }
            catch
            {
                DbContext.RollbackTransaction();
                throw;
            }

            return entity;
        }

        public virtual void Validate(T entity)
        {
            if (!entity.IsValid())
                throw new InvalidModelStateException(entity.ValidationResults());
        }

        protected virtual void OnActionExecuting()
        {
           NHibernateSession.Current.BeginTransaction();
        }

        protected virtual void OnActionExecuted()
        {
            if (NHibernateSession.Current.Transaction.IsActive)
                NHibernateSession.Current.Transaction.Commit();
        }

        #endregion
    }
}

This class basically implements IRepositoryWithTypedId<T, IdT>, and it will be handy when your service is responsible for communicating with the repository, because it will have all
the repository methods.

&amp;lt;pre&amp;gt;public virtual void Validate(T entity)
{
    if (!entity.IsValid())
        throw new InvalidModelStateException(entity.ValidationResults());
}&amp;lt;/pre&amp;gt;

This is my way to validate. I do prefer to throw an exception when something is invalid. So I’ve implemented an InvalidModelStateException, which will transport validation results.

namespace Northwind.Core.Validation
{
    public class InvalidModelStateException : Exception
    {
        public ICollection&amp;lt;IValidationResult&amp;gt; ValidationMessages { get; protected set; }

        public InvalidModelStateException(ICollection&amp;lt;IValidationResult&amp;gt; validationMessages)
        {
            ValidationMessages = validationMessages;
        }
    }
}

I’ve also created my own ValidationResult as needed:

namespace Northwind.Core.Validation
{
    public class ValidationResult : IValidationResult
    {
        public ValidationResult(System.Type classContext, string message, string propertyName)
        {
            Check.Require(message != null, "Validation result must have a message");
            ClassContext = classContext;
            Message = message;
            PropertyName = propertyName;
        }

        #region IValidationResult Members

        public System.Type ClassContext
        {
            get;
            protected set;
        }

        public string Message
        {
            get;
            protected set;
        }

        public string PropertyName
        {
            get;
            protected set;
        }

        #endregion
    }
}

That’s because I wanted to let the class context and the property null sometimes.
In the case when something is invalid but when it’s some business rule, not related
with just one property.

I don’t think the OnActionExecuting/Executed are a good approach to access the NHibernateSession…
There should be a better way, but I couldn’t notice. Tell me if you have any idea.
I though about implementing a new TransactionAttribute to decorate the Service methods when needed,
but I don’t know if it would be good.

Northwind.Services.ServiceInterface.IEmployeeService

namespace Northwind.Services.ServiceInterface
{
    public interface IEmployeeService : IRepository&amp;lt;Employee&amp;gt;
    {
        void Delete(int id);
        Employee Edit(int id, Employee employee);
    }
}

Northwind.Services.Organization.EmployeeService:

namespace Northwind.Services.Organization
{
    public class EmployeeService : ServiceBase&amp;lt;IRepository&amp;lt;Employee&amp;gt;, Employee, int&amp;gt;, IEmployeeService
    {
        public EmployeeService(IRepository&amp;lt;Employee&amp;gt; repository)
        {
            Check.Require(repository != null, "Employee repository cannot be null");

            this.repository = repository;
        }

        public override void Delete(Employee entity)
        {
            repository.Delete(entity);

            try
            {
                base.Delete(entity);
            }
            catch(Exception e)
            {
                DbContext.RollbackTransaction();
                throw new Exception("The employee couldn't be deleted; likely due to a foreign key " +
                        "reference. You could cascade the deletion or you could inform " +
                        "the user better on where the foreign dependencies are and what needs to be " +
                        "done before the employee can be deleted.", e);
            }
        }

        public void Delete(int id)
        {
            Employee employeeToDelete = Get(id);

            if (employeeToDelete == null)
                throw new Exception("An employee with the ID of " + id + " could not be found for deletion.");

            Delete(employeeToDelete);
        }

        public Employee Edit(int id, Employee employee)
        {
            Employee employeeToUpdate = repository.Get(id);

            //This will call IsValid() and throw an InvalidModelStateException if it fails.
            Validate(employee);

            OnActionExecuting();

            TransferFormValuesTo(employeeToUpdate, employee);

            OnActionExecuted();

            return employeeToUpdate;
        }

        private static void TransferFormValuesTo(Employee employeeToUpdate, Employee employeeFromForm)
        {
            employeeToUpdate.FirstName = employeeFromForm.FirstName;
            employeeToUpdate.LastName = employeeFromForm.LastName;
            employeeToUpdate.PhoneExtension = employeeFromForm.PhoneExtension;
        }
    }
}

This is the class responsible to communicate with the EmployeeRepository. We took out the sweet candy from the controller and gave it to our beauty Service. So the controller will have an instance of IEmployeeService, don’t forget to add the EmployeeService in the Castle Windsor Container:

//...
           container.AddComponent("employeeService",
                typeof (IEmployeeService), typeof (EmployeeService));
//...

And finnaly how our new EmployeeController looks like:

namespace Northwind.Web.Controllers.Organization
{
    [HandleError]
    public class EmployeesController : Controller
    {
        public EmployeesController(IEmployeeService employeesService)
        {
            Check.Require(employeesService != null, "employeeRepository may not be null");

            this.employeesService = employeesService;
        }

        /// &amp;lt;summary&amp;gt;
        /// The transaction on this action is optional, but recommended for performance reasons
        /// &amp;lt;/summary&amp;gt;
        [Transaction]
        public ActionResult Index() {
            List&amp;lt;Employee&amp;gt; employees = employeesService.GetAll();
            return View(employees);
        }

        /// &amp;lt;summary&amp;gt;
        /// The transaction on this action is optional, but recommended for performance reasons
        /// &amp;lt;/summary&amp;gt;
        [Transaction]
        public ActionResult Show(int id) {
            Employee employee = employeesService.Get(id);
            return View(employee);
        }

        public ActionResult Create() {
            return View();
        }

        [ValidateAntiForgeryToken]      // Helps avoid CSRF attacks
        [Transaction]                   // Wraps a transaction around the action
        [AcceptVerbs(HttpVerbs.Post)]   // Limits the method to only accept post requests
        public ActionResult Create(Employee employee) {
            try
            {
                employeesService.SaveOrUpdate(employee);
                TempData["message"] = employee.FullName + " was successfully created.";

                return RedirectToAction("Index");
            }
            catch(InvalidModelStateException e)
            {
                MvcValidationAdapter.TransferValidationMessagesTo(ViewData.ModelState, e.ValidationMessages);

                // If it wasn't valid, go back to the input page
                return View();
            }
        }

        /// &amp;lt;summary&amp;gt;
        /// The transaction on this action is optional, but recommended for performance reasons
        /// &amp;lt;/summary&amp;gt;
        [Transaction]
        public ActionResult Edit(int id) {
            Employee employee = employeesService.Get(id);
            return View(employee);
        }

        /// &amp;lt;summary&amp;gt;
        /// Accepts the form submission to update an existing item. This uses
        /// &amp;lt;see cref="DefaultModelBinder" /&amp;gt; since we're going to try to update the persisted
        /// entity and ask it for its validation state rather than relying on the employee
        /// from the form to report validation issues.  This is particularly important when verifying
        /// if the updated persistent object is unique when compared to other entities in the DB.
        /// &amp;lt;/summary&amp;gt;
        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, [ModelBinder(typeof(DefaultModelBinder))] Employee employee)
        {
            try
            {
                var employeeToUpdate = employeesService.Edit(id, employee);
                TempData["message"] = employeeToUpdate.FullName + " was successfully updated.";

                return RedirectToAction("Index");
            }
            catch (InvalidModelStateException e)
            {
                MvcValidationAdapter.TransferValidationMessagesTo(ViewData.ModelState,
                                                                  e.ValidationMessages);
            }

            return View(employee);
        }

        /// &amp;lt;summary&amp;gt;
        /// As described at http://stephenwalther.com/blog/archive/2009/01/21/asp.net-mvc-tip-46-ndash-donrsquot-use-delete-links-because.aspx
        /// there are a lot of arguments for doing a delete via a GET request.  This addresses that, accordingly.
        /// &amp;lt;/summary&amp;gt;
        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int id)
        {
            string resultMessage = null;

            try
            {
                employeesService.Delete(id);
                resultMessage = "The employee was successfully deleted.";
            }
            catch (Exception e)
            {
                resultMessage = e.Message;
            }

            TempData["Message"] = resultMessage;
            return RedirectToAction("Index");
        }

        private readonly IEmployeeService employeesService;
    }
}

Notice that the service is responsible to take care of the values sent by the form. The controller will only call the service’s methods and present validation and result messages.

Basically that’s it.

I’m using this approach in our project here, and it’s working fine. Sorry for taking to long to post this. But I’m working a lot, so I was a bit out of time for it.

Any advices or sugestions are very welcome.

I’m working on a project using the awesome SharpArchitecture library, and I’m amazed. I’ve never used TDD (Test Driven Development) before, and I can admit it improves the code you write, making it clean and brief.

Congratulations Billy McCafferty and all the staff working on it for this amazing library.

Here is the link to download the source code, binary files and information about it as well.

Regards, Rodrigo Leote.


Interesse nas linguagens de programação

January 23, 2009
c#
 
1.00
vb
 
0.55
ruby
 
0.65
c++
 
0.90
java
 
4.40
     

Java ganhando disparado
Java ganhando disparado

Nosso adorável C# está em segundo lugar no overall.

 

Claro, estas estatísticas não significam muito, é algo mais experimental.

Já que muitas buscas por C# são feitas através da keyword “.NET”.

A razão de java estar à frente explica-se além do fato de ser uma linguagem sem custos, 

é a mais adotada pelas faculdades, levando os estudantes a buscarem informações.

c# 
 
1.60  
ruby 
 
1.00  
java 
 
6.95  

C# e Java caem bastante nos finais de semana enquanto ruby mantém-se constante

C# e Java caem bastante nos finais de semana enquanto ruby mantém-se constante

Legal que nos finais de semana a busca por C# é equivalente à Ruby.


O faro do programador

September 25, 2008

No início de meu aprendizado com programação, costumava achar tudo muito fácil. Aqueles algorítmos, pra mim, eram simplórios demais. Não entendia como as pessoas tinham tanta dificuldade. Obviamente, diferente de muitas dessas pessoas, eu exercitava, chegava em casa e resolvia os exercícios passados em aula, com muita dedicação.

Porém eu achava que funcionar era a conta. Felicidade era quando aquele código cheio de ifs, whiles e cases compilava. Nossa, que alegria! “Funcionou”! Eu não sou o único que iniciou com programação achando que o simples fato de funcionar é o suficiente. Uma boa parte dos grandes programadores começaram pensando assim, enquanto outra parte gigantesca de maus programadores permaneceram acreditando em tal heresia.

Meu maior presente foi ter bons programadores sempre ao meu lado. Pessoas experientes e com o potencial de apontar os erros e mostrar soluções poderosas e elegantes. Apartir do momento que se tem contato com esse tipo de pessoas, você começa a se transformar, de um simples programador, em um artista. Seus velhos códigos “de guerra” perdem a máscara e você começa a perceber o quanto eram horrorosos. Fico feliz de conseguir olhar para o que fiz ontem e perceber que muita coisa pode ser melhorada. Isso é a prova de que adquiri conhecimento, evolui como artista da programação.

Ainda não posso me considerar um excelente programador. Estou procurando melhorar a cada dia. E acreditem, ainda acho muita besteira nos meus códigos. E quando não sou eu quem acha, felizmente tenho essas pessoas que apontam o que pode ser melhorado. Acho que tenho a faca e o queijo na mão para ser o que sempre sonhei.

Fico feliz de ter adquirido a habilidade de olhar para um código e dizer “tem merda”. Hoje consigo fazer códigos muito mais entendíveis que no início de minha carreira. E tenho certeza de que o ponto onde estou, pode-se considerar ainda um início. E quando eu olhar o meu código de agora, no futuro, vou pensar no quanto eu escrevia códigos não tão elegantes.

Vejam só, um pequeno exemplo do que passa despercebido quando estamos aprendendo:


public bool IsCodigoElegante()
{
if(programmer.Name.Equals("Neo"))
return true;
else
return false;
}

Legal né? Tem algum problema nisso?

E que tal isso:


public bool IsCodigoElegante()
{
return programmer.Name.Equals("Neo");
}

É… acho que ficou bem melhor.

Pra quem acha que o primeiro exemplo é só pra quem não tem experiência, eu encontrei um código terrivelmente parecido em um projeto sério Open Source que estou trabalhando.
Era algo do tipo:


...
return ((int)dataReader["ResponseId"] == 0) ? false : true;
...

Se você “sentir cheiro”, perceber que tem algo estranho no código, leia, releia, e veja se não há como melhorar.

ps.: Juro pra vocês que tentei identar os códigos acima… mas meu amadorismo com blogs me impediu.

Segue um link interessante para melhorar seu faro.


Apresentação

August 31, 2008

Olá pessoal, bem-vindos ao meu blog, um espaço que pretendo utilizar para falar um pouco de tudo na área da tecnologia, com um foco maior voltado à programação e desenvolvimento de softwares. Inicialmente pretendia falar somente sobre as tecnologias .NET e linguagem C#, mas decidi que farei desse blog uma área para comentar sobre qualquer linguagem e tecnologias que me der vontade.

Após pensar em nomes um tanto “clichê” contendo palavras ‘world’, ‘programming’, ‘development’, etc… nas mais variadas combinações, resolvi utilizar o meu nome como título do blog. Acredito que o destaque do nome será importante, assim serei lembrado quando for realmente muito famoso (apenas algumas pessoas reconhecem que sou o Neo).

Desde já, lhes peço desculpas pela péssima escrita, já que essa sempre foi minha grande dificuldade. Os caras da informática, geralmente, sofrem com isso. Prometo-lhes que investirei muito esforço para que este blog torne-se um espaço agradável para adquirir conhecimentos e prover uma boa leitura.

Já lhes adiantarei que não postarei com tanta frequência, a não ser que eu ache um assunto muito importante, devida à minha mania de gastar um bocado do tempo que me sobra com bobagens e ter uma preguiça ilimitada para escrever.

Obrigado a todos que me deram apoio, e espero que possa contar com a presença de vocês em cada artigo que escrever.


Follow

Get every new post delivered to your Inbox.