Note: The code sample is written in c#, but that shouldn't matter. I've put c# as a tag because I can't find a more appropiate one. This is about the code structure.
I'm reading Clean Code and trying to become a better programmer.
I often find myself struggling to follow the Single Responsibility Principle (classes and functions should do only one thing), specially in functions. Maybe my problem is that "one thing" is not well-defined, but still...
An example: I have a list of Fluffies in a database. We don't care what a Fluffy is. I want a class to recover fluffies. However, fluffies can change according to some logic. Depending on some logic, this class will return the data from cache or get the latest from the database. We could say that it manages fluffies, and that is one thing. To make it simple, let's say loaded data is good for an hour, and then it must be reloaded.
class FluffiesManager
{
private Fluffies m_Cache;
private DateTime m_NextReload = DateTime.MinValue;
// ...
public Fluffies GetFluffies()
{
if (NeedsReload())
LoadFluffies();
return m_Cache;
}
private NeedsReload()
{
return (m_NextReload < DateTime.Now);
}
private void LoadFluffies()
{
GetFluffiesFromDb();
UpdateNextLoad();
}
private void UpdateNextLoad()
{
m_NextReload = DatTime.Now + TimeSpan.FromHours(1);
}
// ...
}
GetFluffies()
seems ok to me. The user asks for some fluffies, we provide them. Going to recover them from the DB if needed, but that could be considered a part of getting the fluffies (of course, that's somewhat subjective).
NeedsReload()
seems right, too. Checks if we need to reload the fluffies.
UpdateNextLoad is fine. Updates the time for the next reload. that's definitely one single thing.
However, I feel what LoadFluffies()
do can't be described as one single thing. It's getting the data from the Database, and it's scheduling the next reload. It's hard to argue that calculating the time for the next reload is part of getting the data. However, I can't find a better way to do it (renaming the function to LoadFluffiesAndScheduleNextLoad
may be better, but it just makes the problem more obvious).
Is there an elegant solution to really write this class according to the SRP? Am I being too pedantic?
Or maybe my class isn't really doing just one thing?
DateTime.UtcNow
so you avoid daylight savings changeovers, or even a change in the current timezone.