Monday, January 17, 2011

How To Not Hate Dependency Injection.

The Dependency Injection pattern is all the rage these days and more and more DI containers are becoming part of how we build .Net applications.  I still have a love / hate relationship with Dependency Injection.  I love the idea of being able to inject any external dependencies into my classes, thereby breaking those dependencies, but I hate the idea of creating an interface for every class that I need to inject, then maintaining that interface as well as any classes that implement it.  Let me show you what I mean.

Dependency Injection on an MVC  Controller Base Class With Interfaces

Typical scenario, I have an ASP.Net MVC2 application that needs to get data from a database. All of my data access code is contained in service classes like UserService, SystemService, CompanyService, etc.  I don’t want to manually declare and instantiate whatever service classes I need in each of my controller classes, so I created an abstract base class for my controllers called AtsControllerBase which has properties that will provide instances of my service classes using a lazy creation pattern.  Here’s an abbreviated version of the base class.

    public abstract class AtsControllerBase : Controller
    {
        //******************************************************
        // PROPERTIES
        //******************************************************

        // StateBox
        private HfStateBox _stateBox;
        public HfStateBox StateBox
        {
            get { return NewIfNull(_stateBox); }
            set { _stateBox = value; }
        }
        // AuthToken
        public AuthToken AuthToken { get { return StateBox.AuthToken; } }
        // ApplicantService
        private ApplicantService _applicantService;
        public ApplicantService ApplicantService
        {
            get { return NewIfNull(_applicantService); }
            set { _applicantService = value; } 
        }
        // CompanyService
        private CompanyService _companyService;
        public CompanyService CompanyService
        {
            get { return NewIfNull(_companyService); }
            set { _companyService = value; }
        }
        // FolderService
        private FolderService _folderService;
        public FolderService FolderService
        {
            get { return NewIfNull(_folderService); }
            set { _folderService = value; }
        }       
        // JobService
        private JobService _jobService;
        public JobService JobService
        {
            get { return NewIfNull(_jobService); }
            set { _jobService = value; }
        }
        // SecurityService
        private SecurityService _securityService;
        public SecurityService SecurityService
        {
            get { return NewIfNull(_securityService); }
            set { _securityService = value; }
        }
        // SystemService
        private SystemService _systemService;
        public SystemService SystemService
        {
            get { return NewIfNull(_systemService); }
            set { _systemService = value; }
        }
        // ServicePlanService
        private ServicePlanService _servicePlanService;
        public ServicePlanService ServicePlanService
        {
            get { return NewIfNull(_servicePlanService); }
            set { _servicePlanService = value; }
        }       
        // UserService
        private UserService _userService;
        public UserService UserService
        {
            get { return NewIfNull(_userService); }
            set { _userService = value; }
        }
        // WorkflowService
        private WorkflowService _workflowService;
        public WorkflowService WorkflowService
        {
            get { return NewIfNull(_workflowService); }
            set { _workflowService = value; }
        }


        //******************************************************
        // UTILITY METHODS
        //******************************************************
       
        // NewIfNull
        public T NewIfNull<T>(T obj) where T:new()
        {
            if (obj == null) { obj = new T(); }
            return obj;
        }
    }

This pattern works well for me because my concrete controllers never need to instantiate a service, they can just access any of the service properties in the base class.  I don’t have the overhead of newing up a bunch of service classes that the concrete controller won’t use because the services aren’t instantiated until the first time the service property is accessed.  That’s the lazy creation part.  Finally, each property has a public setter, so I can replace any of my services if I need to inject a mock or stub or something.

So this already looks a lot like Dependency Injection.  After all we have public setters for each of the services so we could switch them out if needed.  There’s one thing missing though.  We have no interfaces.  Our properties are all using the concrete type of the service class (like FolderService) instead of some public interface (like IFolderService).  So we could inject something, but it would have to be another instance of FolderService.  That get’s us nowhere. How can we inject something else like a MockFolderService??   Hmmmm,  I guess the right way to implement Dependency Injection is to create an IFolderService interface for my FolderService class.  At least that’s the pattern that I always see in books and code samples.  Let’s try that.  Ok, FolderService only has 10 public methods.  That’s not too bad so we’ll start with that one.  Here’s the service code.

    public partial class FolderService : ServiceBase
    {

        //**************************************************************************************
        // FOLDER METHODS
        //**************************************************************************************

        // GetFolderByFolderGuid
        public virtual Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            string sql = @"SELECT *
                           FROM [Folder]                            
                           WHERE [FolderGuid] = @FolderGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@FolderGuid", folderGuid));
            return dao.GetSingle<Folder>(command);
        }

        // GetListOfFolderWithCountsForCompany
        public virtual List<FolderWithCount> GetListOfFolderWithCountsForCompany(Guid companyGuid)
        {
            string sql = @"SELECT f.*, (SELECT COUNT([ApplicantGuid])
FROM [ApplicantInFolder] WHERE [FolderGuid] = f.[FolderGuid]) As ApplicantCount

                          FROM [Folder] f
                          WHERE f.[CompanyGuid] = @CompanyGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@CompanyGuid", companyGuid));
            return (dao.GetList<FolderWithCount>(command));
        }

         // GetListOfFoldersForCompany
        public virtual List<Folder> GetListOfFoldersForCompany(Guid companyGuid)
        {
            string sql = @"SELECT f.*
                                  FROM [Folder] f
                                  WHERE f.[CompanyGuid] = @CompanyGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@CompanyGuid", companyGuid));
            return (dao.GetList<Folder>(command));
        }


        // GetListOfFoldersForApplicant
        public virtual List<Folder> GetListOfFoldersForApplicant(Guid applicantGuid)
        {
            string sql = @"select f.*
                        from Folder f
                        join ApplicantInFolder aif on aif.FolderGuid = f.FolderGuid
                        where aif.ApplicantGuid = @ApplicantGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@ApplicantGuid", applicantGuid));
            return (dao.GetList<Folder>(command));
        }

        // GetCachedListOfFoldersForCompany
        public virtual List<FolderWithCount> GetCachedListOfFoldersForCompany(Guid companyGuid)
        {
            if (companyGuid.Equals(NullValues.NullGuid))
            {
                // return empty list if a null guid was passed
                return new List<FolderWithCount>();
            }
            string key = "__GetCachedListOfFoldersForCompany_" + companyGuid.ToString();
            CacheHelper helper = new CacheHelper();
            List<FolderWithCount> list = helper.TryGet<List<FolderWithCount>>(key);
            if (list == null)
            {
                RefreshCachedListOfFoldersForCompany(companyGuid);
                list = helper.TryGet<List<FolderWithCount>>(key);
            }
            return list;
        }


        // RefreshCachedListOfFoldersForCompany
        public virtual void RefreshCachedListOfFoldersForCompany(Guid companyGuid)
        {
            string key = "__GetCachedListOfFoldersForCompany_" + companyGuid.ToString();
            CacheHelper helper = new CacheHelper();
            List<FolderWithCount> list = helper.TryGet<List<FolderWithCount>>(key);
            list = GetListOfFolderWithCountsForCompany(companyGuid);
            helper.Add(key, list);
        }

        // Insert
        public virtual void Insert(Folder folder)
        {
            this.FolderPersister.Insert(folder);
        }


        // Save
        public virtual void Save(Folder folder)
        {
            this.FolderPersister.Save(folder);        
        }

        // Delete
        public virtual void Delete(Folder folder)
        {
            this.FolderPersister.Delete(folder.FolderGuid);
        }


        // AddApplicantToFolder
        public virtual void AddApplicantToFolder(Guid applicantGuid, Guid companyGuid, Folder folder)
        {
            this.FolderPersister.SafeInsertApplicantInFolder(applicantGuid, folder.FolderGuid);
            RefreshCachedListOfFoldersForCompany(companyGuid);
        }
    }

We’ve basically got 10 public data access methods. Now I need to create a public interface that defines all of the public methods, so I’m going to create a new IFolderService interface.  ReSharper even makes it easy for me with a handy Extract Interface tool.  So my interface looks like this.

    public interface IFolderService
    {
        Folder GetFolderByFolderGuid(Guid folderGuid);
        List<FolderWithCount> GetListOfFolderWithCountsForCompany(Guid companyGuid);
        List<Folder> GetListOfFoldersForCompany(Guid companyGuid);
        List<Folder> GetListOfFoldersForApplicant(Guid applicantGuid);
        List<FolderWithCount> GetCachedListOfFoldersForCompany(Guid companyGuid);
        void RefreshCachedListOfFoldersForCompany(Guid companyGuid);
        void Insert(Folder folder);
        void Save(Folder folder);
        void Delete(Folder folder);
        void AddApplicantToFolder(Guid applicantGuid, Guid companyGuid, Folder folder);
        SqlDao SharedSqlDao { get; set; }
        ApplicantPersister ApplicantPersister { get; set; }
        CareerSiteSettingsPersister CareerSiteSettingsPersister { get; set; }
        CompanyPersister CompanyPersister { get; set; }
        CompanySettingsPersister CompanySettingsPersister { get; set; }
        FolderPersister FolderPersister { get; set; }
        HistoryItemPersister HistoryItemPersister { get; set; }
        JobPersister JobPersister { get; set; }
        JobStubPersister JobStubPersister { get; set; }
        ResumePersister ResumePersister { get; set; }
        UserPersister UserPersister { get; set; }
        WorkflowPersister WorkflowPersister { get; set; }
        T NewIfNull<T>(T obj) where T : new();
        string GetSqlCsv(List<Guid> list);
        string GetSqlCsv(List<int> list);
    }

There, that wasn’t too bad. Now I just need to change my controller FolderService property to type IFolderService and I have Dependency Injection implemented for the FolderService.  I can create new classes that implement IFolderService and inject them into my controller using the public FolderService property like this.

            var controller = new FolderController();
            IFolderService mock = new MockFolderService();
            controller.FolderService = mock;

That’s great! Now I just need to do that for… wait… I’m going to have to do that for every service class in my application.  Then I’m going to have to maintain each of those interfaces every time I make a change to a service class.  That’s a lot of extra code and a lot of work that’s going to have to be repeated every time I make a change to my service classes.  Why am I doing this again?  This is starting to feel like the hate part of the love / hate relationship.

Dependency Injection on an MVC  Controller Base Class Without Interfaces

So I don’t really want to create an interface for every single dependency in my application and then have to maintain that interface as well as my concrete classes, but what other option do I have?  Everybody implements DI using interfaces right?  Interfaces are like a badge of honor that demonstrate you know how to architect an application the right way.  You haven’t been to architecture land until you have your interface badge. We love interfaces!

Well I don’t love any code that I have to spend extra time maintaining every time I make a change to my application.  All that stuff adds up after a while.  I call it the death of a thousand cuts.  One day you look up and all those little extra tasks like maintaining interfaces add up to a mountain of friction that makes it miserable to make changes to your code.  Now there are places for interfaces, but if possible I’m opting for an easier alternative.

So step one in the easier alternative, throw out the interface that I just created and change my FolderService property back to type FolderService (no more IFolderService).  Step two…. actually we don’t need a step two we’re done.  Lets take a closer look at one of the data access methods in our FolderService class.

       // GetFolderByFolderGuid
        public virtual Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            string sql = @"SELECT *
                           FROM [Folder]                            
                           WHERE [FolderGuid] = @FolderGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@FolderGuid", folderGuid));
            return dao.GetSingle<Folder>(command);
        }

Hmmm, that’s a virtual method.  That means that I can create a class that inherits from FolderService and just override the GetFolderByFolderGuid() method.  The FolderService class actually functions as my interface in this scenario.   So, if I’m writing a unit test where I want to stub out my FolderService I could create the following class.

    public class FolderServiceStub: FolderService
    {
        public override Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            return new Folder() {FolderGuid = folderGuid, FolderName = "Test Folder"};
        }
    }

FolderServiceStub inherits from FolderService so I can use that stub class anywhere that an object of type FolderService is expected.  The end result is that my testing code (or any other DI code) winds up looking almost exactly like my code did with full on interface based Dependency injection

    var controller = new FolderController();
    FolderService mock = new FolderServiceStub();
    controller.FolderService = mock;

Summary

So, make all of your public methods virtual and you can implement a Poor Man’s Dependency Injection that doesn’t require interfaces.  It’s not the right solution every situation, but I’ve found that it works most of the time for me. It also has the one quality that I prize most in code.  It’s so simple that I forget it’s even there.

Sunday, January 9, 2011

AAPL Part 7: Building a Generic Data Mapper

I got bored with this series a while back and I haven’t been writing on it, mostly because I’ve been using the architecture (Agile ADO.Net Persistence layer) to write a bunch of code.  The basic idea of AAPL was to create an application architecture that embraced code changes instead of resisting them. I took a look back at all of the application architectures I’ve worked with over the years and thought carefully about the parts of those architectures that caused me pain whenever made changes to the application.  I then threw all those things out and tried to put together an application architecture based on ADO.Net (not LINQ, EF, or nHibernate) that was optimized for making code changes easy and reliable.  I’ve been using the AAPL architecture for a while now and I’m happy to report that those decisions have really paid off. 

Why are we doing this again?

Just a a quick reminder.  The point of this architecture is to give us the ability to write persistence code that looks like this.

        // GetFolderByFolderGuid
        public virtual Folder GetFolderByFolderGuid(Guid folderGuid)
        {
            string sql = @"SELECT *
                           FROM [Folder]                            
                           WHERE [FolderGuid] = @FolderGuid";
            SqlDao dao = SharedSqlDao;
            SqlCommand command = dao.GetSqlCommand(sql);
            command.Parameters.Add(dao.CreateParameter("@FolderGuid", folderGuid));
            return dao.GetSingle<Folder>(command);
        }

Whenever we need a new data access method we want to just write the new query, package it up in an ADO.Net SqlCommand object, then pass both the SqlCommand and the desired model class type to a Data Access Object that will then handle all of the plumbing required to execute the command, get the data, package it up as whatever model type we passed in and then give it back. This is a very low friction way to handle data access.  It’s easy to maintain, new data methods take seconds to create, and we never have to touch the plumbing code.   The end result is that maintaining code and making changes to our model should feel like this…

instead of this…

What is a data mapper?

The key piece of plumbing code that makes this architecture so painless is the GenericDataMapper.  As described above, when we read data we execute an SQLCommand, get the resulting IDataReader, then map the data in that IDataReader to a model class (an entity class).  The DataMapper is the class that encapsulates the code that knows how to map the fields from an IDataReader to the properties in a model class.  For example, the UserMapper class contains the logic needed to take an IDataReader and use it’s data to populate a new object of type User.

What does the Generic Data Mapper do?

We could write a separate DataMapper class for each model type.  We could have a UserMapper, a CompanyMapper, a JobMapper, a WorkflowMapper, an ActionMapper, a StepMapper… you get the idea.  But doing it that way would require that 1) We write all those DataMapper  classes, and 2) We modify those DataMapper classes whenever we make a change to one of our models.  No thanks.

It would be better to write a single DataMapper class that could handle the mapping for any model class that we passed to it. Remember that early on we made the decision that the columns in our database would have the exact same names as the data properties in our model classes.  That constraint makes the mapping logic pretty simple.  We can create a GenericDataMapper that uses reflection to find all the properties on our model class and matches them to any fields with the same name in our IDataReader.  No hard coded mapping logic needed.  Just a little bit of reflection and a standard naming convention and we can create a single GenericDataMapper that will handle mapping for all of our model classes.

DataMapperFactory

We use a DataMapperFactory to get the right DataMapper for a model type.  The logic is simple.  We have a GetMapper() method that takes a type as it’s parameter. It checks to see if we have a custom mapper for the type, if not it returns the GenericMapper .  In the example below we have just one custom data mapper, ListItemDTOMapper.  Every other model class is handled by the GenericMapper.

    class DataMapperFactory
    {
        public IDataMapper GetMapper(Type dtoType)
        {
            switch(dtoType.Name)
            {
                case "ListItemDTO":
                    return new ListItemDTOMapper();
                default:
                    return new GenericMapper(dtoType);
            }      
        }
    }

IDataMapper

All of our DataMappers implement a custom IDataMapper interface.

    interface IDataMapper
    {
        // Main method that populates dto with data
        Object GetData(IDataReader reader);
        // Gets the num results returned. Needed for data paging.
        int GetRecordCount(IDataReader reader);
    }

IDataMapper requires that we implement just two methods.  GetData() takes an IDataReader and returns a model class that contains the data for the current record in that reader (note that one call to GetData() returns one model object, lists can be created by calling GetData() multiple times ).  GetRecordCount() will return the total number of records returned by the IDataReader and is used for data paging.  So these are the only two public methods that we’ll need to implement.

GenericMapper

Now we get down to it.  Here is the complete code for the GenericMapper.

    class GenericMapper : IDataMapper
    {
        public System.Type DtoType { get; set; }
        private bool _isInitialized = false;
        private List<PropertyOrdinalMap> PropertyOrdinalMappings;


        public GenericMapper(System.Type type)
        {
            DtoType = type;
        }


        private void InitializeMapper(IDataReader reader)
        {
            PopulatePropertyOrdinalMappings(reader);
            _isInitialized = true;
        }


        public void PopulatePropertyOrdinalMappings(IDataReader reader)
        {
            // Get the PropertyInfo objects for our DTO type and map them to
            // the ordinals for the fields with the same names in our reader. 
            PropertyOrdinalMappings = new List<PropertyOrdinalMap>();
            PropertyInfo[] properties = DtoType.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                PropertyOrdinalMap map = new PropertyOrdinalMap();
                map.Property = property;
                try
                {
                    map.Ordinal = reader.GetOrdinal(property.Name);
                    PropertyOrdinalMappings.Add(map);
                }
                catch { }
            }
        }


        public Object GetData(IDataReader reader)
        {
            if (!_isInitialized) { InitializeMapper(reader); }
            object dto = Activator.CreateInstance(DtoType);
            foreach (PropertyOrdinalMap map in PropertyOrdinalMappings)
            {
                 if (!reader.IsDBNull(map.Ordinal))
                 {
                     map.Property.SetValue(dto,reader.GetValue(map.Ordinal),null);
                 }
            }
            return dto;
        }


        public int GetRecordCount(IDataReader reader)
        {
            Object count = reader["RecordCount"];
            return count == null ? 0 : Convert.ToInt32(count);
        }


        private class PropertyOrdinalMap 
        {
            public PropertyInfo Property { get; set; }
            public int Ordinal { get; set; }
        }

    }

This isn’t very much code, but the logic can be a little difficult to follow.  Let’s break it down and see how it works. 

When the user creates an instance of GenericMapper, the constructor requires them to pass in the model type they want to map to.  That type is assigned to our local DtoType property (ModelType might have been a better name).  Note that we’re creating an instance, not using static methods.  This is important because once the GenericMapper is created it can be used multiple times for multiple records without having to recalculate the mappings.

The user calls the GetData method which takes an IDataReader as a parameter. GetData is the heart of our mapper.

        public Object GetData(IDataReader reader)
        {
            if (!_isInitialized) { InitializeMapper(reader); }
            object dto = Activator.CreateInstance(DtoType);
            foreach (PropertyOrdinalMap map in PropertyOrdinalMappings)
            {
                 if (!reader.IsDBNull(map.Ordinal))
                 {
                     map.Property.SetValue(dto,reader.GetValue(map.Ordinal),null);
                 }
            }
            return dto;
        }

GetData first checks to see if the GenericMapper has been initialized.  If not it calls InitializeMapper() which handles all initialization including a call to PopulatePropertyOrdinalMappings().  This is where the magic happens. 

        public void PopulatePropertyOrdinalMappings(IDataReader reader)
        {
            // Get the PropertyInfo objects for our DTO type and map them to
            // the ordinals for the fields with the same names in our reader. 
            PropertyOrdinalMappings = new List<PropertyOrdinalMap>();
            PropertyInfo[] properties = DtoType.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                PropertyOrdinalMap map = new PropertyOrdinalMap();
                map.Property = property;
                try
                {
                    map.Ordinal = reader.GetOrdinal(property.Name);
                    PropertyOrdinalMappings.Add(map);
                }
                catch { }
            }
        }

We have a private class named PropertyOrdinalMap which is just a simple container for a System.Reflection.PropertyInfo object and an int. The int represents the ordinal (field index) in our IDataReader for the field that matches the name of the property stored in PropertyInfo.  The PopulatePropertyOrdinalMappings method just loops over all of the properties in our DtoType and tries to find an ordinal in IDataReader for a field with the same name.  If a match exists, a new PropertyOrdinalMap is created an added to the PropertyOrdinalMappings List. If a match doesn’t exist, no PropertyOrdinalMap is created.  The result is that we just skip any properties in our DtoType that the reader doesn’t have a value for.  That’s a key design decision.  We don’t throw an error if a mapping doesn’t exist, we just skip that property and get the data that we can map.

Once the mappings are created it’s all pretty straight forward.  We return to GetData().  We use System.Activator() to create a new instance of our DtoType called dto (short for Data Transfer Object).  Then we iterate over our PropertyOrdinalMappings and use reflection to set the value of each dto property that we have a mapping for.  At that point we have a brand new object of whatever type was passed in to the constructor and it’s been populated with the data from the current record in the IDataReader.  We’re done!  We can just return the dto.

So that’s it.  A little object oriented design, some super-simple reflection code, and I have a GenericMapper that allows me to never right another line of data mapping code (as long as I’m willing to use the same name for my model properties and data table columns).  I haven’t spent any time optimizing this.  In fact, I haven’t really looked at it since I first wrote it.  If anyone has suggestions for improvements please let me know.

Monday, January 3, 2011

Type Argument Specification is Redundant

One of the things I like about ReSharper is that it teaches me things I didn’t know.  Recently I was writing a property that calls a generic helper method that I’d created and ReSharper gave me the little popup below letting me know that I might want to refactor that line of code.

image

“Type argument specification is redundant”,  what the heck does that mean?  So I looked into it and learned something interesting that I didn’t know before.  To understand what’s going on let’s first look at my NewIfNull() method. 

NewIfNull() is a simple generic helper method that takes an object of any type that has a parameterless constructor, it then checks to see if that object is null.  If it is null, the helper returns a new instance of that object’s type.  If the object isn’t null, it just returns the object.  It’s kind of like lazy loading for type instantiation.  It’s useful in situations where I have properties for things like data services that I don’t want to instantiate until the first time I call them (if they’re called at all).  Here’s the NewIfNull() code:

image 

You can see that NewIfNull() is a generic method that takes a type parameter T which represents the type of the object that I’m passing in.  A typical call to NewIfNull looks like  

image 

This isn’t too bad, but it’s a little annoying that I have to pass _workflowService as a parameter and then I also have to specify WorkflowService as my type inside of the angle brackets.  Well apparently that part is completely unnecessary. That little helper message from ReSharper was trying to tell me that since T is just the type of my parameter obj,  .Net can infer the type of T from parameter obj.  Passing type T in the angle brackets is actually redundant. Brilliant!  Now my calls to NewIfNull() look like this.

image

Much cleaner. No angle brackets or generic type parameters needed.  I’ve been writing and using generic methods for quite a while and I never knew .Net would infer types like this.  Thank you ReSharper.  If you want to learn more, the MSDN documentation on Type Inference is pretty good.  Check out Section 26.3.3 Type Inference.