Hope I can explain this somewhat decently, as it's blowing a fuse in my brain today. I'm learning TDD in C#, so I'm still trying to rewire my brain to fit it.
Let's say I have a User class, that previously had a static method to retrieve a User object (simplified below).
public static User GetUser(string username)
{
User user = GetUserFromCache(username);
if(user == null)
{
user = GetUserFromDatabase(username);
StoreObjectInCache(user);
}
return user;
}
So I'm trying to rewrite this to use dependency injection so I can fake out the "GetUserFromDatabase" method if it needs to go there. That means I have to make the function not static. Whereas the data access layer would construct the user object from the database, mapping the returned columns to the object properties, a retrieval from cache would return a true-blue User object. However, in a non-static method, I can't just say
this = GetUserFromCache(username);
Because it just doesn't work that way. Though I'm by no means the world expert in how to dance around this with OO, it looks like I'd almost have to grab the User object from cache and write another mapping function that would store the returned User object properties into the new User instance.
What's the solution here? Any OO magic I'm missing? Is the only solution to refactor everything to use factories instead of having the instantiation logic in the object itself? Or have I been staring at this too long and missing something completely obvious?
They are faster — Static methods are slightly faster than instance methods because in instance methods, you are also working with an implicit this parameter. Eliminating that parameter gives a slight performance boost in most programming languages.
Static dependency is a horror keyword in unit testing. If it's our own code, then we can change it. If static calls are forced by the external library or NuGet package, then we actually cannot get away from it. It will always be there, and the best thing we can do is avoid it.
3.4. Pure functions do not operate on any instance or static variables. Therefore, executing a pure function should also have no side effects. As static methods do not allow overriding and referencing instance variables, they are a great choice for implementing pure functions in Java.
Static methods don't need an instance of the class to be invoked — they can be called on the class itself. Although testing a non-static method (at least one that doesn't call a static method or interact with external dependencies) is straightforward, testing a static method is not an easy task at all.
I don't think you're missing any magic and I think refactoring to remove the persistence code from your business objects and into your persistence layer is the right way to go both from a unit testing and a design perspective. You may want to think about having the cache sit between your business layer and the persistence layer, mediating the retrieval/update of your business objects to simplify things. You should be able to mock/fake your cache and persistence layer if you separate things out this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With