Uwaga: Próbka kodu jest napisana w języku c #, ale to nie powinno mieć znaczenia. Umieściłem c # jako tag, ponieważ nie mogę znaleźć bardziej odpowiedniego. Chodzi o strukturę kodu.
Czytam Clean Code i staram się zostać lepszym programistą.
Często staram się przestrzegać zasady pojedynczej odpowiedzialności (klasy i funkcje powinny robić tylko jedną rzecz), szczególnie w funkcjach. Może moim problemem jest to, że „jedna rzecz” nie jest dobrze zdefiniowana, ale nadal…
Przykład: Mam listę puchu w bazie danych. Nie obchodzi nas, czym jest Puszysty. Chcę, żeby klasa odzyskała puszyste. Jednak puchary mogą się zmieniać zgodnie z pewną logiką. W zależności od logiki ta klasa zwróci dane z pamięci podręcznej lub pobierze najnowsze dane z bazy danych. Można powiedzieć, że zarządza puszystymi, i to jedno. Aby to uprościć, załóżmy, że załadowane dane są dobre przez godzinę, a następnie należy je ponownie załadować.
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()
wydaje mi się w porządku. Użytkownik prosi o niektóre puszyste, zapewniamy je. W razie potrzeby odzyskanie ich od DB, ale można to uznać za część zdobywania puchu (to oczywiście nieco subiektywne).
NeedsReload()
wydaje się również słuszne. Sprawdza, czy musimy ponownie załadować puchaty. UpdateNextLoad jest w porządku. Aktualizuje czas następnego przeładowania. to zdecydowanie jedna rzecz.
Czuję jednak, że tego, LoadFluffies()
czego nie można opisać jako jednej rzeczy. Pobiera dane z bazy danych i planuje następne przeładowanie. Trudno argumentować, że obliczenie czasu do następnego przeładowania jest częścią pozyskiwania danych. Nie mogę jednak znaleźć lepszego sposobu na zrobienie tego (zmiana nazwy funkcji LoadFluffiesAndScheduleNextLoad
może być lepsza, ale sprawia to, że problem jest bardziej oczywisty).
Czy istnieje eleganckie rozwiązanie, aby naprawdę napisać tę klasę według SRP? Czy jestem zbyt pedantyczny?
A może moja klasa tak naprawdę nie robi tylko jednej rzeczy?
DateTime.UtcNow
aby uniknąć zmiany czasu na letni lub nawet zmiany bieżącej strefy czasowej.