Divide and conquer manages complexity by separating a problem into smaller, more independently tractable parts. In software design, this means separating interfaces from implementations so clients depend on stable abstractions rather than internal details. section 1.3.2
Apply the approach through several related design moves:
- Define an API as a contract for operations, inputs, outputs, and types, independent of implementation. section 1.3.2
- Hide replaceable implementations behind interfaces, allowing client code to remain unchanged. section 1.3.2
- Divide applications into architectural layers and error domains, giving each error domain an appropriate handling strategy. section 13.3
- Use low coupling and high cohesion to keep complexity manageable across object-oriented and functional designs. section 1.6
Adapting a thermometer interface
A high-accuracy thermometer exposes Kelvin readings but cannot implement an ISensor interface expecting Celsius. HAThermometerAdapter converts the reading and supplies the expected sensor methods, isolating the mismatch from client code. section 1.4.2
Listing 1.4 Interfaces and inversion of control
final class Receiver extends IConnection { #1
def send(dataType: String, name: String, data: Float) =
server.connection.send(dataType, name, data)
}
final class Thermometer extends ISensor { #2
val correction = -12.5f #3
def transform(data: native.core.Temperature) : Float =
toCelsius(data) + correction
def getName() : String = "T-201A" #4
def getDataType() : String = "temperature"
def getData() : Float = {
val data = native.core.thermometer.getData()
transform(data)
}
}
object Worker { #5
def observeThermometerData() {
val t = new Thermometer()
val r = new Receiver()
val observer = new Observer(t, r) #6
observer.readAndSendData()
}
}
Trace how ISensor, Receiver, Thermometer, and Observer separate sensing, transmission, and coordination responsibilities. section 1.3.2


