Many developers feel, myself included, that C#’s ‘dynamic’ keyword is…well, a little too dynamic. But, recently, I faced a challenging problem which I was only able to solve through the use of the ‘dynamic’ keyword! Here goes…
In short, I had to write a method that adds a WCF behavior to a VS-generated WCF proxy class. What I wanted to do is something like the following:
public void AddCommonWcfBehavior(ICommunicationObject wcfClientProxy) { ClientBase wcfClientBase = wcfClientProxy as ClientBase; wcfClientBase.Endpoint.Behaviors.Add(new MyCommonWcfBehavior()); } /* Note that the method is taking in an object to type 'System.ServiceModel.ICommunicationObject' which is the base-level interface for all WCF client proxies. */
However, I couldn’t do this for the simple reason that ClientBase<> is a generic class and .NET does not provide a non-generic version. Go figure! And no, for reasons that are too detailed to list here, I could not make AddCommonWcfBehavior() a generic method. I wish .NET offered a non-generic ClientBase class. But it doesn’t and thus I was stuck!
It was then that I remembered reading about the dynamic keyword not too long ago. Using the dynamic keyword, the method looks like the following (and works as expected):
public void AddCommonWcfBehavior(ICommunicationObject wcfClientProxy) { dynamic wcfClientBase = wcfClientProxy; wcfClientBase.Endpoint.Behaviors.Add(new MyCommonWcfBehavior()); }
So the moral of the story: Keep the dynamic keyword in mind! In some cases, it may be your one and only savior!
Refactoring Code to enable Unit Testing
Imagine the following (which you’ve very likely run into in the past):
You join a new company and inherit a humongous existing code base. You are told to add some new functionalities without of course breaking existing functionality. “No problem”, you say! “I’ve done this before.”
You’ve got clear requirements and complete access to the existing code base. After some investigation, you figure out that you need to add a few methods to an existing class. One of these methods is:
CustomerService.CanPurchaseProduct(int productId)
The existing CustomerService class looks somewhat like the following:
public class CustomerService { public CustomerService(int customerId) { custManager = new CustomerManager(); cust = custManager.GetCustomer(customerId); } ...other methods... private CustomerManager custManager; private Customer cust; }
You will also be utilizing an existing class named ProductService. Below is a bare-bones outline of this class:
public class ProductService { public ProductService(int productId) { prodManager = new ProductManager(); prod = prodManager.GetProduct(productId) } ... other methods below ..... private ProductManager prodManager; private Product prod; }
Your requirements state the following:
– Product must be in stock
– Customer must be a member IF product is for members only
Being the good developer that you are, you start, of course, by writing the unit tests. They look something like the following:
[TestCase] public void CanPurchaseProduct_InStockAndForAll() { int customerId = 123; int prodId = 1; //TODO: Mock this scenario CustomerService svc = new CustomerService(customerId); Assert.IsTrue(svc.CanPurchaseProduct(1)); } [TestCase] public void CanPurchaseProduct_NotInStock() { int customerId = 123; int prodId = 1; //TODO: Mock this scenario CustomerService svc = new CustomerService(customerId); Assert.IsFalse(svc.CanPurchaseProduct(1)); } [TestCase] public CanPurchaseProduct_NotAMember() { int customerId = 123; int prodId = 1; //TODO: Mock this scenario CustomerService svc = new CustomerService(customerId); Assert.IsFalse(svc.CanPurchaseProduct(1)); }
Your initial implementation of the CanPurchaseProduct() method looks like the following:
public class CustomerService { public bool CanPurchaseProduct(int productId) { ProductService prodService = new ProductService(productId); if(!prodService.IsInStock()) return false; if(prodService.IsMembersOnly() && !custService.IsMember()) return false; return true; } }
If you’re familiar with unit tests, you’ll recognize an issue right away: The way the implementation currently stands, it is impossible to mock out the different scenarios that we have coded for in our test cases. The reason for this is tight coupling and lack of abstraction. The CustomerManager, ProductService and ProductManager classes are being directly instantiated by the classes that use them – an example of tight coupling. Furthermore, the classes do not implement an interface thus making it impossible to substitute mock versions for them – a direct result of lack of abstraction. So how do we fix this with minimal changes to the existing classes? Below is one strategy:
1. Account for dependencies
The first step is figure out the dependencies. A dependency is any class, resource file, configuration file, etc. that your code is using either directly or indirectly. In our case, we have the following dependencies:
- CustomerManager - ProductService - ProductManager (used by ProductService).
2. Make the dependencies “plug-and-play”
Now that we know what the dependencies are and the places where they exist, our next step is to remove all the “knots” so that we can make them plug and play. By “knots”, I refer to statements like the following:
- custManager = new CustomerManager() - productService = new ProductService() - prodManager = new ProductManager()
Instead of the classes directly instantiating dependencies, the idea is to provide it to them. This technique is know as Dependency Injection. There are multiple ways of doing this. Keeping in mind that we need make a minimum number of changes to the existing code base, we’ll go with the simplest one:
Modify the constructors/methods to take in the dependencies as parameters.
This is illustrated below:
public class CustomerService { //Instead of directly instantiating, we pass in the dependency. //All new classes can now start using this one to allow for unit //testing. public CustomerService(int customerId, CustomerManager custManager) { cust = custManager.GetCustomer(customerId); } //Original constructor becomes empty. //We still need to keep it around since it is probably used other //existing classes public CustomerService(int customerId) : this(customerId, new CustomerManager()) { } ... //Note that the method is now taking ProductService as a parameter //instead of directly instantiating it. public bool CanPurchaseProduct(int prodId, ProductService prodService) {...} } public class ProductService { //Instead of directly instantiating, we pass in the dependency. //All new classes can now start using this one to allow for unit //testing. public ProductService(int productId, ProductManager prodManager) { } public ProductService(int productId) : this(productId, new ProductManager()) {} }
Note: When it comes time to re-factor/re-design/re-architect (whatever you want to you call) your entire application, you should go with a better alternative to handle dependency injection instead of the approach shown here. I would recommend using a tool such as Spring .NET.
3. Abstract them away!
The final step then is create an interface for each of the concrete classes and replace all references to the concrete classes with their associated interfaces.
public interface ICustomerService { bool CanPurchaseProduct(int customerId, IProductService prodService); } public interface ICustomerManager {...} public interface IProductService {...} public interface IProductManager {...} public class CustomerService : ICustomerService { public CustomerService(int customerId, ICustomerManager) {...} public bool CanPurchaseProduct(int prodId, IProductService prodService) {...} } public class CustomerManager : ICustomerManager {...} public class ProductService : IProductService { public ProductService(int prodId, IProductManager) {...} } public class ProductManager : IProductManager {...}
Now, we can finally substitute our mocks for the dependencies in our unit tests as shown below. Note that in the test cases below I am using the Moq Unit Testing Framework to setup the mocks but you could use any other framework that you’d like or none at all (if you wish to create the mocks manually).
[TestCase] public void CanPurchaseProduct_InStockAndForAll() { int customerId = 123; int prodId = 1; //create mocks Mock<ICustomerManager> custManager = mockFactory.Create<ICustomerManager>(); Mock<IProductService> prodService = mockFactory.Create<IProductService>(); Customer cust = new Customer(123); cust.IsMember = false; //setup mocks custManager.Setup(cm => cm.GetCustomer(123)).Returns(cust); prodService.Setup(ps => ps.IsInStock()).Returns(true); prodService.Setup(ps => ps.IsMembersOnly()).Returns(false); //run test CustomerService svc = new CustomerService(customerId, custManager.Object); Assert.IsTrue(svc.CanPurchaseProduct(1, prodService.Object)); } [TestCase] public void CanPurchaseProduct_NotInStock() { int customerId = 123; int prodId = 1; //create mocks Mock<ICustomerManager> custManager = mockFactory.Create<ICustomerManager>(); Mock<IProductService> prodService = mockFactory.Create<IProductService>(); Customer cust = new Customer(123); cust.IsMember = false; //setup mocks custManager.Setup(cm => cm.GetCustomer(123)).Returns(cust); prodService.Setup(ps => ps.IsInStock()).Returns(false); //run test CustomerService svc = new CustomerService(customerId, custManager.Object); Assert.IsFalse(svc.CanPurchaseProduct(1, prodService.Object)); } [TestCase] public CanPurchaseProduct_NotAMember() { int customerId = 123; int prodId = 1; //create mocks Mock<ICustomerManager> custManager = mockFactory.Create<ICustomerManager>(); Mock<IProductService> prodService = mockFactory.Create<IProductService>(); Customer cust = new Customer(123); cust.IsMember = false; //setup mocks custManager.Setup(cm => cm.GetCustomer(123)).Returns(cust); prodService.Setup(ps => ps.IsInStock()).Returns(true); prodService.Setup(ps => ps.IsMembersOnly()).Returns(true); //run test CustomerService svc = new CustomerService(customerId, custManager.Object); Assert.IsFalse(svc.CanPurchaseProduct(1, prodService.Object)); }
And there you have it. We were able to take an existing code base that had no support for unit-testing and re-factor it so that the additional methods that we added could be unit-tested. Furthermore, we did this without requiring us to make any sweeping architectural changes to the existing code base.
One could argue if the additional work is really worthwhile. If you’re already a test-driven developer then I don’t need convince you that it is definitely worthwhile. But if you’re not then I’ll highlight a few long-term benefits that result from the additional work:
- The code base is now more extensible. It can work with other implementations for ICustomerManager and IProductService.
- At any given time one can run the test cases and know if anything has been broken.
- Unit-testing forces us to think about the dependencies and code in a manner that leads to clean and easy-to-understand code.
- The test cases serve as an up-to-date documentation on what the code does and how it is being used.
I hope that the above points will encourage you to investigate the pros/cons of test driven development more fully.
Cast<> to the rescue!
Just learn’t something today that I’d like to share.
Say you’ve got a generic list of
IQueryable<Person> persons;
that you’d like to convert to
IQueryable<IPerson> iPersons;
where Person : IPerson.
How do you do this? Very simple:
IQueryable<IPerson> iPersons = persons.Cast<IPerson>();
Note that:
IQueryable<IPerson> iPersons = (IQueryable<IPerson>)persons;
won’t work.
LINQ : Implementing IN and NOT IN
I got tried of typing
var result = from s in source where items.Contains(s) select s;
and so I implemented the IN and NOT IN methods as extension methods:
public static IQueryable<T> In<T>(this IQueryable<T> source, IQueryable<T> checkAgainst) { return from s in source where checkAgainst.Contains(s) select s; } public static IQueryable<T> NotIn<T>(this IQueryable<T> source, IQueryable<T> checkAgainst) { return from s in source where !checkAgainst.Contains(s) select s; }
Thus, I can now just do the following:
var result = source.In(items);
What do you think – Good idea, Bad idea, Useless idea?
Extension methods in C# 3.0
C# 3.0 provides a very useful feature named Extension Methods. Extension methods allow you “extend” existing classes by giving you the ability to define new methods on them. For example, I can implement my very own method, say MyStringMethod(), on the existing .NET System.String class. I would then be able to call this method like any other method in String class:
string s = ""; s.MyStringMethod();
Pretty neat, huh? But besides the syntactic sugar, there are a few additional advantages to using extension methods:
- Extension methods are fully supported by Visual Studio Intellisense making them easier to discover. Thus whenever someone, provided that he/she is using my library, types in ‘string.’, Intellisense will display my method as well.
- The other advantage is related to overall system design and usability. If you’ve been programming for a while, then you’ve probably used and/or implemented utility methods. Typically these are public static methods like:
public static object Clone(object from, object to); public static cbool IsNumeric(string s); public static string FormatDateTime(DateTime d, int timeZoneOffset);
Overtime the utility classes get bigger and bigger making the methods inside them more and more obscure. This can even result into the same method being implemented twice, especially so if you have multiple utility classes that aren’t very well defined. By turning these methods into extension methods we make them easier to find and thus avoid duplication.
So how do we turn them into extension methods? By adding the keyword ‘this’ in front of the parameter to which this method ought to belong. Below is what the above method declarations look like after we turn them into extension methods:
public static object Clone(this object from, object to); public static bool IsNumeric(this string s); public static string FormatDateTime(this DateTime d, int timeZoneOffset);
Note that the methods must be static and must belong to a static class. I personally prefer creating separate extensions classes to house the methods. So,
StringExtensions.cswill contain all my String extension methods,
DateTimeExtensions.cswill contain all my DateTime extension methods……and so on.
I hope you’ve found this post to be helpful and informative. Please leave your feedback and/or comments to help me improve. Thanks!