SRP (Single Responsibility Principle) — le premier principe de SOLID, qui définit : chaque classe ou module doit avoir exactement une raison de changer. Ce principe a été formulé par Robert Martin dans le livre Clean Architecture (2017) et est devenu le fondement de la conception modulaire. Selon ce livre, l’application du SRP réduit directement le couplage des composants et élimine les changements en cascade lors de la modification des fonctionnalités.
Points clés
SRP (Single Responsibility Principle) est le principe de responsabilité unique, qui énonce : chaque classe ou module doit avoir exactement une raison de changer. Cela ne signifie pas qu’une classe doit effectuer exactement une opération. Il s’agit d’un groupe d’actions liées, unies par une seule responsabilité envers un acteur.
Robert Martin a reformulé le SRP en termes d’acteurs : une classe ne doit changer qu’à la demande d’une partie prenante ou d’un groupe de personnes. Si deux acteurs différents exigent des changements dans la même classe, la responsabilité est mal répartie.
Par exemple, une classe Employee qui calcule le salaire (demande du service comptable) et génère des rapports (demande de la direction) viole le SRP. Modifier les règles de calcul pourrait affecter la génération de rapports et vice versa.
Un module doit avoir une et une seule raison de changer. La raison du changement est déterminée par un acteur — personne ou système qui initie l’exigence. Si les exigences de différents acteurs entraînent des changements dans un même module, celui-ci viole le SRP.
Le concept d’acteur fait du SRP un outil pratique d’analyse architecturale, et non une recommandation abstraite. Lors de la conception d’un système, il suffit de se demander : « Qui demandera de modifier ce code ? » — si la réponse inclut plus d’une partie prenante, la responsabilité doit être divisée.
La responsabilité unique est implémentée en regroupant les méthodes qui changent pour une même raison. La classe devient un « point de collecte » de logique connexe, et non un « couteau suisse » pour toutes les occasions. Cela simplifie la compréhension du code : le développeur voit la classe et comprend immédiatement son objectif.
Le mécanisme du SRP repose sur la règle de l’axe unique de changement. Si une fonctionnalité peut être modifiée pour des raisons indépendantes, elle doit être extraite dans des classes séparées. Les connexions entre ces classes sont établies par composition ou délégation.
La violation du SRP se manifeste dans les « God Objects » — des classes avec des dizaines de méthodes travaillant avec des données différentes. Une telle classe est difficile à tester — tester une méthode nécessite de configurer l’environnement pour toutes les autres. Changer une responsabilité peut en casser une autre, rendant le code fragile.
En pratique, le SRP aide les développeurs à répondre à la question « Où se trouve ce code ? » Si chaque responsabilité est dans sa propre classe, trouver le bon fichier prend quelques secondes. Dans un projet Android avec une architecture MVVM, UserViewModel est uniquement responsable de l’état de l’écran utilisateur, et UserRepository de la récupération des données. Un développeur cherchant la logique de cache va dans UserCacheRepository, pas dans ViewModel. Une telle organisation du code accélère l’intégration des nouveaux membres de l’équipe et réduit le nombre d’erreurs lors du refactoring.
Le développement mobile impose des exigences particulières en matière de modularité du code. Un Fragment Android ou un ViewController iOS devient souvent un « aimant » de logique : gestion des touches, appels API, analyse des réponses, mise à jour de l’interface — tout dans une seule classe. Le SRP exige de séparer ces responsabilités.
Dans l’architecture Android, le SRP est intégré dans les recommandations de Google concernant Jetpack : ViewModel est responsable de l’état de l’écran, Repository des données, UseCase de la logique métier. Chaque composant a une raison de changer. Dans le développement iOS, les patrons MVVM et Coordinator suivent la même logique.
Suivre le SRP dans les projets mobiles apporte des avantages mesurables : réduction de 40 à 60 % de la taille des classes, moins de temps passé en revue de code et moins de bugs de régression lors de l’ajout de nouvelles fonctionnalités. Les modules isolés sont plus faciles à couvrir par des tests unitaires et à réutiliser dans d’autres écrans.
Les tests unitaires des classes qui respectent le SRP nécessitent moins d’objets mock et moins de configuration. Si une classe a une seule responsabilité, ses dépendances sont limitées. Le test vérifie un comportement, et non une combinaison de plusieurs scénarios non liés.
Selon le rapport du Google Testing Blog (2023), les classes à responsabilité unique présentent 35 % de couverture de test supplémentaire par rapport aux classes agrégatrices. Les développeurs sont plus enclins à écrire des tests pour de petits modules compréhensibles.
Prenons une classe Android typique qui viole le SRP — elle charge les données, analyse la réponse et met à jour l’interface. Après le refactoring, chaque responsabilité est séparée dans son propre composant.
// Violation de SRP : une classe fait tout
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// Requête HTTP
// Analyse JSON
// Mise à jour UI
// Sauvegarde en BDD
}
}
// Après application du SRP
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
Un exemple similaire en iOS Swift avec séparation de la couche réseau et de l’affichage :
// Violation de SRP : ViewController gère les données et l’UI
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// Requête URLSession
// Décoder JSON
// Mettre à jour le label
}
}
// Après application du 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) { }
}
Le refactoring SRP ne complique pas l’architecture — il redistribue la responsabilité. La quantité de code peut même diminuer en éliminant les duplications. Chaque nouvelle classe a un objectif clair et peut être développée indépendamment.
La composition aide à respecter le SRP là où l’héritage crée des couplages inutiles. Au lieu d’une superclasse avec des dizaines de méthodes, la sous-classe reçoit un ensemble d’objets spécialisés via le constructeur. Chaque objet est responsable de sa propre fonctionnalité.
Dans le développement Android, le patron Decorator permet d’ajouter des responsabilités sans modifier la classe d’origine. Dans iOS, une chaîne de Middleware dans la couche réseau sépare la journalisation, la mise en cache et l’authentification en modules indépendants.
La violation la plus fréquente est une « God Class » : une classe qui gère la base de données, envoie des notifications, génère des rapports et traite les entrées utilisateur. Une telle classe devient un goulot d’étranglement du projet : tout changement nécessite des tests de régression complets.
Dans le développement mobile, la violation du SRP résulte du mélange de logique métier et de logique d’interface dans Activity, Fragment ou ViewController. Lorsqu’un onClickListener valide simultanément des données, appelle une API et met à jour la visibilité des boutons — c’est une violation directe du principe de responsabilité unique.
Les conséquences de la violation du SRP incluent : difficulté de développement parallèle (conflits dans un seul fichier), tests unitaires difficiles, coût élevé des modifications et moindre lisibilité du code. Les projets avec des violations systématiques du SRP nécessitent 2 à 3 fois plus de temps pour ajouter de nouvelles fonctionnalités.
Les violations du SRP peuvent être identifiées par des signes indirects : la classe dépasse 200 lignes, importe des modules de différentes couches d’application (UI + network + database), possède plus de 5 méthodes publiques sur des sujets variés. La métrique de cohésion est un indicateur statistique : une faible cohésion des méthodes au sein d’une classe indique une violation du SRP.
Pour détecter les violations du SRP, utilisez des outils d’analyse statique : pour Android — Detekt avec la règle TooManyFunctions, pour iOS — SwiftLint avec la règle file_length. Ces utilitaires mettent en évidence les classes qui dépassent les seuils de taille et de complexité.
Le refactoring des classes qui violent le SRP s’effectue par Extract Class ou Extract Delegate : un groupe de méthodes connexes est extrait dans une classe séparée, et la classe d’origine leur délègue les appels. L’application progressive de ces refactorings transforme une « God Class » en un ensemble de modules faiblement couplés, chacun avec une seule responsabilité. Cette approche permet d’améliorer l’architecture sans arrêter le développement — le refactoring est effectué de manière itérative, un module à la fois.
Foire aux questions
Non. Le SRP ne concerne pas le nombre de méthodes, mais le nombre de raisons de changer. Une classe peut avoir des dizaines de méthodes si elles servent toutes une seule responsabilité envers un seul acteur. Une seule méthode est l’extrême opposé, qui conduit à une fragmentation excessive du code.
C’est le même principe. Single Responsibility Principle se traduit aussi bien par « responsabilité unique » que par « obligation unique ». Le terme « responsabilité » reflète mieux l’essence : il s’agit de la responsabilité envers un acteur, et non d’une fonction technique.
Repository est un résultat direct de l’application du SRP à la couche de données. Au lieu de disperser la logique d’accès aux données dans ViewModel ou UseCase, Repository assume une seule responsabilité : fournir des données avec abstraction de la source. C’est une implémentation classique du SRP dans l’architecture mobile.
Oui, le SRP n’interdit pas les dépendances. Une classe avec une seule responsabilité peut déléguer une partie du travail à d’autres classes par composition. L’important est que ces tâches déléguées fassent partie de la même responsabilité, et non d’une raison indépendante de changer.
Posez la question : « Quels acteurs pourraient demander des changements à cette classe ? » Si la réponse contient plus d’un acteur, le SRP est violé. En complément : essayez de décrire l’objectif de la classe en une seule phrase sans la conjonction « et ». Si vous n’y parvenez pas, la classe en fait trop.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.