Repositories and factories - Creating a more complex entity

Published by on
Tags:

Following from my post about repositories and factories I am going to look at a more complex entity. This entity will represent a person who can have multiple address. The entities will look something like this:

    public class Person
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public IEnumerable<Address> Addresses { get; set; }
    }

    public class Address : IAddress
    {
        public Guid Id { get; set; }
        public Guid OwnerId { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string Town { get; set; }
        public string County { get; set; }
        public string PostCode { get; set; }
        public AddressType Type { get; set; }
    }

Assuming we are using a database for persistence I don't want to store the individuals details in the same table as the addresses. Our application may have other class that use the Address class and it makes sense to store these together and keep the database properly normalised. We start by making an interface from the Person class to pass to and from the repository that does not include Addresses.

    public interface IPerson
    {
        Guid Id { get; set; }
        int Age { get; set; }
        string FirstName { get; set; }
        string LastName { get; set; }
    }

We can now update the Person class to inherit this interface and pass in the repository that will be used to persist the Person class:

    public class Person : IPerson
    {
        IPersonRepository _repository;

        public Person(IPersonRepository repository)
        {
            _repository = repository;
        }

	.....

We can quickly create a repository and factory class that will retrieve Person objects for us, I won't show the code here but it is included in the source code at the end of the application. So now we can look at populating the list of addresses. To do this we do exactly the same as we did for the simple element, except we must ensure that there is method on the factory called GetAddresses(Guid ownerId) which returns all the addresses for a given Person ID. You may have noticed that we called the parameter ownerId instead of Person ID, this goes back to the fact that multiple classes may have addresses and uncouples the Address class from the Person class. We also need to update the Address class to accept the repository and create methods to persist the address class. The code for the address interface, factory and repository is exactly the same as our simple entity example so I won't go into to much detail.

Now we just need to start putting everything together. Start by updating the PersonFactory to accept the AddressFactory. This will allows use to call the GetAddresses(Guid ownerId) when we populate a Person object.

    public class PersonFactory : IPersonFactory
    {
        IPersonRepository _repository;
        AddressFactory _addressFactory; 

        public PersonFactory(IPersonRepository repository, AddressFactory addressFactory )
        {
            _repository = repository;
            _addressFactory = addressFactory;
        }

        ....

We can now modify the MapToDomain method to call

GetAddresses(Guid ownerId)
on the AddressFactory object to populate the address list.

        private Person MapToDomain(IPerson person)
        {
            return new Person(_repository)
            {
                Age = person.Age,
                FirstName = person.FirstName,
                Id = person.Id,
                LastName = person.LastName,
                Addresses = _addressFactory.GetAddresses(person.Id)
            };
        }

With that done we now have a way of creating a Person with Addresses with each piece of information coming from a different storage location. We can now make use of these classes as below:

            IAddressRepository addressRep = new MemoryAddressRepository();
            IPersonRepository personRep = new MemoryPersonRepository();
            
            AddressFactory addressFact = new AddressFactory(addressRep);
            PersonFactory personFact = new PersonFactory(personRep, addressFact);

            Person somebody = personFact.GetPerson(new Guid("{1BB25355-6ABD-48d3-9FE6-5528C6DAE8E7}"));
            somebody.FirstName = "John";
            //this assumes there is at least one address
            somebody.Addresses.First().Address1 = "32 My House";
            somebody.Addresses.First().Save();
            somebody.Save();

Download: Source Code (.RAR 37.5Kb)

Repositories and factories - Creating a simple entity.

Published by on
Tags:

This post continues on from my first post "Repositories and factories - Introduction". In this post we will look at how to create a simple entity using a repository and a factory.

To start we need to design the properties that our entity is going to have. We are going to use a simple class called Product, this is going to have just a few properties:

public class Product{
	 public Guid Id { get; internal set; }
	 public string Name { get; set; }
	 public string Description { get; set; }
	 public double Price { get; set; }
}

We now need a way to retrieve Product entities, this is where our factory class comes into use. First we need to create an interface for our factory detailing the methods we want:

public interface IProductFactory
{	 
	 Product GetProduct(Guid id);
	 System.Collections.Generic.IEnumerable<Product> GetProducts();
}

Now we need to implement the interface in my concrete class. The factory is not responsible for retrieving the data from the data source, this will be handed of to the repository class. The factory will be responsible for building the product entity based on the data returned by the repository. To make the communication between the repository and factory clearer we are going to create an interface for the Product class. The interface makes it clear the repository what properties need to be persisted and returned from storage, this makes it a lot easier when writing a concrete implementation of the repository.

public interface IProduct
{
        string Description { get; set; }
        Guid Id { get; }
        string Name { get; set; }
        double Price { get; set; }
}

With this we can now create the concrete factory class, the factory class calls methods on the IRepository interface which is detailed further down the post, however you can see that each method called on the IRepository interface returns objects of type IProduct. These are then mapped to domain entities using the MapToDomain method:

    public class ProductFactory : InterfaceTest.IProductFactory
    {
        IProductRepository _repository;
        public ProductFactory(IProductRepository repository)
        {
            _repository = repository;
        }
        public Product GetProduct(Guid id)
        {
            IProduct product = _repository.GetProduct(id);
            return MapToDomain(product);    
        }
        public IEnumerable<Product> GetProducts()
        {
            IEnumerable<IProduct> products = _repository.GetProducts();
            return MapToDomain(products);
        }
        IEnumerable<Product> MapToDomain(IEnumerable<IProduct> products)
        {
            return products.ToList().Select(x => MapToDomain(x));
        }
        Product MapToDomain(IProduct product)
        {
            if (product == null) return null;
            return new Product()
            {
                Description = product.Description,
                Id = product.Id,
                Name = product.Name,
                Price = product.Price
            };
        }
    }

So we have out factory class that builds our entities for use. Now we need to persist them back to the database. Ideally as we don't want to pass the entity back to the factory to save it, if we did we would have to pass a reference to the factory around our application and this would get messy. If we ensure that when the Product entity is created it requires a reference to the repository it came from then we can added a save method to the entity and persist the entity straight back to the repository, so we need to updated the constructor and add a save method:

    public class Product : InterfaceTest.IProduct
    {
	IProductRepository _repository;
        public Product(IProductRepository repository )
        {
            _repository = repository;
            Id = Guid.NewGuid();
        }    
        public void Save(){
            _repository.Save(this);
        }

    }

I then need to update the MapToDomain method in the factory to pass in the repository:

        Product MapToDomain(IProduct product)
        {
            if (product == null) return null;
            return new Product(_repository)
            {
                Description = product.Description,
                Id = product.Id,
                Name = product.Name,
                Price = product.Price
            };
        }

With all this done the IProductRepository should look something like this, I am not going to give any code for a concrete implementation of this interface because the code is pretty straight forward.

public interface IProductRepository{
     void Save(IProduct product);
     IProduct GetProduct(Guid id);
     IEnumerable<IProduct> GetProducts();
}

With all this done we can now use this in our application:

IProductRepository repository = new MemoryRepository();
IProductFactory factory = new ProductFactory(repository);

Product prod = factory.GetProduct(new Guid("{0441907B-45B6-471e-8F7D-A187B81991FC}"));
prod.Name = "box of bananas";
prod.Description = "50 bananas in a large box for a monkey";
prod.Price = 4.5;
prod.Save(); 

This may seem like a little extra working having the factories and repositories but it will allow for my flexibility later on. You can also make the whole task easier using dependency injection to save you having to write so much code.

This post deals with a single entity from a single repository. In the next post I will look at more complex entities that may require multiple repositories.

MVP pushing data to the view

Published by on
Tags:

The other day I was chatting to my friend and we were discussing the model view presenter (MVP) design pattern. We got onto the discussion of display collections of items in the view. It gave me a few thoughts about the different techniques that could be used. Each technique has some advantages and disadvantages and I hope to discuss each of these in turn.

We are going to have a presenter that performs a simple task. I want it to display a list of products to the user. I am going to keep the presenter as simple as possible; the constructor takes no arguments and the class consists of a single Init method that starts the whole process off. When working with MVP I prefer to have an Init method which I will call to kick the whole process off.

So my presenter has this simple template:

     8     public class ProductListPresenter

    9     {

   10         IProductListView _view;

   11         IProductService _service;

   12 

   13         public ProductListPresenter(IProductListView view, IProductService service)

   14         {

   15             _view = view;

   16             _service = service;

   17         }

   18 

   19         public void Init()

   20         {

   21             //TODO: pass the list of products to the view.

   22         }

   23     }

 I am going to use a simple Product entity to represent each product. The class is as follows:

    8     public class Product

    9     {

   10         public string Name { get; set; }

   11         public double Price { get; set; }

   12         public string Description { get; set; }

   13     }

The first method I am going to look at is passing an array of Products to the view and then letting the view deal with how it iterates over the collection of Products. The interface looks like: 

    8     public interface IProductListView

    9     {

   10         public Product[] Products { get; set; }

   11     } 

The presenters Init method can then pass the list of products can be passed directly into the view from the service (yes this is a very simplistic example). 

    19         public void Init()

   20         {

   21             _view.Products = _service.GetAllProducts();

   22         }

 I can now take advantage of some of .Net’s web controls. For example I want to use the System.Web.UI.WebControls.Repeater control to display product information. In the concrete view I can simple the Products property directly to the Repeater controls data source property:

   15         public Product[] Products

   16         {

   17             get

   18             {

   19                 return (Product[])_productRepeater.DataSource;

   20             }

   21             set

   22             {

   23                 _productRepeater.DataSource = value;

   24             }

   25         }  

As you can see this is a very quick way wiring views and presenters but has the disadvantage where the get accessor has to cast from object to the Product array. However we could remedy this by removing the get accessor from the IProductView interface. Another disadvantage is that this method does not give the presenter control over what information about the product is displayed by the view. For example if the product contains an additional field called “ConfidentialInformation” the developer implementing the view would have access to this field and could accidentally render this data to the user. This really isn’t a problem if the developers working on the views have good spec’s to work from but might cause a problem if you are expecting a third party to develop the views. Another lesser issue is exposing entities from the domain to the view which you may or may not wish to do depending on how strict you want your layer separation to be.

Another method is to have your view expose a method which the presenter calls to render the list to the user. For the  The IPresenterView would change to the following:

    8     public class IProductListView

    9     {

   10         void RenderProduct(string productName, double productCost);

   11     }

The presenters Init method then changes to:

   19         public void Init()

   20         {

   21             foreach (Product product in _service.GetAllProducts())

   22             {

   23                 _view.RenderProduct(product.Name, product.Price);

   24             }

   25         }

  

This method gives complete control over what the view renders to the user but has the disadvantage that it makes using the inbuilt .Net web controls more complex; for example we could not simple wire straight into the data source of the render control like we did before. However we can create a simple web control to do something similar:

 

   10     public class ProductView : HtmlControl,  IProductListView

   11     {

   12         public ProductView() : base("ul") { }

   13 

   14         #region IProductListView Members

   15 

   16         public void RenderProduct(string productName, double productCost)

   17         {

   18             HtmlGenericControl listItem = new HtmlGenericControl("li");

   19             listItem.InnerText = string.Format("{0} - {1:C}", productName, productCost);

   20             this.Controls.Add(listItem);   

   21 

   22         }

   23 

   24         #endregion

   25     }

  

   

As yet I am unsure which technique is better and I think both have the benefits. I find that for speed and simplicity the first technique works better and I can trust the developers of the views not to implement incorrect properties, however there is still something about it that makes me feel uncomfortable. Let me know your thoughts and what other techniques you might have for handling collections of items.

 

All blogs tagged with 'patterns'

Projects

Have you read?

Sitecore Get List of Referrers



Blogs by date