SRP (Single Responsibility Principle) — η πρώτη αρχή SOLID που ορίζει: κάθε κλάση ή δομοστοιχείο πρέπει να έχει ακριβώς έναν λόγο για να αλλάξει. Αυτή η αρχή διατυπώθηκε από τον Robert Martin στο βιβλίο Clean Architecture (2017) και έγινε το θεμέλιο του αρθρωτού σχεδιασμού. Σύμφωνα με αυτό το βιβλίο, η εφαρμογή του SRP μειώνει άμεσα τη σύζευξη μεταξύ των στοιχείων και εξαλείφει τις αλυσιδωτές αλλαγές κατά τη βελτίωση της λειτουργικότητας.
Κύρια Σημεία
SRP (Single Responsibility Principle) — η αρχή της ενιαίας ευθύνης που ορίζει: κάθε κλάση ή δομοστοιχείο πρέπει να έχει ακριβώς έναν λόγο για να αλλάξει. Αυτό δεν σημαίνει ότι μια κλάση πρέπει να εκτελεί ακριβώς μία λειτουργία. Πρόκειται για μια ομάδα σχετικών ενεργειών, ενωμένων με μία ευθύνη απέναντι σε έναν φορέα.
Ο Robert Martin αναδιατύπωσε το SRP με όρους φορέων: μια κλάση πρέπει να αλλάζει μόνο με αίτημα ενός ενδιαφερόμενου μέρους ή μιας ομάδας ανθρώπων. Αν δύο διαφορετικοί φορείς ζητούν αλλαγή της ίδιας κλάσης — η ευθύνη είναι εσφαλμένα κατανεμημένη.
Για παράδειγμα, η κλάση Employee, που ταυτόχρονα υπολογίζει τον μισθό (αίτημα λογιστηρίου) και δημιουργεί αναφορά (αίτημα διοίκησης), παραβιάζει το SRP. Η αλλαγή των κανόνων υπολογισμού μπορεί να επηρεάσει τη δημιουργία αναφοράς και αντίστροφα.
Ένα δομοστοιχείο πρέπει να έχει έναν και μοναδικό λόγο για να αλλάξει. Ο λόγος αλλαγής καθορίζεται από τον φορέα — το άτομο ή το σύστημα που ξεκινά την απαίτηση. Αν απαιτήσεις από διαφορετικούς φορείς οδηγούν σε αλλαγή του ίδιου δομοστοιχείου — το δομοστοιχείο παραβιάζει το SRP.
Η έννοια του φορέα καθιστά το SRP πρακτικό εργαλείο αρχιτεκτονικής ανάλυσης, όχι αφηρημένη σύσταση. Κατά τον σχεδιασμό ενός συστήματος, αρκεί να ρωτήσουμε: «Ποιος θα ζητήσει αλλαγή αυτού του κώδικα;» — αν η απάντηση περιλαμβάνει περισσότερα από ένα ενδιαφερόμενα μέρη, η ευθύνη πρέπει να διαχωριστεί.
Η ενιαία ευθύνη υλοποιείται μέσω της ομαδοποίησης μεθόδων που αλλάζουν για έναν λόγο. Η κλάση γίνεται ένα «σημείο συγκέντρωσης» της σχετικής λογικής, όχι ένας «ελβετικός σουγιάς» για κάθε περίσταση. Αυτό απλοποιεί την κατανόηση του κώδικα: ο προγραμματιστής βλέπει την κλάση και καταλαβαίνει αμέσως τον σκοπό της.
Ο μηχανισμός λειτουργίας του SRP βασίζεται στον κανόνα του ενός άξονα αλλαγής. Αν η λειτουργικότητα μπορεί να αλλάξει για ανεξάρτητους λόγους — πρέπει να μεταφερθεί σε ξεχωριστές κλάσεις. Οι συνδέσεις μεταξύ αυτών των κλάσεων χτίζονται μέσω σύνθεσης ή ανάθεσης.
Η παραβίαση του SRP εκδηλώνεται σε «θεϊκές κλάσεις» (God Objects), που περιέχουν δεκάδες μεθόδους που εργάζονται με διαφορετικά δεδομένα. Μια τέτοια κλάση είναι δύσκολο να δοκιμαστεί — η δοκιμή μιας μεθόδου απαιτεί ρύθμιση του περιβάλλοντος για όλες τις υπόλοιπες. Η αλλαγή μιας ευθύνης μπορεί να χαλάσει μια άλλη, καθιστώντας τον κώδικα εύθραυστο.
Στην πράξη, το SRP βοηθά τους προγραμματιστές να απαντήσουν στην ερώτηση «πού βρίσκεται αυτός ο κώδικας;». Αν κάθε ευθύνη είναι απομονωμένη στη δική της κλάση, η εύρεση του απαραίτητου αρχείου διαρκεί δευτερόλεπτα. Σε ένα έργο Android με αρχιτεκτονική MVVM, αυτό σημαίνει ότι το UserViewModel ευθύνεται μόνο για την κατάσταση της οθόνης χρήστη και το UserRepository για την ανάκτηση δεδομένων. Ο προγραμματιστής που αναζητά λογική προσωρινής αποθήκευσης πηγαίνει στο UserCacheRepository, όχι στο ViewModel. Μια τέτοια οργάνωση κώδικα επιταχύνει την ενσωμάτωση νέων μελών της ομάδας και μειώνει τον αριθμό σφαλμάτων κατά την αναδιάρθρωση.
Η ανάπτυξη για κινητά θέτει ειδικές απαιτήσεις για την αρθρωτότητα του κώδικα. Το Android Fragment ή το iOS ViewController συχνά γίνονται «σημεία έλξης» λογικής: επεξεργασία κλικ, κλήση API, ανάλυση απόκρισης, ενημέρωση UI — όλα σε μία κλάση. Το SRP απαιτεί τον διαχωρισμό αυτών των ευθυνών.
Στην αρχιτεκτονική Android, το SRP είναι ενσωματωμένο στις συστάσεις της Google για το Jetpack: το ViewModel ευθύνεται για την κατάσταση οθόνης, το Repository για τα δεδομένα, το UseCase για την επιχειρηματική λογική. Κάθε στοιχείο έχει έναν λόγο για αλλαγή. Στην ανάπτυξη iOS, το μοτίβο MVVM και το Coordinator ακολουθούν την ίδια λογική.
Η τήρηση του SRP σε έργα κινητών προσφέρει μετρήσιμα πλεονεκτήματα: μείωση μεγέθους κλάσεων κατά 40-60%, μείωση χρόνου code review και μείωση σφαλμάτων παλινδρόμησης κατά την προσθήκη νέας λειτουργικότητας. Απομονωμένα δομοστοιχεία είναι ευκολότερο να καλυφθούν με unit tests και να επαναχρησιμοποιηθούν σε άλλες οθόνες.
Τα unit tests κλάσεων που τηρούν το SRP απαιτούν λιγότερα mock αντικείμενα και ρυθμίσεις. Αν μια κλάση έχει μία ευθύνη, οι εξαρτήσεις της είναι περιορισμένες. Το test ελέγχει μία συμπεριφορά, όχι έναν συνδυασμό πολλών άσχετων σεναρίων.
Σύμφωνα με αναφορά του Google Testing Blog (2023), οι κλάσεις με ενιαία ευθύνη εμφανίζουν 35% μεγαλύτερη κάλυψη από tests σε σύγκριση με συγκεντρωτικές κλάσεις. Οι προγραμματιστές γράφουν πιο πρόθυμα tests για μικρές, κατανοητές δομές.
Εξετάστε μια τυπική κλάση Android που παραβιάζει το SRP — φορτώνει δεδομένα, αναλύει την απόκριση και ενημερώνει το UI. Μετά την αναδιάρθρωση, κάθε ευθύνη είναι απομονωμένη σε ξεχωριστό στοιχείο.
// Παραβίαση SRP: μία κλάση κάνει τα πάντα
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// Αίτημα HTTP
// Ανάλυση JSON
// Ενημέρωση UI
// Αποθήκευση στη βάση
}
}
// Μετά την εφαρμογή SRP
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
Παρόμοιο παράδειγμα σε iOS Swift με διαχωρισμό του επιπέδου δικτύου και του επιπέδου παρουσίασης:
// Παραβίαση SRP: ViewController διαχειρίζεται δεδομένα και UI
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// Αίτημα URLSession
// Αποκωδικοποίηση JSON
// Ενημέρωση ετικέτας
}
}
// Μετά την εφαρμογή SRP
protocol UserServiceProtocol {
func fetchUser(id: Int) async throws -> User
}
class ProfileViewModel {
private let service: UserServiceProtocol
func loadProfile(id: Int) { }
}
class ProfileViewController: UIViewController {
func display(user: User) { }
}
Η αναδιάρθρωση SRP δεν περιπλέκει την αρχιτεκτονική — ανακατανέμει την ευθύνη. Η ποσότητα κώδικα μπορεί ακόμη και να μειωθεί με την εξάλειψη των επαναλήψεων. Κάθε νέα κλάση έχει σαφή σκοπό και μπορεί να αναπτυχθεί ανεξάρτητα.
Η σύνθεση βοηθά στην τήρηση του SRP εκεί όπου η κληρονομικότητα δημιουργεί περιττές συζεύξεις. Αντί για μια υπερκλάση με δεκάδες μεθόδους, η υποκλάση λαμβάνει ένα σύνολο εξειδικευμένων αντικειμένων μέσω του κατασκευαστή. Κάθε αντικείμενο ευθύνεται για τη δική του λειτουργικότητα.
Στην ανάπτυξη Android, το μοτίβο Decorator επιτρέπει την προσθήκη ευθυνών χωρίς τροποποίηση της αρχικής κλάσης. Στο iOS, η αλυσίδα Middleware στο επίπεδο δικτύου διαχωρίζει την καταγραφή, την προσωρινή αποθήκευση και την ταυτοποίηση σε ξεχωριστά δομοστοιχεία.
Η συχνότερη παραβίαση — η «God Class»: μια κλάση που διαχειρίζεται τη βάση δεδομένων, στέλνει ειδοποιήσεις, δημιουργεί αναφορές και επεξεργάζεται είσοδο χρήστη. Μια τέτοια κλάση γίνεται εμπόδιο του έργου: κάθε αλλαγή απαιτεί πλήρη δοκιμή παλινδρόμησης.
Στην ανάπτυξη για κινητά, η παραβίαση του SRP προκαλείται από την ανάμειξη επιχειρηματικής λογικής και λογικής UI σε Activity, Fragment ή ViewController. Όταν η μέθοδος onClickListener ταυτόχρονα επικυρώνει δεδομένα, καλεί API και ενημερώνει την ορατότητα κουμπιών — αυτό είναι άμεση παραβίαση της αρχής της ενιαίας ευθύνης.
Οι συνέπειες της παραβίασης του SRP περιλαμβάνουν: δυσκολία παράλληλης ανάπτυξης (συγκρούσεις σε ένα αρχείο), δυσχέρεια unit testing, υψηλό κόστος αλλαγών και μείωση αναγνωσιμότητας κώδικα. Έργα με συστηματική παραβίαση του SRP απαιτούν 2-3 φορές περισσότερο χρόνο για την προσθήκη νέας λειτουργικότητας.
Η παραβίαση του SRP μπορεί να προσδιοριστεί από έμμεσα σημάδια: η κλάση περιέχει πάνω από 200 γραμμές, εισάγει δομοστοιχεία από διαφορετικά επίπεδα της εφαρμογής (UI + network + database), έχει πάνω από 5 δημόσιες μεθόδους με διαφορετική θεματολογία. Η μετρική συνοχής — στατιστικός δείκτης: η χαμηλή συνοχή των μεθόδων μέσα στην κλάση υποδηλώνει παραβίαση του SRP.
Για τον εντοπισμό παραβιάσεων SRP είναι χρήσιμο να χρησιμοποιούνται εργαλεία στατικής ανάλυσης: για Android — Detekt με τον κανόνα TooManyFunctions, για iOS — SwiftLint με τον κανόνα file_length. Αυτά τα εργαλεία επισημαίνουν κλάσεις που υπερβαίνουν τα κατώφλια μεγέθους και πολυπλοκότητας.
Η αναδιάρθρωση κλάσεων που παραβιάζουν το SRP πραγματοποιείται μέσω Extract Class ή Extract Delegate: μια ομάδα σχετικών μεθόδων μεταφέρεται σε ξεχωριστή κλάση και η αρχική κλάση αναθέτει σε αυτές τις κλήσεις. Η σταδιακή εφαρμογή τέτοιων αναδιαρθρώσεων μετατρέπει τη «God Class» σε ένα σύνολο χαλαρά συζευγμένων δομοστοιχείων, το καθένα με μία ευθύνη. Μια τέτοια προσέγγιση επιτρέπει τη βελτίωση της αρχιτεκτονικής χωρίς διακοπή της ανάπτυξης — η αναδιάρθρωση εκτελείται επαναληπτικά, ένα δομοστοιχείο κάθε φορά.
Συχνές Ερωτήσεις
Όχι. Το SRP δεν αφορά τον αριθμό των μεθόδων, αλλά τον αριθμό των λόγων για αλλαγή. Μια κλάση μπορεί να έχει δέκα μεθόδους αν όλες εξυπηρετούν μία ευθύνη απέναντι σε έναν φορέα. Η μία μέθοδος — είναι το άλλο άκρο που οδηγεί σε υπερβολικό κατακερματισμό του κώδικα.
Είναι η ίδια αρχή. Το Single Responsibility Principle μεταφράζεται και ως «ενιαία ευθύνη» και ως «ενιαία υποχρέωση». Ο όρος «ευθύνη» αντικατοπτρίζει ακριβέστερα την ουσία: πρόκειται για ευθύνη απέναντι σε έναν φορέα, όχι για τεχνική λειτουργία.
Repository — το άμεσο αποτέλεσμα εφαρμογής του SRP στο επίπεδο δεδομένων. Αντί να διασκορπίζεται η λογική πρόσβασης δεδομένων σε ViewModel ή UseCase, το Repository αναλαμβάνει μία ενιαία ευθύνη: παροχή δεδομένων με αφαίρεση της πηγής. Αυτή είναι μια κλασική υλοποίηση του SRP στην αρχιτεκτονική κινητών.
Ναι, το SRP δεν απαγορεύει τις εξαρτήσεις. Μια κλάση με μία ευθύνη μπορεί να αναθέσει μέρος της εργασίας σε άλλες κλάσεις μέσω σύνθεσης. Σημαντικό είναι ότι αυτές οι ανατιθέμενες εργασίες αποτελούν μέρος της ίδιας ευθύνης, όχι ανεξάρτητος λόγος για αλλαγή.
Κάντε την ερώτηση: «Ποιοι φορείς μπορεί να ζητήσουν αλλαγή αυτής της κλάσης;» Αν η απάντηση περιλαμβάνει περισσότερους από έναν φορείς — το SRP παραβιάζεται. Επιπλέον: προσπαθήστε να περιγράψετε τον σκοπό της κλάσης με μία πρόταση χωρίς τον σύνδεσμο «και». Αν δεν τα καταφέρετε — η κλάση κάνει πάρα πολλά.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης