Sunday 21 October 2018

If you can't inject, use Actions/Funcs

We all know that Dependency Injection is a good thing. It is aligned with SOLID principles and gives us far more control over object lifecycles.

But, what to do when dealing with static methods?

Consider this for an example.

public interface ILogger
{
    void Log(string message);
}

public interface IRepository
{
     void DoSomething();
}

public class Logger : ILogger
{
 ......
}

public class Repository : IRepository
{
     private ILogger logger;
     public Repository (ILogger logger)
    {
        this.logger = logger;
    }
    
    public void DoSomething()
   {
        TestClass c = new TestClass();
        c.ToGuid(); 
       ......
   }
}

public static class MyExtensions
{
      public static string ToGuid(this TestClass class)
      {
           // How do i get my logger here for logging??
      }
}


It is a frequent situation where you are writing extension methods or utility methods. In most cases you SHOULD not need any dependencies but for argument's sake assume we need it.

Well, we can make use of Action or Func to ensure that abstraction is maintained. So I can potentially change the code like:

public static class MyExtensions
{
      public static string ToGuid(this TestClass class, Action logAction)
      {
               if(logAction != null) { logAction("my message"); }
      }
}

public class Repository : IRepository
{
     private ILogger logger;
     public Repository (ILogger logger)
    {
        this.logger = logger;
    }
    
    public void DoSomething()
   {
        TestClass c = new TestClass();
        c.ToGuid(new Action(logger.Log); 
       ......
   }
}

Monday 1 October 2018

Don't play with items stored in InMemory cache

How often do you use a form of in-memory store in your application? My guess is "a lot". There are multiple variations of the in-memory store that you can use - MemoryCache, Custom Dictionary, Http Cache, Application Cache etc. They all use process memory as the store for keeping the information (read objects). One great thing about in-memory cache is that it is FAST :). There are downsides though.

1. It adds to the total memory hogged by the process over its lifetime. Unless you have a good eviction strategy in place, the objects will just remain there forever. That may or may not be an issue depending on the context of the application.

2. General implementation of such cache is to keep objects as-is in its store. e.g.

Cache.Add("Key", obj);

Above code means that whosoever holds a reference to the object can still make a change to the object - what does that mean?

Say, 

1. Class 1 and Class 2 have reference to one object Obj1. 
2. Class 1 saved the object to cache. 
3. Class 2 made a change to the object in its implementation. 
4. Class 1 retrieves object from cache.

Class 1 will get the updated values and that can surprise the program logic :)

So what should we do?

Couple of options:

1. Serialize the object before storing in cache. e.g.

Cache.Add("Key", Serialize(obj));

2. Clone the object before storing in cache.

Hope this helps in catching strange issues if you use in-memory cache.

PS: Distributed cache stores do not have this issue as the objects are serialized before being transferred over to the cache store.