J'apprends la programmation informatique et, à plusieurs endroits, je suis tombé sur le concept de cohésion et je comprends qu'il est souhaitable qu'un logiciel ait une "grande cohésion", mais qu'est-ce que cela signifie? Je suis un programmeur Java, C et Python qui apprend le C++ à partir du livre C++ Primer qui mentionne la cohésion sans l'avoir dans l'index. Pouvez-vous m'indiquer des liens sur ce sujet? Je n'ai pas trouvé la page wikipedia sur la cohésion informatique informative car elle dit simplement qu'il s'agit d'une mesure qualitative et ne donne pas d'exemples de code réels.
La cohésion est élevée quand vous avez une classe qui fait un travail bien défini. Il y a faible cohésion quand une classe fait beaucoup de travaux qui n'ont pas beaucoup en commun.
Prenons cet exemple:
Vous avez une classe qui ajoute deux nombres, mais la même classe crée une fenêtre affichant le résultat. Il s'agit d'une classe à faible cohésion, car la fenêtre et l'opération d'ajout n'ont pas grand-chose en commun. La fenêtre est la partie visuelle du programme et la fonction d’ajout est la logique derrière elle.
Pour créer une solution hautement cohérente, vous devez créer une classe Window et une classe Sum. La fenêtre appellera la méthode de Sum pour obtenir le résultat et l'afficher. De cette façon, vous développerez séparément la logique et l'interface graphique de votre application.
Une explication de ce qu'il est extrait de Code Complete de Steve McConnell:
La cohésion fait référence à la proximité de toutes les routines d'une classe ou de toutes les code dans une routine supporte un objectif central. Les classes qui contiennent fonctionnalité étroitement liée sont décrits comme ayant une forte cohésion, et l'objectif heuristique est de rendre la cohésion aussi forte que possible. La cohésion est un outil utile pour gérer la complexité car plus le code d'une classe prend en charge un objectif central, plus il est facile votre cerveau peut se souvenir de tout ce que fait le code.
Un moyen de l'obtenir à partir de Clean Code:
Les classes doivent avoir un petit nombre de variables d'instance. Chacun de les méthodes d'une classe doivent manipuler une ou plusieurs de ces variables . En général, plus une méthode est manipulée par plusieurs méthodes, plus la méthode est cohérente À sa classe. Une classe dans laquelle chaque variable est utilisée par chaque méthode est cohésive au maximum.
En général, il n'est ni conseillé ni possible de créer des classes aussi cohérentes au maximum; de l'autre Par contre, nous voudrions que la cohésion soit forte. Quand la cohésion est élevée, ça signifie que les méthodes et les variables de la classe sont co-dépendantes et accrocher ensemble comme un tout logique.
La notion de cohésion est étroitement liée à la notion de couplage; Il existe également un principe basé sur l'heuristique de la cohésion élevée, appelé Principe de responsabilité unique (le S de SOLID).
La haute cohésion est un concept de génie logiciel. En gros, il est dit qu’une classe ne devrait faire que ce qu’elle est supposée faire, et le fait pleinement. Ne le surchargez pas avec des fonctions qu'il n'est pas censé faire et tout ce qui y est directement lié ne devrait pas non plus apparaître dans le code d'une autre classe.
L'exemple est assez subjectif, car nous devons également considérer l'échelle. Un programme simple ne doit pas être trop modularisé ou il sera fragmenté; alors qu'un programme complexe peut nécessiter plus d'abstractions pour prendre en charge la complexité.
par exemple. Classe email. Il doit contenir les données membres de, depuis, cc, cci, sujet et corps, et peut contenir ces méthodes saveAsDraft (), send (), discardDraft (). Mais login () ne devrait pas être ici, car il existe un certain nombre de protocoles de messagerie, et devrait être implémenté séparément.
La cohésion est généralement mesurée à l'aide de l'une des métriques LCOM (manque de cohésion), la métrique LCOM d'origine provenant de Chidamber et Kemerer. Voir par exemple: http://www.computing.dcu.ie/~renaat/ca421/LCOM.html
Un exemple plus concret: Si une classe a par exemple un champ privé et trois méthodes; lorsque les trois méthodes utilisent ce champ pour effectuer une opération, la classe est très cohérente.
Pseudo code d'une classe cohésive:
class FooBar {
private SomeObject _bla = new SomeObject();
public void FirstMethod() {
_bla.FirstCall();
}
public void SecondMethod() {
_bla.SecondCall();
}
public void ThirdMethod() {
_bla.ThirdCall();
}
}
Si une classe a par exemple trois champs privés et trois méthodes; lorsque les trois méthodes utilisent un seul des trois champs, la classe est peu cohérente.
Pseudo-code d'une classe peu cohérente:
class FooBar {
private SomeObject _bla = new SomeObject();
private SomeObject _foo = new SomeObject();
private SomeObject _bar = new SomeObject();
public void FirstMethod() {
_bla.Call();
}
public void SecondMethod() {
_foo.Call();
}
public void ThirdMethod() {
_bar.Call();
}
}
Le principe de la classe qui fait une chose est le Principe de responsabilité unique qui provient de Robert C. Martin et est l’un des principes SOLIDE . Le principe prescrit qu'une classe ne devrait avoir qu'une seule raison de changer.
Rester proche du principe de responsabilité unique pourrait éventuellement aboutir à un code plus cohérent, mais à mon avis, ce sont deux choses différentes.
Voici un exemple de faible cohésion:
class Calculator
{
public static void main(String args[])
{
//calculating sum here
result = a + b;
//calculating difference here
result = a - b;
//same for multiplication and division
}
}
Mais une cohésion élevée implique que les fonctions dans les classes fassent ce qu’elles sont censées faire (comme elles sont nommées). Et pas une fonction faisant le travail d'une autre fonction. Voici donc un exemple de grande cohésion:
class Calculator
{
public static void main(String args[])
{
Calculator myObj = new Calculator();
System.out.println(myObj.SumOfTwoNumbers(5,7));
}
public int SumOfTwoNumbers(int a, int b)
{
return (a+b);
}
//similarly for other operations
}
Une façon générale de penser au principe de cohésion est de localiser un code avec un autre code qui en dépend ou dont il dépend. La cohésion peut et doit être appliquée à des niveaux de composition supérieurs au niveau de la classe. Par exemple, un paquet ou un espace de noms devrait idéalement contenir des classes qui se rapportent à un thème commun et qui sont davantage interdépendantes que dépendant d'autres paquets/espaces de nom C'est à dire. garder les dépendances locales.
la cohésion signifie qu'une classe ou une méthode effectue un seul travail défini. le nom de la méthode ou de la classe doit également être explicite. Par exemple, si vous écrivez une calculatrice, vous devez nommer la classe "calculatrice" et non "asdfghj". vous devez également envisager de créer une méthode pour chaque tâche, par exemple. subtract () add () etc ... le programmeur qui pourrait utiliser votre programme à l'avenir sait exactement ce que font vos méthodes. une bonne dénomination peut réduire les efforts de commentaires
aussi un principe est DRY - ne vous répétez pas
Le terme cohésion a été utilisé à l'origine pour décrire les modules de code source en tant que mesure qualitative de la relation entre le code source du module et les autres. L'idée de cohésion est utilisée dans divers domaines. Par exemple, un groupe de personnes tel qu'une unité militaire peut être cohésif, ce qui signifie que les membres de l'unité travaillent ensemble dans le but d'atteindre un objectif commun.
L'essence de la cohésion du code source réside dans le fait que le code source d'un module fonctionne ensemble vers un objectif commun et bien défini. La quantité minimale de code source nécessaire pour créer les sorties du module est dans le module et pas plus. L'interface est bien définie et les entrées passent par l'interface et les sorties sont renvoyées par l'interface. Il n'y a pas d'effets secondaires et l'accent est mis sur le minimalisme.
L'un des avantages des modules fonctionnellement cohésifs est que le développement et l'automatisation des tests unitaires sont simples. En fait, une bonne mesure de la cohésion d’un module réside dans la facilité avec laquelle il est possible de créer un ensemble complet de tests unitaires exhaustifs pour le module.
Un module peut être une classe dans un langage orienté objet ou une fonction dans un langage fonctionnel ou un langage non orienté objet tel que le langage C. Une grande partie du travail original dans ce domaine de mesure de la cohésion consistait principalement à travailler avec des programmes COBOL chez IBM. La cohésion n’est donc certainement pas uniquement un concept orienté objet.
L'intention initiale de la recherche à l'origine du concept de cohésion et du concept de couplage qui lui est associé était la recherche sur les caractéristiques de programmes faciles à comprendre, à gérer et à développer. L'objectif était de pouvoir apprendre les meilleures pratiques en matière de programmation, de les codifier, puis d'enseigner les pratiques à d'autres programmeurs.
Le but d'un bon programmeur est d'écrire un code source dont la cohésion est la plus grande possible compte tenu de l'environnement et du problème à résoudre. Cela implique que dans une grande application, certaines parties du corps du code source varieront d'autres parties quant au niveau de cohésion du code source dans ce module ou cette classe. Parfois, le meilleur que vous puissiez obtenir est la cohésion temporelle ou séquentielle en raison du problème que vous essayez de résoudre.
Le meilleur niveau de cohésion est la cohésion fonctionnelle. Un module avec une cohésion fonctionnelle est similaire à une fonction mathématique en ce sens que vous fournissez un ensemble d'entrées et que vous obtenez une sortie spécifique. Un module réellement fonctionnel n'aura pas d'effets secondaires en plus de la sortie, ni ne maintiendra aucun type d'état. Au lieu de cela, il aura une interface bien définie qui encapsulera les fonctionnalités du module sans exposer aucun des éléments internes du module et la personne utilisant le module fournira un ensemble particulier d’entrées et obtiendra une sortie particulière en retour. Un module réellement fonctionnel doit également être thread-safe.
De nombreuses bibliothèques de langages de programmation contiennent un certain nombre d'exemples de modules fonctionnels, qu'il s'agisse de classes, de modèles ou de fonctions. Les exemples cohésifs les plus fonctionnels seraient des fonctions mathématiques telles que sin, cosinus, racine carrée, etc.
D'autres fonctions peuvent avoir des effets secondaires ou maintenir un état quelconque, rendant l'utilisation de ces fonctions plus compliquée.
Par exemple, une fonction qui lève une exception ou définit une variable d'erreur globale (errno
en C) ou doit être utilisée dans une séquence (la fonction strtok()
est un exemple tiré de la bibliothèque Standard C car elle conserve un état interne) ou qui fournit un pointeur qui doit alors être géré ou émet un journal pour un utilitaire de journal sont tous des exemples d’une fonction qui n’est plus une cohésion fonctionnelle.
J'ai lu le livre original de Yourdon et de Constantine, Structured Programming, où je suis d'abord tombé sur l'idée de cohésion dans les années 1980 et l'ouvrage de Meilir Page-Jones, intitulé Guide pratique de la conception de systèmes structurés, et Page-Jones a beaucoup mieux décrit couplage et cohésion. Le livre Yourdon et Constantine semble un peu plus académique. Le livre Code Complete de Steve McConnell est assez bon et pratique et l'édition révisée en dit long sur les bonnes pratiques de programmation.
L'article de MSDN est probablement plus informatif que Wikipedia dans ce cas.