Ответ
Нарушение Принципа единственной ответственности (Single Responsibility Principle - SRP):
Класс ReportGenerator отвечает и за формирование данных отчета, и за их форматирование в HTML, и за отправку по email.
class ReportGenerator {
func fetchData() -> Data { /* ... */ }
func analyzeData(_ data: Data) -> AnalysisResult { /* ... */ }
func createHTMLReport(from result: AnalysisResult) -> String { /* ... */ }
func sendEmail(with html: String, to recipient: String) { /* ... */ }
}
// Нарушение: класс имеет как минимум три причины для изменения:
// 1. Изменение логики получения данных.
// 2. Изменение формата отчета (PDF, CSV).
// 3. Изменение способа доставки (сохранение в файл, push-уведомление).
Исправленная архитектура (соответствует SRP):
class DataFetcher { func fetch() -> Data { /* ... */ } }
class DataAnalyzer { func analyze(_ data: Data) -> AnalysisResult { /* ... */ } }
class HTMLReportBuilder { func build(from result: AnalysisResult) -> String { /* ... */ } }
class EmailSender { func send(content: String, to recipient: String) { /* ... */ } }
// Каждый класс имеет одну, четко определенную ответственность.
Нарушение Принципа открытости/закрытости (Open/Closed Principle - OCP): Код не закрыт для модификаций при добавлении новой функциональности.
class AreaCalculator {
func area(of shape: Any) -> Double {
if let circle = shape as? Circle {
return Double.pi * pow(circle.radius, 2)
} else if let square = shape as? Square {
return pow(square.side, 2)
}
// Добавление нового типа фигуры (Triangle) требует изменения этого метода.
return 0
}
}
Исправление с помощью протокола (соответствует OCP):
protocol Shape {
var area: Double { get }
}
struct Circle: Shape {
let radius: Double
var area: Double { Double.pi * radius * radius }
}
struct Square: Shape {
let side: Double
var area: Double { side * side }
}
// Чтобы добавить Triangle, нужно создать новый тип, соответствующий протоколу Shape.
// Класс AreaCalculator изменять не требуется.
class AreaCalculator {
func totalArea(of shapes: [Shape]) -> Double {
return shapes.reduce(0) { $0 + $1.area }
}
}