Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ochococo/ood-principles-in-swift
๐ The Principles of OOD (SOLID) based on Uncle Bob articles.
https://github.com/ochococo/ood-principles-in-swift
computer-science dependency-inversion-principle interface-segregation-principle liskov-substitution-principle object-oriented ood ood-principles open-closed-principle playground single-responsibility-principle solid swift
Last synced: 25 days ago
JSON representation
๐ The Principles of OOD (SOLID) based on Uncle Bob articles.
- Host: GitHub
- URL: https://github.com/ochococo/ood-principles-in-swift
- Owner: ochococo
- License: gpl-3.0
- Created: 2015-02-25T10:21:33.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2023-11-06T13:51:50.000Z (about 1 year ago)
- Last Synced: 2024-10-14T21:42:10.328Z (25 days ago)
- Topics: computer-science, dependency-inversion-principle, interface-segregation-principle, liskov-substitution-principle, object-oriented, ood, ood-principles, open-closed-principle, playground, single-responsibility-principle, solid, swift
- Language: Swift
- Homepage:
- Size: 207 KB
- Stars: 1,893
- Watchers: 75
- Forks: 157
- Open Issues: 1
-
Metadata Files:
- Readme: README-ko-KR.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
๊ฐ์ฒด์งํฅ ์ค๊ณ ์์น in Swift 5
=========================A short cheat-sheet with Playground ([OOD-Principles-In-Swift-ko-KR.playground.zip](https://raw.githubusercontent.com/ochococo/OOD-Principles-In-Swift/master/OOD-Principles-In-Swift-ko-KR.playground.zip)).
๐ท Project maintained by: [@nsmeme](http://twitter.com/nsmeme) (Oktawian Chojnacki)
๐ฐ๐ท Translated by: [jwonyLee](https://github.com/jwonyLee) (JiWon Lee)
S.O.L.I.D.
==========* [The Single Responsibility Principle (๋จ์ผ ์ฑ ์ ์์น)](#-the-single-responsibility-principle-๋จ์ผ-์ฑ ์-์์น)
* [The Open Closed Principle (๊ฐ๋ฐฉ ํ์ ์์น)](#-the-open-closed-principle-๊ฐ๋ฐฉ-ํ์-์์น)
* [The Liskov Substitution Principle (๋ฆฌ์ค์ฝํ ์นํ ์์น)](#-the-liskov-substitution-principle-๋ฆฌ์ค์ฝํ-์นํ-์์น)
* [The Interface Segregation Principle (์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น)](#-the-interface-segregation-principle-์ธํฐํ์ด์ค-๋ถ๋ฆฌ-์์น)
* [The Dependency Inversion Principle (์์กด๊ด๊ณ ์ญ์ ์์น)](#-the-dependency-inversion-principle-์์กด๊ด๊ณ-์ญ์ -์์น)# ๐ ํด๋์ค์๋ ๋จ ํ ๊ฐ์ง ๋ณ๊ฒฝ ์ด์ ๋ง ์กด์ฌํด์ผ ํ๋ค. ([์์ธํ](https://docs.google.com/open?id=0ByOwmqah_nuGNHEtcU5OekdDMkk))
์์:
```swift
protocol Openable {
mutating func open()
}protocol Closeable {
mutating func close()
}// ๋ฌธ. ์บก์ํ๋ ์ํ๋ฅผ ๊ฐ๊ณ ์์ผ๋ฉฐ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ๋ณ๊ฒฝํ ์ ์๋ค.
struct PodBayDoor: Openable, Closeable {private enum State {
case open
case closed
}private var state: State = .closed
mutating func open() {
state = .open
}mutating func close() {
state = .closed
}
}// ์ฌ๋ ์ผ๋ง ๋ด๋นํ๋ฉฐ ์์ ๋ฌด์์ด ๋ค์ด์๋ ์ง, ์ด๋ป๊ฒ ๋ซ๋ ์ง ๋ชจ๋ฅธ๋ค.
final class DoorOpener {
private var door: Openableinit(door: Openable) {
self.door = door
}func execute() {
door.open()
}
}// ๋ซ๋ ์ผ๋ง ๋ด๋นํ๋ฉฐ ์์ ๋ฌด์์ด ๋ค์ด์๋ ์ง, ์ด๋ป๊ฒ ์ฌ๋ ์ง ๋ชจ๋ฅธ๋ค.
final class DoorCloser {
private var door: Closeableinit(door: Closeable) {
self.door = door
}func execute() {
door.close()
}
}let door = PodBayDoor()
// โ ๏ธ `DoorOpeneer`๋ง์ด ๋ฌธ์ ์ฌ๋ ์ฑ ์์ด ์๋ค.
let doorOpener = DoorOpener(door: door)
doorOpener.execute()// โ ๏ธ ๋ฌธ์ ๋ซ์ ํ ๋ค๋ฅธ ์์ ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ,
// ์๋์ ์ผ๋ ๊ฒ์ฒ๋ผ `DoorOpener` ํด๋์ค๋ฅผ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค.
let doorCloser = DoorCloser(door: door)
doorCloser.execute()```
# โ The Open Closed Principle (๊ฐ๋ฐฉ ํ์ ์์น)
ํด๋์ค์ ๋์์ ์์ ํ์ง ์๊ณ , ํ์ฅํ ์ ์์ด์ผ ํ๋ค. ([์์ธํ](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgN2M5MTkwM2EtNWFkZC00ZTI3LWFjZTUtNTFhZGZiYmUzODc1&hl=en))
์์:
```swiftprotocol Shooting {
func shoot() -> String
}// ๋ ์ด์ ๋น. ์ ์ ์๋ค.
final class LaserBeam: Shooting {
func shoot() -> String {
return "Ziiiiiip!"
}
}// ๋ฌด๊ธฐ๊ฐ ์๊ณ ๋ชจ๋ ๊ฑธ ํ ๋ฒ์ ๋ฐ์ฌํ ์ ์๋ค๊ณ ๋ฏฟ๋๋ค. ๋นต์ผ! ๋นต์ผ! ๋นต์ผ!
final class WeaponsComposite {let weapons: [Shooting]
init(weapons: [Shooting]) {
self.weapons = weapons
}func shoot() -> [String] {
return weapons.map { $0.shoot() }
}
}let laser = LaserBeam()
var weapons = WeaponsComposite(weapons: [laser])weapons.shoot()
// ๋ก์ผ ๋ฐ์ฒ. ๋ก์ผ์ ์ ์ ์๋ค.
// โ ๏ธ ๋ก์ผ ๋ฐ์ฒ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด ๊ธฐ์กด ํด๋์ค์์ ์๋ฌด๊ฒ๋ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค.
final class RocketLauncher: Shooting {
func shoot() -> String {
return "Whoosh!"
}
}let rocket = RocketLauncher()
weapons = WeaponsComposite(weapons: [laser, rocket])
weapons.shoot()```
# ๐ฅ The Liskov Substitution Principle (๋ฆฌ์ค์ฝํ ์นํ ์์น)
ํ์๋ ํด๋์ค๋ ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ๋์ฒดํ ์ ์์ด์ผ ํ๋ค. ([์์ธํ](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgNzAzZjA5ZmItNjU3NS00MzQ5LTkwYjMtMDJhNDU5ZTM0MTlh&hl=en))
์์:
```swift
let requestKey: String = "NSURLRequestKey"
// NSError ์๋ธํด๋์ค. ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง๋ง ์๋ ๊ธฐ๋ฅ์ ์๋ง์ผ๋ก ๋ง๋ค์ง ์๋๋ค.
class RequestError: NSError {var request: NSURLRequest? {
return self.userInfo[requestKey] as? NSURLRequest
}
}// ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค์ง ๋ชปํ๋ฉด RequestError๋ฅผ ๋ฐํํ๋ค.
func fetchData(request: NSURLRequest) -> (data: NSData?, error: RequestError?) {let userInfo: [String:Any] = [requestKey : request]
return (nil, RequestError(domain:"DOMAIN", code:0, userInfo: userInfo))
}// RequestError๊ฐ ๋ฌด์์ธ์ง ๋ชจ๋ฅด๊ณ ์คํจํ ๊ฒ์ด๋ฉฐ, NSError๋ฅผ ๋ฐํํ๋ค.
func willReturnObjectOrError() -> (object: AnyObject?, error: NSError?) {let request = NSURLRequest()
let result = fetchData(request: request)return (result.data, result.error)
}let result = willReturnObjectOrError()
// โ ๏ธ ํ์ธ. ์ด๊ฒ์ ๋ด ๊ด์ ์์ ์๋ฒฝํ NSError ์ธ์คํด์ค์ด๋ค.
let error: Int? = result.error?.code// โ ๏ธ ํ์ง๋ง ์ด๋ด! ์ด๊ฒ ๋ฌด์จ ์ผ์ด์ฃ ? RequestError์ด๊ธฐ๋ ํ๋ค! ๋๋จํด!
if let requestError = result.error as? RequestError {
requestError.request
}```
# ๐ด The Interface Segregation Principle (์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น)
ํด๋ผ์ด์ธํธ๋ณ๋ก ์ธ๋ถํ๋ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ([์์ธํ](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgOTViYjJhYzMtMzYxMC00MzFjLWJjMzYtOGJiMDc5N2JkYmJi&hl=en))
์์:
```swift// ๋ฐฉ๋ฌธ ์ฌ์ดํธ๊ฐ ์๋ค.
protocol LandingSiteHaving {
var landingSite: String { get }
}// LandingSiteHaving ๊ฐ์ฒด์ ์ฐฉ๋ฅํ ์ ์๋ค.
protocol Landing {
func land(on: LandingSiteHaving) -> String
}// ํ์ด๋ก๋๊ฐ ์๋ค.
protocol PayloadHaving {
var payload: String { get }
}// ์ฐจ๋์์ ํ์ด๋ก๋๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค (์. Canadaarm์ ํตํด).
protocol PayloadFetching {
func fetchPayload(vehicle: PayloadHaving) -> String
}final class InternationalSpaceStation: PayloadFetching {
// โ ๏ธ ์ฐ์ฃผ ์ ๊ฑฐ์ฅ์ SpaceXCRS8์ ์ฐฉ๋ฅ ๋ฅ๋ ฅ์ ๋ํด ์ ํ ๋ชจ๋ฅธ๋ค.
func fetchPayload(vehicle: PayloadHaving) -> String {
return "Deployed \(vehicle.payload) at April 10, 2016, 11:23 UTC"
}
}// ๋ฐ์ง์ - ์ฐฉ๋ฅ ์ง์ ์ด ์๋ค (well, you get the idea).
final class OfCourseIStillLoveYouBarge: LandingSiteHaving {
let landingSite = "a barge on the Atlantic Ocean"
}// ํ์ด๋ก๋๊ฐ ์๊ณ ์ฐฉ๋ฅ ์ง์ ์ด ์๋ ๊ณณ์ ์ฐฉ๋ฅํ ์ ์๋ค.
// ๋งค์ฐ ์ ํ๋ ์ฐ์ฃผ ๋นํ์ฒด๋ผ๋ ๊ฒ์ ์๋ค.
final class SpaceXCRS8: Landing, PayloadHaving {let payload = "BEAM and some Cube Sats"
// โ ๏ธ CRS8 ์ ์ฐฉ๋ฅ์ง ์ ๋ณด๋ง ์๊ณ ์๋ค.
func land(on: LandingSiteHaving) -> String {
return "Landed on \(on.landingSite) at April 8, 2016 20:52 UTC"
}
}let crs8 = SpaceXCRS8()
let barge = OfCourseIStillLoveYouBarge()
let spaceStation = InternationalSpaceStation()spaceStation.fetchPayload(vehicle: crs8)
crs8.land(on: barge)
```# ๐ The Dependency Inversion Principle (์์กด๊ด๊ณ ์ญ์ ์์น)
๊ตฌ์ฒดํ์ ์์กดํ์ง ๋ง๊ณ ์ถ์ํ์ ์์กดํ๋ผ. ([์์ธํ](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgMjdlMWIzNGUtZTQ0NC00ZjQ5LTkwYzQtZjRhMDRlNTQ3ZGMz&hl=en))
์์:
```swift
protocol TimeTraveling {
func travelInTime(time: TimeInterval) -> String
}final class DeLorean: TimeTraveling {
func travelInTime(time: TimeInterval) -> String {
return "Used Flux Capacitor and travelled in time by: \(time)s"
}
}final class EmmettBrown {
private let timeMachine: TimeTraveling// โ ๏ธ Emmet Brown์ `DeLorean`์ ๊ตฌ์ฒด์ ์ธ ํด๋์ค์ธ `DeLorean`์ด ์๋, `TimeTraveling` ์ฅ์น๋ก ๋ฐ๋๋ค.
init(timeMachine: TimeTraveling) {
self.timeMachine = timeMachine
}func travelInTime(time: TimeInterval) -> String {
return timeMachine.travelInTime(time: time)
}
}let timeMachine = DeLorean()
let mastermind = EmmettBrown(timeMachine: timeMachine)
mastermind.travelInTime(time: -3600 * 8760)
```Info
====๐ Descriptions from: [The Principles of OOD by Uncle Bob](http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod)