You are on page 1of 23

Partitioning and Layering Fundamentals

The Basic Problem


Change is a fact of life Requirements Technologies Bug Fixes Software Must Adapt

Solution: Software Layers


Reduce software coupling Minimize the consequences of change Focused Unit Tests to verify change Example of Code Refactoring

Fundamental Concepts
Difference between a type and an object Complex type Composition Interface

Type
class Employee { string name; void Pay() . }
Simple Type Complex Type

Data

Behavior

Object

Employee emp = new Employee();

Object Composition
class Auto { Engine engine; Wheel[4] wheels; void Drive() {}; }

Object composition introduces dependencies


class Engine { string manufacturer; int horsepower; void Start(){}; void Stop(){}; } class Wheel { string manufacturer; float tirePressure; void Turn(){}; }

Write your applications so that the dependencies of one type on another are eliminated or minimized.

Make types dependent on type's behavior, not its implementation.

Unit tests verify that a type's behavior is correct.

Interfaces
Interfaces describe behavior, not implementation
interface IEngine { void Start(); void Stop(); } interface IWheel { void Turn(); }

Rewritten Engine, Wheel Classes


class Engine : IEngine { string manufacturer; int horsepower; void Start () {} void Stop() {} } class Wheel : IWheel { string manufacturer float tirePressure; void Turn(); }

Interface Composition
class Auto { IEngine engine; IWheel[4] wheels; void Drive() {} }

Interfaces Hide Implementation


class Diesel: IEngine { string manufacturer; int horsepower; void Start () {} void Stop() {} } } class WankelEngine : IEngine { string manufacturer; int rotationSpeed; void Start () {} void Stop() {}

Coupling
Preserve Essential Coupling
Essential Semantics

Remove Inessential Coupling


Programming Artifacts

Electrical Analogy
Wall socket interface removes the inessential coupling due to the physical shape of plugs and appliances An interface cannot remove the essential behavioral coupling of voltage and amperage of standard current

Complexity vs. Flexibility


Interfaces add a level of indirection Put interfaces along application fault lines Hard to refactor out of a bad design

Interfaces vs. Inheritance


Favor interface over object composition Interface Composition vs. Inheritance?
class RacingCar : HighPerformanceCar : Auto

Static Definition Need to Understand Base Class Behavior

"Inheritance Breaks Encapsulation"


class HighPerformanceCar { virtual void Start() { TurnIgnition(); Press GasPedal(); } } class RacingCar : HighPerformanceCar { }

Interfaces
Avoid Inheriting Implementation Restrict Inessential Coupling Make Interfaces Easy to Modify

Design Patterns
Minimize Dependencies in Implementation Use Design Patterns Electrical Analogy Design to work with 110 or 220 volts? Use Transformer Pattern Flexibility even with Essential Coupling

Summary
Reduce coupling and dependencies of complex types Use Interface Based Design Use Composition rather than Implementation Inheritance Write unit tests to validate behavior

You might also like