Swift API Design Guidelines - 2
[3] Conventions
(1) General conventions
computed property์ ๋ณต์ก๋๊ฐ O(1)์ด ์๋๋ผ๋ฉด ๋ณต์ก๋๋ฅผ ์ฃผ์์ผ๋ก ๋จ๊ฒจ์ฃผ์ธ์.
import Founcation
/// Time Complexity: O(n^2)
class Company {
var numberOfEmployees: Int {
var result: Int = 0
(0...n).forEach {
(0...n).forEach{
(0...n).forEach{
result += 1
}
}
}
return result
}
}
์ ์ญ ํจ์ ๋์ ์ method์ property๋ฅผ ์ฌ์ฉํ์ธ์.
์ ์ญ ํจ์๋ ์๋์ ๊ฐ์ด ํน์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ๋ฉ๋๋ค.
// ๋ช
ํํ self ๊ฐ ์๋๊ฒฝ์ฐ
min(x, y, z)
//function์ด generic์ผ๋ก ์ ์ฝ์กฐ๊ฑด์ด ๊ฑธ๋ ค์์ง ์์ ๋
print(x)
//function ๊ตฌ๋ฌธ์ด ํด๋น ๋๋ฉ์ธ์ ํ๊ธฐ๋ฒ์ธ ๊ฒฝ์ฐ
sin(x)
๋์๋ฌธ์ ์ปจ๋ฒค์ ์ ๋ฐ๋ฅด์ธ์.
type, protocol์ ์ด๋ฆ์ UpperCamelCase
, ๋๋จธ์ง๋ lowerCamelCase
๋ฅผ ๋ฐ๋ฆ
๋๋ค.
var utf8Bytes: [UTF8] = []
var webstieURL: URL?
var urlString: String?
๊ธฐ๋ณธ ๋ป์ด ๊ฐ๊ฑฐ๋ ๊ตฌ๋ณ๋๋ ์๋ก ๊ตฌ๋ณ๋๋ ๋๋ฉ์ธ์์ ์๋ํ๋ Method๋ base name์ ๋์ผํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๐ [์ข์ ์์ 1]
๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ ๋์
์ ํ๋ ๋ฉ์๋๋ค์ ๋์ด
struct Shape {
func contains(_ otehr: Point) -> Bool {}
func contains(_ other: Shape) -> Bool {}
}
let shape = Shape()
shape.contains(Point())
shape.contains(Shape())
๐ [์ข์ ์์ 2]
์์ Shape ์ collection type์ ๊ตฌ๋ณ๋ ๋๋ฉ์ธ์ด๊ธฐ ๋๋ฌธ์, ๊ฐ์ ํ๋ก๊ทธ๋จ ์์์ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
struct Shape {
func contains(_ otehr: Point) -> Bool {}
func contains(_ other: Shape) -> Bool {}
}
extension Collection where Element : Equatable {
func contains(_ sought: Element) -> Bool { ... }
}
๐ [๋์ ์์ 1]
์๋์ index method๋ ๋ค๋ฅธ ์๋ฏธ
๋ฅผ ๊ฐ๊ณ ์๊ธฐ ๋๋ฌธ์, ๋ค๋ฅด๊ฒ ๋ค์ด๋ฐ
๋์ด์ผ ํฉ๋๋ค.
extension Database {
/// Rebuilds the database's search index
func index() { ... }
/// Returns the `n`th row in the given table.
func index(_ n: Int, inTable: TableID) -> TableRow { ... }
}
๐ [๋์ ์์ 2]
"overloading on return type"(๋ฆฌํด ๊ฐ์ ์ค๋ฒ๋ก๋ฉ ํ๋ ๊ฒฝ์ฐ)
์ ํ์
์ถ๋ก ์ ์ ๋ฌด์ ๋ฐ๋ผ ๋ชจํธํ ๊ฒฝ์ฐ๊ฐ ์์ด์ ๊ถ์ฅ๋์ง ์์ต๋๋ค.
struct Box {
private let rawValue: Int
init(_ rawValue: Int) {
self.rawValue = rawValue
}
func value() -> Int? {
rawValue
}
func value() -> String {
"\(rawValue)"
}
}
let myBox = Box(100)
myBox.value() as Int?
myBox.value() as String?
let intBoxValue: Int? = myBox.value()
(2) Parameters
์ฃผ์์ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค์ด์ฃผ๋ ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ ์ ํํ์ธ์.
๐ [์ข์ ์์]
/// Return an `Array` containing the elements of `self`
/// that satisfy `predicate`.
func filter(_ predicate: (Element) -> Bool) -> [Generator.Element]
/// Replace the given `subRange` of elements with `newElements`.
mutating func replaceRange(_ subRange: Range, with newElements: [E])
func move(from start: Point, to end: Point){}
๐ [๋์ ์์]
/// Return an `Array` containing the elements of `self`
/// that satisfy `includedInResult`.
func filter(_ includedInResult: (Element) -> Bool) -> [Generator.Element]
/// Replace the range of elements indicated by `r` with
/// the contents of `with`.
mutating func replaceRange(_ r: Range, with: [E])
์ผ๋ฐ์ ์ธ ์ฌ์ฉ์ ๋จ์ํ ํ ์ ์๋ค๋ฉด, Defaulted Parameters
๋ฅผ ์ฌ์ฉํ์ธ์
๐ [์ข์ ์์]
// #1
let order = lastName
.compare(royalFamilyName, options: [], range: nil, locale: nil)
let order = lastName.compare(royalFamilyName)
// #2
extension String {
/// ...description...
public func compare(
_ other: String, options: CompareOptions = [],
range: Range? = nil, locale: Locale? = nil
) -> Ordering
}
๐ [๋์ ์์]
extension String {
/// ...description 1...
public func compare(_ other: String) -> Ordering
/// ...description 2...
public func compare(_ other: String, options: CompareOptions) -> Ordering
/// ...description 3...
public func compare(
_ other: String, options: CompareOptions, range: Range) -> Ordering
/// ...description 4...
public func compare(
_ other: String, options: StringCompareOptions,
range: Range, locale: Locale) -> Ordering
}
Default parameter๋ฅผ parameter list ๋ ๋ถ๋ถ
์ ๋๋ ๊ฒ์ ์ ํธํฉ๋๋ค
//Default Parameter๋ฅผ ๋๋ถ๋ถ์ ๋์์ ๊ฒฝ์ฐ์ ํธ์ถ๋ฌธ
compare("A")
compare("B", locale: nil)
compare("B", options:[], locale: nil)
compare("B", options:[], range: nil, locale: nil)
//Default Parameter๋ฅผ ๋๋ถ๋ถ์ ๋์ง ์์์ ๊ฒฝ์ฐ์ ํธ์ถ๋ฌธ
compare("A")
compare(locale: nil, "B")
compare(options:[], locale: nil, "B")
compare(options:[], range: nil, locale: nil, "B")
(3) Argument Labels
// from๊ณผ to๊ฐ arugument label
func move(from start: Point, to end: Point)
x.move(from: x, to: y)
label์ ์จ๋ ์ ์ฉํ๊ฒ ๊ตฌ๋ถ์ด ๋์ง ์๋๋ค๋ฉด ๋ชจ๋ label์ ์๋ตํ์ธ์
min(number1, number2)
zip(sequence1, sequence2)
๊ฐ์ ์ ์งํ๋ฉด์ ํ์ ๋ณํ์ ํด์ฃผ๋ initializer์์, ์ฒซ๋ฒ์งธ argument label์ ์๋ตํ์ธ์.
Int64(someUInt32) // UInt32์์ Int64๋ก ํ์ฅ๋๋ฏ๋ก
์ฒซ๋ฒ์งธ argument๋ ํญ์ source of conversion ์ด์ด์ผ ํ๋ค.
extension String {
// Convert `x` into its textual representation in the given radix
init(_ x: BigInt, radix: Int = 10) โ Note the initial underscore
}
text = "The value is: "
text += String(veryLargeNumber)
text += " and in hexadecimal, it's"
text += String(veryLargeNumber, radix: 16)
๊ฐ์ ๋ฒ์๊ฐ ์ขํ์ง๋ ํ์ ๋ณํ์ ๊ฒฝ์ฐ, label์ ๋ถ์ฌ์ ์ค๋ช ํ๋ ๊ฒ์ ์ถ์ฒํฉ๋๋ค
extension UInt32 {
/// Creates an instance having the specified `value`.
init(_ value: Int16) โ Widening, so no label
/// Creates an instance having the lowest 32 bits of `source`.
// ๊ฐ์ด ์ค์ฌ์ง๋ฏ๋ก truncating ๋ถ์ด์ผ ํ๋ค.
init(truncating source: UInt64)
/// Creates an instance having the nearest representable
/// approximation of `valueToApproximate`.
init(saturating valueToApproximate: UInt64)
}
์ฒซ ๋ฒ์งธ argument๊ฐ ์ ์น์ฌ๊ตฌ์ ์ผ๋ถ์ผ ๋, argument label๋ก ์ง์ ํฉ๋๋ค
argument label์ ๋ณดํต ์ ์น์ฌ๋ก ์์ํฉ๋๋ค.
func removeBoxes(havingLength length: Int) {}
x.removeBoxes(havingLength: 12)
์ฒ์์ ๋์ค๋ 2๊ฐ์ argument๋ค์ด ๋จ์ผ ์ถ์ํ๋ฅผ ํํํ๋ ๊ฒฝ์ฐ๋ ์์ธ์ ๋๋ค.
// ๐ ์ข์ ์์
a.moveTo(x: b, y: c)
a.fadeFrom(red: b, green: c, blue: d)
// ๐ ๋์ ์์
a.move(toX: b, y: c)
a.fade(fromRed: b, green: c, blue: d)
๋ง์ฝ ์ฒซ๋ฒ์งธ argument๊ฐ ๋ฌธ๋ฒ์ ๊ตฌ์ ์ ๋ง๋ ๋ค๋ฉด label์ ์ ๊ฑฐํ๊ณ , ํจ์ ์ด๋ฆ์ base name์ ์ถ๊ฐํฉ๋๋ค.
x.addSubview(y)
์ฒซ๋ฒ์งธ argument๊ฐ ๋ฌธ๋ฒ์ ์ผ๋ก ๊ตฌ์ ์ ๋ง๋ค์ง ์๋๋ค๋ฉด, label์ ๋ฌ์ผํ๋ค๋ ๊ฒ์ ์์ํฉ๋๋ค.
// ๐ ์ข์ ์์
view.dismiss(animated: false)
let text = words.split(maxSplits: 12)
let studentsByName = students.sorted(isOrderedBefore: Student.namePrecedes)
// ๐ ๋์ ์์
view.dismiss(false) Don't dismiss? Dismiss a Bool?
words.split(12) Split the number 12?
default value๋ฅผ ๊ฐ์ง argument๋ ์๋ต๋ ์ ์์ผ๋ฉฐ, ์ด ๊ฒฝ์ฐ ๋ฌธ๋ฒ ๊ตฌ๋ฌธ์ ์ผ๋ถ๋ฅผ ํ์ฑํ์ง ์์ผ๋ฏ๋ก ํญ์ ๋ ์ด๋ธ์ด ์์ด์ผ ํฉ๋๋ค.
extension String {
/// ...description...
public func compare(
_ other: String, options: CompareOptions = [],
from range: Range? = nil, with locale: Locale? = nil
) -> Ordering
}
๋๋จธ์ง ๋ชจ๋ ๊ฒฝ์ฐ, argument๋ค์ Label์ ๋ถ์ฌ์ผ ํฉ๋๋ค
[4] Special Instructions
tuple members์ closure parameters์ Label์ ๋ถ์ด์ธ์.
struct Storage {
func doSomething() -> (reallocated: Bool, capacityChanged: Bool) {
return (true, false)
}
}
let storage = Storage()
let result = storage.doSomething()
result.reallocated // true
result.capacityChanged //false
overload set์์์ ๋ชจํธํจ์ ํผํ๊ธฐ ์ํด, ์ ์ฝ ์๋ ๋คํ์ฑ์ ๊ฐ๋ณํ ์ฃผ์ํ์ธ์.
๐ ์ข์ ์์
struct Array {
/// Inserts `newElement` at `self.endIndex`.
public mutating func append(_ newElement: Element)
/// Inserts the contents of `newElements`, in order, at
/// `self.endIndex`.
public mutating func append(contentsOf newElements: S)
where S.Generator.Element == Element
}
var values: [Any] = [1, "a"]
values.append(contentsOf:[2, 3, 4]) //[1,"a", 2, 3, 4]
๐ ๋์ ์์
struct Array {
/// Inserts `newElement` at `self.endIndex`.
public mutating func append(_ newElement: Element)
/// Inserts the contents of `newElements`, in order, at
/// `self.endIndex`.
public mutating func append(_ newElements: S)
where S.Generator.Element == Element
}
var values: [Any] = [1, "a"]
values.append([2, 3, 4]) // [1, "a", [2, 3, 4]] or [1, "a", 2, 3, 4]?
์ฐธ๊ณ
'๊ณต์๋ฌธ์ ํบ์๋ณด๊ธฐ > Swift API Design Guidelines' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Swift API Design Guidelines - 1 (0) | 2023.03.13 |
---|
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
Swift API Design Guidelines - 1
Swift API Design Guidelines - 1
2023.03.13