Motivation
I’ve seen several different approaches to Dependency Injection, each of which have their own strengths and weaknesses. I run an internship program in which I teach these patterns to college students. I believe each pattern and anti-pattern has its pros and cons, but my observation is that even experienced devs haven’t fully articulated the cost-benefit of each approach to themselves. This is my attempt to do that.
Property Injection
“Property Injection” or “Setter Injection” refers to the process of assigning dependencies to an object through a Property or Setter method.
Example
<br />public class Widget
{
public Bar Bar {get; set; }
public void Foo(string someValue)
{
Bar.SomeMethod(someValue);
}
}
There are pros and cons to this approach.
Pros
- Enables easy faking for test purposes.
- Keeps method signatures tidy.
- Dependencies are clearly specified if you are looking at the class.
Cons
- Temporal Dependency
What is a temporal dependency? Perhaps it’s best to illustrate with an example. Here is my first attempt at using the class as defined above.
var widget = new Widget();
widget.Foo("Hello World!");
Did you spot the problem? I never set Bar
. When I attempt to call Foo
I’ll get the oh-so-helpful NullReferenceException
. I find out after I try to use the class that I have a missing dependency. I have to open the class to find out which dependency is missing. Then I have to modify my code as follows:
var widget = new Widget();
widget.Bar = new Bar();
widget.Foo("Hello World!");
It’s called a temporal dependency because I have to set it before I can call any methods on the class. What’s worse, the API of the class doesn’t give me any indication that anything is wrong until after I attempt to run it.
Method Injection
“Method Injection” refers to passing dependencies to the method that uses them.
Example
<br />public class Widget
{
public void Foo(Bar bar, string someValue)
{
// snipped
}
}
Pros
- No temporal dependencies
- dependencies are clearly communicated via the API
- Easily replace dependencies with fakes for testing purposes
Cons
- Method signature explosion
- Method signature fragility
- Clients have to concern themselves with the classes dependencies
What are method signature explosion and fragility? Method Signature Explosion means that arguments to my method signatures will increase as dependencies change. This leads to Method Signature Fragility which means that as dependencies change, clients of the method have to change as well. In other words, we lose the benefit of encapsulated logic.
Constructor Injection
Constructor Injection is the process of making dependencies available to a class through its constructor.
Example
<br />public class Widget
{
private Bar _bar;
public Widget(Bar bar)
{
_bar = bar;
}
public void Foo(string someValue)
{
_bar.SomeMethod(someValue);
}
}
Pros
- Enables easy faking for test purposes.
- Keeps method signatures tidy.
- Dependencies are clearly specified through the API
- No temporal dependencies
- No Method Signature Explosion
- No Method Signature Fragility
Cons
- none – other than those inherent to the nature of using Dependency Injection in the first place.
Of the three approaches listed so far, I strongly prefer Constructor Injection. I see nothing but benefits in this approach.
Lazy Injection
If you’re getting started with Dependency Injection, I strongly recommend researching a Dependency Injection Framework such as Ninject to make constructing your class hierarchies easy. If you’re not ready to bite that off you might consider using Lazy Injection. This is a technique by which your constructor arguments are given default values so that you can instantiate your class with all of your default system values at run-time, but pass fakes during test-time.
Example
<br />public class Widget
{
private Bar _bar;
public Widget(Bar bar = new Bar())
{
_bar = bar;
}
public void Foo(string someValue)
{
_bar.SomeMethod(someValue);
}
}
You can do this with Property Injection as well, mitigating some of the cons of that approach. You are still left opening the class to figure out how and what to fake however.
Example
<br />public class Widget
{
public Bar Bar {get; set; }
public class Widget()
{
Bar = new Bar();
}
public void Foo(string someValue)
{
Bar.SomeMethod(someValue);
}
}
Service Locator
Service Locator is widely considered to be an anti-pattern. To understand why, read “ServiceLocator is an Anti-Pattern“.
Service Locator involves making an open-ended registry of dependencies widely available to any class that wants them.
Example
<br />public class Widget
{
public Bar Bar {get; private set; }
public class Widget()
{
Bar = ServiceLocator.Get<Bar>();
}
public void Foo(string someValue)
{
Bar.SomeMethod(someValue);
}
}
On the surface this looks awesome.
Pros
- Keeps method signatures tidy.
- No temporal dependencies
- No Method Signature Explosion
- No Method Signature Fragility
Cons
- Dependencies are not clearly specified through the API
- Because my API doesn’t communicate my dependencies, I have to understand the classes’ implementation details to properly test it.
- It encourages dependency explosion inside the class. This is another way of saying that a class with too many constructor arguments is a “smell” and I lose the benefit of being confronted with that “smell” if I use ServiceLocator.
Despite these flaws, it is sometimes useful as a scaffolding mechanism to introduce a Dependency Injection Framework into an application that was not designed with Dependency Injection in mind. I want to stress that I believe this pattern should only be used as an interim step on the road to full Dependency Injection Framework support in legacy applications. You should make it a point to remove ServiceLocator as quickly as possible after introducing it.
Closing Thoughts
These patterns are by no means exhaustive, but they are the common one’s I’ve seen over the years.
If you are using a Dependency Injection Framework (my favorite is Ninject), some of the cons of these approaches may be mitigated by the Framework. This may change the equation with respect to which method is appropriate for your use-case.
I was reading this stack overflow question: How can I solve this: Nhibernate Querying in an n-tier architecture?
The author is trying to abstract away NHibernate and is being counseled rather heavily not to do so. In the comments there are a couple of blog entries by Ayende on this topic:
The false myth of encapsulating data access in the DAL
Architecting in the pit of doom the evils of the repository abstraction layer
Ayende is pretty down on abstracting away NHIbernate. The answers on StackOverflow push the questioner toward just standing up an in-memory Sqlite instance and executing the tests against that.
The Sqlite solution is pretty painful with complex databases. It requires that you set up an enormous amount of data that isn’t really germane to your test in order to satisfy FK and other constraints. The ceremony of creating this extra data clutters the test and obscures the intent. To test a query for employees who are managers, I’d have to create Departments and Job Titles and Salary Types etc., etc., etc.. Dis-like.
What problem am I trying to solve?
In the .NET space developers tend to want to use LINQ to access, filter, and project data. NHibernate (partially) supports LINQ via an extension method off of ISession. Because ISession.Query<T> is an extension method, it is not stubbable with free mocking tools such as RhinoMocks, Moq, or my favorite: NSubstitute. This is why people push you to use the Sqlite solution—because the piece of the underlying interface that you want to use most of the time is not built for stubbing.
I think that a fundamental problem with NHibernate is that it is trying to serve 2 masters. On the one hand it wants to be a faithful port of Hibernate. On the other, it wants to be a good citizen for .NET. Since .NET has LINQ and Java doesn’t, the support for LINQ is shoddy and doesn’t really fit in well the rest of the API design. LINQ support is an “add-on” to the Java api, and not a first-class citizen. I think this is why it was implemented as an extension method instead of as part of the ISession interface.
I firmly disagree with Ayende on Generic Repository. However, I do agree with some of the criticisms he offers against specific implementations. I think his arguments are a little bit of straw man, however. It is possible to do Generic Repository well.
I prefer to keep my IRepository interface simple:
public interface IRepository : IDisposable { IQueryable<T> Find<T>() where T: class; T Get<T>(object key) where T : class; void Save<T>(T value) where T: class; void Delete<T>(T value) where T: class; ITransaction BeginTransaction(); IDbConnection GetUnderlyingConnection(); }
Here are some of my guidelines when using a Generic Repository abstraction:
- My purpose in using Generic Repository is not to “hide” the ORM, but
- to ease testability.
- to provide a common interface for accessing multiple types of databases (e.g., I have implemented IRepository against relational and non-relational databases) Most of my storage operations follow the Retrieve-Modify-Persist pattern, so Find<T>, Get<T>, and Save<T> support almost everything I need.
- I don’t expose my data models outside of self-contained operations, so Attach/Detach are not useful to me.
- If I need any of the other advanced ORM features, I’ll use the ORM directly and write an appropriate integration test for that functionality.
- I don’t use Attach/Detach, bulk operations, Flush, Futures, or any other advanced features of the ORM in my IRepository interface. I prefer an interface that is clean, simple, and useful in 95% of my scenarios.
- I implemented Find<T> as an IQueryable<T>. This makes it easy to use the Specification pattern to perform arbitrary queries. I wrote a specification package that targets LINQ for this purpose.
- In production code it is usually easy enough to append where-clauses to the exposed IQueryable<T>
- For dynamic user-driven queries I will write a class that will convert a flat request contract into the where-clause needed by the operation.
- I expose the underlying connection so that if someone needs to execute a sproc or raw sql there is a convenient way of doing that.
At Redacted Associates, we’ve been having a discussion about whether we should use the Generic Repository pattern on top of NHibernate. We have a simple IRepository interface as follows:
For my part, I like don’t like to spend a lot of time worrying about the way my ORM interacts with the database. I prefer to spend my design-energy around how to architect the application such that interacting with the database is a minor implementation detail, almost an afterthought even.
At least one of my co-workers disagrees, and has given a really good argument for a specific case when using direct features in NHibernate saved some work. This discussion has spurred me to ask myself “what are the most important features of an ORM?” and “at what level of abstraction should we work with an ORM?” There’s no way to answer these questions without identifying your purpose in using the ORM to begin with. With that in mind, I decided to categorize the features we all look for in an ORM and compare them to our Generic Repository implementation.
ORM features basically fall into one of 3 categories:
-
Queryability
-
Linq Provider
In .NET, Linq remains the most discoverable way to query an ORM. NHibernate has the QueryOver api, but I find it to be hopelessly unreadable anything but the simplest query.
-
Specification pattern
The easiest specification pattern in .NET relies on Linq. It’s a very nice way to allow api clients to construct their own queries without concerning themselves with database schema details. In an SOA architecture, it provides a flat contract to support complex query results. It minimizes the number of service methods because you don’t have to write GetCustomersByNameAndCityAndProduct.
-
Fully mapped relationships between objects.
I depend on having a fully expressed query model to use for linq queries. Getting the right data to work with often involves a number of database relationships and it’s impossible to predict when some new object or property will be needed to satisfy a query. It’s easiest to ensure that the model fully expresses the database and that all fields and relationships are present in the model. The model should fully and accurately express the database schema.
-
Id navigation properties.
Id navigation properties as a companion to the object relationship properties are really handy. They can reduce query-syntax clutter quite a bit. Employee.ManagerId is cleaner than Employee.Manager.Id. Some ORM’s will pull back the whole Manager to get the Id. I hate that.
-
Full support for all relationship types (one-to-one, one-to-many, many-to-many).
These relationships are standard in relational db’s. Any Object-Relational Mapper should support them.
-
Lazy Loading
-
-
Behavior
-
Cascade mappings.
This is not personally a value to me, but I recognize that in some cases it’s useful.
-
Trigger-behavior.
This sort of behavior is useful when you want the ORM to handle things like audit fields, soft deletes, or log table entries.
-
Sql-Efficiencies.
Sometimes pulling back large datasets and mapping them to in-memory objects can be very expensive. If performance is a concern, it’s nice to be able to have the ORM optimize the operation. NHibernate’s “Merge” operation is a good example of this.
-
-
Testability
-
In-memory testability
-
Mockable/Stubbable
-
I composed the following table listing the features we are seeking from an ORM and how each tool fares against our needs.
NHibernate |
Entity Framework |
Generic Repository |
Micro ORMs |
|
Linq Provider |
Not Fully Implemented | Fully Implemented | Depends on ORM | No |
Specification Pattern |
Easy to implement against partially implemented Linq provider. Hard otherwise. | Easy to implement. | Depends on ORM | No |
Can Fully Map Relationships |
Yes | Yes | Depends on ORM | No |
Id Navigation Properties |
Not without extreme (and not very useful) hacks | Yes | Depends on ORM | Yes |
Full support for relationship types |
One-to-one doesn’t work well. Results in N+1 queries on one side of the relationship | * Haven’t tested this. | Depends on ORM | Sort of |
Lazy Loading |
Yes | Yes | Depends on ORM | No |
Cascade Mappings |
Yes | Yes | Depends on ORM | No |
Trigger Behavior |
Yes | Yes | Depends on ORM | No |
Sql Efficiences |
Yes | Yes | Depends on ORM | No |
In-memory testability |
Yes, provided you use SqlLite. | Yes, provided you use SqlCompact edition—or you can interface your DbContext. | Yes | No |
Mockable-Stubbable |
Mostly. Some of the methods you use on ISession are in fact extension methods. .Query is an extension method which is problematic since that’s an obvious one I’d like to stub. | Mostly. Methods such as .Include() are extension methods with no in-memory counterpart. If I really need to use .Include() I’ll write an integration test instead. | Yes | No |
Notes |
|
|
|
Fantastic for quick and dirty CRUD on single tables. Not so great otherwise. |
Takeaways
My advice is to use Generic Repository except when you need to get close to the metal of your ORM for some fine-grained control over your data access.
I was reading some interesting blogs on the specification pattern today. I was hoping to find a NuGet package, but no such luck. So, I put together the best ideas from the blogs I read and created a new NuGet package called Isg.Specification. Much of this work is not original—my contribution is putting the work of these other developers together in an integrated way and publishing it on NuGet.
Although the write-up of the specification pattern on wikipedia doesn’t mention my specific usage goal, I want to create a parameter object that provides a specification to be used by a LINQ query in EntityFramework. In this way, I can provide a single Get<T>(ParameterObject specification) method to service all Get queries. This simplifies a service interface by removing all the various GetById, GetByName, GetByHasInvoices methods. All that differs between those methods is the predicate applied to the query, so passing the predicate into Get() as a parameter just feels natural. However, I don’t want the caller to be able to specify any predicate they want so using a parameter object that converts itself into a predicate services the purpose of limiting the callers query access as well as simplifying the query API.
Even though my target usage is EntityFramework, and the source code is in the same repository as Isg.EntityFramework, Isg.Specification in no way depends on EntityFramework.
The simplest form of the specification pattern uses simple boolean functions. However, since my target usage is EntityFramework, I needed the functions to be convertible to SQL by the EntityFramework. For this reason, my implementation of ISpecification<T> uses Expression<Func<T, bool>> instead of Func<T, bool> as its signature.
1: public interface ISpecification<T>
2: {
3: Expression<Func<T, bool>> IsSatisfied();
4: }
The simplest way to get started using the library is to inherit from CompositeSpecification<T>. Using the same sample DbContext I used for Isg.EntityFramework, here is a sample implementation of a Specification object against Customer:
1: public class CustomerSpecification : CompositeSpecification<Customer>
2: {
3: public string Name { get; set; }
4: public bool? HasInvoices { get; set; }
5:
6: protected override IEnumerable<Expression<Func<Customer, bool>>> GetExpressions()
7: {
8: if (!string.IsNullOrWhiteSpace(Name))
9: yield return ByName();
10:
11: if (HasInvoices.HasValue)
12: yield return ByHasInvoices();
13: }
14:
15: private Expression<Func<Customer, bool>> ByHasInvoices()
16: {
17: if (HasInvoices.Value)
18: return c => c.Invoices.Any();
19: return c => !c.Invoices.Any();
20: }
21:
22: private Expression<Func<Customer, bool>> ByName()
23: {
24: return c => c.Name.StartsWith(Name);
25: }
26: }
Usage is pretty easy. ISpecification<T> exposes a single method called IsSatisfied(). Feed the result of this method to a LINQ Where clause and you’re off to the races. CompositeSpecification<T> aggregates the expressions provided by GetExpressions() into a single And-ed expression and uses that for the filter.
In my test cases I create 2 customers, one of whom has invoices and one who does not. You can review the test cases in full here:
Here is sample usage:
1: [Test]
2: public void HasInvoices()
3: {
4: // Arrange
5: var filter = new CustomerSpecification()
6: {
7: HasInvoices = true,
8: };
9:
10: // Act
11: using (var context = new CustomerDbContext())
12: {
13: var query = context.Customers
14: .Where(filter.IsSatisfied())
15: .ToList();
16:
17: // Assert
18: Assert.That(query, Has.Count.EqualTo(1));
19: var result = query.Single();
20: Assert.That(result.Name, Is.EqualTo("Dagny Taggart"));
21: }
22: }
I just wanted to give some link-love to the blogs that were helpful to me in implementing the Specification Pattern. Stay tuned for Isg.Specifications on NuGet!
http://davedewinter.com/2009/05/31/linq-expression-trees-and-the-specification-pattern/
http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx
http://iainjmitchell.com/blog/?p=550
http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/
http://devlicio.us/blogs/jeff_perrin/archive/2006/12/13/the-specification-pattern.aspx
I’m trying to catalog View-ViewModel Binding Patterns so that I can compare their strengths and weaknesses. So far I can think of 2 basic ones. The names I gave them are made up. What are the others?
Name: View-Instantiation.
Description: The View directly instantiates the ViewModel and assigns it to the data context.
Sample:
<
Window.DataContext
>
<
ViewModels:MyViewModel
/>
</
Window.DataContext
>
Pros: Easy to set up and get going. Easy to add design-time data.
Cons: Requires default constructor on ViewModel. This makes Dependency Injection scenarios difficult.
Name: View Templates
Description: The View is chosen by a data template associated with the ViewModel type.
Pros: ViewModels fit easily into Dependency Injection scenarios.
Cons: Design-time data is more difficult to accommodate. Tooling cannot tell the type of the ViewModel associated to the View during View development.
System.Enum is a powerful type to use in the .NET Framework. It’s best used when the list of possible states are known and are defined by the system that uses them. Enumerations are not good in any situation that requires third party extensibility. While I love enumerations, they do present some problems.
First, the code that uses them often exists in the form of switch statements that get repeated about the code base. This violation of DRY is not good.
Second, if a new value is added to the enumeration, any code that relies on the enumeration must take the new value into account. While not technically a violation of the LSP, it’s close.
Thrid, Enums are limited in what they can express. They are basically a set of named integer constants treated as a separate type. Any other data or functionality you might wish them to have has to be added on through other objects. A common requirement is to present a human-readable version of the enum field to the user, which is most often accomplished through the use of the Description Attribute. A further problem is the fact that they are often serialized as integers, which means that the textual representation has to be reproduced in whatever database, reporting tool, or other system that consumes the serialized value.
Polymorphism is always an alternative to enumerations. Polymorphism brings a problem of its own—lack of discoverability. It would be nice if we could have the power of a polymorphic type coupled with the discoverability of an enumeration.
Fortunately, we can. It’s a variation on the Flyweight pattern. I don’t think it fits the technical definition of the Flyweight pattern because it has a different purpose. Flyweight is generally employed to minimize memory usage. We’re going to use some of the mechanics of the pattern employed to a different purpose.
Consider a simple domain model with two objects: Task, and TaskState. A Task has a Name, Description, and TaskState. A TaskState has a Name, Value, and boolean method that indicates if a task can move from one state to the other. The available states are Pending, InProgress, Completed, Deferred, and Cancelled.
If we implemented this polymorphically, we’d create an abstract class or interface to represent the TaskState. Then we’d provide the various property and method implementations for each subclass. We would have to search the type system to discover which subclasses are available to represent TaskStates.
Instead, let’s create a sealed TaskState class with a defined list of static TaskState instances and a private constructor. We seal the class because our system controls the available TaskStates. We privatize the constructor because we want clients of this class to be forced to use the pre-defined static instances. Finally, we initialize the static instances in a static constructor on the class. Here’s what the code looks like:
public sealed class TaskState { public static TaskState Pending { get; private set; } public static TaskState InProgress { get; private set; } public static TaskState Completed { get; private set;} public static TaskState Deferred { get; private set; } public static TaskState Canceled { get; private set; } public string Name { get; private set; } public string Value { get; private set; } private readonly List<TaskState> _transitions = new List<TaskState>(); private TaskState AddTransition(TaskState value) { this._transitions.Add(value); return this; } public bool CanTransitionTo(TaskState value) { return this._transitions.Contains(value); } private TaskState() { } static TaskState() { BuildStates(); ConfigureTransitions(); } private static void ConfigureTransitions() { Pending.AddTransition(InProgress).AddTransition(Canceled); InProgress.AddTransition(Completed).AddTransition(Deferred).AddTransition(Canceled); Deferred.AddTransition(InProgress).AddTransition(Canceled); } private static void BuildStates() { Pending = new TaskState() { Name = "Pending", Value = "Pending", }; InProgress = new TaskState() { Name = "In Progress", Value = "InProgress", }; Completed = new TaskState() { Name = "Completed", Value = "Completed", }; Deferred = new TaskState() { Name = "Deferred", Value = "Deferred", }; Canceled = new TaskState() { Name = "Canceled", Value = "Canceled", }; } }
This pattern allows us to consume the class as if it were an enumeration:
var task = new Task() { State = TaskState.Pending, }; if (task.State.CanTransitionTo(TaskState.Completed)) { // do something }
We still have the flexibility of polymorphic instances. I’ve used this pattern several times with great effect in my software. I hope it benefits you as much as it has me.