Loose coupling

Last updated

In computing and systems design, a loosely coupled system is one

Contents

  1. in which components are weakly associated (have breakable relationships) with each other, and thus changes in one component least affect existence or performance of another component.
  2. in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services. [1] Loose coupling is the opposite of tight coupling.

Advantages and disadvantages

Components in a loosely coupled system can be replaced with alternative implementations that provide the same services. Components in a loosely coupled system are less constrained to the same platform, language, operating system, or build environment.

If systems are decoupled in time, it is difficult to also provide transactional integrity; additional coordination protocols are required. Data replication across different systems provides loose coupling (in availability), but creates issues in maintaining consistency (data synchronization).

In integration

Loose coupling in broader distributed system design is achieved by the use of transactions, queues provided by message-oriented middleware, and interoperability standards. [2]

Four types of autonomy, which promote loose coupling, are: reference autonomy , time autonomy, format autonomy, and platform autonomy. [3]

Loose coupling is an architectural principle and design goal in service-oriented architectures. Eleven forms of loose coupling and their tight coupling counterparts are listed in: [4]

Enterprise Service Bus (ESB) middleware was invented to achieve loose coupling in multiple dimensions. [5] However, overengineered and mispositioned ESBs can also have the contrary effect and create undesired tight coupling and a central architectural hotspot.

Event-driven architecture also aims at promoting loose coupling. [6]

Methods for decreasing coupling

Loose coupling of interfaces can be enhanced by publishing data in a standard format (such as XML or JSON).

Loose coupling between program components can be enhanced by using standard data types in parameters. Passing customized data types or objects requires both components to have knowledge of the custom data definition.

Loose coupling of services can be enhanced by reducing the information passed into a service to the key data. For example, a service that sends a letter is most reusable when just the customer identifier is passed and the customer address is obtained within the service. This decouples services because services do not need to be called in a specific order (e.g. GetCustomerAddress, SendLetter).

In programming

Coupling refers to the degree of direct knowledge that one component has of another. Loose coupling in computing is interpreted as encapsulation versus non-encapsulation.

An example of tight coupling is when a dependent class contains a pointer directly to a concrete class which provides the required behavior. The dependency cannot be substituted, or its "signature" changed, without requiring a change to the dependent class. Loose coupling occurs when the dependent class contains a pointer only to an interface, which can then be implemented by one or many concrete classes. This is known as dependency inversion. The dependent class's dependency is to a "contract" specified by the interface; a defined list of methods and/or properties that implementing classes must provide. Any class that implements the interface can thus satisfy the dependency of a dependent class without having to change the class. This allows for extensibility in software design. A new class implementing an interface can be written to replace a current dependency in some or all situations, without requiring a change to the dependent class; the new and old classes can be interchanged freely. Strong coupling does not allow this.

This is a UML diagram illustrating an example of loose coupling between a dependent class and a set of concrete classes, which provide the required behavior:

Loose Coupling Example.JPG

For comparison, this diagram illustrates the alternative design with strong coupling between the dependent class and a provider:

Strong Coupling Example.JPG

Other forms

Computer programming languages having notions of either functions as the core module (see Functional programming) or functions as objects provide excellent examples of loosely coupled programming. Functional languages have patterns of Continuations, Closure, or generators. See Clojure and Lisp as examples of functional programming languages. Object-oriented languages like Smalltalk and Ruby have code blocks, whereas Eiffel has agents. The basic idea is to objectify (encapsulate as an object) a function independent of any other enclosing concept (e.g. decoupling an object function from any direct knowledge of the enclosing object). See First-class function for further insight into functions as objects, which qualifies as one form of first-class function.

For example, in an object-oriented language, when a function of an object is referenced as an object (freeing it from having any knowledge of its enclosing host object) the new function object can be passed, stored, and called at a later time. Recipient objects (to whom these functional objects are given) can safely execute (call) the contained function at their own convenience without any direct knowledge of the enclosing host object. In this way, a program can execute chains or groups of functional objects, while safely decoupled from having any direct reference to the enclosing host object.

Phone numbers are an excellent analog and can easily illustrate the degree of this decoupling.

For example, some entity provides another with a phone number to get a particular job done. When the number is called, the calling entity is effectively saying, "Please do this job for me." The decoupling or loose coupling is immediately apparent. The entity receiving the number may have no knowledge of where the number came from (e.g. a reference to the supplier of the number). On the other side, the caller is decoupled from specific knowledge of who they are calling, where they are, and knowing how the receiver of the call operates internally.

Carrying the example a step further, the caller might say to the receiver of the call, "Please do this job for me. Call me back at this number when you are finished." The 'number' being offered to the receiver is referred to as a "Call-back". Again, the loose coupling or decoupled nature of this functional object is apparent. The receiver of the call-back is unaware of what or who is being called. It only knows that it can make the call and decides for itself when to call. In reality, the call-back may not even be to the one who provided the call-back in the first place. This level of indirection is what makes function objects an excellent technology for achieving loosely coupled programs.

Communication between loosely coupled components may be based on a flora of mechanisms, like the mentioned asynchronous communication style or the synchronous message passing style [7]

Measuring data element coupling

The degree of the loose coupling can be measured by noting the number of changes in data elements that could occur in the sending or receiving systems and determining if the computers would still continue communicating correctly. These changes include items such as:

  1. Adding new data elements to messages
  2. Changing the order of data elements
  3. Changing the names of data elements
  4. Changing the structures of data elements
  5. Omitting data elements

See also

Related Research Articles

In software engineering, multitier architecture is a client–server architecture in which presentation, application processing and data management functions are physically separated. The most widespread use of multitier architecture is the three-tier architecture.

<i>Design Patterns</i> 1994 software engineering book

Design Patterns: Elements of Reusable Object-Oriented Software (1994) is a software engineering book describing software design patterns. The book was written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, with a foreword by Grady Booch. The book is divided into two parts, with the first two chapters exploring the capabilities and pitfalls of object-oriented programming, and the remaining chapters describing 23 classic software design patterns. The book includes examples in C++ and Smalltalk.

The facade pattern is a software design pattern commonly used in object-oriented programming. Analogous to a façade in architecture, it is an object that serves as a front-facing interface masking more complex underlying or structural code. A facade can:

In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program's running behavior.

In software design and engineering, the observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

The Law of Demeter (LoD) or principle of least knowledge is a design guideline for developing software, particularly object-oriented programs. In its general form, the LoD is a specific case of loose coupling. The guideline was proposed by Ian Holland at Northeastern University towards the end of 1987, and the following three recommendations serve as a succinct summary:

  1. Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
  2. Each unit should only talk to its friends; don't talk to strangers.
  3. Only talk to your immediate friends.

Message-oriented middleware (MOM) is software or hardware infrastructure supporting sending and receiving messages between distributed systems. MOM allows application modules to be distributed over heterogeneous platforms and reduces the complexity of developing applications that span multiple operating systems and network protocols. The middleware creates a distributed communications layer that insulates the application developer from the details of the various operating systems and network interfaces. APIs that extend across diverse platforms and networks are typically provided by MOM.

GNOWSYS is a specification for a generic distributed network based memory/knowledge management. It is developed as an application for developing and maintaining semantic web content. It is written in Python. It is implemented as a Django app. The GNOWSYS project was launched by Nagarjuna G. in 2001, while he was working at Homi Bhabha Centre for Science Education (HBCSE).

In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information. The exchange can be between software, computer hardware, peripheral devices, humans, and combinations of these. Some computer hardware devices, such as a touchscreen, can both send and receive data through the interface, while others such as a mouse or microphone may only provide an interface to send data to a given system.

In software engineering, service-oriented architecture (SOA) is an architectural style that focuses on discrete services instead of a monolithic design. SOA is a good choice for system integration. By consequence, it is also applied in the field of software design where services are provided to the other components by application components, through a communication protocol over a network. A service is a discrete unit of functionality that can be accessed remotely and acted upon and updated independently, such as retrieving a credit card statement online. SOA is also intended to be independent of vendors, products and technologies.

Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.

In computer science, message passing is a technique for invoking behavior on a computer. The invoking program sends a message to a process and relies on that process and its supporting infrastructure to then select and run some appropriate code. Message passing differs from conventional programming where a process, subroutine, or function is directly invoked by name. Message passing is key to some models of concurrency and object-oriented programming.

<span class="mw-page-title-main">Coupling (computer programming)</span> Degree of interdependence between software modules

In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.

<span class="mw-page-title-main">Dependency injection</span> Software programming technique

In software engineering, dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally. Dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs. The pattern ensures that an object or function that wants to use a given service should not have to know how to construct those services. Instead, the receiving 'client' is provided with its dependencies by external code, which it is not aware of. Dependency injection makes implicit dependencies explicit and helps solve the following problems:

In software engineering, inversion of control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework. The term "inversion" is historical: a software architecture with this design "inverts" control as compared to procedural programming. In procedural programming, a program's custom code calls reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls the custom code.

In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupled software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. The principle states:

Event-driven architecture (EDA) is a software architecture paradigm concerning the production and detection of events.

The Spring Framework is an application framework and inversion of control container for the Java platform. The framework's core features can be used by any Java application, but there are extensions for building web applications on top of the Java EE platform. The framework does not impose any specific programming model.. The framework has become popular in the Java community as an addition to the Enterprise JavaBeans (EJB) model. The Spring Framework is free and open source software.

Object-oriented design (OOD) is the process of planning a system of interacting objects to solve a software problem. It is a method for software design. By defining classes and their functionality for their children, each object can run the same implementation of the class with its state.

The hexagonal architecture, or ports and adapters architecture, is an architectural pattern used in software design. It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. This makes components exchangeable at any level and facilitates test automation.

References

  1. Loosely Coupled: The Missing Pieces of Web Services by Doug Kaye
  2. Pautasso C., Wilde E., Why is the Web Loosely Coupled? Archived 2021-10-12 at the Wayback Machine , Proc. of WWW 2009
  3. F. Leymann Loose Coupling and Architectural Implications Archived 2016-10-02 at the Wayback Machine , ESOCC 2016 keynote
  4. N. Josuttis, SOA in Practice. O'Reilly, 2007, ISBN   978-0-596-52955-0.
  5. M. Keen et al, Patterns: Implementing an SOA using an Enterprise Service Bus, IBM, 2004
  6. How EDA extends SOA and why it is important Jack van Hoof
  7. Mielle, Grégoire. "Microservices patterns: synchronous vs asynchronous communication". Microservices patterns: synchronous vs asynchronous communication. greeeg. Retrieved 18 February 2022.