Powiem od siebie tyle, że dobre zasady, SOLID, DRY, KISS, etc. one nie są celami samymi w sobie. Celem jest stworzenie utrzymywalnego i wysokiej jakości, i kiedy się go takiego stworzy - wtedy zaczyna się zauważać że "przypadkiem" kod zaczyna spełniać te zasady. Z reguły dobry kod spełnia te zasady; ale one nie są celem samym w sobie i po prostu "wrzucenie" ich na siłę nie koniecznie musi znaczyć o jakości kodu. Dla przykładu - z reguły jak ktoś się umyje, to nie śmierdzi. Ale to nie znaczy że każdy kto nie śmierdzi się myje. Przyczynowość nie idzie w stornę "stosuj SRP" -> "to będziesz miał dobry kod".
Co do samego SRP - Ogólnie, nazwa w SRP jest trochę problemem. "Single responsibility" jest trochę nieosiągalne. Nie tylko w programowaniu, ale w ogóle w życiu. Wyobraź sobie że ktoś daje Ci zasadę "zjedz tylko jeden posiłek dziennie". I co, nie możesz np zjeść kanapki a potem kiełby; ale możesz to połączyć w hotdoga, i to już jedna rzecz. Po drugie, jeśli miałbyś klasę która na prawdę ma jedną odpowiedzialność, to mógłbyś też wydzielić drugą z niej która również ma jedną - bo co jeśli masz klasę która ma jedną odpowiedzialność i podzielisz ją na dwie? Wychodzą Ci dwie które mają pół odpowiedzialności? Czy może każda ma po jednej? Ale jeśli mają po jednej, to jak je połączysz to mają dwie? Czy nadal jedną? chyba że mają jedną, ale wspólną? Ale skoro mają wspólną to czemu dało się je rozdzielić. Podobnie gdyby ktoś Ci powiedział: "Napisz tylko jedną opowieść", ale co jest tą "jedną opowieścią"? Książka? Może rozdział, albo saga?
Więc z uwagi na to że programy są kompozytami funkcji i klas - idea "pojedynczej odpowiedzialności" nie ma prawa bytu (chyba że jako uproszczenie).
Nie da się stwierdzić czy klasa ma jedną odpowiedzialność czy więcej, bo to zależy od tego co uznasz za odpowiedzialność a co nie. Można by napisać funkcję na 10000 linijek która konwertuje jpg na png i powiedzieć "Ta funkcja ma jedną odpowiedzialność - i jest nią konwertowanie jpg na png".
Tak na prawdę w SRP nie chodzi o żadną "pojedynczą odpowiedzialność", "robienie jednej rzeczy", "powody do zmiany", to są brednie - albo ewentualnie określenia które mogą pomóc amatorom. W SRP tak na prawdę chodzi o ograniczenie scope'u i poziomów abstrakcji jednostki (klasy, moduł lub funkcji). Im mniejszy scope, i mniej poziomów abstrakcji, tym bardziej prawdopodobne, że kodzik nam spełnia solid.
Ja osobiście uważam że kod spełnia SRP, tak jak sugeruje Robert Martin w swoich filmach, czyli kod wtedy spełnia SRP, kiedy nie można w sensowny sposób wydzielić metod z kodu. Jeśli możesz, to powinieneś.
Tak może tytułem luźnej dygresji, powiem tak - jeśli chcesz być dobrym programistą, i chcesz się nauczyć co to są właśnie SRP, SOLID, MVC, TDD, MVVM, i inne takie skrótowce albo elementy - to zapomnij o prostych nazwach i sposobach. Podobnie z paradygmatami. Programowanie to nie jest prosta sprawa, i takich skomplikowanych konceptów jak SRP albo MVC nie da się streścić jednym czy kilkoma zdaniami. Jeśli Ci się zdaje, że coś jest proste, np nie wiem "TDD" to "pisanie testów przed kodem", a "LSP" to "możliwość używania dziecka tam gdzie rodzica", to szybko się przekonasz że to nie prawda, i tak na prawdę te koncepty odnoszą się do dużo bardziej skomplikowanych idei.