Structure Oriented Programming VS Protocol Oriented Programming in Swift

Boris Bugor
ITNEXT
Published in
3 min readNov 5, 2023

--

Photo by Mathew Schwartz on Unsplash

In this article we will look at the main aspects of structure-oriented programming: how to write code according to the SOLID principles without using protocols and without losing abstraction.

The Structure Oriented Programming is a paradigm based on the fact that any protocol can be replaced by a structure.

The advantages of this approach is performance.
Since the structure-oriented approach is based on structures that use static dispatch, the dispatch speed will be significantly different from protocols with dynamic dispatch in the protocol-oriented approach.

1. Replacing a protocol with an equivalent structure

Let’s start by trying to replace the protocol with an equivalent structure.

In a protocol-oriented approach, the protocol itself allows abstraction from the implementation.

In the structure-oriented approach, generics and closures help to provide abstraction.

Consider, as an example, the composition of a protocol and a class, in which the protocol provides the square of a number for any object that will conform to this protocol:

// Abstraction
protocol RegularProtocol {
var sqrValue: Int { get }
}

// Object
class RegularClass {

let value: Int

init(value: Int) {
self.value = value
}
}

// Realization
extension RegularClass: RegularProtocol {
var sqrValue: Int {
value * value
}
}

let onbject = RegularClass(value: 25)
print(onbject.sqrValue)

Thus, the extension to the protocol adopt RegularProtocol.

For a structure-oriented approach, the above would look like this:

// Abstraction
struct RegularStruct<AdoptedObject> {
var sqrValue: (AdoptedObject) -> Int

init(sqrValue: @escaping (AdoptedObject) -> Int) {
self.sqrValue = sqrValue
}
}

// Object
class RegularClass {

let value: Int

init(value: Int) {
self.value = value
}
}

// Realization
extension RegularStruct where AdoptedObject == RegularClass {
init() {
sqrValue = { object in object.value * object.value }
}
}

let onbject = RegularStruct<RegularClass>()
print(onbject.sqrValue(.init(value: 25)))

2. Covering all kinds of cases

To understand how to use structure-oriented approach in practice, let’s consider the most likely cases of using the protocol:

  1. Computed property
  2. Property with getter and setter
  3. Static property
  4. Regular method
  5. Static function
  6. Function with associated value
  7. Parent protocol function when inheriting protocols

For protocol-oriented approach all these cases are presented below:

protocol ProtocolExample: ParentProtocolExpample {
// 1
var getVariable: Int { get }

// 2
var getSetVariable: Int { get set }

// 3
static var staticVariable: Int { get }

// 4
func regularFunction(value: Int) -> Bool

// 5
static func staticFunction(value: Int) -> Bool

// 6
associatedtype Value
func assosiatedFunction(value: Value) -> Bool
}

protocol ParentProtocolExample {
// 7
func inheritedFunction() -> String
}

An equivalent composition for a structure-oriented approach looks like this:

struct StructExample<AdoptedObject, Value> {
// 1
var getVariable: (_ object: AdoptedObject) -> Int

// 2
var setVariable: (_ object: AdoptedObject, Int) -> Void

// 3
var staticVariable: () -> Int

// 4
var regularFunction: (_ object: AdoptedObject, _ value: Int) -> Bool

// 5
var staticFunction: (_ value: Int) -> Bool

// 6
var assosiatedFunction: (_ object: AdoptedObject, _ value: Value) -> Bool

// 7
var parentStruct: ParentStructExample<AdoptedObject>
var inheritedFunction: () -> String
}

struct ParentStructExample<AdoptedObject> {
var inheritedFunction: () -> String
}

3. Performance benefits

The effect of the implementation was tested with XCTest and the Optimization Level flags — Fastest, Smallest [-Os] and showed that dispatching is 3–4 times faster for the structure-oriented approach.

Protocol-oriented approach:

Structure-oriented approach

Don’t hesitate to contact me on Twitter if you have any questions. Also, you can always buy me a coffee.

--

--

Senior iOS Developer | Co-founder of VideoEditor: Reels & Stories | Founder of Flow: Diary, Calendar, Gallery | #ObjC | #Swift | #UIKit | #SwiftUI