SOLID 원칙은 객체 지향 설계의 다섯 가지 기본 원칙을 의미한다. 이 원칙들을 따르면 유지보수 가능하고 확장 가능한 소프트웨어를 설계할 수 있다. 각 원칙을 설명하고 간단한 코드 예제를 포함한다.
클래스는 하나의 책임만 가져야 한다. 즉, 클래스는 하나의 변경 이유만 가져야 한다.
class ReportGenerator {
func generateReport() -> String {
return "Report Content"
}
}
class ReportPrinter {
func printReport(_ report: String) {
print(report)
}
}
// 사용 예
let generator = ReportGenerator()
let report = generator.generateReport()
let printer = ReportPrinter()
printer.printReport(report)
소프트웨어 구성 요소는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.
protocol Shape {
func area() -> Double
}
class Circle: Shape {
var radius: Double
init(radius: Double) {
self.radius = radius
}
func area() -> Double {
return Double.pi * radius * radius
}
}
class Rectangle: Shape {
var width: Double
var height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
func area() -> Double {
return width * height
}
}
func totalArea(shapes: [Shape]) -> Double {
return shapes.reduce(0) { $0 + $1.area() }
}
// 사용 예
let shapes: [Shape] = [Circle(radius: 5), Rectangle(width: 10, height: 5)]
let area = totalArea(shapes: shapes)
print(area)
하위 클래스는 언제나 자신의 상위 클래스로 교체할 수 있어야 한다.
class Bird {
func fly() {
print("Flying")
}
}
class Sparrow: Bird {
}
class Penguin: Bird {
override func fly() {
fatalError("Penguins can't fly")
}
}
// 사용 예
let birds: [Bird] = [Sparrow(), Penguin()]
for bird in birds {
bird.fly()
}
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
protocol Printer {
func printDocument()
}
protocol Scanner {
func scanDocument()
}
class MultiFunctionPrinter: Printer, Scanner {
func printDocument() {
print("Printing document")
}
func scanDocument() {
print("Scanning document")
}
}
class SimplePrinter: Printer {
func printDocument() {
print("Printing document")
}
}
// 사용 예
let devices: [Printer] = [MultiFunctionPrinter(), SimplePrinter()]
for device in devices {
device.printDocument()
}
고수준 모듈은 저수준 모듈에 의존해서는 안 된다. 둘 다 추상화에 의존해야 한다.
protocol Database {
func save(data: String)
}
class MySQLDatabase: Database {
func save(data: String) {
print("Saving data to MySQL database")
}
}
class DataHandler {
private let database: Database
init(database: Database) {
self.database = database
}
func saveData(data: String) {
database.save(data: data)
}
}
// 사용 예
let database = MySQLDatabase()
let handler = DataHandler(database: database)
handler.saveData(data: "Some data")
SOLID 원칙을 따르면 코드의 유연성과 유지보수성이 크게 향상된다. 각 원칙을 이해하고 적용하여 더 나은 객체 지향 설계를 하도록 한다.