Functional Thread 15 : Composition

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Reaction score
405
Location

Composition
Wikipedia
The term composition (from Latin com- "with" and ponere "to place"), in written language, refers to the body of important features established by the author in their creation of literature. Composition relates to narrative works of literature, but also relates to essays, biographies, and other works established in the field of rhetoric.

The goal of this thread will to explore the general term of composition; more specifically, what we mean when we talk about composition in programming. The topic on its surface is not all that concise to quantify both in the general sense, and in programming.

For example:
Composition in programming can refer to a broad range of concepts:
  • "Object composition, association, aggregation and inheritance"
  • "Interface composition"
  • "Function composition"
  • "Binary composition"
  • "Logical composition"
  • "Monoid composition"
  • "Functor composition"
  • "Kleisli composition"
  • "Monadic transformer composition"
  • ...
Target
The thread will be beginner friendly discussion of a diverse range of concepts that are implied when talking about composition in programming.
 
Introduction
The word composition is a concept that can be lathered like a common sauce on a diverse set of seemingly different topics in programming.... So how can one thing appear to have so many different meanings both in application and across paradigms?

Ultimately it's a concept that's derived from mathematics; but we don't need to formally review the math to understand the concept or to be able to draw parallels between a variety of different constructs that are a form of composition.

What is composition?
We can summarise composition as follows:
Construction of a new type that represents the combination of the processing of two other sub types.

Short and sweet; but it doesn't quite do justice to what can be considered as composition; so to clarify it a little more; let's explore some different constructs that fall under the umbrella term of composition.


Category Theory
In category theory a composition is represented by the following arrow graph, where ƒ can be though of as a function that takes a X and transforms it into a Y; similarly g is a function that takes a Y and transforms it into a Z; and finally g . ƒ defines a composition of ƒ and g where the output from function ƒ is fed into function g -- essentially creating a composition function that takes a X and transforms it into a Z.
Composition.png

Composition is however not specifically just limited to the mathematic concept of composition.
 
Last edited:
Object Oriented
In OOP; we often hear the phrase "it's best to favour composition over inheritance" -- so let's explore a little what that means and whether it's the only thing we think about when we reference composition.

Inheritance
In object-oriented programming, inheritance is the mechanism of basing an object or class upon another object (prototype-based inheritance) or class (class-based inheritance), retaining similar implementation.

For examPle:
C#:
  // Inheritance (composition of classes)
  public class Person { }
  public class Employee : Person { } // Inherits the attributes of Person
  public class Plumber : Employee { } // Inherits the attributes of both Employee and Person
Classes and objects created through inheritance are tightly coupled because changing the parent or superclass in an inheritance relationship risks breaking your code.

Note:
Inheritance itself is a process of composition; where the child class is a composition of the attributes of its parent class and its own attributes.


Object Composition
In computer science, object composition is a way to combine objects or data types into more complex ones. Compositions relate to, but are not the same as, data structures, and common ones are the tagged union, set, sequence, and various graph structures, as well as the object used in object-oriented programming.

"it's best to favour composition over inheritance"

C#:
  // Composition (favor over inheritance)
  // Enables dependency injection
  class Contact { }
  class Address { }
  class Customer {
    public Address[] Addresses { get; }
    public Contact[] Contacts { get; }
  }
Classes and objects created through composition are loosely coupled, meaning that you can more easily change the component parts without breaking your code.


Interfaces
It is however not strictly true that composition on its own does enough to avoid tight coupling... because the property composition itself can be considered tight coupling and to avoid that the properties can be composed using defined interfaces.

Meaning that any class conforming to the interface could be interchangeable as the instance for that property -- which is the underlying concept of dependency injection.

Aside from helping to avoid tight coupling with the composition of property types in a class; interfaces themselves can also be compose.
C#:
// Composition of interfaces
  /// Composition of interfaces
  public interface IPlumber { }
  public interface IElectrician { }
  public interface IHandyman : IPlumber, IElectrician { }
The IHandman is a composition of the conformance requirements for both the IPlumber and the IElectrican.

This flexibility is however still not a perfect solution because you end up with an interface whose definition is tightly coupled to the classes that conform to it; meaning you can't change the interface without affecting all the classes that are dependent on it.

The only way to work around this problem prior to C# 8.0 was to create a new interface with the added conformances and then add that as an new conformance requirement to the classes where you needed this.


Default Interface Implementations
With C# 8.0 and default method implementations for interfaces this limitation is upgraded; because you can now add new functionality to existing classes that conform to the interface without the requirement to change all these classes. This is done by adding a default implementation of the methods to the interface, which exposes this new functionality to all dependant objects without the need for code changes. The need for this was derived primarily by C# Xamarin framework; specifically its need to operate in both the Android Java world and the iOS Swift world -- because both of those languages have had support for default interface method implementations.

Side Note:
In Swift, interfaces are called protocols, and a style of programming using default method implementations for interfaces is called Protocol Oriented Programming (POP); a technique that also leans heavily on interface and class extensions; similar to how Linq is implemented.

The equivalent style of programming in C# would probably have to be called Interface Oriented Programming. Java doesn't (yet?) have support for extension methods so it's not (yet?) possible to duplicate this style of code design.

This is an new area of design to be explored in C# since 8.0; to further reduce the tight coupling in OOP design; the combination of both extensions methods and default interface implementations make it possible to extend the functionality of existing classes without the need to modify to adopt the interface conformance changes. It not quite as flexible as Swift (yet?) re extension methods cannot be used interchangeably with default interface methods; and overall whilst this adds flexibility to C#; it still has its limits and most of these are fairly widely discussed in Swift blogs posts about POP.


Inheritance and Interface Composition
We can also mix the composition of both Inheritance and composition using classes and interfaces, for example:
C#:
  // Inheritance (composition??) of classes & interfaces
  // Inheritance (composition??) of classes & interfaces
  class EmployeeA1 : Employee, IPlumber {
    public Address[] Addresses { get; }
    public Contact[] Contacts { get; }
  }

  class EmployeeA2 : Employee, IElectrician {
    public Address[] Addresses { get; }
    public Contact[] Contacts { get; }
  }

  class EmployeeA3 : Employee, IHandyman {
    public Address[] Addresses { get; }
    public Contact[] Contacts { get; }
  }
...and of course all the inheritance could be swapped out for composition and the composition of Classes could be swapped out for Interfaces, etc.


Composition of values
All OOP languages include as part of their standard library the ability to compose values together, for example:
C#:
// Integer composition using the binary + operator
1 + 2 + 3

// String composition using the binary + operator
"the" + "movement" + "of"


Composition of logical conditions
Similarly the ability to create a composition of logical conditions, for example:
C#:
if (person.Name.startWith("A") && person.Sex == Sex.Male)  || (person.Name.startWith("B") && person.Sex == Sex.Female) { }

for (var i = 0; i < 10 && j < 20 ; i++) { }

while (inputChar.isWhiteSpace() && !stream.EOF()) { }


Composition of function / method calls
We can also build up a new process as a composition of function / methods calls, for example:
C#:
 // Composition of function calls
  public static class Circle {
    public static double Area(double radius) {
      return Math.PI * Math.Pow(radius, 2d);
    }
  }
Math.PI is a function that returns the mathematical value for PI and Math.Pow is a function to raise a number to a specified power i.e. squared.

Naturally these composition of functions calls and method calls can be substantially more complexly interwoven -- the ultimate benefit of this style of composition is to simplify the work of a single function / method in order to simplify testing. This style programming is collectively termed the Single Responsibility Principle (SRP).

OOP Summary
That roughly covers what can be thought of as composition from the Object Oriented Programmer's point of view.

Next we'll move onto the functional view of what constitutes composition; many concepts of which have become seamlessly integrated into most modern OOP languages.
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X