Fundamentals

  • ์‚ฌ์šฉ์ฒ˜์— ๋Œ€ํ•œ โ€œ๋ช…๋ฃŒํ•จโ€์ด ์ตœ์šฐ์„ ์ด๋‹ค.
  • โ€œ๊ฐ„๊ฒฐํ•จโ€๋ณด๋‹ค โ€œ๋ช…๋ฃŒํ•จโ€์ด ๋ณด๋‹ค ์ค‘์š”ํ•˜๋‹ค.
  • ๋ชจ๋“  ์„ ์–ธ์— ๋Œ€ํ•ด ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•ด๋ผ.
    • ???
    • ํด๋ฆฐ์ฝ”๋“œ์™€ ๋Œ€์น˜๋œ๋‹ค.

Promote Clear Usage

์ฝ”๋“œ๋ฅผ ์ฝ์„ ๋•Œ ์‚ฌ๋žŒ์—๊ฒŒ ๋ชจํ˜ธํ•จ์„ ์ฃผ์ง€ ์•Š๋„๋ก ํ•„์š”ํ•œ ๋ชจ๋“  ๋‹จ์–ด๋ฅผ ํฌํ•จํ•ด๋ผ.

extension List {
  public mutating func remove(at position: Index) -> Element
}
employees.remove(at: x)
 
employees.remove(x) // unclear: are we removing x?
 

๋ถˆํ•„์š”ํ•œ ๋‹จ์–ด๋Š” ์ƒ๋žตํ•œ๋‹ค.

  • ์ค‘๋ณต๋˜๋Š” ๋‹จ์–ด๋Š” ์ œ๊ฑฐํ•œ๋‹ค. ๊ตณ์ด ๋ฐ˜๋ณตํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
public mutating func removeElement(_ member: Element) -> Element?
 
allViews.removeElement(view)
 
public mutating func remove(_ member: Element) -> Element?
 
allViews.remove(view) // Clearer!

๋ณ€์ˆ˜, ๋งค๊ฐœ๋ณ€์ˆ˜, ์—ฐ๊ด€ ํƒ€์ž…์€ โ€œ์—ญํ• โ€์— ๋งž์ถฐ ์ง“๋Š”๋‹ค. ํƒ€์ž…์— ๋งž์ถ”์ง€ ์•Š๋Š”๋‹ค.

  • ํƒ€์ž… ์ž์ฒด์˜ ์˜๋ฏธ๊ฐ€ ๋ณ€์ˆ˜์ด๋ฆ„์— ๋“ค์–ด๊ฐ€๋ฉด ๋ช…ํ™•ํ•˜์ง€๋„ ์•Š๊ณ , ํ‘œํ˜„๋ ฅ๋„ ์ข‹์ง€ ์•Š๋‹ค.
  • โ€œ์—ญํ• โ€์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฆ„์ด์–ด์•ผ ์ข‹๋‹ค.
var string = "Hello" // Stringํƒ€์ž…์„ ๋ณ€์ˆ˜ ์ด๋ฆ„์œผ๋กœ ์ง€์ •ํ•จ
 
protocol ViewController {
  associatedtype ViewType : View // ์—ญํ• ์ด ์•„๋‹ˆ๊ณ  ํƒ€์ž…์— ๋งž์ถฐ์„œ ์ง€์Œ
}
 
class ProductionLine {
  func restock(from widgetFactory: WidgetFactory) // ์—ญํ• ์— ๋งž์ถฐ์„œ ์ง€์Œ
}
var greeting = "Hello"
protocol ViewController {
  associatedtype ContentView : View
}
class ProductionLine {
  func restock(from supplier: WidgetFactory)
}
  • ๊ทธ๋Ÿฐ๋ฐ ์ฝ”๋”ฉ์„ ํ•˜๋‹ค๋ณด๋ฉด, ํŠน์ • ํ”„๋กœํ† ์ฝœ ํƒ€์ž…์ด๋ฆ„์ด ๋ณ€์ˆ˜๋ฅผ ๋Œ€๋ณ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.
  • ์ด๋Ÿฐ ๊ฒฝ์šฐ ํ”„๋กœํ† ์ฝœ์— Protocol์ด๋ผ๋Š” ์ ‘๋ฏธ์‚ฌ๋ฅผ ๋ถ™์—ฌ์„œ ๋ฌธ์ œ๋ฅผ ํ”ผํ•œ๋‹ค.
protocol Sequence {
  associatedtype Iterator : IteratorProtocol
}
protocol IteratorProtocol { ... }

ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์•ฝํ•œ ํƒ€์ž…์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ณด์™„ํ•ด๋ผ.

  • ๋งค๊ฐœ๋ณ€์ˆ˜ ์œ ํ˜•์ด NSObject, Any, AnyObject, Int, String๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ ์œ ํ˜•์ธ ๊ฒฝ์šฐ
  • ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ์ด ๋งŒ๋“  ์˜๋„๋ฅผ ์™„์ „ํžˆ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ๋‹ค.
func add(_ observer: NSObject, for keyPath: String)
 
grid.add(self, for: graphics) // ์ฝ์„ ๋•Œ ๊ทธ๋ž˜์„œ ์ด๊ฒŒ ๋ฌด์Šจ ํƒ€์ž…์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์• ๋งคํ•˜๋‹ค.
func addObserver(_ observer: NSObject, forKeyPath path: String)
 
grid.addObserver(self, forKeyPath: graphics) // clear

Strive for Fluent Usage

์˜์–ด ๊ตฌ๋ฌธ์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ฝํžˆ๋„๋ก ๋งŒ๋“ค์–ด๋ผ.

x.insert(y, at: z)          โ€œx, insert y at zโ€
x.subViews(havingColor: y)  โ€œx's subviews having color yโ€
x.capitalizingNouns()       โ€œx, capitalizing nounsโ€

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์€ make๋กœ ์‹œ์ž‘ํ•ด๋ผ.

x.makeIterator()

์ƒ์„ฑ์ž์™€ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์— Label์— Base name์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ.

  • Label: argument label
  • Base name: โ€œmakeโ€์™€ ๊ฐ™์€ ๋‹จ์–ด
// GOOD
let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)
let ref = Link(target: destination)
// BAD
let foreground = Color(havingRGBValuesRed: 32, green: 64, andBlue: 128)
let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)
let ref = Link(to: destination)

Side Effect์— ๋”ฐ๋ผ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๊ตฌ๋ถ„ํ•ด๋ผ.

  • side-effect: ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’ ์™ธ์—๋„, ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ชฝ์—์„œ๋„ ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒฝ์šฐ
  • side-effect๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด โ€œ๋ช…์‚ฌโ€๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • x.distance(to: y), i.successor()
  • ์žˆ๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด โ€œ๋™์‚ฌโ€๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • x.sort(), x.append(y)

Mutating / Nonmutating ๋ฉ”์„œ๋“œ์„ ํ•œ ์Œ์œผ๋กœ ๊ตฌ์„ฑํ•ด๋ผ.

  • ํŠน์ • ๋™์ž‘์ด ์• ์ดˆ์— โ€œ๋™์‚ฌโ€๋กœ ๋ฐ–์— ํ‘œํ˜„๋  ์ˆ˜ ์—†๋‹ค๋ฉด,
  • nonmutating function์˜ ์ด๋ฆ„์— โ€œedโ€, โ€œingโ€๋ฅผ ๋ถ™์—ฌ์„œ nonmutating function์˜ ์ด๋ฆ„์„ ๋งŒ๋“ค์–ด๋ผ.
MutatingNonmutating
x.sort()z = x.sorted()
x.append(y)z = x.appending(y)
  • ํŠน์ • ๋™์ž‘์ด ์• ํฌ์— โ€œ๋ช…์‚ฌโ€๋กœ ๋ฐ–์— ํ‘œํ˜„๋  ์ˆ˜ ์—†๋‹ค๋ฉด,
  • mutating function์˜ ์ด๋ฆ„์— โ€œformโ€์„ ๋ถ™์—ฌ์„œ mutating function์˜ ์ด๋ฆ„์„ ๋งŒ๋“ค์–ด๋ผ.
MutatingNonmutating
x.formUnion(z)z = x.unioned(z)
x.formSuccessor(y)z = x.successor(&y)

Boolean์€ ์ด๋ฅผ ๋ฐ›๋Š” ์ชฝ์—์„œ โ€œassertโ€๋ฌธ์„ ์ฝ๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ํ‘œํ˜„๋˜์–ด์•ผ ํ•œ๋‹ค.

  • x.contains(y)
  • x.isDisjoint(with: y)
  • x.isSubset(of: y)
  • x.isEmpty

โ€๋ฌด์—‡์ธ์ง€โ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ์˜ ์ด๋ฆ„์€ ๋ช…์‚ฌ๋กœ ํ‘œํ˜„ํ•ด๋ผ.

ํ”„๋กœํ† ์ฝœ ์ด๋ฆ„ํ”„๋กœํ† ์ฝœ ์„ค๋ช…
Collection์ปฌ๋ ‰์…˜(collection)์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ
IteratorProtocol์ดํ„ฐ๋ ˆ์ดํ„ฐ(iterator)์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ
Sequence์ˆœ์„œ๊ฐ€ ์žˆ๋Š” ์‹œํ€€์Šค(sequence)์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ
OptionSet์˜ต์…˜ ์ง‘ํ•ฉ(option set)์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ

๋Šฅ๋ ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ์˜ ์ด๋ฆ„์€ โ€œableโ€๋กœ ๋๋‚˜์•ผ ํ•œ๋‹ค.

ํ”„๋กœํ† ์ฝœ ์ด๋ฆ„ํ”„๋กœํ† ์ฝœ ์„ค๋ช…
Comparable๋น„๊ต ๊ฐ€๋Šฅํ•œ(comparable) ๊ฐ’์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ
Equatable๋™๋“ฑ๋น„๊ต(equatable) ๊ฐ€๋Šฅํ•œ ๊ฐ’์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ
RawRepresentableraw value๋ฅผ ๊ฐ€์ง€๋Š”(raw-representable) ํƒ€์ž…์˜ ํŠน์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ

Type, Perperty, variables, constants๋Š” ๋ช…์‚ฌ๋กœ ์ฝํ˜€์•ผ ํ•œ๋‹ค.

Use Terminology Well

๋ชจํ˜ธํ•œ ์šฉ์–ด๋ฅผ ํ”ผํ•ด๋ผ.

  • ๋” ์ผ๋ฐ˜์ ์ธ ๋‹จ์–ด๋กœ ์˜๋ฏธ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ชจํ˜ธํ•œ ์šฉ์–ด๋Š” ํ”ผํ•ด๋ผ.
  • ๊ตณ์ด โ€œํ”ผ๋ถ€โ€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ โ€œํ‘œํ”ผโ€๋กœ ํ‘œํ˜„ํ•  ํ•„์š”๋Š” ์—†๋‹ค.
  • ์ „๋ฌธ ์šฉ์–ด๋Š” ํ•„์ˆ˜์ ์ผ ๋•Œ๋งŒ ์‚ฌ์šฉํ•ด๋ผ. ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๋†“์น  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋˜๊ฐ€.

์ƒˆ๋กœ์šด ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๊ทธ ์˜๋ฏธ์— ๋”ฑ ๋งž๊ฒŒ ์‚ฌ์šฉํ•ด๋ผ.

  • ์ด๋ฏธ ์žˆ๋Š” ๋‹จ์–ด์ธ๋ฐ ๋‹ค๋ฅธ ๋‹จ์–ด๋ฅผ ์“ด๋‹ค๋ฉด ์ƒ์‚ฌ๊ฐ€ ํ™”๋‚ผ ๊ฑฐ๋‹ค.
  • ์ €์—ฐ์ฐจ ์‹ ์ž…๋„ ๊ฒฐ๊ตญ ๋ณดํŽธ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋‹จ์–ด๋ฅผ ์ฐพ์„ ๊ฒƒ์ด๋‹ค.

์•ฝ์–ด ์‚ฌ์šฉ์„ ํ”ผํ•ด๋ผ.

  • ํŠนํžˆ ๋น„ํ‘œ์ค€ ์•ฝ์–ด๋Š” ๊ฑฐ์˜ ์ „๋ฌธ ์šฉ์–ด๋ผ ๋ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.
  • ๋งŒ์•ฝ ์•ฝ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•  ์ •๋„๋กœ ๋ณดํŽธ์ ์ด์–ด์•ผ ํ•œ๋‹ค.

์ด์ „์˜ ๋ฌธํ™”๋ฅผ ์ˆ˜์šฉํ•ด๋ผ.

  • ์™„์ „ ์ดˆ๋ณด์ž๋Š” Array๋ณด๋‹ค List๊ฐ€ ๋” ์‰ฌ์šธ ์ˆ˜ ์žˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ๋ฐฐ์—ด์€ ์ปดํ“จํŒ…์˜ ๊ธฐ๋ณธ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹๋‹ค.
  • ์ต์ˆ™ํ•œ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๊ทธ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ •๋ณด๋ฅผ ์ตํžˆ๋Š” ์‹œ๊ฐ„๋„ ์ค„๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ์— ๋Œ€ํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค.
  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ verticalPositionOnUnitCircleAtOriginOfEndOfRadiusWithAngle(x)๋ณด๋‹ค sin(x)๊ฐ€ ๋” ์ข‹๋‹ค.

Conventions

O(1)์ด ์•„๋‹Œ ๋ชจ๋“  computed property์˜ ๋ณต์žก๋„๋ฅผ ๋ฌธ์„œํ™”ํ•ด๋ผ.

  • ๋ณดํ†ต ์‚ฌ์šฉํ•  ๋•Œ ๋ณต์žก๋„๊ฐ€ ๋†’์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒฝํ–ฅ์ด ํฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Free functions๋ณด๋‹ค๋Š” methods๋ฅผ ์‚ฌ์šฉํ•ด๋ผ.

  • Free functions: print์™€ ๊ฐ™์ด ํƒ€์ž…์— ์†ํ•˜์ง€ ์•Š์€ ํ•จ์ˆ˜
  • ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜์ž.
    • min(x, y, z): ๋ช…ํ™•ํ•œ self๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ
    • print(x): Generic์œผ๋กœ ์ œ๊ณต๋˜์–ด์•ผ ํ•  ๋–„
    • sin(x): ํŠน์ • ํ•จ์ˆ˜๊ฐ€ ์ด๋ฏธ ์ž˜ ์ •๋ฆฝ๋œ ๋„๋ฉ”์ธ์˜ ์ผ์ข…์ผ ๋•Œ (์ˆ˜ํ•™)

Case Convention์„ ์ง€ํ‚ค์ž.

  • Type, Protocol: UpperCamelCase
  • EveryThingElse: lowerCamelCase
  • ์•ฝ์–ด์˜ ๊ฒฝ์šฐ์—๋Š” ๋ชจ๋‘ Uppercase๋กœ ํ‘œํ˜„ํ•œ๋‹ค.
    • URL, HTTP, JSON, XML, HTML, CSS, ID, API, iOS, macOS

๋ฉ”์„œ๋“œ๋Š” ๊ธฐ๋ณธ ์ด๋ฆ„์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ด๊ฑด ์‚ฌ์‹ค ๋‹น์—ฐํ•œ ๊ฒƒ.
  • value ๋ผ๋Š” ์˜๋ฏธ๋Š” ๊ฐ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋‚˜ ์ด๋ฆ„์€ ๊ณต์œ ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Reference