Raja's Exocortex

Cohesion, Coupling and Composition

Definitions

Cohesion and coupling are two key software design concepts that measure the quality of a system design. Good system design aims for high cohesion and loose coupling. Further, the different components of a system must communicate with each other using clearly defined or industry standard interfaces.

Composition is the mechanism or ease with with different system modules are assembled together. Modules can be composed statically or dynamically.

Cohesion

Cohesion measures the degree to which elements within a single module or component are dependent upon each other and serve a single purpose or function.

Coupling

Coupling refers to the degree of interdependence between software modules. High coupling means that modules are closely connected and changes in one module may affect other modules. Loose coupling means that modules are independent and changes in one module have little impact on other modules.

# Why Loose Coupling is Good

                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚ Limit change radius โ”‚      โ”‚ Higher agility      โ”‚      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚             โ”œโ”€โ”€โ”€โ”€โ”€โ–บโ”‚ (design-time)       โ”œโ”€โ”€โ”€โ”€โ”€โ–บโ”‚ and veolcity        โ”œโ”€โ”€โ”€โ”€โ”€โ–บโ”‚            โ”‚
โ”‚   Loose     โ”‚      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚ Cost and   โ”‚
โ”‚  Coupling   โ”‚      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚ Complexity โ”‚
โ”‚             โ”œโ”€โ”€โ”€โ”€โ”€โ–บโ”‚ Limit error radius  โ”œโ”€โ”€โ”€โ”€โ”€โ–บโ”‚ Reliable, tolerable โ”œโ”€โ”€โ”€โ”€โ”€โ–บโ”‚            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚ (run-time)          โ”‚      โ”‚ operations          โ”‚      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Coupling can occur over many dimensions and facets. A system can never be entirely decoupled, some degree of coupling at various levels must be tolerated. The appropriate level of (design-time) coupling depends on the level of control you have over the endpoints .However, the interfaces between the endpoints must be clearly defined.

Coupling Facets Examples
Technology dependency Java vs C++
Location dependency IP address, DNS
Data format dependency Binary, XML, JSON, Protobuf, etc
Data type dependency int16/int32, string/UTF-8, Null/empty, etc
Semantic dependency Name, Middlename, ZIP
Temporal dependency sync, async, pub/sub
Interaction style dependency messsaging, RPC, GraphQL
Conversation dependency pagination, caching, retries

Components of a Software Application

Software applications are typically composed of three different components or layers:

1. Application Environment

This includes all the dependencies for the actual application code - the user space environment, runtime and the external libraries required by the actual application code. I.e. all the support code required to run the actual application.

2. Application Code

This is the actual application itself, either in source or binary form. The runtime and external library dependencies are already provided by the previous component.

This also includes any configuration required to locate dependent services like DB, SMTP gateway, etc.

3. Application Data

This is the data managed by the application in databases, files or external storage services like an S3 object storage bucket.

Examples

1. App Environment 2. App Code 3. Data
Tomcat, Java JRE app.jar Oracle DB and local files
Python interpreter, python modules app.py Postgres DB and local files
Apache, PHP, PHP libraries index.php MySQL DB and uploaded files
Nginx, .NetCore runtime app.exe MS SQL Server and S3 object storage
Distroless golangapp.exe ClickHouse DB

Cohesion and Coupling using Docker

Docker offers an excellent mechanism for architecting systems that follow the cohesion, coupling and composition best practices.

1. Application Environment

Package the application runtime and libraries into a docker container. Do NOT package the application code into the container, that will be bind mounted from the docker host.

PHP

  1. user space components (ubuntu-minimal)
  2. install apache, php and common php libraries (php-mysql, etc)

Java

  1. user space components (ubuntu-minimal)
  2. install tomcat, JRE

.NetCore

  1. user space components (ubuntu-minimal) or distroless
  2. install dotnetcore runtime

2. Application Code

Inject the application code into the runtime component by bind mounting the code from the docker host into the running container instance. This creates a isolated "VM like" environment for the code to run. Different runtime versions can be run on the same docker host with full isolation.

As a security best practice, the application code can be mounted into the container without write access. As docker containers are ephemeral and do not save state when removed, recovering a compromised container involves simply stopping/deleting the container and starting a new one in its place (docker-compose down; docker-compose up -d).

3. Application Data

Similar to application code, the data files required for the application can stored on the docker host and bind mounted inside the container at runtime. External services like databases can be run as separate containers within a single docker-compose file or on external systems.

Complete Example - Deploying WordPress

WordPress requires

  1. A minimal userland, Apache web server with mod-PHP and a list of PHP libraries. The php-apache-ubuntu container provides all these components.
  2. The actual WordPress application with modules and themes. These files are bind mounted from the docker host into the container in /var/www/html.
  3. A location to store file the media library either in an uploads folder, or external S3 compatible storage. The uploads folder wp-content is part of the /var/www/html mount.
  4. Supported database server like MySQL/MariaDB. The DB can be provided as an additional service in the same docker-compose or run as a separate docker service on the host.

Example WordPress docker-compose.yaml

# Filename: /src/example.com/docker-compose.yml
# WordPress website for example.com

version: "2.4"

name: example.com

services:
  example-com:
    image: rsubr/php-apache-ubuntu:jammy
    container_name: example.com
    restart: always

	environment:
      - WORDPRESS_DB_HOST=${WORDPRESS_DB_HOST}
      - WORDPRESS_DB_USER=${WORDPRESS_DB_USER}
      - WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
      - WORDPRESS_DB_NAME=${WORDPRESS_DB_NAME}

    volumes:
      - ./www:/var/www/html

	labels:
      - com.centurylinklabs.watchtower.enable=true
      - traefik.enable=true
      - traefik.http.routers.example-com.rule=Host(`example.com`, `www.example.com`)
      - traefik.http.routers.example-com.tls=true
      - traefik.http.routers.example-com.tls.certresolver=lets-encrypt

References