Qu'est-ce qu'un «couplage lâche»? Veuillez fournir des exemples

172

Je n'arrive pas à comprendre le concept de «couplage lâche». Je suppose que cela n'aide pas que le mot «lâche» ait généralement une connotation négative, alors j'oublie toujours qu'un couplage lâche est une bonne chose.

Quelqu'un voudra-t-il montrer du code «avant» et «après» (ou pseudocode) qui illustre ce concept?

trebormf
la source
Je ne sais pas comment cela peut être dissocié d'une langue particulière, car une partie du concept est la façon dont on utilise une langue pour empêcher les unités de code de s'emmêler les unes avec les autres. Je note également que plusieurs des réponses ont recours au code pour illustrer le concept.
Onorio Catenacci
11
En désaccord complètement, les aspects pratiques peuvent être illustrés différemment dans différentes langues, et cela est particulièrement apparent dans les langues dynamiques et compilées. Mais le concept est le même dans tous les cas.
Owen
Loose vs Tight et couplage vs découplage . Taguer n'est pas toujours une bonne chose, parfois bien / parfois pas bien ... Comme nous devrions avoir notre propre indépendance , les classes aussi.
bonCodigo

Réponses:

180

Considérez une application de panier simple qui utilise une classe CartContents pour garder une trace des articles dans le panier et une classe Order pour traiter un achat. La commande doit déterminer la valeur totale du contenu du panier, elle pourrait le faire comme ceci:

Exemple étroitement couplé:

public class CartEntry
{
    public float Price;
    public int Quantity;
}

public class CartContents
{
    public CartEntry[] items;
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        float cartTotal = 0;
        for (int i = 0; i < cart.items.Length; i++)
        {
            cartTotal += cart.items[i].Price * cart.items[i].Quantity;
        }
        cartTotal += cartTotal*salesTax;
        return cartTotal;
    }
}

Notez comment la méthode OrderTotal (et donc la classe Order) dépend des détails d'implémentation des classes CartContents et CartEntry. Si nous devions essayer de changer cette logique pour permettre des remises, nous devrons probablement changer les 3 classes. De plus, si nous passons à l'utilisation d'une collection List pour garder une trace des éléments, nous devrons également modifier la classe Order.

Voici maintenant une meilleure façon de faire la même chose:

Exemple moins couplé:

public class CartEntry
{
    public float Price;
    public int Quantity;

    public float GetLineItemTotal()
    {
        return Price * Quantity;
    }
}

public class CartContents
{
    public CartEntry[] items;

    public float GetCartItemsTotal()
    {
        float cartTotal = 0;
        foreach (CartEntry item in items)
        {
            cartTotal += item.GetLineItemTotal();
        }
        return cartTotal;
    }
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        return cart.GetCartItemsTotal() * (1.0f + salesTax);
    }
}

La logique spécifique à la mise en œuvre de l'élément de campagne du panier ou de la collecte du panier ou de la commande est limitée à cette seule classe. Nous pourrions donc changer l'implémentation de l'une de ces classes sans avoir à changer les autres classes. Nous pourrions pousser encore plus loin ce découplage en améliorant la conception, en introduisant des interfaces, etc., mais je pense que vous voyez le point.

Coin
la source
Pourriez-vous développer la réponse en introduisant un découplage supplémentaire par injection de dépendances (bien que le constructeur devrait être idéal)?
BAD_SEED
4
@Wedge, je ne vois aucune raison pour que l ' Orderait la moindre connaissance d'un Cart. Les achats en direct et la facturation sont deux contextes différents. Lorsque le client est prêt à payer, vous pouvez avoir un processus chargé de traduire les CartEntries en quelque chose de signifiant pour le Order. De cette façon, la Orderclasse serait également instanciée et utilisée sans Cart.
plalx
@Wedge Pouvez-vous réagir à mon commentaire s'il vous plaît?
plalx
Eh bien et simplement expliqué. J'ai commencé à voir la lumière à "..Notez comment la méthode OrderTotal (et donc la classe Order) dépend des détails d'implémentation des classes CartContents et CartEntry .."
okey_on
Cet exemple est clairement présenté. Cependant, de nos jours, de plus en plus d'architectes conviennent que ce style trop orienté objet est une mauvaise pratique. Il ne sert à rien de cacher les détails de «mise en œuvre» de CartEntryet CartContents. Comme ceux-ci ont une signification parfaitement claire, ils doivent être simplement modélisés comme des données mortes. en termes de base de données, il suffit ici d'une tableCREATE TABLE entry (price INTEGER, quantity INTEGER)
Jo So
160

De nombreux produits intégrés (en particulier par Apple) tels que les iPod , les iPad sont un bon exemple de couplage serré: une fois que la batterie est épuisée, vous pouvez aussi bien acheter un nouvel appareil car la batterie est soudée fixe et ne se détache pas, ce qui rend le remplacement très coûteux. Un lecteur faiblement couplé permettrait de changer sans effort la batterie.

Il en va de même pour le développement logiciel: il est généralement (beaucoup) préférable d'avoir un code faiblement couplé pour faciliter l'extension et le remplacement (et pour rendre les différentes parties plus faciles à comprendre). Mais, très rarement, dans des circonstances particulières, un couplage étroit peut être avantageux car l'intégration étroite de plusieurs modules permet une meilleure optimisation.

Konrad Rudolph
la source
Le couplage desserré ou serré est-il bon? Comment décider de mettre en œuvre un couplage lâche ou un couplage serré?
Sreekanth Karumanaghat
2
merci pour ce bel exemple. J'ai passé beaucoup de temps sur d'autres réponses mais ça ne vaut pas la peine comme ça
alamin
1
Sreekanth Karumanaghat, préférez-vous dépenser moins d'argent juste pour une batterie et avoir à nouveau un iPod en état de marche ou préférez-vous dépenser beaucoup d'argent pour un iPod entier?
Koshera
1
@SreekanthKarumanaghat En général, un couplage lâche est préférable car il favorise la modularité et facilite ainsi la maintenance du code. Si vous associez étroitement vos classes / bibliothèques / code, tout petit changement que vous apportez à une classe devra être implémenté dans toutes les classes qui l'utilisent.
Kenny Worden
56

J'utiliserai Java comme exemple. Disons que nous avons une classe qui ressemble à ceci:

public class ABC
{
   public void doDiskAccess() {...}
}

Lorsque j'appelle la classe, je dois faire quelque chose comme ceci:

ABC abc = new ABC();

abc. doDiskAccess();

Jusqu'ici tout va bien. Maintenant, disons que j'ai une autre classe qui ressemble à ceci:

public class XYZ
{
   public void doNetworkAccess() {...}
}

Cela ressemble exactement à ABC, mais disons que cela fonctionne sur le réseau plutôt que sur le disque. Alors maintenant, écrivons un programme comme celui-ci:

if(config.isNetwork()) new XYZ().doNetworkAccess();
else new ABC().doDiskAccess();

Cela fonctionne, mais c'est un peu difficile à manier. Je pourrais simplifier cela avec une interface comme celle-ci:

public interface Runnable
{
    public void run();
}

public class ABC implements Runnable
{
   public void run() {...}
}

public class XYZ implements Runnable
{
   public void run() {...}
}

Maintenant, mon code peut ressembler à ceci:

Runnable obj = config.isNetwork() ? new XYZ() : new ABC();

obj.run();

Voyez à quel point c'est plus propre et plus simple à comprendre? Nous venons de comprendre le premier principe de base du couplage lâche: l'abstraction. La clé ici est de s'assurer que ABC et XYZ ne dépendent d'aucune méthode ou variable des classes qui les appellent. Cela permet à ABC et XYZ d'être des API totalement indépendantes. Ou en d'autres termes, ils sont "découplés" ou "faiblement couplés" des classes parentes.

Mais que faire si nous avons besoin d'une communication entre les deux? Eh bien, nous pouvons utiliser d'autres abstractions comme un modèle d'événement pour nous assurer que le code parent n'a jamais besoin de se coupler avec les API que vous avez créées.

64BitBob
la source
2
Cet exemple présente encore un niveau de couplage assez élevé. Pour le moment, au lieu d'être couplé à une seule classe, vous avez le choix entre deux. Cet exemple suppose qu'il n'y aura que deux implémentations «exécutables» disponibles. Dans ce cas, une interface n'est même pas nécessaire.
Owen
Ces méthodes nommées Run * et Do * sont une énorme odeur de code pour moi. Vous pouvez également refactoriser cela en utilisant IHandleStuff ou IFrobnicateThings. Runnable est un terme beaucoup trop générique dans ce cas.
Wedge
8
Owen, bébé fait les pas de mon ami. S'il ne comprend pas le couplage, comment va-t-il comprendre ce que lui achète un patron d'usine? Cet exemple de code le met sur la bonne voie. L'intention est qu'il comprendra mieux le problème et réalisera comment faire abstraction de la création des objets.
64BitBob
6
Serait-ce plus lisible si ABC et XYZ étaient renommés quelque chose comme DiskAccessoret NetworkAccessor? Je ne sais pas java ...
MusiGenesis
Utilise-t-il également un modèle de conception d'usine? Parce que nous créons de nouveaux objets XYZ ou ABC en fonction des besoins.
munmunbb
37

Désolé, mais «couplage lâche» n'est pas un problème de codage, c'est un problème de conception. Le terme «couplage lâche» est intimement lié à l'état souhaitable de «cohésion élevée», étant opposé mais complémentaire.

Un couplage lâche signifie simplement que des éléments de conception individuels doivent être construits afin de réduire la quantité d'informations inutiles dont ils ont besoin sur d'autres éléments de conception.

Une cohésion élevée est un peu comme un «couplage serré», mais une cohésion élevée est un état dans lequel les éléments de conception qui ont vraiment besoin de se connaître sont conçus pour qu'ils fonctionnent ensemble proprement et élégamment.

Le fait est que certains éléments de conception doivent connaître des détails sur d'autres éléments de conception, ils doivent donc être conçus de cette façon, et non par accident. Les autres éléments de conception ne doivent pas connaître les détails des autres éléments de conception, ils doivent donc être conçus de cette manière, à dessein, plutôt que de manière aléatoire.

La mise en œuvre est laissée comme un exercice pour le lecteur :).

David M. Karr
la source
33

Un code étroitement couplé repose sur une implémentation concrète. Si j'ai besoin d'une liste de chaînes dans mon code et que je la déclare comme ceci (en Java)

ArrayList<String> myList = new ArrayList<String>();

alors je suis dépendant de l'implémentation ArrayList.

Si je veux changer cela en code faiblement couplé, je fais de ma référence un type d'interface (ou autre abstrait).

List<String> myList = new ArrayList<String>();

Cela m'empêche d'appeler une méthode myListspécifique à l'implémentation ArrayList. Je suis limité aux seules méthodes définies dans l'interface de liste. Si je décide plus tard que j'ai vraiment besoin d'une LinkedList, je n'ai besoin de changer mon code qu'à un seul endroit, où j'ai créé la nouvelle List, et pas à 100 endroits où j'ai fait des appels aux méthodes ArrayList.

Bien sûr, vous pouvez instancier une ArrayList en utilisant la première déclaration et vous empêcher de n'utiliser aucune méthode qui ne fait pas partie de l'interface List, mais l'utilisation de la deuxième déclaration permet au compilateur de vous garder honnête.

Bill le lézard
la source
Cela se rapporte à peine ce « couplage » en fait est . Voir stackoverflow.com/questions/39946/coupling-and-cohesion pour quelques bonnes réponses.
Rogério
@Rogerio: Je pense que ça se rapporte. Peut-être que vous êtes confus par les autres définitions de «couplage», mais vous devriez lire Couplage lâche . "Un couplage fort se produit lorsqu'une classe dépendante contient un pointeur directement vers une classe concrète qui fournit le comportement requis ... Un couplage lâche se produit lorsque la classe dépendante contient un pointeur uniquement vers une interface, qui peut ensuite être implémentée par une ou plusieurs classes concrètes . " Dans mon exemple, mon code serait faiblement couplé à un ArrayList via l'interface List.
Bill the Lizard
@Bill: Merci pour le lien, mais cet article me semble complètement faux. Il semble «réinterpréter» les idées d'un autre domaine (comportement organisationnel), donnant une définition du «couplage lâche» qui contredit la définition originale spécifique au logiciel de Larry Constantine: en.wikipedia.org/wiki/Coupling_(computer_science) .
Rogério
@Rogerio: L'article de Constantine a été écrit en 1974. Il est probable que beaucoup de réinterprétations se soient déroulées au cours des 36 dernières années, mais je ne pense pas que l'article de Wikipédia en soit la source. Par exemple, des modèles comme l' injection de dépendances reposent sur des interfaces pour desserrer le couplage comme je le décris dans ma réponse.
Bill the Lizard
2
@Bill: Bien sûr, le travail de Constantine sur la conception structurée est ancien, mais je ne vois aucune raison de l'invalider ou de le réinterpréter radicalement. Les concepts originaux de cohésion et de couplage sont au cœur de la conception orientée objet, tout autant que l'héritage et le polymorphisme. DI (un meilleur article est martinfowler.com/articles/injection.html ) est simplement une technique pour la configuration externe des plug-ins (interfaces abstraites avec des implémentations sélectionnées au moment de l'exécution via le code de configuration); une autre technique de ce type est le modèle Service Locator. DI et couplage sont des concepts indépendants.
Rogério
27

Le degré de différence entre les réponses montre ici pourquoi ce serait un concept difficile à saisir mais pour le dire aussi simplement que je peux le décrire:

Pour que je sache que si je te lance une balle, tu peux l'attraper, je n'ai vraiment pas besoin de savoir quel âge tu as. Je n'ai pas besoin de savoir ce que tu as mangé au petit-déjeuner, et je me fiche de qui était ton premier béguin. Tout ce que j'ai besoin de savoir, c'est que vous pouvez attraper. Si je le sais, alors je m'en fiche si c'est toi que je te lance une balle ou à ton frère.

Avec des langages non dynamiques comme c # ou Java, etc., nous y parvenons via des interfaces. Disons donc que nous avons l'interface suivante:

public ICatcher
{
   public void Catch();
}

Et maintenant, disons que nous avons les classes suivantes:

public CatcherA : ICatcher
{
   public void Catch()
   {
      console.writeline("You Caught it");
   }

}
public CatcherB : ICatcher
{
   public void Catch()
   {
      console.writeline("Your brother Caught it");
   }

}

À présent, CatcherA et CatcherB implémentent la méthode Catch, de sorte que le service qui nécessite un Catcher peut utiliser l'un ou l'autre de ces derniers et ne pas vraiment se tromper de quel il s'agit. Ainsi, un service étroitement couplé pourrait directement instancier un ie

public CatchService
{
   private CatcherA catcher = new CatcherA();

   public void CatchService()
   {
      catcher.Catch();
   }

}

Ainsi, le CatchService peut faire exactement ce qu'il a prévu de faire, mais il utilise CatcherA et utilisera toujours CatcherA. Il est codé en dur, donc il reste là jusqu'à ce que quelqu'un vienne le refactoriser.

Prenons maintenant une autre option, appelée injection de dépendances:

public CatchService
{
   private ICatcher catcher;

   public void CatchService(ICatcher catcher)
   {
      this.catcher = catcher;
      catcher.Catch();
   }
}

Ainsi, les cals qui instanment CatchService peuvent effectuer les opérations suivantes:

CatchService catchService = new CatchService(new CatcherA());

ou

CatchService catchService = new CatchService(new CatcherB());

Cela signifie que le service Catch n'est pas étroitement couplé à CatcherA ou CatcherB.

Il existe plusieurs autres stratégies pour coupler de manière lâche des services comme celui-ci, comme l'utilisation d'un framework IoC, etc.

Owen
la source
1
J'aime cet exemple mieux que les autres, car ce genre de chose se produit dans le monde des affaires au jour le jour. Si Class Person s'exécute, Class Cat s'exécute, Class Dog s'exécute, etc. Ce serait un énorme programme pour détailler toutes ces classes qui s'exécutent. Mais l'utilisation d'une interface appelée runs, où chaque classe fait la même chose, rend votre programme beaucoup plus flexible et gérable. :)
sksallaj
Très bien expliqué monsieur, juste pour clarifier dans le dernier exemple vous l'avez fait avec l'injection de dépendance, et le premier exemple est également faiblement couplé?
Ali Sajid
Wow, vieille réponse commentée :). Donc la réponse est non, le premier exemple a une forte dépendance sur CatcherA, donc ils sont fortement couplés
Owen
23

Vous pouvez penser au couplage (serré ou lâche) comme étant littéralement la quantité d'effort qu'il vous faudrait pour séparer une classe particulière de sa dépendance à une autre classe. Par exemple, si chaque méthode de votre classe avait un petit bloc final en bas où vous avez appelé Log4Net pour enregistrer quelque chose, alors vous diriez que votre classe était étroitement couplée à Log4Net. Si votre classe contenait à la place une méthode privée nommée LogSomething qui était le seul endroit qui appelait le composant Log4Net (et les autres méthodes toutes appelées LogSomething à la place), alors vous diriez que votre classe était vaguement couplée à Log4Net (car cela ne prendrait pas beaucoup effort pour retirer Log4Net et le remplacer par autre chose).

MusiGenesis
la source
1
Donc, "faiblement couplé" signifie en fait moins de dépendances? Ai-je raison?
user314362
4
Ce n'est pas vraiment lié au nombre total de dépendances d'une classe particulière. Le couplage (serré ou lâche) est en fait une propriété de la relation entre deux classes. Ainsi, vous pourriez avoir une classe qui est faiblement couplée à 100 autres classes, ou une autre classe qui est étroitement couplée à seulement 2 autres classes (par exemple).
MusiGenesis
2
Mauvais exemple, je dirais: ce que vous avez, c'est une duplication de code, pas un couplage étroit. Et avec un bon outil de refactoring, une telle duplication pourrait être éliminée en quelques secondes.
Rogério
@Rogerio: ce n'est probablement pas le meilleur exemple. J'aime 64BitBobmieux la réponse de moi-même.
MusiGenesis
12

Définition

Essentiellement, le couplage est la mesure dans laquelle un objet donné ou un ensemble d'objets dépend d'un autre objet ou d'un autre ensemble d'objets pour accomplir sa tâche.

Couplage élevé

Pensez à une voiture. Pour que le moteur démarre, une clé doit être insérée dans le contact, tournée, de l'essence doit être présente, une étincelle doit se produire, les pistons doivent tirer et le moteur doit prendre vie. On pourrait dire qu'un moteur de voiture est fortement couplé à plusieurs autres objets. C'est un couplage élevé, mais ce n'est pas vraiment une mauvaise chose.

Couplage lâche

Pensez à un contrôle utilisateur pour une page Web qui est chargé d'autoriser les utilisateurs à publier, modifier et afficher certains types d'informations. Le contrôle unique peut être utilisé pour permettre à un utilisateur de publier une nouvelle information ou de modifier une nouvelle information. Le contrôle doit pouvoir être partagé entre deux chemins différents - nouveau et édition. Si le contrôle est écrit de telle manière qu'il a besoin d'un type de données provenant des pages qui le contiendront, alors vous pourriez dire qu'il est trop fortement couplé. Le contrôle ne doit pas avoir besoin de quoi que ce soit de sa page conteneur.

À M
la source
7

C'est un concept assez général, donc les exemples de code ne donneront pas une vue d'ensemble.

Un gars ici au travail m'a dit: "Les motifs sont comme des fractales, vous pouvez les voir lorsque vous zoomez très près et lorsque vous effectuez un zoom arrière au niveau de l'architecture."

La lecture de la brève page wikipedia peut vous donner une idée de cette généralité:

http://en.wikipedia.org/wiki/Loose_coupling

En ce qui concerne un exemple de code spécifique ...

Voici un couplage lâche avec lequel j'ai travaillé récemment, du truc Microsoft.Practices.CompositeUI.

    [ServiceDependency]
    public ICustomizableGridService CustomizableGridService
    {
        protected get { return _customizableGridService; }
        set { _customizableGridService = value; }
    }

Ce code déclare que cette classe a une dépendance sur un CustomizableGridService. Au lieu de simplement référencer directement l'implémentation exacte du service, il indique simplement qu'il nécessite une implémentation de ce service. Ensuite, au moment de l'exécution, le système résout cette dépendance.

Si ce n'est pas clair, vous pouvez lire une explication plus détaillée ici:

http://en.wikipedia.org/wiki/Dependency_injection

Imaginez que ABCCustomizableGridService est l'implémentation que j'ai l'intention de connecter ici.

Si je le souhaite, je peux retirer cela et le remplacer par XYZCustomizableGridService ou StubCustomizableGridService sans aucune modification de la classe avec cette dépendance.

Si j'avais directement référencé ABCCustomizableGridService, alors je devrais apporter des modifications à cette / ces référence / s afin de permuter dans une autre implémentation de service.

riz
la source
6

Le couplage concerne les dépendances entre les systèmes, qui peuvent être des modules de code (fonctions, fichiers ou classes), des outils dans un pipeline, des processus serveur-client, etc. Moins les dépendances sont générales, plus elles deviennent "étroitement liées", car changer un système nécessitait de changer les autres systèmes qui en dépendent. La situation idéale est un «couplage lâche» où un système peut être changé et les systèmes qui en dépendent continueront à fonctionner sans modification.

La manière générale d'obtenir un couplage lâche consiste à utiliser des interfaces bien définies. Si l'interaction entre deux systèmes est bien définie et respectée des deux côtés, il devient alors plus facile de modifier un système tout en s'assurant que les conventions ne sont pas rompues. Il arrive généralement en pratique qu'aucune interface bien définie ne soit établie, ce qui entraîne une conception bâclée et un couplage serré.

Quelques exemples:

  • L'application dépend d'une bibliothèque. Sous un couplage étroit, l'application est interrompue sur les nouvelles versions de la bibliothèque. Google pour "DLL Hell".

  • L'application client lit les données d'un serveur. Sous un couplage étroit, les modifications apportées au serveur nécessitent des correctifs côté client.

  • Deux classes interagissent dans une hiérarchie orientée objet. En cas de couplage étroit, les modifications apportées à une classe nécessitent que l'autre classe soit mise à jour pour correspondre.

  • Plusieurs outils de ligne de commande communiquent dans un canal. S'ils sont étroitement couplés, les modifications apportées à la version d'un outil de ligne de commande entraîneront des erreurs dans les outils qui liront sa sortie.

Parappa
la source
5

Le couplage fait référence à la manière dont les classes sont étroitement liées les unes aux autres. Les classes étroitement couplées contiennent un nombre élevé d'interactions et de dépendances.

Les classes faiblement couplées sont le contraire en ce que leurs dépendances les unes des autres sont réduites au minimum et reposent plutôt sur les interfaces publiques bien définies les unes des autres.

Legos, les jouets qui S'AGRAMMENT ensemble seraient considérés comme faiblement couplés parce que vous pouvez simplement assembler les pièces et construire le système que vous voulez. Cependant, un puzzle a des pièces qui sont étroitement couplées. Vous ne pouvez pas prendre une pièce d'un puzzle (système) et l'enclencher dans un puzzle différent, car le système (puzzle) est très dépendant des pièces très spécifiques qui ont été construites spécifiquement pour cette «conception» particulière. Les legos sont construits de manière plus générique afin qu'ils puissent être utilisés dans votre Lego House, ou dans mon Lego Alien Man.

Référence: https://megocode3.wordpress.com/2008/02/14/coupling-and-cohesion/

user1263981
la source
4

Deux composants sont fortement couplés lorsqu'ils dépendent d'une mise en œuvre concrète l'un de l'autre.

Supposons que j'ai ce code quelque part dans une méthode de ma classe:

this.some_object = new SomeObject();

Maintenant, ma classe dépend de SomeObject, et ils sont fortement couplés. D'un autre côté, disons que j'ai une méthode InjectSomeObject:

void InjectSomeObject(ISomeObject so) { // note we require an interface, not concrete implementation
  this.some_object = so;
}

Ensuite, le premier exemple peut simplement utiliser SomeObject injecté. Ceci est utile lors des tests. Avec un fonctionnement normal, vous pouvez utiliser des classes lourdes, utilisant une base de données, utilisant le réseau, etc., tandis que pour les tests réussissant une implémentation légère et simulée. Avec un code étroitement couplé, vous ne pouvez pas faire cela.

Vous pouvez simplifier certaines parties de ce travail en utilisant des conteneurs d'injection de dépendances. Vous pouvez en savoir plus sur DI sur Wikipedia: http://en.wikipedia.org/wiki/Dependency_injection .

Il est parfois facile d'aller trop loin. À un moment donné, vous devez rendre les choses concrètes, sinon votre programme sera moins lisible et compréhensible. Utilisez donc ces techniques principalement à la limite des composants et sachez ce que vous faites. Assurez-vous de profiter d'un couplage desserré. Sinon, vous n'en avez probablement pas besoin à cet endroit. DI peut rendre votre programme plus complexe. Assurez-vous de faire un bon compromis. En d'autres termes, maintenez un bon équilibre. Comme toujours lors de la conception de systèmes. Bonne chance!

Paweł Hajdan
la source
3

Considérez une application Windows avec FormA et FormB. FormA est le formulaire principal et il affiche FormB. Imaginez que FormB ait besoin de renvoyer des données à son parent.

Si vous avez fait ceci:

class FormA 
{
    FormB fb = new FormB( this );

    ...
    fb.Show();
}

class FormB 
{
    FormA parent;

    public FormB( FormA parent )
    {
        this.parent = parent;
    }     
}

FormB est étroitement couplé à FormA. FormB ne peut avoir d'autre parent que celui de type FormA.

Si, en revanche, vous demandez à FormB de publier un événement et que FormA s'abonne à cet événement, alors FormB peut renvoyer les données via cet événement à n'importe quel abonné de cet événement. Dans ce cas, FormB ne sait même pas qu'il répond à son parent; grâce au couplage lâche que l'événement fournit, il parle simplement aux abonnés. Tout type peut désormais être parent de FormA.

rp

rp.
la source
3

En informatique, il y a une autre signification pour "couplage lâche" que personne d'autre n'a publié ici, alors ... Voilà - j'espère que vous me donnerez quelques votes pour que ce ne soit pas perdu au fond du tas! Sûrement le sujet de ma réponse appartient à toute réponse complète à la question ... À savoir:

Le terme "Loose Coupling" est entré pour la première fois dans le calcul comme un terme utilisé comme adjectif concernant l'architecture CPU dans une configuration multi-CPU. Son homologue est «couplage serré». Le couplage lâche se produit lorsque les processeurs ne partagent pas beaucoup de ressources en commun et le couplage serré le fait.

Le terme «système» peut prêter à confusion ici, veuillez donc analyser attentivement la situation.

Habituellement, mais pas toujours, plusieurs processeurs dans une configuration matérielle dans laquelle ils existent dans un système (comme dans des boîtiers "PC" individuels) seraient étroitement couplés. À l'exception de certains systèmes à très haute performance qui ont des sous-systèmes qui partagent en fait la mémoire principale entre les «systèmes», tous les systèmes divisibles sont faiblement couplés.

Les termes Tightly Coupled et Loosely Coupled ont été introduits avant invention des processeurs multi-thread et multi-core, donc ces termes peuvent nécessiter des compagnons pour articuler pleinement la situation actuelle. Et, en effet, aujourd'hui, on peut très bien avoir un système qui englobe les deux types dans un système global. En ce qui concerne les systèmes logiciels actuels, il existe deux architectures communes, une de chaque variété, qui sont suffisamment communes pour qu'elles soient familières.

Premièrement, comme c'était le sujet de la question, quelques exemples de systèmes à couplage lâche:

  • VaxClusters
  • Clusters Linux

En revanche, quelques exemples étroitement couplés:

  • Systèmes d'exploitation SMP (Semetrical-Multi-Processing) - par exemple Fedora 9
  • Processeurs multi-threads
  • Processeurs multicœurs

Dans l'informatique d'aujourd'hui, les exemples des deux fonctionnant dans un seul système global ne sont pas rares. Par exemple, prenez les processeurs Pentium double ou quadricœur modernes exécutant Fedora 9 - ce sont des systèmes informatiques étroitement couplés. Ensuite, combinez plusieurs d'entre eux dans un cluster Linux faiblement couplé et vous avez maintenant un calcul à la fois lâche et étroitement couplé! Oh, le matériel moderne n'est-il pas merveilleux!

Richard T
la source
3

Dans un langage simple, couplé de manière lâche signifie qu'il ne dépend pas d'un autre événement. Il s'exécute indépendamment.

Ravindra Miyani
la source
1
Ce n'est pas vraiment vrai - comme mentionné dans d'autres exemples, il ne s'agit pas tant de savoir s'il existe ou non une relation entre les entités (modules, classes), mais de savoir si elles peuvent être facilement échangées contre d'autres classes mettant en œuvre la même fonctionnalité. par exemple, un ViewModel peut fonctionner avec différents modèles, mais il ne fonctionnera certainement pas sans un
Hayden Crocker
hein, pas très utile
brgs
2

Quelques longues réponses ici. Le principe est cependant très simple. Je soumets la déclaration liminaire de wikipedia :

«Le couplage lâche décrit une relation résiliente entre deux ou plusieurs systèmes ou organisations avec une sorte de relation d'échange.

Chaque extrémité de la transaction rend ses exigences explicites et fait peu d'hypothèses sur l'autre extrémité.

Ben Aston
la source
1
Si c'était si simple, nous n'aurions pas cette discussion.
brgs
2

Je propose un test très simple de couplage de code :

  1. Le morceau A de code est étroitement couplé au morceau B de code s'il existe une modification possible de la pièce B qui forcerait des changements dans la pièce A afin de conserver l'exactitude.

  2. La pièce A de code n'est pas étroitement couplée à la pièce B de code s'il n'y a pas de modification possible de la pièce B qui rendrait nécessaire une modification de la pièce A.

Cela vous aidera à vérifier le degré de couplage entre les morceaux de votre code. pour raisonner à ce sujet, consultez ce billet de blog: http://marekdec.wordpress.com/2012/11/14/loose-coupling-tight-coupling-decoupling-what-is-that-all-about/

Marek déc
la source
2

Lorsque vous créez un objet d'une classe à l'aide de new mot-clé dans une autre classe, vous faites en fait un couplage serré (mauvaise pratique) à la place, vous devez utiliser un couplage lâche, ce qui est une bonne pratique

--- A.java ---

package interface_package.loose_coupling;

public class A {

void display(InterfaceClass obji)
{
    obji.display();
    System.out.println(obji.getVar());
}
}

--- B.java ---

package interface_package.loose_coupling;

public class B implements InterfaceClass{

private String var="variable Interface";

public String getVar() {
    return var;
}

public void setVar(String var) {
    this.var = var;
}

@Override
public void display() {
    // TODO Auto-generated method stub
    System.out.println("Display Method Called");
}
}

--- InterfaceClass ---

package interface_package.loose_coupling;

public interface InterfaceClass {

void display();
String getVar();
}

--- MainClass ---

package interface_package.loose_coupling;

public class MainClass {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    A obja=new A();
    B objb=new B();
    obja.display(objb);     //Calling display of A class with object of B class 

}
}

Explication:

Dans l'exemple ci-dessus, nous avons deux classes A et B

La classe B implémente Interface, c'est-à-dire InterfaceClass.

InterfaceClass définit un contrat pour la classe B car InterfaceClass a des méthodes abstraites de la classe B qui peuvent être accédées par n'importe quelle autre classe, par exemple A.

Dans la classe A, nous avons une méthode d'affichage qui peut exclure un objet de classe qui implémente InterfaceClass (dans notre cas, c'est la classe B). Et sur cet objet, la méthode de la classe A appelle display () et getVar () de la classe B

Dans MainClass, nous avons créé un objet de classe A et B. Et l'appel de la méthode d'affichage de A en passant un objet de classe B, c'est-à-dire objb. La méthode d'affichage de A sera appelée avec un objet de classe B.

Parlons maintenant de couplage lâche. Supposons qu'à l'avenir vous deviez changer le nom de la classe B en ABC, alors vous n'avez pas à changer son nom dans la méthode d'affichage de la classe B, faites simplement l'objet de new (classe ABC) et passez-le à la méthode d'affichage dans MailClass. Vous n'avez rien à changer dans la classe A

réf: http://p3lang.com/2013/06/loose-coupling-example-using-interface/

Abhishek Aggarwal
la source
0

Vous pouvez en savoir plus sur le concept générique de «couplage lâche» .

En bref, c'est une description d'une relation entre deux classes, où chaque classe en sait le moins sur l'autre et chaque classe pourrait potentiellement continuer à fonctionner très bien que l'autre soit présente ou non et sans dépendance sur l'implémentation particulière de l'autre classe.

Franci Penov
la source
-8

Le couplage lâche, en général, consiste en 2 acteurs travaillant indépendamment les uns des autres sur la même charge de travail. Donc, si vous aviez 2 serveurs Web utilisant la même base de données principale, vous diriez que ces serveurs Web sont faiblement couplés. Un couplage serré serait illustré par le fait d'avoir 2 processeurs sur un serveur Web ... ces processeurs sont étroitement couplés.

J'espère que c'est quelque peu utile.

Steve
la source
1
Je vois ce que vous recherchez, mais ce n'est toujours pas un très bon moyen d'expliquer que le couplage étroit se produit lorsque deux `` choses '' sont interdépendantes l'une de l'autre, par rapport à un couplage lâche lorsque deux `` choses '' existent indépendamment - là où une `` chose '' peut être changé sans changements à l'autre `` chose '' ...
Bryan Rehbein
Steve, vous avez tout à fait raison - vous ne méritiez AUCUN des votes négatifs. C'est juste que votre public n'était pas prêt pour votre terminologie et trop de personnes sur ce site ont l'habitude de rejeter ce qu'elles ne comprennent pas ou ce qui ne leur est pas familier. -shrug-
Richard T
Je pense que Steve a raté le point. Un couplage lâche n'implique pas toujours que 2 acteurs travaillent indépendamment sur la même charge de travail.
Rob