Swift API Design Guidelines - 1
[1] Foundamentals
์ฌ์ฉํ ๋ ๋ช ํํ๊ฒ ๋๋ผ๋ ๊ฒ์ด ๊ฐ์ฅ ์ค์ํฉ๋๋ค.
๋ช
ํํ ๊ฒ
์ด ๊ฐ๊ฒฐํ ๊ฒ๋ณด๋ค ์ค์ํฉ๋๋ค.
let blackButton (๐)
let blackBtn (๐)
๋ชจ๋ ์ ์ธ์ ๋ํด ๋ฌธ์ ์ฃผ์(Documentation Comment) ๋ฅผ ์์ฑํด ์ฃผ์ธ์
/// Writes the textual representation of each
/// element of `items` to the standard output.
/// โ Blank line ๋น์ค
/// The textual representation for each item `x`
/// is generated by the expression `String(x)`.
///
/// - Parameter separator: text to be printed โซ
/// between items. โ
/// - Parameter terminator: text to be printed โฌ Parameters section
/// at the end. โ
/// โญ
/// - Note: To print without a trailing โซ
/// newline, pass `terminator: ""` โ
/// โฌ Symbol commands
/// - SeeAlso: `CustomDebugStringConvertible`, โ
/// `CustomStringConvertible`, `debugPrint`. โญ
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
[2] Naming
(1) Promote Clear Usage
ํ์ํ ๋จ์ด๋ค์ ๋ชจ๋ ํฌํจํด ๋์ธ์
employees.remove(at: x) (๐)
employees.remove(x) (๐)
๋ถํ์ํ ๋จ์ด๋ฅผ ์๋ตํ์ธ์
allViews.removeElement(cancelButton) (๐)
allViews.remove(cancelButton) (๐)
ํ์ ๋์ ์ญํ ์ ๋ฐ๋ผ ๋ณ์(variables), ํ๋ผ๋ฏธํฐ(parameters), ์ฐ๊ดํ์ (associated types)์ ๋ค์ด๋ฐํ์ธ์.
///Good(๐)
var greeting = "Hello"
protocol ViewController {
associatedtype ContentView : View
}
class ProductionLine {
func restock(from supplier: WidgetFactory)
}
///Bad(๐)
var string = "Hello"
protocol ViewController {
associatedtype ViewType : View
}
class ProductionLine {
func restock(from widgetFactory: WidgetFactory)
}
ํ๋ผ๋ฏธํฐ์ ์ญํ ์ ๋ช ํํ ํ๊ธฐ ์ํด ๋ถ์ถฉ๋ถํ type ์ ๋ณด๋ฅผ ๋ณด์ถฉํ์ธ์
///Good(๐)
final class MyNotificationCenter{
private var observers: [String:NSObject] = [:]
func add(_ observer: NSObject, forKeyPath keyPath: String) {
observers[keyPath] = observer
}
}
let center = MyNotificationCenter()
center.add(self, forKeyPat: "mykey")
///Bad(๐)
final class MyNotificationCenter{
private var observers: [String:NSObject] = [:]
func add(_ observer: NSObject, for keyPath: String) {
observers[keyPath] = observer
}
}
let center = MyNotificationCenter()
center.add(self, for: "key")
(2) Strive for Fluent Usage
method์ function์ ์์ด ๋ฌธ์ฅ์ฒ๋ผ ์ฌ์ฉํ ์ ์๋๋ก ํ๊ธฐ
///Good(๐)
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โ
///Bad(๐)
x.insert(y, position: z)
x.subViews(color: y)
x.nounCapitalize()
๐ง ์์ธ) ์ฒซ๋ฒ์งธ ๋๋ ๋๋ฒ์งธ argument ์ดํ์ ์ฃผ์ argument๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ์ ์ฐฝํจ์ด ๋จ์ด์ง๋ ๊ฒ์ด ํ์ฉ๋ฉ๋๋ค.
AudioUnit.instantiate(
with: description,
options: [.inProcess], completionHandler: stopProgressBar)
factory method์ ์์์ make
๋ก ์์ํฉ๋๋ค.
struct List {
func makeIterator() -> IteratorProtocol {
Iterator(self)
}
}
x.makeIterator()
initializer์ argument์ factory method ํธ์ถ์๋ ๊ฒฝ๋ก๋ก ์์ํ๋ ๊ตฌ์ ๋ก ๊ตฌ์ฑํ์ง ๋ง์ธ์
//Good(๐)
///#1
struct Color {
init(red: Int, green: Int, blue: Int) {}
func makeWidget(gears: Int, spindles: Int) -> Widget{ Widget() }
}
let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)
///#2
struct Link {
init(target: Destination) {}
}
let ref = Link(target: destination)
///#3
struct RGBColor{
init(_ cmykColor: CMYKColor) {}
}
let rgbColor = RGBColor(cmykColor)
//Bad(๐)
///#1
struct Color {
init(havingRed red: Int, green: Int, and Blue: Int) {}
func makeWidget(havingGearCount: Int, andSpindleCount: Int) -> Widget { Widget() }
}
let foreground = Color(havingRGBValuesRed: 32, green: 64, andBlue: 128)
let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)
///#2
struct Link {
init(to target: Destination) {}
}
let ref = Link(to: destination)
๋ถ์ํจ๊ณผ(side-effect)๋ฅผ ๊ธฐ๋ฐํด์ function ๊ณผ method์ ๋ค์ด๋ฐ์ ํ์ธ์.
- side-effect๊ฐ ์๋ ๊ฒ์ ๋ช ์ฌ๋ก ์ฝํ์ผ ํจ. e.g.) x.distance(to:y), i.successor()
- side-effect๊ฐ ์๋ ๊ฒ์ ๋์ฌ๋ก ์ฝํ์ผ ํจ e.g.) print(x), x.sort(), x.append(y)
- mutating/nonmutating method์ ์ด๋ฆ์ ์ผ๊ด์ฑ ์๊ฒ ์ง๊ธฐ.
- operation์ด ๋์ฌ๋ก ์ค๋ช ๋๋ ๊ฒฝ์ฐ: mutating์๋ ๋์ฌ์ ๋ช ๋ นํ(sort(), append())์ ์ฌ์ฉ, nonmutating์๋ 'ed', 'ing'๋ฅผ ์ ๋ฏธ์ฌ๋ก ๋ถ์ฌ์(sorted(), appending()) ์ฌ์ฉํจ
- operation์ด ๋ช ์ฌ๋ก ์ค๋ช ๋๋ ๊ฒฝ์ฐ: mutating์๋ form์ ๋์ฌ ๋ถ์ฌ์ ์ฌ์ฉ(formUnion, formSuccessor), nonmutating์๋ ๋ช ์ฌ ํ์ฉ(union, successor)
nonmutating์ธ Boolean ๋ฉ์๋์ ํ๋กํผํฐ๋ ํธ์ถ๋๋ ๊ฐ์ฒด์ ๋ํ ์ฃผ์ฅ๋ฌธ์ฒ๋ผ ์ฝํ์ผ ํ๋ค
x.isEmpty , line1.intersects(line2)
์ด๋ค ๊ฒ์ด ๋ฌด์์ธ์ง๋ฅผ ์ค๋ช ํ๋ ํ๋กํ ์ฝ์ ๋ช ์ฌ๋ก ์ฝํ์ผ ํฉ๋๋ค
Collection
๋ฅ๋ ฅ์ ์ค๋ช ํ๋ ํ๋กํ ์ฝ์ able, ible, ing๋ฅผ ์ฌ์ฉํ ์ ๋ฏธ์ฌ๋ก ๋ค์ด๋ฐํด์ผ ํฉ๋๋ค
Equatable , ProgressReporting
protocol ProgressReporting{}
extension ProgressReporting{
func reportProgress() {
}
}
๋๋จธ์ง types, properties, variables, constants๋ ๋ช ์ฌ๋ก ์ฝํ์ผ ํฉ๋๋ค
(3) Use Terminology Well
- ์ผ๋ฐ์ ์ธ ๋จ์ด๊ฐ ์๋ฏธ๋ฅผ ๋ ์ ์ ๋ฌํ๋ค๋ฉด ์ ์๋ ค์ ธ ์์ง ์์ ์ฉ์ด๋ฅผ ์ฌ์ฉํ์ง ๋ง์ธ์.
- ์ ๋ฌธ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋์ค์๊ฒ ์ธ์ ๋ฐ๋ ์ ์ ๋ฅผ ์ฌ์ฉํ์ธ์.
- ์ฝ์ด(์ค์๋ง, abbreviations)์ ํผํ์ธ์
- ๊ด๋ก๋ฅผ ๋ฐ๋ฅด์ธ์.
์ฐธ๊ณ
'๊ณต์๋ฌธ์ ํบ์๋ณด๊ธฐ > Swift API Design Guidelines' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Swift API Design Guidelines - 2 (0) | 2023.03.13 |
---|
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
Swift API Design Guidelines - 2
Swift API Design Guidelines - 2
2023.03.13