iOS 개발의 SOLID 원칙
iOS 개발의 SOLID 원칙
😩 좋습니다. 아마 이 용어를 이미 들었을 것입니다. 하지만 실제로는 무슨 뜻인가요? 언제 사용합니까? 어떻게 사용합니까? 마지막으로 배우기 위해 계속 읽으십시오
우선, SOLID는 소프트웨어 디자인을 보다 이해하기 쉽고 유연하며 유지 관리하기 쉽게 만들기 위한 다섯 가지 디자인 원칙의 니모닉 약어입니다.
모든 튜토리얼에서 나는 SOLID 원칙을 행동으로 보여주고 SOLID를 따르지 않는 코드를 보여줄 것입니다.
자, 가자 😁
S - 단일 책임 원칙
클래스는 변경(존재)해야 하는 한 가지 이유가 있어야 합니다.
신청 팁
💢 단일 책임 원칙이 적용되지 않음
class Handler_NOT_SOLID {
func handle() {
let data = requestDataToAPI()
guard let dataReceive = data else { return }
let array = parse(data: dataReceive)
saveToDB(array: array)
}
private func requestDataToAPI() -> Data?{
// send API request and wait the response
return nil
}
private func parse(data:Data)->[String]?{
// parse the data and create an array
return nil
}
private func saveToDB(array:[String]?){
// save array in a database
}
}
당신은 볼 수 있습니까?
Handler_NOT_SOLID 클래스에는 몇 가지 책임이 있습니다.
👍 단일 책임 원칙 적용
class Handler_SOLID {
let apiHandler: APIHandler
let parseHandler: ParseHandler
let dbHandler: DBHandler
init(apiHandler: APIHandler, parseHandler: ParseHandler, dbHandler: DBHandler) {
self.apiHandler = apiHandler
self.parseHandler = parseHandler
self.dbHandler = dbHandler
}
}
class APIHandler {
func requestDataToAPI() -> Data?{
// send API request and wait the response
return nil
}
}
class ParseHandler {
func parse(data:Data) -> [String]?{
// parse the data and create an array
return nil
}
}
class DBHandler {
func saveToDB(array:[String]?){
// save array in a database
}
}
이제 각 엔터티는 하나의 책임만 가집니다.
O - 개방/폐쇄 원리
소프트웨어 엔터티는 확장에는 열려 있어야 하지만 수정에는 닫혀 있어야 합니다.
신청 팁
💢 NOT Open/Closed 원칙 적용
class Vehicles_NOT_SOLID {
func printData() {
let cars = [
Car_NOT_SOLID(name: "Batmobile", color: "Black"),
Car_NOT_SOLID(name: "SuperCar", color: "Gold"),
Car_NOT_SOLID(name: "FamilyCar", color: "Grey")
]
cars.forEach { car in
print(car.printDetails())
}
let buses = [
Bus_NOT_SOLID(type: "School bus"),
Bus_NOT_SOLID(type: "Minibus"),
Bus_NOT_SOLID(type: "Minicoach")
]
buses.forEach { bus in
print(bus.printDetails())
}
}
}
class Car_NOT_SOLID {
let name:String
let color:String
init(name: String, color: String) {
self.name = name
self.color = color
}
func printDetails() -> String {
return "name : \(name) color :\(color)"
}
}
class Bus_NOT_SOLID {
let type:String
init(type: String) {
self.type = type
}
func printDetails() -> String {
return "bus type : \(type)"
}
}
당신은 볼 수 있습니까?
printData가 다른 유형의 객체를 수신하면 더 많은 규칙을 추가해야 합니다.
새 클래스의 세부 정보도 인쇄할 수 있는 가능성을 추가하려면 새 클래스를 기록할 때마다 printData 구현을 변경해야 합니다.
👍 개방/폐쇄 원칙 적용
protocol Printable {
func printDetails() -> String
}
class Vehicles_SOLID {
func printData() {
let cars:[Printable] = [
Car_SOLID(name: "Batmobile", color: "Black"),
Car_SOLID(name: "SuperCar", color: "Gold"),
Car_SOLID(name: "FamilyCar", color: "Grey"),
Bus_SOLID(type: "School bus"),
Bus_SOLID(type: "Minibus"),
Bus_SOLID(type: "Minicoach")
]
cars.forEach { car in
print(car.printDetails())
}
}
}
class Car_SOLID:Printable {
let name: String
let color: String
init(name: String, color: String) {
self.name = name
self.color = color
}
func printDetails() -> String {
return "name : \(name) color :\(color)"
}
}
class Bus_SOLID: Printable {
let type: String
init(type: String) {
self.type = type
}
func printDetails() -> String {
return "bus type : \(type)"
}
}
printData의 동작을 변경할 필요가 없습니다. printData와 클래스 사이에 레이어를 만들기만 하면 됩니다.
L - Liskov 대체 원리
개체는 해당 프로그램의 정확성을 변경하지 않고 하위 유형의 인스턴스로 교체할 수 있어야 합니다.
신청 팁
💢 NOT Liskov 대체 원칙 적용
class Rectangle_NOT_SOLID {
var width: Double = 0
var height: Double = 0
var area: Double {
return width * height
}
}
class Square_NOT_SOLID: Rectangle_NOT_SOLID {
override var width: Double {
didSet {
height = width
}
}
}
// MARK: - Implementations
func printArea(of rectangle: Rectangle_NOT_SOLID) {
rectangle.width = 10
rectangle.height = 4
print(rectangle.area)
}
let rect = Rectangle_NOT_SOLID()
printArea(of: rect) // 40
let square = Square_NOT_SOLID()
printArea(of: square ) // 40
printArea(of rectangle:Rectangle_NOT_SOLID)가 각 클래스의 특정 값을 반환하는 대신 다른 유형으로 동일한 결과를 반환하는지 확인합니다.
👍 리스코프 대체 원칙 적용
protocol Polygon {
var area :Double { get }
}
class Rectangle_SOLID: Polygon {
let width:Double
let height:Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
var area: Double {
return width * height
}
}
class Square_SOLID: Polygon {
let side:Double
init(side: Double) {
self.side = side
}
var area: Double {
return pow(side, 2)
}
}
/// MARK: - Implementations
func printArea(of polygon:Polygon){
print(polygon.area)
}
let rect = Rectangle_SOLID(width: 10, height: 40)
printArea(of: rect) // 400.0
let square = Square_SOLID(side: 10)
printArea(of: square) // 100.0
I - 인터페이스 분리 원리
(M)모든 클라이언트별 인터페이스가 하나의 범용 인터페이스보다 낫습니다.
신청 팁
💢 NOT 인터페이스 분리 원칙 적용
//MARK:- Fat Interface (Protocol)
protocol GestureProtocol {
func didTap()
func didLongPress()
func didSwipe()
}
class RichButton_NOT_SOLID: GestureProtocol {
func didTap() {
print("tap button")
}
func didLongPress() {
print("long press")
}
func didSwipe() {
print("swipe")
}
}
class PoorButton_NOT_SOLID: GestureProtocol {
func didTap() {
print("tap")
}
func didLongPress() {}
func didSwipe() {}
}
PoorButton_NOT_SOLID 클래스에 사용할 수 없는 메서드가 있는지 확인합니다.
👍 인터페이스 분리 원칙 적용
protocol TapGesture {
func didTap()
}
protocol LongPressGesture {
func didLongPress()
}
protocol SwipeGesture {
func didSwipe()
}
class RichButton_SOLID: TapGesture, LongPressGesture, SwipeGesture{
func didTap() {
print("tap button")
}
func didLongPress() {
print("long press")
}
func didSwipe() {
print("swipe")
}
}
class PoorButton_SOLID: TapGesture {
func didTap() {
print("tap button")
}
}
이제 불필요한 메서드를 모두 제거합니다.
D - 종속성 역전 원칙
고수준 모듈은 저수준 모듈에 의존해서는 안 됩니다. 둘 다 추상화에 의존해야 합니다.
신청 팁
💢 종속성 반전 원칙이 적용되지 않음
class SaveData_NOT_SOLID {
let filesSystemManager = FilesSystemManager_NOT_SOLID()
func handle(data:String){
filesSystemManager.save(data: data)
}
}
class FilesSystemManager_NOT_SOLID {
func save(data:String){
// save data
}
}
이것으로 데이터를 저장하는 방법이 있습니다. 데이터베이스를 사용하려면?
👍 종속성 역전 원칙 적용
protocol Storage {
func save(data:Any)
}
class SaveData_SOLID {
let storage:Storage
init(storage: Storage) {
self.storage = storage
}
func handle(data: Any){
self.storage.save(data: data)
}
}
class FilesSystemManager_SOLID: Storage {
func save(data: Any) {}
}
class MySQLDataBase: Storage {
func save(data: Any) {}
}
이제 모든 저장 방법을 사용할 수 있습니다.
👊 읽어주셔서 감사합니다!! SOLID에 대한 모든 원칙과 더 나은 소프트웨어를 구축하기 위해 매일 적용하는 방법을 이해하셨기를 바랍니다. 의심스러운 점이 있으면 아래에 의견을 남겨 주시면 도와 드리겠습니다.
Github Project
Reference
이 문제에 관하여(iOS 개발의 SOLID 원칙), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mkilmer/solid-principles-in-ios-development-5cie텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)