2009-08-30 15 views

Répondre

6

La granularité de votre conception OO est une question de goût et pourrait être inappropriée pour d'autres. Ainsi, je ne chercherais pas des exemples de rupture du principe de responsabilité unique dans une classe de logique commerciale, en discutant si elle a trop ou trop peu à faire. À mon avis, les meilleurs exemples (avec les pires effets secondaires) viennent de la rupture de la superposition de votre application. P.ex de

  • Exécution logique métier dans la couche d'accès aux données (dont la seule responsabilité devrait fournir l'accès de persistance à l'application)
  • Accès aux services d'affaires de (par) le modèle de domaine (dont la seule responsabilité devrait à stocker la plupart du état de l'application)
  • Exécution logique métier complexe
0

La moindre idée de SRP est de définir les responsabilités afin que votre mise en œuvre ne juste cette chose. C'est comme si vous établissiez une règle (en donnant un nom et une responsabilité à une classe), puis en essayant de la suivre. Donc, si vous ne le suivez pas, ne définit pas la règle correctement ou vous êtes incohérent lors de l'implémentation (ou les deux, ce qui peut être le cas le plus courant).

Je trouve généralement les classes qui ne donnent pas un essai demi-décent de définir une seule responsabilité principale ou un bon nom pour être les meilleures violations. Ensuite, il vous suffira de lire toute la classe pour essayer de déterminer s'il y a des responsabilités bien définies.

3

est ici un code d'un projet PHP que je devais prendre:

class Session 
{ 
    function startSession() 
    { 
     // send HTTP session cookies 
    } 

    function activateUserAccount() 
    { 
     // query the DB and toggle some flag in a column 
    } 

    function generateRandomId() 
    {} 

    function editAccount() 
    { 
     // issue some SQL UPDATE query to update an user account 
    } 

    function login() 
    { 
     // perform authentication logic 
    } 

    function checkAccessRights() 
    { 
     // read cookies, perform authorization 
    } 
} 

Je crois que cette classe ne waaay à beaucoup.

1

en fait, la couche de vue (responsable de la présentation des données & d'entrée utilisateur) dans la plupart des langages OO que je l'ai utilisé, le haut-le vel Object classe est un bon exemple. Dans Ruby, par exemple, la classe Object (ou plus précisément le mixin Kernel, qui est mélangé en Object) a 45 méthodes d'instance publiques. Maintenant, certains d'entre eux sont des alias, mais il doit toujours y en avoir au moins 20, et ils viennent de partout. Je peux facilement identifier au moins 5 responsabilités. Maintenant, je ne veux pas choisir Ruby. C'est mon langage de programmation préféré. C'est pourquoi je l'ai utilisé comme exemple: parce que c'est la langue que je connais le mieux. Et je suis raisonnablement sûr que ce que j'ai écrit sur Ruby s'applique également à 100% à Java et .NET.

0

C'est une question qualitative de déterminer les «responsabilités» d'une classe. Le simple fait de regarder un code de classe donné ne peut en aucun cas nous donner une idée de la façon dont il gère sa responsabilité.
Il est très nécessaire, au moins selon mon expérience, de prendre en compte la manière dont les changements d'exigences de la classe se propageront à d'autres modules (ou comment les changements d'autres classes seront propagés à cette classe). Comme @schmeedy donne une bonne explication de «briser la superposition du système», ce qui, selon moi, n'est qu'une des façons d'analyser le «domaine de la responsabilité».

J'ai tenté d'approfondir la discussion. Mes tentatives consistent à définir la «responsabilité» de manière quantitative.
Quelques discussions sur mon blog: http://design-principle-pattern.blogspot.in/2013/12/single-responsibility-principle.html

0
#import <Foundation/Foundation.h> 
#import <CoreGraphics/CoreGraphics.h> 

@interface Spreadsheet : NSObject 

- (void)loadFromURL:(NSURL *)url; 
- (void)saveToURL:(NSURL *)url; 
- (void)drawTo:(CGRect*)targetArea withContext:(CGContextRef *)context; 

@end 

Je dirais que l'exemple ci-dessus constitue une violation de la SRP. À première vue, il est clair que la classe est responsable d'une chose: les feuilles de calcul. Il se distingue des autres entités du domaine du problème de gestion de documents, telles que le traitement de texte. Cependant, considérez les raisons pour lesquelles l'objet Spreadsheet pourrait changer.

Il se peut que le modèle sous-tendant la feuille de calcul soit modifié. Cela affecte le chargement et le code de sauvegarde mais n'a aucune incidence sur la façon dont la feuille de calcul est dessinée. Les responsabilités de chargement/sauvegarde sont donc distinctes des responsabilités de dessin. Notre classe a deux responsabilités. Donc, si nous pensons à toutes les raisons raisonnablement prévisibles de changer de classe et que seules les méthodes particulières de la classe seraient affectées, nous voyons une opportunité d'éliminer la responsabilité d'obtenir une classe plus ciblée.

Une classe révisée serait:

@interface SpreadsheetEncoder 

- (NSData *)encodedSpreadsheet:(Spreadsheet *)spreadsheet; 
- (Spreadsheet *)spreadsheetFromEncodedData:(NSData *)data; 

@end 

@interface Spreadsheet2 : NSObject 

- (NSData *)data; 
- (instancetype)initSpreadsheetFromData:(NSData *)data; 
- (void)drawTo:(CGRect*)targetArea withContext:(CGContextRef *)context; 

@end 

Comme les progrès de développement de produits, nous pouvons nous demander à nouveau « ce qui pourrait changer » et factoriser alors les classes pour les garder responsables pour une seule préoccupation. SRP est seulement relatif au domaine du problème et à notre compréhension de celui-ci à un moment donné.

SRP, à mon avis, se résume à demander «qu'est-ce qui peut changer? et "qu'est-ce qui serait affecté". Lorsque «ce qui peut changer» ne concerne qu'une seule chose qui est affectée, vous avez des classes qui appliquent le principe SRP.

Questions connexes